Ticket #6568: trac_6568-jinja_migration_v2.patch

File trac_6568-jinja_migration_v2.patch, 137.4 KB (added by mpatel, 12 years ago)

Fixed introspection, minor clean-ups. Apply only this patch.

  • sage/server/notebook/notebook.py

    # HG changeset patch
    # User Mitesh Patel <qed777@gmail.com>
    # Date 1250300225 25200
    # Node ID b9893319d0926141a5e3c8e5f4973c3bb48c69e4
    # Parent  4a994d18ceef6dadc9419b812d5a9aacb45e1b62
    #6568, notebook Jinja migration, combined Tim Dumol's patches
    * * *
    * Migrated notebook.py from HTML to Jinja.
    ** notebook._html_body
    ** notebook._html_head
    ** notebook.html_topbar
    ** notebook.html_banner_and_control
    ** notebook.html_user_control
    ** notebook.html_banner
    ** notebook.html_debug_window
    ** notebook.plain_text_worksheet_html
    ** notebook.worksheet_html
    ** notebook.html_worksheet_revision_list
    ** html_specific_revision
    ** history_html
    ** html_worksheet_revision_list
    ** html_specific_revision
    ** html_share
    ** html_download_or_delete_datafile
    ** html_slide_controls
    ** html_debug_window
    ** html_edit_window
    ** html_beforepublish_window
    ** html_afterpublish_window
    ** html_upload_data_window
    ** html
    ** html_settings
    ** html_doc
    * Created a template to replace html_worksheet_page_template
    * * *
    * Completed migration of worksheet.py to Jinja and added doctests
    ** worksheet.html
    ** worksheet.html_title
    ** worksheet.html_share_publish_buttons
    ** worksheet.html_menu
    ** worksheet.html_worksheet_body
    ** worksheet.time_since_last_edited
    ** worksheet.attached_html
    ** worksheet.format_completions_as_html
    * Changed template directory scheme from a flat to nested tree
    * Removed unused functions:
    ** notebook.html_system_select_form_element
    ** notebook.html_pretty_print_check_form_element
    ** notebook.html_slide_controls
    ** notebook.html_worksheet_page_template
    ** notebook._html_head
    ** notebook.html_worksheet_topbar
    ** notebook._html_body
    * * *
    * Fixed various bugs in the templates.
    ** Fixed bug in `published_worksheet.html` and `worksheet_body.html`
       that allowed editing of published worksheets.
    ** Fixed bug in `afterpublish_window.html` that caused the
       "re-publish" and "stop publishing" buttons not to work.
    ** Fixed bug in various templates that caused ``main.css`` not to load.
    ** Fixed bug in print representation of a worksheet that caused
       ``main.css`` not to load.
    ** Fixed typo: 'reviisions' to 'revisions'
    * * *
    * Fixed bug in styling of documentation pages
    * * *
    * Fixed a few bugs in templating.
    ** Fixed bug where `worksheet.html` was not passed the do_print argument.
    ** Fixed typo in `beforepublish_window.html`
    
    diff --git a/sage/server/notebook/notebook.py b/sage/server/notebook/notebook.py
    a b from sage.misc.misc import (alar 
    2424                                    tmp_dir, pad_zeros, cputime)
    2525from   sage.misc.package   import is_package_installed
    2626from   sage.version        import version
     27
    2728# Sage Notebook
    2829import css          # style
    2930import js           # javascript
    import keyboards # keyboard layouts 
    3334import server_conf  # server configuration
    3435import user_conf    # user configuration
    3536import user         # users
     37from template import template
    3638
    3739from cgi import escape
    3840
    class Notebook(SageObject): 
    167169        # quickly, etc.
    168170        shutil.rmtree(dir, ignore_errors=True)
    169171
     172    def systems(self):
     173        return SYSTEMS
     174
     175    def system_names(self):
     176        return SYSTEM_NAMES
    170177    ##########################################################
    171178    # Users
    172179    ##########################################################
    class Notebook(SageObject): 
    908915            return MAX_HISTORY_LENGTH
    909916       
    910917    def history_html(self):
    911         t = self.history_text()
    912         t = escape(t)
    913         s = '<head>\n'
    914         s += '<title>Command History</title>\n'
    915         s += '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'
    916         s += '</head>\n'
    917         s += '<body>\n'       
    918         s += '<pre>' + t + '</pre>\n'
    919         s += '<a name="bottom"></a>\n'
    920         s += '<script type="text/javascript"> window.location="#bottom"</script>\n'
    921         s += '</body>\n'
    922         return s
     918        return template("notebook/command_history.html", history_text = escape(self.history_text()))
    923919
    924920       
    925921    def history_with_start(self, start):
    class Notebook(SageObject): 
    11691165    # Importing and exporting worksheets to a plain text format
    11701166    ##########################################################
    11711167
    1172     def plain_text_worksheet_html(self, name, prompts=True):
    1173         W = self.get_worksheet_with_filename(name)
    1174         t = W.plain_text(prompts = prompts)
    1175         t = escape(t)
    1176         s = '<head>\n'
    1177         s += '<title>Sage Worksheet: %s</title>\n'%W.name()
    1178         s += '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'
    1179         s += '</head>\n'
    1180         s += '<body>\n'
    1181         s += '<h1><a href=".">Sage Worksheet: %s</a></h1>\n'%W.name()
    1182         s += '<pre>' + t + '</pre>'
    1183         s += '</body>\n'
    1184         return s
     1168    def plain_text_worksheet_html(self, filename, prompts=True):
     1169        """
     1170        Outputs html containing the plain text version of a worksheet
     1171
     1172        INPUT:
     1173        - ``filename`` - filename of a worksheet
     1174        - ``prompts``  - boolean
     1175
     1176        OUTPUT:
     1177        - A string containing the html for the plain text version
     1178        """
     1179        worksheet = self.get_worksheet_with_filename(filename)
     1180        text = escape(worksheet.plain_text(prompts = prompts))
     1181        return template("notebook/plain_text_worksheet.html",
     1182                        worksheet_name = worksheet.name(),
     1183                        worksheet_plain_text = text)
    11851184
    11861185    ##########################################################
    11871186    # Directories for worksheets, etc.
    class Notebook(SageObject): 
    13101309        return s
    13111310
    13121311    def worksheet_html(self, filename, do_print=False):
    1313         W = self.get_worksheet_with_filename(filename)
    1314         s = '<head>\n'
    1315         s += '<title>Sage Worksheet: %s</title>\n'%W.name()
    1316         s += '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'
    1317         s += '<script type="text/javascript" src="/javascript_local/jquery/jquery.js"></script>'
    1318         s += '<script type="text/javascript" src="/javascript/main.js"></script>\n'
    1319         if do_print:
    1320             s += '<script type="text/javascript" src="/javascript_local/jsmath/jsMath.js"></script>\n'
    1321         s += '<link rel=stylesheet href="/css/main.css">\n'
    1322         s += '</head>\n'
    1323         if do_print:
    1324             s += '<body>\n'
    1325             s += '<div class="worksheet_print_title">%s</div>'%W.name()
    1326         else:
    1327             s += '<body class="worksheet-online" onLoad="initialize_the_notebook();">\n'
    1328         s += W.html(include_title=False, do_print=do_print)
    1329         if do_print:
    1330             s += '<script type="text/javascript">jsMath.Process();</script>\n'
    1331         s += '\n</body>\n'
    1332         return s
     1312        """
     1313        Returns the HTML for the worksheet.
     1314
     1315        INPUT:
     1316        - ``username`` - a string
     1317        - ``worksheet`` - an instance of Worksheet
     1318
     1319        OUTPUT:
     1320        - a string containing the HTML
     1321
     1322        EXAMPLES::
     1323       
     1324            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     1325            sage: W = nb.create_new_worksheet('Test', 'admin')
     1326            sage: nb.worksheet_html(W.filename())
     1327            '\n<!D...ript type="text/javascript">cell_id_list=[0];</script>\n\n\n\n\n\n    </body>\n</html>'
     1328        """
     1329        worksheet = self.get_worksheet_with_filename(filename)
     1330        return template("notebook/worksheet.html", worksheet_name = worksheet.name(),
     1331                 worksheet_html = worksheet.html(include_title=False, do_print=do_print),
     1332                        do_print = do_print)
    13331333
    13341334   
    13351335
    class Notebook(SageObject): 
    13551355        sort_worksheet_list(W, sort, reverse)  # changed W in place
    13561356        return W
    13571357
    1358     def html_topbar(self, user, pub=False):
    1359         s = ''
    1360         entries = []
    1361        
    1362         if self.user_is_guest(user):
    1363             entries.append(('/', 'Log in', 'Please log in to the Sage notebook'))
    1364         else:
    1365             entries.append(('/home/%s'%user, 'Home', 'Back to your personal worksheet list'))
    1366             entries.append(('/pub', 'Published', 'Browse the published worksheets'))
    1367             entries.append(('help()', 'Help', 'Documentation'))
    1368 
    1369         ## TODO -- settings
    1370         #if self.user(user).is_admin():
    1371         #    entries.insert(1, ('/notebook_settings', 'Server', 'Change general Sage notebook server configuration'))
    1372         if not pub:
    1373             entries.insert(2, ('history_window()', 'Log', 'View a log of recent computations'))
    1374         if not self.user_is_guest(user):
    1375             entries.append(('/settings', 'Settings', 'Change account settings including password'))
    1376             entries.append(('/logout', 'Sign out', 'Log out of the Sage notebook'))
    1377 
    1378         s += self.html_banner_and_control(user, entries)           
    1379         s += '<hr class="usercontrol">'
    1380         return s
    1381 
    1382     def html_banner_and_control(self, user, entries):
    1383         return """
    1384         <table width="100%%"><tr><td>
    1385         %s
    1386         </td><td align=right>
    1387         %s
    1388         </td></tr>
    1389         </table>
    1390         """%(self.html_banner(),
    1391              self.html_user_control(user, entries))
    1392        
    1393 
    1394     def html_user_control(self, user, entries):
    1395         s = ''
    1396         s += '<span class="username">%s</span>'%user
    1397         for href, name, title in entries:
    1398             if '(' in href:
    1399                 action = 'onClick="%s"'%href
    1400             else:
    1401                 action = 'href="%s"'%href
    1402             x = '<a title="%s" class="usercontrol" %s>%s</a>\n'%(title, action, name)
    1403             s += vbar + x
    1404         return s
    1405 
    1406     def html_banner(self):
    1407         ver=version
    1408         s = """
    1409         <div class="banner">
    1410         <table width="100%%"><tr><td>
    1411         <a class="banner" href="http://www.sagemath.org"><img align="top" src="/images/sagelogo.png" alt="Sage"> Notebook</a></td><td><span class="ping" id="ping">Searching for Sage server...</span></td>
    1412         </tr><tr><td style="font-size:xx-small; text-indent:13px; color:black">Version %s</td><td></td></tr></table>
    1413         </div>
    1414         """%ver
    1415         return s
    1416 
    1417 
    14181358    ##########################################################
    14191359    # Revision history for a worksheet
    14201360    ##########################################################
    14211361    def html_worksheet_revision_list(self, username, worksheet):
    1422         head, body = self.html_worksheet_page_template(worksheet, username, "Revision history", select="revisions")
     1362        """
     1363        Returns the HTML for the revision list of a worksheet.
     1364
     1365        INPUT:
     1366        - ``username`` - a string
     1367        - ``worksheet`` - an instance of Worksheet
     1368
     1369        OUTPUT:
     1370        - a string containing the HTML
     1371
     1372        EXAMPLES::
     1373       
     1374            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     1375            sage: W = nb.create_new_worksheet('Test', 'admin')
     1376            sage: nb.html_worksheet_revision_list('admin', W)
     1377            '\n<!D...seconds ago</span></td>\n    </tr>\n\n</table>\n\n\n    </body>\n</html>'
     1378        """
    14231379        data = worksheet.snapshot_data()  # pairs ('how long ago', key)
    1424         rows = []
    1425         i = 0
    1426         for i in range(len(data)):
    1427             desc, key = data[i]
    1428             rows.append('<tr><td></td><td><a href="revisions?rev=%s">Revision %s</a></td><td><span class="revs">%s</span></td></tr>'%
    1429                         (key, i, desc))
    1430            
    1431         rows = list(reversed(rows))
    1432         rows = '\n'.join(rows)
    1433         body += """
    1434         <hr class="usercontrol">
    1435 <table width="100%%">
    1436 <tr><td width="1%%"></td><td width="20%%"><b>Revision</b></td> <td width="20%%"><b>Last Edited</b></td><td width="30%%"></td>
    1437 %s
    1438 </table>
    1439 """%rows
    14401380
    1441         return """
    1442         <html>
    1443         <head>%s</head>
    1444         <body>%s</body>
    1445         </html>
    1446         """%(head, body)
     1381        return template("notebook/worksheet_revision_list.html", data = data,
     1382                        worksheet = worksheet,
     1383                        worksheet_filename = worksheet.filename(),
     1384                        username = username,
     1385                        JSMATH = JSMATH,
     1386                        JSMATH_IMAGE_FONTS = JSMATH_IMAGE_FONTS,
     1387                        JEDITABLE_TINYMCE = JEDITABLE_TINYMCE,
     1388                        sage_jsmath_macros = sage_jsmath_macros)
    14471389
    14481390
    14491391    def html_specific_revision(self, username, ws, rev):
     1392        """
     1393        Returns the HTML for a revision of the worksheet.
     1394
     1395        INPUT:
     1396        - ``username`` - a string
     1397        - ``ws`` - an instance of Worksheet
     1398        - ``rev`` - a string containing the key of the revision
     1399
     1400        OUTPUT:
     1401        - a string containing the HTML
     1402        """
    14501403        t = time.time() - float(rev[:-4])
    1451         when = worksheet.convert_seconds_to_meaningful_time_span(t)
    1452         head, body = self.html_worksheet_page_template(ws, username,
    1453                                        "Revision from %s ago&nbsp;&nbsp;&nbsp;&nbsp;<a href='revisions'>Revision List</a>"%when, select="revisions")
     1404        time_ago = worksheet.convert_seconds_to_meaningful_time_span(t)
    14541405       
    14551406        filename = ws.get_snapshot_text_filename(rev)
    14561407        txt = bz2.decompress(open(filename).read())
    14571408        W = self.scratch_worksheet()
    14581409        W.delete_cells_directory()
    14591410        W.edit_save(txt)
    1460         html = W.html_worksheet_body(do_print=True, publish=True)
     1411        body_worksheet_html = W.html_worksheet_body(do_print=True, publish=True)
    14611412
    14621413        data = ws.snapshot_data()  # pairs ('how long ago', key)
    14631414        prev_rev = None
    class Notebook(SageObject): 
    14701421                    next_rev = data[i+1][1]
    14711422                break
    14721423           
    1473         if prev_rev:
    1474             prev = '<a class="listcontrol" href="revisions?rev=%s">Older</a>&nbsp;&nbsp;'%prev_rev
    1475         else:
    1476             prev = 'Oldest'
    1477            
    1478         if next_rev:
    1479             next = '<a class="listcontrol" href="revisions?rev=%s">Newer</a>&nbsp;&nbsp;'%next_rev
    1480         else:
    1481             next = 'Newest'
    1482 
    1483         actions = """
    1484         %s
    1485         %s
    1486         <a class="listcontrol" href="revisions?rev=%s&action=revert">Revert to this one</a>  <span class="lastedit">(note that images are note recorded)</span>&nbsp;&nbsp;
    1487         <a class="listcontrol" href="revisions?rev=%s&action=publish">Publish this one</a>&nbsp;&nbsp;
    1488         """%(prev, next, rev, rev)
    1489        
    1490         s = """
    1491         %s
    1492         <hr class="usercontrol">       
    1493 <table width="100%%">
    1494 %s
    1495         <hr class="usercontrol">
    1496 %s       
    1497 </table>
    1498 """%(actions, html, actions)
    1499         body += s
    1500 
    1501         return """
    1502         <html>
    1503         <head>%s</head>
    1504         <body>%s</body>
    1505         </html>
    1506         """%(head, body)
    1507 
    1508     def html_worksheet_page_template(self, worksheet, username, title, select=None, backwards=False):
    1509         head = self._html_head(worksheet_filename=worksheet.filename(), username=username)
    1510         head += '<script  type="text/javascript">worksheet_filename="%s"; worksheet_name="%s"; server_ping_while_alive(); </script>'%(worksheet.filename(), worksheet.name())
    1511         body = self._html_body(worksheet.filename(), top_only=True, username=username)
    1512         body += self.html_worksheet_topbar(worksheet, select=select, username=username, backwards=backwards)
    1513         body += '<hr class="usercontrol">'
    1514         body += '<span class="sharebar">%s</span>'%title
    1515         body += '<br>'*3
    1516         return head, body
     1424        return template("notebook/specific_revision.html", worksheet = ws,
     1425                        worksheet_filename = ws.filename(),
     1426                        username = username, rev = rev,
     1427                        prev_rev = prev_rev, next_rev = next_rev,
     1428                        time_ago = time_ago,
     1429                        body_worksheet_html = body_worksheet_html,
     1430                        JSMATH = JSMATH,
     1431                        JSMATH_IMAGE_FONTS = JSMATH_IMAGE_FONTS,
     1432                        JEDITABLE_TINYMCE = JEDITABLE_TINYMCE,
     1433                        sage_jsmath_macros = sage_jsmath_macros)
    15171434       
    15181435
    15191436    def html_share(self, worksheet, username):
    1520         head, body = self.html_worksheet_page_template(worksheet, username, "Share this document", select="share")
     1437        """
     1438        Returns the HTML for the share page of a worksheet.
    15211439
    1522         if not (self.user(username).is_admin() or username == worksheet.owner()):
    1523             body += "Only the owner of a worksheet is allowed to share it."
    1524             body += 'You can do whatever you want if you <a href="copy">make your own copy</a>.'
    1525         else:
    1526             body += 'This Sage Worksheet is currently shared with the people listed in the box below.<br>'
    1527             body += 'You may add or remove collaborators (separate user names by commas).<br><br>'
     1440        INPUT:
     1441        - ``username`` - a string
     1442        - ``worksheet`` - an instance of Worksheet
    15281443
    1529             collabs = ', '.join(worksheet.collaborators())
    1530             body += '<form width=70% method="post" action="invite_collab">\n'
    1531             body += '<textarea name="collaborators" rows=5 cols=70 class="edit" id="collaborators">%s</textarea><br><br>'%collabs
    1532             body += '<input type="submit" title="Give access to your worksheet to the above collaborators" value="Invite Collaborators">'
    1533             body += '</form>'
     1444        OUTPUT:
     1445        - a string containing the HTML
     1446       
     1447        EXAMPLES::
     1448       
     1449            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     1450            sage: W = nb.create_new_worksheet('Test', 'admin')
     1451            sage: nb.html_share(W, 'admin')
     1452            '\n<!D...span class="username">Sage Users:</span>\n<span class="users">\n    \n</span>\n\n\n\n    </body>\n</html>'
     1453        """
     1454        U = self.users()
     1455        other_users = [x for x, u in U.iteritems() if not u.is_guest() and not u.username() in [username, 'pub', '_sage_']]
     1456        other_users.sort(lambda x,y: cmp(x.lower(), y.lower()))
    15341457
    1535             body += '<br>'*2
    1536             body += '<hr class="usercontrol">'
    1537             body += '<span class="username">Sage Users:</span>'
    1538             U = self.users()
    1539             K = [x for x, u in U.iteritems() if not u.is_guest() and not u.username() in [username, 'pub', '_sage_']]
    1540             def mycmp(x,y):
    1541                 return cmp(x.lower(), y.lower())
    1542             K.sort(mycmp)
    1543             body += '<span class="users">%s</span>'%(', '.join(K))
    1544 
    1545 
    1546         return """
    1547         <html>
    1548         <head>%s</head>
    1549         <body>%s</body>
    1550         </html>
    1551         """%(head, body)
    1552 
     1458        return template("notebook/worksheet_share.html", worksheet = worksheet,
     1459                        worksheet_filename = worksheet.filename(),
     1460                        username = username, other_users = other_users,
     1461                        user_is_admin = self.user(username).is_admin(),
     1462                        JSMATH = JSMATH,
     1463                        JSMATH_IMAGE_FONTS = JSMATH_IMAGE_FONTS,
     1464                        JEDITABLE_TINYMCE = JEDITABLE_TINYMCE,
     1465                        sage_jsmath_macros = sage_jsmath_macros)
    15531466
    15541467
    15551468    def html_download_or_delete_datafile(self, ws, username, filename):
    1556         head, body = self.html_worksheet_page_template(ws, username, "Data file: %s"%filename)
     1469        """
     1470        Returns the HTML for the download or delete datafile page.
     1471
     1472        INPUT:
     1473        - ``username`` - a string
     1474        - ``ws`` - an instance of Worksheet
     1475        - ``filename`` - the name of the file
     1476
     1477        OUTPUT:
     1478        - a string containing the HTML
     1479
     1480        EXAMPLES::
     1481       
     1482            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     1483            sage: W = nb.create_new_worksheet('Test', 'admin')
     1484            sage: nb.html_download_or_delete_datafile(W, 'admin', 'bar')
     1485            '\n<!D...ploaded to this worksheet.</p>\n\n<hr class="usercontrol" />\n\n\n\n\n    </body>\n</html>'
     1486        """
    15571487        path = "/home/%s/data/%s"%(ws.filename(), filename)
    1558         body += 'You may download <a href="%s">%s</a>'%(path, filename)
    15591488
    1560         X = self.get_worksheets_with_viewer(username)
    1561         v = [x for x in X if x.is_active(username)]
    1562         sort_worksheet_list(v, 'name', False)
    1563         ws_form = ['<option selected>select worksheet</option>'] + \
    1564                   ["""<option value='link_datafile("%s","%s")'>%s</option>"""%(
    1565                            x.filename(), filename, x.name()) for x in v]
    1566         ws_form = '\n'.join(ws_form)
    1567         ws_form = "<select onchange='go_option(this);' class='worksheet'>%s</select>"%ws_form
    1568         body += ' or create a linked copy to the worksheet %s,'%ws_form
    1569         body += ' or <a href="/home/%s/datafile?name=%s&action=delete">delete %s.</a>'%(ws.filename(),filename, filename)
     1489        worksheets = self.get_worksheets_with_viewer(username)
     1490        active_worksheets = [worksheet for worksheet in worksheets if worksheet.is_active(username)]
     1491        sort_worksheet_list(active_worksheets, 'name', False)
     1492       
     1493        ext = os.path.splitext(filename)[1].lower()
     1494        file_is_image, file_is_text = False, False
     1495        text_file_content = ""
     1496       
     1497        if ext in ['.png', '.jpg', '.gif']:
     1498            file_is_image = True
     1499        if ext in ['.txt', '.tex', '.sage', '.spyx', '.py', '.f', '.f90', '.c']:
     1500            file_is_text = True
     1501            text_file_content = open('%s/%s'%(ws.data_directory(), filename)).read()
    15701502
    1571         body += "<br><br>Access %s in this worksheet by typing <tt>DATA+'%s'</tt>.  Here DATA is a special variable that gives the exact path to all data files uploaded to this worksheet.<br><br>"%(filename, filename)
    1572        
    1573         body += '<hr class="usercontrol">'
    1574         ext = os.path.splitext(filename)[1].lower()
    1575         if ext in ['.png', '.jpg', '.gif']:
    1576             body += '<div align=center><img src="%s"></div>'%path
    1577         elif ext in ['.txt', '.tex', '.sage', '.spyx', '.py', '.f', '.f90', '.c']:
    1578             body += '<form method="post" action="savedatafile" enctype="multipart/form-data">'
    1579             body += '<input type="submit" value="Save Changes" name="button_save"> <input type="submit" value="Cancel" name="button_cancel"><br>'
    1580             body += '<textarea class="edit" name="textfield" rows=17 cols=70 id="textfield">%s</textarea>'%open('%s/%s'%(ws.data_directory(), filename)).read()
    1581             body += '<input type="hidden" name="filename" value="%s" id="filename">'%filename
    1582             body += '</form>'
    1583 
    1584         return """
    1585         <html>
    1586         <head>%s</head>
    1587         <body>%s</body>
    1588         </html>
    1589         """%(head, body)
     1503        return template("notebook/download_or_delete_datafile.html",
     1504                        worksheet = ws,
     1505                        worksheet_filename = ws.filename(),
     1506                        username = username,
     1507                        active_worksheets = active_worksheets,
     1508                        filename_ = filename,
     1509                        path = path,
     1510                        file_is_image = file_is_image,
     1511                        file_is_text = file_is_text,
     1512                        text_file_content = text_file_content,
     1513                        JSMATH = JSMATH,
     1514                        JSMATH_IMAGE_FONTS = JSMATH_IMAGE_FONTS,
     1515                        JEDITABLE_TINYMCE = JEDITABLE_TINYMCE,
     1516                        sage_jsmath_macros = sage_jsmath_macros)
    15901517
    15911518
    15921519
    class Notebook(SageObject): 
    16851612    ###########################################################
    16861613    # HTML -- generate most html related to the whole notebook page
    16871614    ###########################################################
    1688     def html_slide_controls(self):
    1689         return """
    1690           <div class="hidden" id="slide_controls">
    1691             <div class="slideshow_control">
    1692              <a class="slide_arrow" onClick="slide_next()">&gt;</a>
    1693               <a class="slide_arrow" onClick="slide_last()">&gt;&gt;</a> %s
    1694               <a class="cell_mode" onClick="cell_mode()">Exit</a>
    1695             </div>
    1696             <div class="slideshow_progress" id="slideshow_progress" onClick="slide_next()">
    1697               <div class="slideshow_progress_bar" id="slideshow_progress_bar">&nbsp;</div>
    1698               <div class="slideshow_progress_text" id="slideshow_progress_text">&nbsp;</div>
    1699             </div>
    1700             <div class="slideshow_control">
    1701               <a class="slide_arrow" onClick="slide_first()">&lt;&lt;</a>
    1702               <a class="slide_arrow" onClick="slide_prev()">&lt;</a>
    1703             </div>
    1704           </div>
    1705           """%vbar
     1615    def html_debug_window(self):
     1616        """
     1617        Returns the HTML for the debug window
    17061618
    1707     def html_debug_window(self):
    1708         return """
     1619        OUTPUT:
     1620        - the HTML for the debug window
     1621   
     1622        EXAMPLES::
     1623
     1624        sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     1625        sage: print(nb.html_debug_window())
    17091626        <div class='debug_window'>
    1710         <div class='debug_output'><pre id='debug_output'></pre></div>
    1711         <textarea rows=5 id='debug_input' class='debug_input'
    1712          onKeyPress='return debug_keypress(event);'
    1713          onFocus='debug_focus();' onBlur='debug_blur();'></textarea>
    1714         </div>"""
     1627            <div class='debug_output'><pre id='debug_output'></pre></div>
     1628            <textarea rows=5 id='debug_input' class='debug_input'
     1629                      onKeyPress='return debug_keypress(event);'
     1630                      onFocus='debug_focus();' onBlur='debug_blur();'></textarea>
     1631        </div>
     1632        """
     1633        return template("notebook/debug_window.html")
    17151634
    17161635   
    1717     def _html_head(self, worksheet_filename, username):
    1718         if worksheet_filename is not None:
    1719             worksheet = self.get_worksheet_with_filename(worksheet_filename)
    1720             head = '\n<title>%s (Sage)</title>'%(worksheet.name())
    1721         else:
    1722             head = '\n<title>Sage Notebook | Welcome</title>'
    1723 
    1724         head += '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'
    1725         # Load the Sage javascript libray.
    1726         head += '\n<script type="text/javascript" src="/javascript_local/jquery/jquery.js"></script>'
    1727         head += '\n<script type="text/javascript" src="/javascript/main.js"></script>\n'
    1728         head += '\n<link rel=stylesheet href="/css/main.css" type="text/css">\n'
    1729 
    1730         if JSMATH:
    1731             # turn off the ugly scary font warning.
    1732             head += '\n <STYLE> #jsMath_Warning {display: none} </STYLE>\n'
    1733             head += '<script type="text/javascript">jsMath = {Controls: {cookie: {scale: 115}}}</script>\n'
    1734             if not JSMATH_IMAGE_FONTS:
    1735                 head +=' <script type="text/javascript" src="/javascript_local/jsmath/plugins/noImageFonts.js"></script>\n'
    1736 
    1737             # Move the jsMath button 20 pixels from the right edge
    1738             # (apparently in some browsers, it covers up the scroll
    1739             # bar)
    1740             head += """<script type="text/javascript">
    1741 jsMath.styles = {
    1742         '#jsMath_button':   'position:fixed; bottom:1px; right:20px; background-color:white; '
    1743                                 + 'border: solid 1px #959595; margin:0px; padding: 0px 3px 1px 3px; '
    1744                                 + 'z-index:102; color:black; text-decoration:none; font-size:x-small; '
    1745                                 + 'width:auto; cursor:hand;',
    1746       };
    1747     </script>
    1748 """
    1749             head += '<script type="text/javascript" src="/javascript_local/jsmath/jsMath.js"></script>\n'
    1750             head += r'''<script type="text/javascript">/*The extensions here do the following:
    1751       - verb implements the \verb command:
    1752         see http://www.math.union.edu/~dpvc/jsMath/authors/verb.html
    1753       - moreArrows implements \xrightarrow, among other things:
    1754         see http://www.math.union.edu/~dpvc/jsMath/authors//moreArrows.html
    1755       - AMSmath implements a number of AMS math commands:
    1756         see http://www.math.union.edu/~dpvc/jsMath/authors/AMSmath.html
    1757     */
    1758          jsMath.Extension.Require("verb");
    1759          jsMath.Extension.Require("moreArrows");
    1760          jsMath.Extension.Require("AMSmath");
    1761          jsMath.Extension.Require("AMSsymbols");
    1762 </script>'''
    1763 
    1764         # import latex macros
    1765         for m in sage_jsmath_macros:
    1766             head += '<script>' + m + '</script>\n'
    1767        
    1768         # Load the jquery and ui-jquery javascript library.
    1769         # This is used for interact functionality in the notebook, and will be used
    1770         # to enable drag and drop, image zoom, etc.
    1771         head += '''
    1772 <script type="text/javascript" src="/javascript_local/jqueryui/jquery.ui.all.min.js"></script>
    1773 <script type="text/javascript" src="/javascript_local/jquery/plugins/farbtastic/farbtastic.min.js"></script>
    1774 <script type="text/javascript" src="/javascript_local/jquery/plugins/dimensions/jquery.dimensions.min.js"></script>
    1775 <script type="text/javascript" src="/javascript_local/jquery/plugins/jquery.event.extendedclick.js"></script>
    1776 
    1777 <link rel="stylesheet" href="/javascript_local/jquery/plugins/farbtastic/farbtastic.css" type="text/css" /> 
    1778 <link rel="stylesheet" href="/javascript_local/jqueryui/themes/flora/flora.all.css">
    1779          '''
    1780 # TODO: get the lazy loading plugin
    1781 
    1782 # TODO: Load individual ui plugins, not the whole package:
    1783 # <script type="text/javascript" src="/javascript_local/jqueryui/ui.mouse.min.js"></script>
    1784 # <script type="text/javascript" src="/javascript_local/jqueryui/ui.slider.min.js"></script>
    1785 # <script type="text/javascript" src="/javascript_local/jqueryui/ui.draggable.min.js"></script>
    1786 # <script type="text/javascript" src="/javascript_local/jqueryui/ui.draggable.ext.min.js"></script>
    1787 # <script type="text/javascript" src="/javascript_local/jqueryui/ui.resizable.min.js"></script>
    1788 # <script type="text/javascript" src="/javascript_local/jqueryui/ui.dialog.min.js"></script>
    1789 
    1790 
    1791         # This was for syntax hilighting 
    1792 #        head +=' <script type="text/javascript" src="/javascript/highlight/prettify.js"></script>\n'
    1793 #        head += '<link rel=stylesheet href="/css/highlight/prettify.css" type="text/css">\n'
    1794 
    1795         head +=' <script type="text/javascript" src="/javascript/sage3d.js"></script>\n'
    1796 
    1797         # Jmol -- embedded 3d graphics.
    1798         head +=' <script type="text/javascript" src="/java/jmol/appletweb/Jmol.js"></script>\n'
    1799        
    1800         head +=' <script>jmolInitialize("/java/jmol");jmolSetCallback("menuFile","/java/jmol/appletweb/SageMenu.mnu");</script>\n' # this must stay in the <head>
    1801 
    1802         # TinyMCE and jEditable -- in-place editing of text cells
    1803         if JEDITABLE_TINYMCE:
    1804             head += """<script type="text/javascript" src="/javascript_local/tiny_mce/tiny_mce.js"></script>
    1805 <script src="/javascript_local/jquery/plugins/jquery.jeditable.mini.js" type="text/javascript" charset="utf-8"></script>
    1806 <script type="text/javascript">
    1807 
    1808 function toggleEditor(id) {
    1809         if (!tinyMCE.get(id))
    1810                 tinyMCE.execCommand('mceAddControl', false, id);
    1811         else
    1812                 tinyMCE.execCommand('mceRemoveControl', false, id);
    1813 }
    1814 
    1815 $.fn.tinymce = function(options){
    1816    return this.each(function(){
    1817       tinyMCE.execCommand("mceAddControl", true, this.id);
    1818    });
    1819 }
    1820 
    1821 function initMCE(){
    1822    tinyMCE.init({mode : "none",
    1823       plugins: "table,searchreplace,safari,paste,autosave",
    1824       theme : "advanced",
    1825       theme_advanced_toolbar_location : "top",
    1826       theme_advanced_toolbar_align : "left",
    1827       theme_advanced_statusbar_location : "bottom",
    1828       theme_advanced_buttons1 : "\
    1829 formatselect,fontselect,fontsizeselect,bold,italic,underline,strikethrough,forecolor,backcolor,|,\
    1830 bullist,numlist,|,\
    1831 undo,redo,search,pastetext,pasteword",
    1832       theme_advanced_buttons2 : "\
    1833 justifyleft,justifycenter,justifyright,justifyfull,outdent,indent,|,\
    1834 charmap,|,\
    1835 table,tablecontrols,|,\
    1836 code,|,\
    1837 link,image,unlink",
    1838       theme_advanced_buttons3 : "",
    1839       theme_advanced_resizing : true,
    1840       setup : function(ed) {
    1841       ed.onKeyDown.add(function(ed, e) {
    1842           if(key_enter_shift(key_event(e))) {
    1843             $(ed.formElement).submit();
    1844           }
    1845       })}
    1846    });
    1847 };
    1848 
    1849 initMCE();
    1850 
    1851 
    1852 $.editable.addInputType('mce', {
    1853    element : function(settings, original) {
    1854       var textarea = $('<textarea id="'+$(original).attr("id")+'_mce"/>');
    1855       if (settings.rows) {
    1856          textarea.attr('rows', settings.rows);
    1857       } else {
    1858          textarea.height(settings.height);
    1859       }
    1860       if (settings.cols) {
    1861          textarea.attr('cols', settings.cols);
    1862       } else {
    1863          textarea.width(settings.width);
    1864       }
    1865       $(this).append(textarea);
    1866          return(textarea);
    1867       },
    1868    plugin : function(settings, original) {
    1869       tinyMCE.execCommand("mceAddControl", true, $(original).attr("id")+'_mce');
    1870       },
    1871    submit : function(settings, original) {
    1872       tinyMCE.triggerSave();
    1873       tinyMCE.execCommand("mceRemoveControl", true, $(original).attr("id")+'_mce');
    1874       },
    1875    reset : function(settings, original) {
    1876       tinyMCE.execCommand("mceRemoveControl", true, $(original).attr("id")+'_mce');
    1877       original.reset();
    1878    }
    1879 });
    1880 </script>
    1881 """
    1882 
    1883         return head
    1884 
    1885     def html_worksheet_topbar(self, worksheet, select=None, username='guest', backwards=False):
    1886         body = ''
    1887         body += """
    1888 <table width="100%%" id="topbar">
    1889 <tr>
    1890   <td align=left> %s </td>   <td align=right> %s </td>
    1891 </tr>
    1892 <tr>
    1893   <td align=left> %s </td>   <td align=right> %s </td>
    1894 </tr>
    1895 </table>
    1896 """%(worksheet.html_title(username), worksheet.html_save_discard_buttons(),
    1897      worksheet.html_menu(), worksheet.html_share_publish_buttons(select=select, backwards=backwards))
    1898        
    1899         body += self.html_slide_controls()
    1900         return body
    1901 
    1902 
    1903     def _html_body(self, worksheet_filename, show_debug=False, username='', top_only=False):
    1904         worksheet = self.get_worksheet_with_filename(worksheet_filename)
    1905         worksheet_html = worksheet.html()
    1906 
    1907         body = ''
    1908 
    1909         if worksheet.is_published() or self.user_is_guest(username):
    1910             original_worksheet = worksheet.worksheet_that_was_published()
    1911             if original_worksheet.user_is_collaborator(username) or original_worksheet.is_owner(username):
    1912                 s = "Edit this."
    1913                 url = 'edit_published_page'
    1914             elif self.user_is_guest(username):
    1915                 s = 'Log in to edit a copy.'
    1916                 url = '/'
    1917             else:
    1918                 s = 'Edit a copy.'
    1919                 url = 'edit_published_page'
    1920             r = worksheet.rating()
    1921             if r == -1:
    1922                 rating = ''
    1923             else:
    1924                 rating = '<a class="usercontrol" href="rating_info">This page is rated %.1f.</a>'%r
    1925             if not self.user_is_guest(username) \
    1926                    and not worksheet.is_publisher(username):
    1927                 if worksheet.is_rater(username):
    1928                     action = "Rerate"
    1929                 else:
    1930                     action = "Rate"
    1931                 rating += '&nbsp;&nbsp; <span class="usercontrol">%s it: </span>'%action
    1932                 rating += '  '.join(['<a class="usercontrol" onClick="rate_worksheet(%s)">&nbsp;%s&nbsp;</a>'%(i,i) for
    1933                                    i in range(5)])
    1934                 rating += '&nbsp;&nbsp; <input name="rating_comment" id="rating_comment"></input>'
    1935 
    1936             download_name = os.path.split(worksheet.name())[-1]
    1937             edit_line = '<a class="usercontrol" href="%s">%s</a>'%(url, s) + \
    1938                         '  <a class="usercontrol" href="download/%s.sws">Download.</a>'%download_name + \
    1939                         '  <span class="ratingmsg">%s</span>'%rating
    1940 
    1941             body += edit_line
    1942             #This document was published using <a href="/">Sage</a>.'           
    1943             body += '<span class="pubmsg">'
    1944             body += '<a href="/pub/">Other published documents...</a></span>'
    1945             body += '<hr class="usercontrol">'
    1946             body += '<h1 align=center>%s</h1>'%original_worksheet.name()
    1947             body += '<h2 align=center>%s</h2>'%worksheet.html_time_since_last_edited()
    1948             body += worksheet_html
    1949             body += '<hr class="usercontrol">'
    1950             body += '&nbsp;'*10
    1951            
    1952 
    1953 
    1954         else:
    1955 
    1956             entries = [("$('#topbar').toggle()", 'Toggle', 'Toggle the top bar'),
    1957                        ('/', 'Home', 'Back to your personal worksheet list'),
    1958                        ('/pub', 'Published', 'Browse the published worksheets'),
    1959                        ('history_window()', 'Log', 'View a log of recent computations'),
    1960                        ('/settings', 'Settings', 'Account Settings'),
    1961                        ('bugreport()', 'Report a Problem', 'Report a problem or submit a bug to improve Sage'),
    1962                        ('help()', 'Help', 'Documentation')]
    1963 
    1964             if not self.user_is_guest(username):
    1965                 entries.append(('/logout', 'Sign out', 'Log out of the Sage notebook'))
    1966 
    1967             body += self.html_banner_and_control(username, entries)
    1968             if top_only:
    1969                 return body
    1970            
    1971             if worksheet_filename:
    1972                 body += self.html_worksheet_topbar(worksheet, select="use", username=username)
    1973                
    1974             if self.__show_debug or show_debug:
    1975                 body += self.html_debug_window()
    1976 
    1977 
    1978             body += '<div class="worksheet" id="worksheet">%s</div>'%worksheet_html
    1979 
    1980         endpanespan = '</td></tr></table></span>\n'
    1981 
    1982        
    1983         if worksheet is None:
    1984              return body + endpanespan
    1985 
    1986         if worksheet.user_is_only_viewer(username):
    1987             body += '<script type="text/javascript">worksheet_locked=true;</script>'
    1988         else:
    1989             body += '<script type="text/javascript">worksheet_locked=false;</script>'
    1990 
    1991         if worksheet.computing():
    1992             # Set the update checking back in motion.
    1993             body += '<script type="text/javascript"> active_cell_list = %r; \n'%worksheet.queue_id_list()
    1994             body += 'for(var i = 0; i < active_cell_list.length; i++)'
    1995             body += '    cell_set_running(active_cell_list[i]); \n'
    1996             body += 'start_update_check();\n'
    1997             body +=' </script>\n'
    1998 
    1999         return body
    2000 
    20011636    def html_plain_text_window(self, worksheet, username):
    20021637        """
    2003         Return a window that displays a plain text version of the
     1638        Returns a window that displays a plain text version of the
    20041639        worksheet
    20051640       
    20061641        INPUT:
     1642        -  ``worksheet`` - a worksheet
     1643        -  ``username`` - name of the user
     1644
     1645        OUTPUT:
     1646        - a window that displays a plain text version of the
     1647        worksheet
    20071648       
     1649        EXAMPLES::
    20081650       
    2009         -  ``worksheet`` - a worksheet
    2010        
    2011         -  ``username`` - name of the user
     1651            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     1652            sage: W = nb.create_new_worksheet('Test', 'admin')
     1653            sage: nb.html_plain_text_window(W, 'admin')
     1654            '\n<!D...>\n\n<pre class="plaintext" id="cell_intext" name="textfield"></pre>\n\n\n    </body>\n</html>'
    20121655        """
    2013         head, body = self.html_worksheet_page_template(worksheet, username, 'View plain text', select="text")
    2014 
    2015         t = worksheet.plain_text(prompts=True, banner=False)
    2016         t = escape(t)
    2017         body += """
    2018         <pre class="plaintext" id="cell_intext" name="textfield">%s
    2019         </pre>
    2020         """%t.strip()
     1656        plain_text = worksheet.plain_text(prompts=True, banner=False)
     1657        plain_text = escape(plain_text).strip()
    20211658         
    2022         return """
    2023         <html>
    2024         <head>%s</head>
    2025         <body>%s</body>
    2026         </html>
    2027         """%(head, body)
    2028 
     1659        return template("notebook/plain_text_window.html", worksheet = worksheet,
     1660                        worksheet_filename = worksheet.filename(),
     1661                        username = username,
     1662                        plain_text = plain_text, JSMATH = JSMATH,
     1663                        JSMATH_IMAGE_FONTS = JSMATH_IMAGE_FONTS,
     1664                        JEDITABLE_TINYMCE = JEDITABLE_TINYMCE,
     1665                        sage_jsmath_macros = sage_jsmath_macros)
     1666                       
    20291667    def html_edit_window(self, worksheet, username):
    20301668        r"""
    20311669        Return a window for editing ``worksheet``.
    20321670       
    20331671        INPUT:
     1672        - ``username`` - a string containing the username
     1673        - ``worksheet`` - a Worksheet instance
     1674
     1675        OUTPUT:
     1676        - html for a window for editing ``worksheet``.
     1677
     1678        EXAMPLES::
    20341679       
    2035        
    2036         -  ``worksheet`` - a worksheet
     1680            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     1681            sage: W = nb.create_new_worksheet('Test', 'admin')
     1682            sage: nb.html_edit_window(W, 'admin')
     1683            '\n<!D...Test\nsystem:sage\n\n{{{id=0|\n\n///\n}}}</textarea>\n</form>\n\n\n    </body>\n</html>'
    20371684        """
    2038         head, body = self.html_worksheet_page_template(worksheet, username, '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">', select="edit")
    2039 
    2040 
    2041         body += """<script type="text/javascript">
    2042 function save_worksheet() {
    2043 }
    2044 function save_worksheet_and_close() {
    2045 }
    2046         </script>
    2047         """
    2048         t = worksheet.edit_text()
    2049         t = escape(t)
    2050         body = '<form method="post" action="save" enctype="multipart/form-data">' + body
    2051         body += """
    2052         <textarea class="plaintextedit" id="cell_intext" name="textfield" rows="%s">%s</textarea>
    2053         </form>
    2054         """%(t.count("\n")+1,t)
     1685        text = worksheet.edit_text()
     1686        text = escape(text)
     1687        n_lines = text.count("\n")+1
    20551688         
    2056         return """
    2057         <html>
    2058         <head>%s</head>
    2059         <body>%s</body>
    2060         </html>
    2061         """%(head, body)
     1689        return template("notebook/edit_window.html", worksheet = worksheet,
     1690                        worksheet_filename = worksheet.filename(),
     1691                        username = username, text = text,
     1692                        n_lines = n_lines, JSMATH = JSMATH,
     1693                        JSMATH_IMAGE_FONTS = JSMATH_IMAGE_FONTS,
     1694                        JEDITABLE_TINYMCE = JEDITABLE_TINYMCE,
     1695                        sage_jsmath_macros = sage_jsmath_macros)
    20621696   
    20631697    def html_beforepublish_window(self, worksheet, username):
    20641698        """
    20651699        Return the html code for a page dedicated to worksheet publishing
    20661700        prior to the publication of the given worksheet.
    20671701       
    2068         INPUT: worksheet - instance of Worksheet username - string
     1702        INPUT:
     1703        - ``worksheet`` - instance of Worksheet
     1704        - ``username`` - string
     1705
     1706        EXAMPLES::
     1707       
     1708            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     1709            sage: W = nb.create_new_worksheet('Test', 'admin')
     1710            sage: nb.html_beforepublish_window(W, 'admin')
     1711            '\n<!D...publish when changes are made</form></span>\n<br /><br /><br />\n\n\n    </body>\n</html>'
    20691712        """
    20701713        msg = """You can publish your worksheet to the Internet, where anyone will be able to access and view it online.
    20711714        Your worksheet will be assigned a unique address (URL) that you can send to your friends and colleagues.<br/><br/>
    function save_worksheet_and_close() { 
    20771720        <input type="checkbox" name="auto" style="margin-left:13px" /> Automatically re-publish when changes are made
    20781721        </form>
    20791722        """
    2080         head, body = self.html_worksheet_page_template(worksheet, username, msg, select="publish", backwards=True)
     1723        return template("notebook/beforepublish_window.html", worksheet = worksheet,
     1724                        worksheet_filename = worksheet.filename(),
     1725                        username = username, JSMATH = JSMATH,
     1726                        JSMATH_IMAGE_FONTS = JSMATH_IMAGE_FONTS,
     1727                        JEDITABLE_TINYMCE = JEDITABLE_TINYMCE,
     1728                        sage_jsmath_macros = sage_jsmath_macros)
    20811729       
    2082         return """
    2083         <html>
    2084         <head>%s</head>
    2085         <body>%s</body>
    2086         </html>
    2087         """%(head, body)
    2088        
    2089     def html_afterpublish_window(self, worksheet, username, addr, dtime):
     1730    def html_afterpublish_window(self, worksheet, username, url, dtime):
    20901731        """
    20911732        Return the html code for a page dedicated to worksheet publishing
    20921733        after the publication of the given worksheet.
    20931734       
    2094         INPUT: worksheet - instance of Worksheet username - string addr -
    2095         string dtime - instance of time.struct_time
     1735        INPUT:
     1736        - ``worksheet`` - instance of Worksheet
     1737        - ``username`` - string
     1738        - ``url`` - a string representing the url of the published worksheet
     1739        - ``dtime`` - instance of time.struct_time representing the publishing time
    20961740        """
    20971741        from time import strftime
    20981742        time = strftime("%B %d, %Y %I:%M %p", dtime)
    2099         msg = """Worksheet is publicly viewable at <a href="%s" style="color:#FFF" target="_blank">%s</a><br />
    2100         Published on %s<br/><br />
    2101         <input type="button" value="Re-publish worksheet" onClick="parent.location=\'?re'"><input type="button" value="Stop publishing" style="margin-left:5px" onClick="parent.location=\'?stop'"><br /><br />
    2102 <input type="checkbox" name="auto"%s onchange="parent.location=\'?auto'"/> Automatically re-publish when changes are made
    2103         """ % (addr, addr, time, ' checked="true" ' if worksheet.is_auto_publish() else '')
    2104         head, body = self.html_worksheet_page_template(worksheet, username, msg, select="publish", backwards=True)
    21051743       
    2106         return """
    2107         <html>
    2108         <head>%s</head>
    2109         <body>%s</body>
    2110         </html>
    2111         """%(head, body)
     1744        return template("notebook/afterpublish_window.html", worksheet = worksheet,
     1745                        worksheet_filename = worksheet.filename(),
     1746                        username = username, url = url,
     1747                        time = time, JSMATH = JSMATH,
     1748                        JSMATH_IMAGE_FONTS = JSMATH_IMAGE_FONTS,
     1749                        JEDITABLE_TINYMCE = JEDITABLE_TINYMCE,
     1750                        sage_jsmath_macros = sage_jsmath_macros)
    21121751
    21131752    def html_upload_data_window(self, ws, username):
    2114         head, body = self.html_worksheet_page_template(ws, username, "Upload or Create Data File")
     1753        """
     1754        Returns the html for the "Upload Data" window
     1755
     1756        INPUT:
     1757        - ``worksheet`` - instance of Worksheet
     1758        - ``username`` - string
     1759
     1760        EXAMPLES::
    21151761       
    2116         body += """
    2117               <div class="upload_worksheet_menu" id="upload_worksheet_menu">
    2118               <h1><font size=+1>Upload or create data file attached to the worksheet '%s'</font></h1>
    2119               <hr>
    2120               <form method="POST" action="do_upload_data"
    2121                     name="upload" enctype="multipart/form-data">
    2122               <table><tr>
    2123               <td>
    2124               Browse your computer to select a file to upload:<br>
    2125               <input class="upload_worksheet_menu" size="50" type="file" name="fileField" value="" id="upload_filename"></input><br><br>
    2126               Or enter the url of a file on the web:<br>
    2127              
    2128               <input class="upload_worksheet_menu" size="50" type="text" name="urlField" value="" id="upload_url"></input></br>
    2129               <br><br>
    2130               Or enter the name of a new file, which will be created:<br>
    2131               <input class="upload_worksheet_menu" size="50" type="text" name="newField" value="" id="upload_filename"></input><br><br>
    2132              
    2133               What do you want to call it? (if different than the original name)<br>
    2134               <input class="upload_worksheet_menu" size="50" type="text" name="nameField" value="" id="upload_name"></input></br>
    2135               </td>
    2136               </tr>
    2137               <tr>
    2138               <td><br><input type="button" class="upload_worksheet_menu" value="Upload File" onClick="form.submit();"></td>
    2139               </tr>
    2140               </form><br>
    2141               </div>
    2142             </body>
    2143           </html>
    2144          """%(ws.name())
    2145 
    2146         return """
    2147         <html>
    2148         <head>%s</head>
    2149         <body>%s</body>
    2150         </html>
    2151         """%(head, body)
     1762            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     1763            sage: W = nb.create_new_worksheet('Test', 'admin')
     1764            sage: nb.html_upload_data_window(W, 'admin')
     1765            '\n<!D...orksheet_menu" value="Upload File" onClick="form.submit()...r />\n</div>\n\n\n    </body>\n</html>'
     1766        """
     1767        return template("notebook/upload_data_window.html", worksheet = worksheet,
     1768                        worksheet_filename = ws.filename(),
     1769                        username = username, JSMATH = JSMATH,
     1770                        JSMATH_IMAGE_FONTS = JSMATH_IMAGE_FONTS,
     1771                        JEDITABLE_TINYMCE = JEDITABLE_TINYMCE,
     1772                        sage_jsmath_macros = sage_jsmath_macros)
     1773   
    21521774
    21531775    def html(self, worksheet_filename=None, username='guest', show_debug=False, admin=False):
     1776        """
     1777        Returns the html for index page of a worksheet.
     1778
     1779        INPUT:
     1780        - ``worksheet_filename`` - a string
     1781        - ``username`` - a string
     1782        - ``show_debug`` - a boolean
     1783        - ``admin`` - a boolean
     1784
     1785        EXAMPLES::
     1786       
     1787            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     1788            sage: W = nb.create_new_worksheet('Test', 'admin')
     1789            sage: nb.html(W.filename(), 'admin')
     1790            '\n<!D...ipt type="text/javascript">worksheet_locked=false;</script>\n\n\n\n    </body>\n</html>'
     1791        """
    21541792        if worksheet_filename is None or worksheet_filename == '':
    21551793            worksheet_filename = None
    21561794            W = None
    function save_worksheet_and_close() { 
    21601798            except KeyError:
    21611799                W = None
    21621800
    2163         head = self._html_head(worksheet_filename=worksheet_filename, username=username)
    2164         body = self._html_body(worksheet_filename=worksheet_filename, username=username, show_debug=show_debug)
    2165 
    2166         head += '<script type="text/javascript">user_name="%s"; </script>'%username
    2167 
    2168         if worksheet_filename is not None:
    2169             head += '<script  type="text/javascript">worksheet_filename="%s"; worksheet_name="%s"; server_ping_while_alive(); </script>'%(worksheet_filename, W.name())
    2170 
    2171             # Uncomment this to force rename when the worksheet is opened (annoying!)
    2172             #if W and W.name() == "Untitled":
    2173             #    head += '<script  type="text/javascript">setTimeout("rename_worksheet()",1)</script>'
    2174 
    2175         return """
    2176         <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    2177         <html>
    2178         <head>%s</head>
    2179         <body class="worksheet-online" onLoad="initialize_the_notebook();">%s</body>
    2180         </html>
    2181         """%(head, body)
     1801        template_page = "notebook/index.html"
     1802        if W.docbrowser():
     1803            template_page = "notebook/doc_page.html"
     1804           
     1805        return template(template_page, worksheet = W,
     1806                        worksheet_filename = W.filename(),
     1807                        worksheet_html = W.html(),
     1808                        notebook = self, username = username,
     1809                        show_debug = show_debug,
     1810                        JSMATH = JSMATH,
     1811                        JSMATH_IMAGE_FONTS = JSMATH_IMAGE_FONTS,
     1812                        JEDITABLE_TINYMCE = JEDITABLE_TINYMCE,
     1813                        sage_jsmath_macros = sage_jsmath_macros)
    21821814
    21831815    ####################################################################
    21841816    # Configuration html.
    21851817    # In each case the settings html is a form that when submitted
    21861818    # pulls up another web page and sets the corresponding options.
    21871819    ####################################################################
    2188     def html_system_select_form_element(self, ws):
    2189         system = ws.system()
    2190         options = ''
    2191         i = SYSTEM_NAMES.index(system)
    2192         for j, S in enumerate(SYSTEMS):
    2193             if i == j:
    2194                 selected = "selected"
    2195             else:
    2196                 selected = ''
    2197             T = SYSTEM_NAMES[j]
    2198             options += '<option title="Evaluate all input cells using %s" %s value="%s">%s</option>\n'%(T, selected, T,S)
    2199         s = """<select  onchange="go_system_select(this, %s);" class="worksheet">
    2200             %s
    2201             </select>"""%(i, options)
    2202         return s
    2203    
    2204     def html_pretty_print_check_form_element(self, ws):
    2205         pretty_print = ws.pretty_print()
    2206         if pretty_print:
    2207             check='checked="checked"'
    2208         else:
    2209             check=''
    2210         s = """<input type="checkbox" title="Enable/disable pretty_printing"
    2211         onchange="pretty_print_check(this.checked);"
    2212         class="worksheet" value="pretty_print" %s>&nbsp;Typeset"""%(check)
    2213         return s
    22141820
    22151821
    22161822    def html_worksheet_settings(self, ws, username):
    2217         head, body = self.html_worksheet_page_template(ws, username, 'Worksheet Settings &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<button name="button_save">Save Settings</button>  <input type="submit" value="Cancel" name="button_cancel"/>')
     1823        """
     1824        Returns the html for the setings page of the worksheet.
     1825       
     1826        INPUT:
     1827        - ``ws`` - instance of Worksheet
     1828        - ``username`` - string
    22181829
    2219         body = '<form width=70%% method="post" action="input_settings"  enctype="multipart/form-data">' + body
    2220         body += '</form>'
    2221            
    2222         return """
    2223         <html>
    2224         <head>%s</head>
    2225         <body>%s</body>
    2226         </html>
    2227         """%(head, body)
     1830        EXAMPLES::
     1831       
     1832            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     1833            sage: W = nb.create_new_worksheet('Test', 'admin')
     1834            sage: nb.html_worksheet_settings(W, 'admin')
     1835            '\n<!D...lue="Cancel" name="button_cancel"/></span>\n<br /><br /><br />\n\n</form>\n\n\n    </body>\n</html>'
     1836        """
     1837        return template("notebook/worksheet_settings.html", worksheet = ws,
     1838                        worksheet_filename = ws.filename(),
     1839                        username = username, JSMATH = JSMATH,
     1840                        JSMATH_IMAGE_FONTS = JSMATH_IMAGE_FONTS,
     1841                        JEDITABLE_TINYMCE = JEDITABLE_TINYMCE,
     1842                        sage_jsmath_macros = sage_jsmath_macros)
    22281843
    22291844    def html_settings(self):
    22301845        s = """
    function save_worksheet_and_close() { 
    22411856        return s
    22421857
    22431858    def html_doc(self, username):
    2244         top = self._html_head(None, username) + self.html_topbar(username)
    2245         body = """
    2246         <br>
    2247         <div class="docidx">
    2248         <h1>Sage Documentation</h1>
    2249         <br>
    2250         <hr class="usercontrol">
    2251         <br><br>
    2252         <font size=+2>
    2253         <a href="/doc/live/">Live Documentation</a><br><br>
    2254         <a href="/doc/static/">Static Documentation</a><br><br>
    2255         <a href="/help/">Sage Notebook Howto</a><br><br>
    2256         <br><br>
    2257         <br>
    2258         <hr class="usercontrol">
    2259         </font>
    2260         </div>
    2261         """       
    2262         #(<a href="/doc/static/">static</a>)
     1859        """
     1860        Returns the html for the documentation pages.
     1861       
     1862        INPUT:
     1863        - ``worksheet_filename`` - a string
     1864        - ``username`` - a string
     1865        - ``show_debug`` - a boolean
     1866        - ``admin`` - a boolean
    22631867
    2264         s = """
    2265         <html>
    2266         %s
    2267         <body>
    2268         %s
    2269         </body>
    2270         </html>
    2271         """%(top, body)
     1868        EXAMPLES::
    22721869       
    2273         return s
     1870            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     1871            sage: W = nb.create_new_worksheet('Test', 'admin')
     1872            sage: nb.html_doc('admin')
     1873            '\n<!D...c Documentation</a><br /><br />\n        <a href="/help/">Sage Notebook Howto...   </body>\n</html>'
     1874        """
     1875        return template("notebook/doc.html", username = username,
     1876                        JSMATH = JSMATH,
     1877                        JSMATH_IMAGE_FONTS = JSMATH_IMAGE_FONTS,
     1878                        JEDITABLE_TINYMCE = JEDITABLE_TINYMCE,
     1879                        sage_jsmath_macros = sage_jsmath_macros)
    22741880       
    22751881
    22761882####################################################################
  • sage/server/notebook/templates/account_recovery.html

    diff --git a/sage/server/notebook/templates/account_recovery.html b/sage/server/notebook/templates/account_recovery.html
    a b  
     1
    12{% extends "base.html" %}
    23
    34{% block title %}Account Recovery{% endblock %}
  • sage/server/notebook/templates/account_settings.html

    diff --git a/sage/server/notebook/templates/account_settings.html b/sage/server/notebook/templates/account_settings.html
    a b  
     1
    12{% extends "base.html" %}
    23
    34{% block title %}Account Settings{% endblock %}
  • sage/server/notebook/templates/banner.html

    diff --git a/sage/server/notebook/templates/banner.html b/sage/server/notebook/templates/banner.html
    a b  
     1
    12<div class="banner">
    2   <table width="100%%">
     3  <table width="100%">
    34    <tr>
    45      <td>
    56        <a class="banner" href="http://www.sagemath.org">
    6         <img align="top" src="/images/sagelogo.png" alt="Sage">Notebook</a>
     7        <img align="top" src="/images/sagelogo.png" alt="Sage">&nbsp;Notebook</a>
    78      </td>
    89      <td>
    910        <span class="ping" id="ping">Searching for Sage server...</span>
  • sage/server/notebook/templates/base.html

    diff --git a/sage/server/notebook/templates/base.html b/sage/server/notebook/templates/base.html
    a b  
     1
    12<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
    23<html lang="en">
    3 <head>
    4     <title>{% block title %}{% endblock %} | {{ sitename }}</title>
    5     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    6     <link type="text/css" rel="stylesheet" href="/css/{% block css %}master{% endblock %}.css" media="screen" />
    7     {% block javascript %}{% endblock %}
    8 </head>
    9 <body{% block onload %}{% endblock %}>
    10     {% block body %}{% endblock %}
    11 </body>
    12 </html>
     4    <head>
     5        <title>{% block title %}{% endblock %}</title>
     6        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     7        {% block pre_main_css %}{% endblock %}
     8        <link type="text/css" rel="stylesheet" href="/css/{% block css %}master{% endblock %}.css" media="screen" />
     9        {% block more_css %}{% endblock %}
     10        {% block javascript %}{% endblock %}
     11    </head>
     12    <body {% block body_attrs %}{% endblock %}>
     13        {% block body %}{% endblock %}
     14    </body>
     15</html>
     16 No newline at end of file
  • sage/server/notebook/templates/base_authenticated.html

    diff --git a/sage/server/notebook/templates/base_authenticated.html b/sage/server/notebook/templates/base_authenticated.html
    a b  
     1
    12{% extends "base.html" %}
    23
    34{% block css %}main{% endblock %}
  • new file sage/server/notebook/templates/command_history.html

    diff --git a/sage/server/notebook/templates/command_history.html b/sage/server/notebook/templates/command_history.html
    new file mode 100644
    - +  
     1
     2{#
     3INPUT:
     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
  • sage/server/notebook/templates/error_message.html

    diff --git a/sage/server/notebook/templates/error_message.html b/sage/server/notebook/templates/error_message.html
    a b  
     1
    12{% extends "base.html" %}
    23
    34{% block title %}Error{% endblock %}
    45
    5 {% block content %}
     6{% block body %}
    67<br><a class="usercontrol" href="/">Home</a>
    78<hr class="usercontrol">
    89<br/><br/>
  • sage/server/notebook/templates/history.html

    diff --git a/sage/server/notebook/templates/history.html b/sage/server/notebook/templates/history.html
    a b  
     1
    12{% extends "base.html" %}
    23
    34{% block title %}Sage: History for {{username}} {% endblock %}
  • sage/server/notebook/templates/list_top.html

    diff --git a/sage/server/notebook/templates/list_top.html b/sage/server/notebook/templates/list_top.html
    a b  
     1
    12{% include 'top_bar.html' %}
    23
    34
  • sage/server/notebook/templates/login.html

    diff --git a/sage/server/notebook/templates/login.html b/sage/server/notebook/templates/login.html
    a b  
     1
    12{% extends "base.html" %}
    23
    34{% block title %}Sign in{% endblock %}
  • new file sage/server/notebook/templates/notebook/afterpublish_window.html

    diff --git a/sage/server/notebook/templates/notebook/afterpublish_window.html b/sage/server/notebook/templates/notebook/afterpublish_window.html
    new file mode 100644
    - +  
     1
     2{% extends "notebook/worksheet_page_template.html" %}
     3{#
     4INPUT:
     5- worksheet - an instance of Worksheet
     6- worksheet_filename - a string containing a worksheet's filename
     7- username - a string containing a username
     8- url - a string containing the url of the published page
     9- time - a string representing the time of publication
     10- JSMATH - a boolean stating whether to include jsMath
     11- JSMATH_IMAGE_FONTS - a boolean stating whether to include jsMath iamage fonts
     12- JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE
     13- sage_jsmath_macros - an array containing strings of Javascript of Sage macros for jsMath
     14#}
     15
     16{% set checked = 'checked="true"' if worksheet.is_auto_publish() else '' %}
     17
     18{% set title = 'Worksheet is publicly viewable at <a href="%s" style="color:#FFF" target="_blank">%s</a><br />Published on %s<br/><br /><input type="button" value="Re-publish worksheet" onClick="parent.location=\'?re\'"><input type="button" value="Stop publishing" style="margin-left:5px" onClick="parent.location=\'?stop\'"><br /><br /><input type="checkbox" name="auto" %s onchange="parent.location=\'?auto\'"/> Automatically re-publish when changes are made'|format(url, url, time, checked) %}
     19{% set select = "publish" %}
     20{% set backwards = true %}
     21 No newline at end of file
  • new file sage/server/notebook/templates/notebook/beforepublish_window.html

    diff --git a/sage/server/notebook/templates/notebook/beforepublish_window.html b/sage/server/notebook/templates/notebook/beforepublish_window.html
    new file mode 100644
    - +  
     1
     2{% extends "notebook/worksheet_page_template.html" %}
     3{#
     4INPUT:
     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- JSMATH_IMAGE_FONTS - a boolean stating whether to include jsMath iamage fonts
     10- JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE
     11- sage_jsmath_macros - an array containing strings of Javascript of Sage macros for jsMath
     12#}
     13
     14{% set title = '<p>You can publish your worksheet to the Internet, where anyone will be able to access and view it online.</p><p>Your worksheet will be assigned a unique address (URL) that you can send to your friends and colleagues.</p><p>Do you want to publish this worksheet?</p><form method="get" action="."><input type="hidden" name="yes" value="" /><input type="submit" value="Yes" style="margin-left:10px" /><input type="button" value="No" style="margin-left:5px" onClick="parent.location=\'../\'"><br/><br/><input type="checkbox" name="auto" style="margin-left:13px" /> Automatically re-publish when changes are made</form>' %}
     15{% set select = "publish" %}
     16{% set backwards = true %}
     17 No newline at end of file
  • new file sage/server/notebook/templates/notebook/debug_window.html

    diff --git a/sage/server/notebook/templates/notebook/debug_window.html b/sage/server/notebook/templates/notebook/debug_window.html
    new 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
  • new file sage/server/notebook/templates/notebook/doc.html

    diff --git a/sage/server/notebook/templates/notebook/doc.html b/sage/server/notebook/templates/notebook/doc.html
    new file mode 100644
    - +  
     1{% extends "base.html" %}
     2{#
     3INPUT:
     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- JSMATH_IMAGE_FONTS - a boolean stating whether to include jsMath iamage fonts
     9- JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE
     10- sage_jsmath_macros - an array containing strings of Javascript of Sage macros for jsMath
     11#}
     12
     13{% include "notebook/head.tmpl" %}
     14
     15{% block title %}
     16{{ common_title(worksheet_filename, worksheet) }}
     17{% endblock %}
     18   
     19{% block css %}main{% endblock %}
     20
     21{% block morecss %}<style type="text/css" rel="stylesheet" href="_static/default.css" media="screen" />{% endblock %}
     22
     23{% block javascript %}
     24{{ common_javascript(worksheet, worksheet_filename, username, JSMATH, JSMATH_IMAGE_FONTS, JEDITABLE_TINYMCE, sage_jsmath_macros) }}
     25{% endblock %}
     26
     27{% block body %}
     28<br />
     29<div class="docidx">
     30    <h1>Sage Documentation</h1>
     31    <br />
     32    <hr class="usercontrol" />
     33    <br /><br />
     34    <font size=+2>
     35        <a href="/doc/live/">Live Documentation</a><br /><br />
     36        <a href="/doc/static/">Static Documentation</a><br /><br />
     37        <a href="/help/">Sage Notebook Howto</a><br /><br />
     38        <br /><br />
     39        <br />
     40        <hr class="usercontrol" />
     41    </font>
     42</div>
     43{% endblock %}
     44 No newline at end of file
  • new file sage/server/notebook/templates/notebook/doc_page.html

    diff --git a/sage/server/notebook/templates/notebook/doc_page.html b/sage/server/notebook/templates/notebook/doc_page.html
    new file mode 100644
    - +  
     1{% extends "notebook/index.html" %}
     2
     3{% block pre_main_css %}
     4<link type="text/css" rel="stylesheet" href="_static/default.css" media="screen" />
     5{% endblock %}
     6 No newline at end of file
  • new file sage/server/notebook/templates/notebook/download_or_delete_datafile.html

    diff --git a/sage/server/notebook/templates/notebook/download_or_delete_datafile.html b/sage/server/notebook/templates/notebook/download_or_delete_datafile.html
    new file mode 100644
    - +  
     1
     2{% extends "notebook/worksheet_page_template.html" %}
     3{#
     4INPUT:
     5- worksheet - an instance of Worksheet
     6- worksheet_filename - a string containing a worksheet's filename
     7- username - a string containing a username
     8- active_worksheets - a list of the Worksheet instances that are active for username
     9- filename_ - the name of the file
     10- path - the path to the file
     11- file_is_image - a boolean stating whether the file is an image
     12- file_is_text - a boolean stating whether the file is a text file
     13- text_file_content - a string containing the content of a text file
     14- JSMATH - a boolean stating whether to include jsMath
     15- JSMATH_IMAGE_FONTS - a boolean stating whether to include jsMath iamage fonts
     16- JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE
     17- sage_jsmath_macros - an array containing strings of Javascript of Sage macros for jsMath
     18#}
     19{% set title = "Data file: %s"|format(filename_) %}
     20
     21{% block body_addition %}
     22<p>You may download <a href="{{ path }}">{{ filename_ }}</a> or create a linked copy to the worksheet <select onchange="go_option(this);" class="worksheet">
     23<option selected>select worksheet</option>
     24{% for worksheet in active_worksheets %}
     25    <option value='link_datafile("{{ worksheet.filename() }}","{{ filename_ }}")'>{{ worksheet.name() }}</option>
     26{% endfor %}
     27</select> or <a href="/home/{{ worksheet.filename() }}/datafile?name={{ filename_ }}&action=delete">delete {{ filename_ }}.</a></p>
     28
     29<p>Access {{ filename_ }} in this worksheet by typing <tt>DATA+'{{ filename_ }}'</tt>.  Here DATA is a special variable that gives the exact path to all data files uploaded to this worksheet.</p>
     30
     31<hr class="usercontrol" />
     32
     33{% if file_is_image %}
     34<div align=center><img src="{{ path }}"></div>
     35{% elif file_is_text %}
     36<form method="post" action="savedatafile" enctype="multipart/form-data">
     37    <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>
     39    <input type="hidden" name="filename" value="{{ filename_ }}" id="filename" />
     40</form>
     41{% endif %}
     42{% endblock %}
     43
     44
     45
     46
  • new file sage/server/notebook/templates/notebook/edit_window.html

    diff --git a/sage/server/notebook/templates/notebook/edit_window.html b/sage/server/notebook/templates/notebook/edit_window.html
    new file mode 100644
    - +  
     1{% extends "notebook/worksheet_page_template.html" %}
     2{#
     3INPUT:
     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- 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#}
     14
     15{% set title = '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">' %}
     16{% set select = "edit" %}
     17
     18{% block before_sharebar %}
     19<form method="post" action="save" enctype="multipart/form-data">
     20{% endblock %}
     21{% block body_addition %}
     22<script type="text/javascript">
     23    function save_worksheet() {
     24    }
     25    function save_worksheet_and_close() {
     26    }
     27</script>
     28    <textarea class="plaintextedit" id="cell_intext" name="textfield" rows="{{ n_lines }}">{{ text }}</textarea>
     29</form>
     30{% endblock %}
  • new file sage/server/notebook/templates/notebook/guest_top_bar_and_worksheet.html

    diff --git a/sage/server/notebook/templates/notebook/guest_top_bar_and_worksheet.html b/sage/server/notebook/templates/notebook/guest_top_bar_and_worksheet.html
    new file mode 100644
    - +  
     1
     2{#
     3INPUT:
     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 = os.path.split(worksheet.name())[-1] %}
     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">{{ original_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
  • new file sage/server/notebook/templates/notebook/head.tmpl

    diff --git a/sage/server/notebook/templates/notebook/head.tmpl b/sage/server/notebook/templates/notebook/head.tmpl
    new file mode 100644
    - +  
     1
     2{#
     3INPUT:
     4- worksheet - an instance of Worksheet
     5- worksheet_filename - a string containing a worksheet's filename
     6- username - a string containing a user's name
     7- JSMATH - a boolean stating whether to include jsMath
     8- JSMATH_IMAGE_FONTS - a boolean stating whether to include jsMath iamage fonts
     9- JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE
     10- sage_jsmath_macros - an array containing strings of Javascript of Sage macros for jsMath
     11  #}
     12{% macro common_title(worksheet_filename, worksheet) %}
     13    {% if worksheet_filename %}
     14        {{ worksheet.name() }} (Sage)
     15    {% else %}
     16        Sage Notebook | Welcome
     17    {% endif %}
     18{% endmacro %}
     19
     20{% macro common_css %}
     21<link rel=stylesheet href="/css/main.css" type="text/css" />
     22{% endmacro %}
     23
     24{% macro common_javascript(worksheet, worksheet_filename, username, JSMATH, JSMATH_IMAGE_FONTS, JEDITABLE_TINYMCE, sage_jsmath_macros) %}
     25<!-- Load the Sage javascript library. -->
     26<script type="text/javascript" src="/javascript_local/jquery/jquery.js"></script>
     27<script type="text/javascript" src="/javascript/main.js"></script>
     28 
     29{% if JSMATH %}
     30    <!-- Turn off font warning. -->
     31    <style>
     32        #jsMath_Warning {display: none}
     33    </style>
     34    <script type="text/javascript">
     35        jsMath = {Controls: {cookie: {scale: 115}}}
     36    </script>
     37    {% if not JSMATH_IMAGE_FONTS %}
     38        <script type="text/javascript" src="/javascript_local/jsmath/plugins/noImageFonts.js"></script>
     39    {% endif %}
     40    <!-- Move the jsMath button 20 pixels from the right edge
     41         (apparently in some browsers, it covers up the scroll
     42         bar) -->
     43    <script type="text/javascript">
     44        jsMath.styles = {
     45            '#jsMath_button':
     46                'position:fixed; bottom:1px; right:20px; background-color:white;'
     47                    + 'border: solid 1px #959595; margin:0px; padding: 0px 3px 1px 3px; '
     48                    + 'z-index:102; color:black; text-decoration:none; font-size:x-small; '
     49                    + 'width:auto; cursor:hand;',
     50        };
     51    </script>
     52    <script type="text/javascript" src="/javascript_local/jsmath/jsMath.js"></script>
     53    <script type="text/javascript">
     54        /* The extensions here do the following:
     55            - verb implements the \verb command:
     56              see http://www.math.union.edu/~dpvc/jsMath/authors/verb.html
     57            - moreArrows implements \xrightarrow, among other things:
     58              see http://www.math.union.edu/~dpvc/jsMath/authors//moreArrows.html
     59            - AMSmath implements a number of AMS math commands:
     60              see http://www.math.union.edu/~dpvc/jsMath/authors/AMSmath.html
     61        */
     62        jsMath.Extension.Require("verb");
     63        jsMath.Extension.Require("moreArrows");
     64        jsMath.Extension.Require("AMSmath");
     65        jsMath.Extension.Require("AMSsymbols");
     66    </script>
     67{% endif %}
     68<!-- Import LaTeX macros -->
     69{% for m in sage_jsmath_macros %}
     70<script> {{ m }} </script>
     71{% endfor %}
     72
     73<!-- Load the jquery and ui-jquery javascript library.
     74     This is used for interact functionality in the notebook, and will be used
     75     to enable drag and drop, image zoom, etc. -->
     76<script type="text/javascript" src="/javascript_local/jqueryui/jquery.ui.all.min.js"></script>
     77<script type="text/javascript" src="/javascript_local/jquery/plugins/farbtastic/farbtastic.min.js"></script>
     78<script type="text/javascript" src="/javascript_local/jquery/plugins/dimensions/jquery.dimensions.min.js"></script>
     79<script type="text/javascript" src="/javascript_local/jquery/plugins/jquery.event.extendedclick.js"></script>
     80
     81<link rel="stylesheet" href="/javascript_local/jquery/plugins/farbtastic/farbtastic.css" type="text/css" /> 
     82<link rel="stylesheet" href="/javascript_local/jqueryui/themes/flora/flora.all.css" />
     83
     84<!-- TODO: get the lazy loading plugin -->
     85
     86<!-- TODO: Load individual ui plugins, not the whole package:
     87     <script type="text/javascript" src="/javascript_local/jqueryui/ui.mouse.min.js"></script>
     88     <script type="text/javascript" src="/javascript_local/jqueryui/ui.slider.min.js"></script>
     89     <script type="text/javascript" src="/javascript_local/jqueryui/ui.draggable.min.js"></script>
     90     <script type="text/javascript" src="/javascript_local/jqueryui/ui.draggable.ext.min.js"></script>
     91     <script type="text/javascript" src="/javascript_local/jqueryui/ui.resizable.min.js"></script>
     92     <script type="text/javascript" src="/javascript_local/jqueryui/ui.dialog.min.js"></script>
     93-->
     94
     95<!-- This was for syntax highlighting
     96     <script type="text/javascript" src="/javascript/highlight/prettify.js"></script>
     97     <link rel=stylesheet href="/css/highlight/prettify.css" type="text/css" />
     98-->
     99
     100<script type="text/javascript" src="/javascript/sage3d.js"></script
     101
     102<!-- Jmol - embedded 3D graphics -->
     103<script type="text/javascript" src="/java/jmol/appletweb/Jmol.js"></script>
     104<script>jmolInitialize("/java/jmol");jmolSetCallback("menuFile","/java/jmol/appletweb/SageMenu.mnu");</script> <!-- This must stay in <head> -->
     105
     106<!-- TinyMCE and jEditable - in-place editing of text cells -->
     107{% if JEDITABLE_TINYMCE %}
     108    <script type="text/javascript" src="/javascript_local/tiny_mce/tiny_mce.js"></script>
     109    <script src="/javascript_local/jquery/plugins/jquery.jeditable.mini.js" type="text/javascript" charset="utf-8"></script>
     110    <script type="text/javascript">
     111   
     112    function toggleEditor(id) {
     113            if (!tinyMCE.get(id))
     114                    tinyMCE.execCommand('mceAddControl', false, id);
     115            else
     116                    tinyMCE.execCommand('mceRemoveControl', false, id);
     117    }
     118   
     119    $.fn.tinymce = function(options){
     120       return this.each(function(){
     121          tinyMCE.execCommand("mceAddControl", true, this.id);
     122       });
     123    }
     124   
     125    function initMCE(){
     126       tinyMCE.init({mode : "none",
     127          plugins: "table,searchreplace,safari,paste,autosave",
     128          theme : "advanced",
     129          theme_advanced_toolbar_location : "top",
     130          theme_advanced_toolbar_align : "left",
     131          theme_advanced_statusbar_location : "bottom",
     132          theme_advanced_buttons1 : "\
     133    formatselect,fontselect,fontsizeselect,bold,italic,underline,strikethrough,forecolor,backcolor,|,\
     134    bullist,numlist,|,\
     135    undo,redo,search,pastetext,pasteword",
     136          theme_advanced_buttons2 : "\
     137    justifyleft,justifycenter,justifyright,justifyfull,outdent,indent,|,\
     138    charmap,|,\
     139    table,tablecontrols,|,\
     140    code,|,\
     141    link,image,unlink",
     142          theme_advanced_buttons3 : "",
     143          theme_advanced_resizing : true,
     144          setup : function(ed) {
     145          ed.onKeyDown.add(function(ed, e) {
     146              if(key_enter_shift(key_event(e))) {
     147                $(ed.formElement).submit();
     148              }
     149          })}
     150       });
     151    };
     152   
     153    initMCE();
     154   
     155   
     156    $.editable.addInputType('mce', {
     157       element : function(settings, original) {
     158          var textarea = $('<textarea id="'+$(original).attr("id")+'_mce"/>');
     159          if (settings.rows) {
     160             textarea.attr('rows', settings.rows);
     161          } else {
     162             textarea.height(settings.height);
     163          }
     164          if (settings.cols) {
     165             textarea.attr('cols', settings.cols);
     166          } else {
     167             textarea.width(settings.width);
     168          }
     169          $(this).append(textarea);
     170             return(textarea);
     171          },
     172       plugin : function(settings, original) {
     173          tinyMCE.execCommand("mceAddControl", true, $(original).attr("id")+'_mce');
     174          },
     175       submit : function(settings, original) {
     176          tinyMCE.triggerSave();
     177          tinyMCE.execCommand("mceRemoveControl", true, $(original).attr("id")+'_mce');
     178          },
     179       reset : function(settings, original) {
     180          tinyMCE.execCommand("mceRemoveControl", true, $(original).attr("id")+'_mce');
     181          original.reset();
     182       }
     183    });
     184    </script>
     185{% endif %}
     186<script type="text/javascript">user_name= "{{ username }}";</script>
     187{% if worksheet_filename %}
     188<script  type="text/javascript">
     189    worksheet_filename="{{ worksheet_filename }}";
     190    worksheet_name="{{ worksheet.name() }}";
     191    server_ping_while_alive();
     192</script>
     193{% endif %}
     194<!-- Uncomment this to force rename when the worksheet is opened (annoying!)
     195     if W and
     196        W.name() == "Untitled":
     197        <script  type="text/javascript">setTimeout("rename_worksheet()",1)</script> -->
     198{% endmacro %}
     199 No newline at end of file
  • new file sage/server/notebook/templates/notebook/index.html

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

    diff --git a/sage/server/notebook/templates/notebook/plain_text_window.html b/sage/server/notebook/templates/notebook/plain_text_window.html
    new file mode 100644
    - +  
     1
     2{% extends "notebook/worksheet_page_template.html" %}
     3{#
     4INPUT:
     5- worksheet - an instance of Worksheet
     6- worksheet_filename - a string containing a worksheet's filename
     7- username - a string containing a username
     8- plain_text - a string containing the plain text version
     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#}
     14
     15{% set title = "View plain text" %}
     16{% set select = "text" %}
     17
     18{% block body_addition %}
     19<pre class="plaintext" id="cell_intext" name="textfield">{{ plain_text }}</pre>
     20{% endblock %}
  • new file sage/server/notebook/templates/notebook/plain_text_worksheet.html

    diff --git a/sage/server/notebook/templates/notebook/plain_text_worksheet.html b/sage/server/notebook/templates/notebook/plain_text_worksheet.html
    new file mode 100644
    - +  
     1
     2{#
     3INPUT:
     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 sage/server/notebook/templates/notebook/slide_controls.html

    diff --git a/sage/server/notebook/templates/notebook/slide_controls.html b/sage/server/notebook/templates/notebook/slide_controls.html
    new 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
  • new file sage/server/notebook/templates/notebook/specific_revision.html

    diff --git a/sage/server/notebook/templates/notebook/specific_revision.html b/sage/server/notebook/templates/notebook/specific_revision.html
    new file mode 100644
    - +  
     1
     2{% extends "notebook/worksheet_page_template.html" %}
     3{#
     4INPUT:
     5- worksheet - an instance of Worksheet
     6- worksheet_filename - a string containing a worksheet's filename
     7- username - a string containing a username
     8- rev - this revision's key
     9- prev_rev - the previous revision's key
     10- next_rev - the next revision's key
     11- time_ago - a string containing the time since revision
     12- body_worksheet_html - the body html of the worksheet
     13- JSMATH - a boolean stating whether to include jsMath
     14- JSMATH_IMAGE_FONTS - a boolean stating whether to include jsMath iamage fonts
     15- JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE
     16- sage_jsmath_macros - an array containing strings of Javascript of Sage macros for jsMath
     17#}
     18
     19{% set select = "revisions" %}
     20{% set title = "Revision from %s ago&nbsp;&nbsp;&nbsp;&nbsp;<a href='revisions'>Revision List</a>"|format(time_ago) %}
     21   
     22{% macro actions %}
     23{% if prev_rev %}
     24    <a class="listcontrol" href="revisions?rev={{ prev_rev }}">Older</a>&nbsp;&nbsp;
     25{% else %}
     26    Oldest
     27{% endif %}
     28
     29{% if next_rev %}
     30    <a class="listcontrol" href="revisions?rev={{ next_rev }}">Newer</a>&nbsp;&nbsp;
     31{% else %}
     32    Newest
     33{% endif %}
     34
     35<a class="listcontrol" href="revisions?rev={{ rev }}&action=revert">Revert to this one</a> <span class="lastedit">(note that images are not recorded)</span>&nbsp;&nbsp;
     36<a class="listcontrol" href="revisions?rev={{ rev }}&action=publish">Publish this one</a>&nbsp;&nbsp;
     37{% endmacro %}
     38
     39{% block body_addition %}
     40{{ actions() }}
     41<hr class="usercontrol" />       
     42<table width="100%%">
     43{{ body_worksheet_html }}
     44<hr class="usercontrol" />
     45{{ actions() }}
     46{% endblock %}
  • new file sage/server/notebook/templates/notebook/top_bar_and_worksheet.html

    diff --git a/sage/server/notebook/templates/notebook/top_bar_and_worksheet.html b/sage/server/notebook/templates/notebook/top_bar_and_worksheet.html
    new file mode 100644
    - +  
     1
     2{#
     3INPUT:
     4- username - a string containing a username
     5- worksheet_filename - a string containing a worksheet's filename
     6- worksheet_html - a string containing the html for a worksheet
     7- show_debug - a boolean stating whether to show debug information
     8  #}
     9{% include "notebook/user_controls.tmpl" %}
     10{% include "notebook/worksheet_topbar.tmpl" %}
     11{% set entries = [("$('#topbar').toggle()", 'Toggle', 'Toggle the top bar'),
     12                       ('/', 'Home', 'Back to your personal worksheet list'),
     13                       ('/pub', 'Published', 'Browse the published worksheets'),
     14                       ('history_window()', 'Log', 'View a log of recent computations'),
     15                       ('/settings', 'Settings', 'Account Settings'),
     16                       ('bugreport()', 'Report a Problem', 'Report a problem or submit a bug to improve Sage'),
     17                       ('help()', 'Help', 'Documentation'),
     18                       ('/logout', 'Sign out', 'Log out of the Sage notebook')] %}
     19<table width="100%">
     20    <tr>
     21        <td>{% include "banner.html" %}</td>
     22        <td align="right">{{ user_controls(username, entries) }}</td>
     23    </tr>
     24</table>
     25{% if worksheet_filename %}
     26{{ worksheet_topbar(worksheet, "use", username) }}
     27{% endif %}
     28{% if show_debug %}
     29{% include "notebook/debug_window.html" %}
     30{% endif %}
     31
     32<div class="worksheet" id="worksheet">
     33    {{ worksheet_html }}
     34</div>
  • new file sage/server/notebook/templates/notebook/upload_data_window.html

    diff --git a/sage/server/notebook/templates/notebook/upload_data_window.html b/sage/server/notebook/templates/notebook/upload_data_window.html
    new file mode 100644
    - +  
     1
     2{% extends "notebook/worksheet_page_template.html" %}
     3{#
     4INPUT:
     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- JSMATH_IMAGE_FONTS - a boolean stating whether to include jsMath iamage fonts
     10- JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE
     11- sage_jsmath_macros - an array containing strings of Javascript of Sage macros for jsMath
     12#}
     13
     14{% set title = 'Upload or Create Data File' %}
     15
     16{% block body_addition %}
     17<div class="upload_worksheet_menu" id="upload_worksheet_menu">
     18    <h1><font size=+1>Upload or create data file attached to the worksheet '%s'</font></h1>
     19    <hr />
     20    <form method="POST" action="do_upload_data"
     21          name="upload" enctype="multipart/form-data">
     22        <table>
     23            <tr>
     24                <td>
     25                    Browse your computer to select a file to upload:<br />
     26                    <input class="upload_worksheet_menu" size="50" type="file" name="fileField" value="" id="upload_filename"></input><br /><br />
     27                    Or enter the url of a file on the web:<br />
     28                   
     29                    <input class="upload_worksheet_menu" size="50" type="text" name="urlField" value="" id="upload_url"></input><br />
     30                    <br /><br />
     31                    Or enter the name of a new file, which will be created:<br />
     32                    <input class="upload_worksheet_menu" size="50" type="text" name="newField" value="" id="upload_filename"></input><br /><br />
     33                   
     34                    What do you want to call it? (if different than the original name)<br />
     35                    <input class="upload_worksheet_menu" size="50" type="text" name="nameField" value="" id="upload_name"></input><br />
     36                </td>
     37            </tr>
     38            <tr>
     39                <td><br /><input type="button" class="upload_worksheet_menu" value="Upload File" onClick="form.submit();" /></td>
     40            </tr>
     41        </table>
     42    </form>
     43    <br />
     44</div>
     45{% endblock %}
     46       
     47 No newline at end of file
  • new file sage/server/notebook/templates/notebook/user_controls.tmpl

    diff --git a/sage/server/notebook/templates/notebook/user_controls.tmpl b/sage/server/notebook/templates/notebook/user_controls.tmpl
    new file mode 100644
    - +  
     1
     2{% macro user_controls(user, entries) %}
     3    <span class="username">{{ user }}</span>
     4    {% for href, name, title in entries %}
     5        {% if '(' in href %}
     6            {% set action = 'onClick="' ~ href ~ '"' %}
     7        {% else %}
     8            {% set action = 'href="' ~ href ~ '"' %}
     9        {% endif %}
     10        <span class="vbar"></span>
     11        <a title="{{ title }}" class="usercontrol" {{ action }}>{{ name }}</a>
     12    {% endfor %}
     13{% endmacro %}
  • new file sage/server/notebook/templates/notebook/worksheet.html

    diff --git a/sage/server/notebook/templates/notebook/worksheet.html b/sage/server/notebook/templates/notebook/worksheet.html
    new file mode 100644
    - +  
     1
     2{#
     3INPUT:
     4     - worksheet_name - a string containing a worksheet's name
     5     - worksheet_html - a string containing the html for a worksheet
     6     - do_print - a boolean stating whether to render a print version of the
     7                  worksheet
     8  #}
     9{% extends "base.html" %}
     10
     11{% block title %}Sage Worksheet: {{ worksheet_name }}{% endblock %}
     12
     13{% block css %}main{% endblock %}
     14
     15{% block javascript %}
     16<script type="text/javascript" src="/javascript_local/jquery/jquery.js"></script>
     17<script type="text/javascript" src="/javascript/main.js"></script>
     18{% if do_print %}
     19    <script type="text/javascript" src="/javascript_local/jsmath/jsMath.js"></script>
     20{% endif %}   
     21{% endblock %}
     22
     23{% block body_attrs %}
     24{% if not do_print %}
     25    class="worksheet-online" onLoad="initialize_the_notebook();"
     26{% endif %}
     27{% endblock %}
     28
     29{% block body %}
     30{% if do_print %}
     31    <div class="worksheet_print_title"> {{ worksheet_name }}</div>
     32{% endif %}
     33{{ worksheet_html }}
     34{% if do_print %}
     35    <script type="text/javascript">jsMath.Process();</script>
     36{% endif %}
     37{% endblock %}
     38 No newline at end of file
  • new file sage/server/notebook/templates/notebook/worksheet_page_template.html

    diff --git a/sage/server/notebook/templates/notebook/worksheet_page_template.html b/sage/server/notebook/templates/notebook/worksheet_page_template.html
    new file mode 100644
    - +  
     1{% extends "base.html" %}
     2{#
     3INPUT:
     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- JSMATH_IMAGE_FONTS - a boolean stating whether to include jsMath iamage fonts
     12- JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE
     13- sage_jsmath_macros - an array containing strings of Javascript of Sage macros for jsMath
     14#}
     15
     16{% if not select %}
     17    {% set select = none %}
     18{% endif %}
     19
     20{% if not backwards %}
     21    {% set backwards = false %}
     22{% endif %}
     23   
     24{% include "notebook/head.tmpl" %}
     25{% include "notebook/worksheet_top.tmpl" %}
     26{% include "notebook/worksheet_topbar.tmpl" %}
     27
     28{% block title %}
     29{{ common_title(worksheet_filename, worksheet) }}
     30{% endblock %}
     31   
     32{% block css %}main{% endblock %}
     33
     34{% block javascript %}
     35{{ common_javascript(worksheet, worksheet_filename, username, JSMATH, JSMATH_IMAGE_FONTS, JEDITABLE_TINYMCE, sage_jsmath_macros) }}
     36{% endblock %}
     37
     38{% block body %}
     39{{ worksheet_top(username) }}
     40{{ worksheet_topbar(worksheet, select, username, backwards) }}
     41<hr class="usercontrol" />
     42{% block before_sharebar %}{% endblock %}
     43<span class="sharebar">{{ title }}</span>
     44<br /><br /><br />
     45{% block body_addition %}{% endblock %}
     46{% endblock %}
     47 No newline at end of file
  • new file sage/server/notebook/templates/notebook/worksheet_revision_list.html

    diff --git a/sage/server/notebook/templates/notebook/worksheet_revision_list.html b/sage/server/notebook/templates/notebook/worksheet_revision_list.html
    new file mode 100644
    - +  
     1
     2{% extends "notebook/worksheet_page_template.html" %}
     3{#
     4INPUT:
     5- data - a list of pairs of the form ('how long ago', key)
     6- worksheet - an instance of Worksheet
     7- worksheet_filename - a string containing a worksheet's filename
     8- username - a string containing a username
     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  #}
     14
     15
     16{% set title  = "Revision History" %}
     17{% set select = "revisions" %}
     18
     19{% block body_addition %}
     20<hr class="usercontrol">
     21<table width="100%%">
     22    <tr>
     23        <td width="1%%"></td>
     24        <td width="20%%"><b>Revision</b></td>
     25        <td width="20%%"><b>Last Edited</b></td>
     26        <td width="30%%"></td>
     27    </tr>
     28{% for desc, key in data|reverse %}
     29    <tr>
     30        <td></td>
     31        <td><a href="revisions?rev={{ key }}">Revision {{ loop.revindex0 }}</a></td>
     32        <td><span class="revs">{{ desc }}</span></td>
     33    </tr>
     34{% endfor %}
     35</table>
     36{% endblock %}
     37 No newline at end of file
  • new file sage/server/notebook/templates/notebook/worksheet_settings.html

    diff --git a/sage/server/notebook/templates/notebook/worksheet_settings.html b/sage/server/notebook/templates/notebook/worksheet_settings.html
    new file mode 100644
    - +  
     1
     2{% extends "notebook/worksheet_page_template.html" %}
     3{#
     4INPUT:
     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- JSMATH_IMAGE_FONTS - a boolean stating whether to include jsMath iamage fonts
     10- JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE
     11- sage_jsmath_macros - an array containing strings of Javascript of Sage macros for jsMath
     12#}
     13
     14{% set title = 'Worksheet Settings &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<button name="button_save">Save Settings</button>  <input type="submit" value="Cancel" name="button_cancel"/>' %}
     15
     16{% block before_sharebar %}
     17<form width=70%% method="post" action="input_settings"  enctype="multipart/form-data">
     18{% endblock %}
     19{% block body_addition %}
     20</form>
     21{% endblock %}
     22
     23
     24
  • new file sage/server/notebook/templates/notebook/worksheet_share.html

    diff --git a/sage/server/notebook/templates/notebook/worksheet_share.html b/sage/server/notebook/templates/notebook/worksheet_share.html
    new file mode 100644
    - +  
     1
     2{% extends "notebook/worksheet_page_template.html" %}
     3{#
     4INPUT:
     5    - worksheet - an instance of Worksheet
     6    - worksheet_filename - a string containing a worksheet's filename
     7    - username - a string containing a username
     8    - other_users - a list of strings containing other users names
     9    - user_is_admin - a boolean stating whether the user is an admin
     10    - JSMATH - a boolean stating whether to include jsMath
     11    - JSMATH_IMAGE_FONTS - a boolean stating whether to include jsMath iamage fonts
     12    - JEDITABLE_TINYMCE - a boolean stating whether to include jEditable and TinyMCE
     13    - sage_jsmath_macros - an array containing strings of Javascript of Sage macros for jsMath
     14#}
     15
     16{% set title = "Share this document" %}
     17{% set select = "share" %}
     18
     19{% block body_addition %}
     20{% if not (user_is_admin or username == worksheet.owner()) %}
     21    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>.
     22{% else %}
     23<p>This Sage Worksheet is currently shared with the people listed in the box below.</p>
     24<p style="margin-bottom:1em">You may add or remove collaborators (separate user names by commas).</p>
     25
     26<form width=70% method="post" action="invite_collab" style="margin-bottom:1em">
     27    <textarea name="collaborators" rows=5 cols=70 class="edit" id="collaborators" style="display:block; margin-bottom:1em;">{{ worksheet.collaborators()|join(', ') }}</textarea>
     28    <input type="submit" title="Give access to your worksheet to the above collaborators" value="Invite Collaborators" />
     29</form>
     30
     31<hr class="usercontrol" />
     32<span class="username">Sage Users:</span>
     33<span class="users">
     34    {{ other_users|join(', ') }}
     35</span>
     36{% endif %}
     37{% endblock %}
  • new file sage/server/notebook/templates/notebook/worksheet_top.tmpl

    diff --git a/sage/server/notebook/templates/notebook/worksheet_top.tmpl b/sage/server/notebook/templates/notebook/worksheet_top.tmpl
    new file mode 100644
    - +  
     1{#
     2INPUT:
     3- username - a string containing a username
     4#}
     5
     6{% macro worksheet_top(username) %}
     7{% include "notebook/user_controls.tmpl" %}
     8{% include "notebook/worksheet_topbar.tmpl" %}
     9{% set entries = [("$('#topbar').toggle()", 'Toggle', 'Toggle the top bar'),
     10                       ('/', 'Home', 'Back to your personal worksheet list'),
     11                       ('/pub', 'Published', 'Browse the published worksheets'),
     12                       ('history_window()', 'Log', 'View a log of recent computations'),
     13                       ('/settings', 'Settings', 'Account Settings'),
     14                       ('bugreport()', 'Report a Problem', 'Report a problem or submit a bug to improve Sage'),
     15                       ('help()', 'Help', 'Documentation'),
     16                       ('/logout', 'Sign out', 'Log out of the Sage notebook')] %}
     17<table width="100%">
     18    <tr>
     19        <td>{% include "banner.html" %}</td>
     20        <td align="right">{{ user_controls(username, entries) }}</td>
     21    </tr>
     22</table>
     23{% endmacro %}
  • new file sage/server/notebook/templates/notebook/worksheet_topbar.tmpl

    diff --git a/sage/server/notebook/templates/notebook/worksheet_topbar.tmpl b/sage/server/notebook/templates/notebook/worksheet_topbar.tmpl
    new file mode 100644
    - +  
     1
     2{#
     3INPUT:
     4- worksheet - an instance of Worksheet
     5- select    - a string containing the control that is selected
     6- username  - a string containing a username
     7- backwards - a boolean
     8  #}
     9{% macro worksheet_topbar(worksheet, select=None, username='guest', backwards=false) %}
     10    <table width="100%%" id="topbar">
     11        <tr>
     12            <td align="left"> {{ worksheet.html_title(username) }} </td>
     13            <td align="right"> {{ worksheet.html_save_discard_buttons() }} </td>
     14        </tr>
     15        <tr>
     16            <td align="left"> {{ worksheet.html_menu() }} </td>
     17            <td align="right"> {{ worksheet.html_share_publish_buttons(select, backwards) }}</td>
     18        </tr>
     19    </table>
     20    <div class="hidden" id="slide_controls">
     21        <div class="slideshow_control">
     22            <a class="slide_arrow" onClick="slide_next()">&gt;</a>
     23            <a class="slide_arrow" onClick="slide_last()">&gt;&gt;</a> <span class="vbar"></span>
     24            <a class="cell_mode" onClick="cell_mode()">Exit</a>
     25        </div>
     26        <div class="slideshow_progress" id="slideshow_progress" onClick="slide_next()">
     27            <div class="slideshow_progress_bar" id="slideshow_progress_bar">&nbsp;</div>
     28            <div class="slideshow_progress_text" id="slideshow_progress_text">&nbsp;</div>
     29        </div>
     30        <div class="slideshow_control">
     31            <a class="slide_arrow" onClick="slide_first()">&lt;&lt;</a>
     32            <a class="slide_arrow" onClick="slide_prev()">&lt;</a>
     33        </div>
     34    </div>
     35{% endmacro %}
  • sage/server/notebook/templates/registration.html

    diff --git a/sage/server/notebook/templates/registration.html b/sage/server/notebook/templates/registration.html
    a b  
     1
    12{% extends "base.html" %}
    23
    34{% block title %}Sign up{% endblock %}
  • sage/server/notebook/templates/search.html

    diff --git a/sage/server/notebook/templates/search.html b/sage/server/notebook/templates/search.html
    a b  
     1
    12<span class="flush-right">
    23<input id="search_worksheets" size=20 onkeypress="return search_worksheets_enter_pressed(event, '{{ typ }}');" value="{{ search }}"></input>
    34<button class="add_new_worksheet_menu" onClick="search_worksheets('{{ typ }}');">Search Worksheets</button>
  • sage/server/notebook/templates/source_code.html

    diff --git a/sage/server/notebook/templates/source_code.html b/sage/server/notebook/templates/source_code.html
    a b  
     1
    12{% extends "base.html" %}
    23
    34{% block title %}{{ src_filename }} - Source Code{% endblock %}
  • sage/server/notebook/templates/template_error.html

    diff --git a/sage/server/notebook/templates/template_error.html b/sage/server/notebook/templates/template_error.html
    a b  
     1
    12{% extends "base.html" %}
    23
    34{% block title %}Error{% endblock %}
  • sage/server/notebook/templates/top_bar.html

    diff --git a/sage/server/notebook/templates/top_bar.html b/sage/server/notebook/templates/top_bar.html
    a b  
     1
    12<table width="100%%">
    23  <tr>
    34    <td>
  • sage/server/notebook/templates/upload.html

    diff --git a/sage/server/notebook/templates/upload.html b/sage/server/notebook/templates/upload.html
    a b  
     1
    12{% extends "base.html" %}
    23
    34{% block title %}Upload File{% endblock %}
  • sage/server/notebook/templates/user_management.html

    diff --git a/sage/server/notebook/templates/user_management.html b/sage/server/notebook/templates/user_management.html
    a b  
     1
    12{% extends "base.html" %}
    23
    34{% block title %}User Management{% endblock %}
  • new file sage/server/notebook/templates/worksheet/attached.html

    diff --git a/sage/server/notebook/templates/worksheet/attached.html b/sage/server/notebook/templates/worksheet/attached.html
    new file mode 100644
    - +  
     1{#
     2INPUT:
     3- attached_files - dictionary of attached files
     4#}
     5{% for file, tm in attached_files %}
     6<div class="attached_filename" onClick="inspect_attached_file('{{ file }}')">
     7    {{ file }}
     8</div>
     9{% endfor %}
     10 No newline at end of file
  • new file sage/server/notebook/templates/worksheet/completions.html

    diff --git a/sage/server/notebook/templates/worksheet/completions.html b/sage/server/notebook/templates/worksheet/completions.html
    new file mode 100644
    - +  
     1{#
     2INPUT:
     3- cell_id - id for the cell of the completions
     4- completions_enumerated - enumerated (enumerate()) 2D list of completions in
     5column-major order
     6#}
     7<ul class='completion_menu_one'
     8    {% for col_i, column in completions_enumerated %}
     9    <li class='completion_menu_one'>
     10        <ul class='completion_menu_two'>
     11        {% for row in column %}
     12            <li id='completion{{ cell_id }}_{{ loop.index0 }}_{{ col_i }}' class='completion_menu_two'>
     13                <a onClick='do_replacement({{ cell_id }}, "{{ row }}"); return false;'
     14                   onMouseOver='this.focus(); select_replacement({{ loop.index0 }},{{ col_i }});'>{{ row }}</a>
     15            </li>
     16        {% endfor %}
     17        </ul>
     18    </li>
     19    {% endfor %}
     20</ul>
  • new file sage/server/notebook/templates/worksheet/menu.html

    diff --git a/sage/server/notebook/templates/worksheet/menu.html b/sage/server/notebook/templates/worksheet/menu.html
    new file mode 100644
    - +  
     1{#
     2INPUT
     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&nbsp;&nbsp;&nbsp;<select class="worksheet"  onchange="go_option(this);">
     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();">Upload 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('{{ name }}');">Download 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);" >
     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
     38<select class="worksheet" onchange="handle_data_menu(this);" >
     39    <option title="Select an attached file" value="" selected>Data...</option>
     40    <option title="Upload or create a data file in a wide range of formats" value="__upload_data_file__">Upload or create file...</option>
     41    <option value="">--------------------</option>
     42    {% for name in data %}
     43    <option value="datafile?name={{ option }}">{{ option }}</option>
     44    {% endfor %}
     45</select>
     46
     47{% if not doc_worksheet %}
     48<select onchange="go_system_select(this, {{ current_system_index }});" class="worksheet">
     49    {% for system_index, system_name in systems_enumerated %}
     50        <option title="Evaluate all input cells using {{ system_names[system_index] }}"
     51            {{ "selected" if current_system_index == system_index else "" }} value="{{ system_names[system_index] }}">
     52            {{ system_name }}
     53        </option>
     54    {% endfor %}
     55</select>   
     56<input type="checkbox" title="Enable/disable pretty_printing"
     57       onchange="pretty_print_check(this.checked);"
     58       class="worksheet" value="pretty_print" {{ "checked" if pretty_print else "" }} />&nbsp;Typeset
     59{% endif %}
     60 No newline at end of file
  • new file sage/server/notebook/templates/worksheet/published_worksheet.html

    diff --git a/sage/server/notebook/templates/worksheet/published_worksheet.html b/sage/server/notebook/templates/worksheet/published_worksheet.html
    new file mode 100644
    - +  
     1{#
     2INPUT:
     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 "worksheet/worksheet_body.html" %}
     10
     11
     12<script language=javascript>jsMath.ProcessBeforeShowing();</script>
  • new file sage/server/notebook/templates/worksheet/save_discard_buttons.html

    diff --git a/sage/server/notebook/templates/worksheet/save_discard_buttons.html b/sage/server/notebook/templates/worksheet/save_discard_buttons.html
    new file mode 100644
    - +  
     1{#
     2INPUT:
     3doc_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 %}
  • new file sage/server/notebook/templates/worksheet/share_publish_buttons.html

    diff --git a/sage/server/notebook/templates/worksheet/share_publish_buttons.html b/sage/server/notebook/templates/worksheet/share_publish_buttons.html
    new file mode 100644
    - +  
     1
     2{#
     3INPUT:
     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="usercontrol" 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 %}
  • new file sage/server/notebook/templates/worksheet/time_last_edited.html

    diff --git a/sage/server/notebook/templates/worksheet/time_last_edited.html b/sage/server/notebook/templates/worksheet/time_last_edited.html
    new file mode 100644
    - +  
     1{#
     2INPUT:
     3- time - string of time of  last edit
     4- last_editor - string of name of last editor
     5#}
     6<span class="lastedit">last edited on {{ time }} by {{ last_editor }}</span>
     7 No newline at end of file
  • new file sage/server/notebook/templates/worksheet/time_since_last_edited.html

    diff --git a/sage/server/notebook/templates/worksheet/time_since_last_edited.html b/sage/server/notebook/templates/worksheet/time_since_last_edited.html
    new file mode 100644
    - +  
     1{#
     2INPUT:
     3- time - string of time since last edit
     4- last_editor - string of name of last editor
     5#}
     6<span class="lastedit">{{ time }} ago by {{ last_editor }}</span>
  • new file sage/server/notebook/templates/worksheet/title.html

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

    diff --git a/sage/server/notebook/templates/worksheet/worksheet.html b/sage/server/notebook/templates/worksheet/worksheet.html
    new file mode 100644
    - +  
     1{#
     2INPUT:
     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#}
     10{% include "worksheet/worksheet_body.html" %}
     11
     12{% if do_print %}
     13<script language="javascript">jsMath.ProcessBeforeShowing();</script>
     14{% else %}
     15<script type="text/javascript">cell_id_list={{ cell_id_list }};</script>
     16{% endif %}
     17
     18{% if not do_print and confirm_before_leave %}
     19<script type="text/javascript">
     20            window.onbeforeunload = confirmBrowseAway;
     21            function confirmBrowseAway()
     22            {
     23            return "Unsubmitted cells will be lost.";
     24            }
     25</script>
     26{% endif %}
     27 No newline at end of file
  • new file sage/server/notebook/templates/worksheet/worksheet_body.html

    diff --git a/sage/server/notebook/templates/worksheet/worksheet_body.html b/sage/server/notebook/templates/worksheet/worksheet_body.html
    new file mode 100644
    - +  
     1{#
     2INPUT:
     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
  • sage/server/notebook/templates/worksheet_listing.html

    diff --git a/sage/server/notebook/templates/worksheet_listing.html b/sage/server/notebook/templates/worksheet_listing.html
    a b  
     1
    12{% extends "base.html" %}
    23
    34{% if pub %}
  • sage/server/notebook/templates/yes_no.html

    diff --git a/sage/server/notebook/templates/yes_no.html b/sage/server/notebook/templates/yes_no.html
    a b  
     1
    12{% extends "base.html" %}
    23
    34{% block title %}Confirm{% endblock %}
  • sage/server/notebook/twist.py

    diff --git a/sage/server/notebook/twist.py b/sage/server/notebook/twist.py
    a b class WorksheetFile(resource.Resource): 
    191191        s = notebook.html(worksheet_filename = W.filename(),
    192192                          username = self.username)
    193193
    194         #Hack to add in the needed CSS to get it to display nicely
    195         css_tag = lambda path: r'<link rel=stylesheet href="%s" type="text/css">'%path
    196         main_css = css_tag('/css/main.css')
    197         s = s.replace(main_css,css_tag('_static/default.css')+"\n"+main_css )
    198 
    199194        return HTMLResponse(stream=s)
    200195       
    201196    def childFactory(self, request, name):
    class ListOfUsers(resource.Resource): 
    21992194            if user_type(self.username) != 'admin':
    22002195                s = message('You must an admin to manage other users.')
    22012196            else:
    2202                 s = template('user_management.html', {'users':notebook.valid_login_names()})
     2197                s = template('user_management.html', users = notebook.valid_login_names())
    22032198            return HTMLResponse(stream = s)
    22042199
    22052200class InvalidPage(resource.Resource):
  • sage/server/notebook/worksheet.py

    diff --git a/sage/server/notebook/worksheet.py b/sage/server/notebook/worksheet.py
    a b import sage.server.support as support 
    5252# Imports specifically relevant to the sage notebook
    5353import worksheet_conf
    5454from   cell import Cell, TextCell
     55from template import template
    5556
    5657# Set some constants that will be used for regular expressions below.
    5758whitespace = re.compile('\s')  # Match any whitespace character
    class Worksheet: 
    22112212    ##########################################################
    22122213    def html(self, include_title=True, do_print=False,
    22132214             confirm_before_leave=False, read_only=False):
     2215        """
     2216        INPUT:
     2217        - publish - a boolean stating whether the worksheet is published
     2218        - do_print - a boolean
     2219
     2220        OUTPUT:
     2221        - returns the html for the worksheet
     2222       
     2223        EXAMPLES::
     2224       
     2225            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     2226            sage: W = nb.create_new_worksheet('Test', 'admin')
     2227            sage: W.html()
     2228            '\n\n\n<div class="cell_input_active" id="cell_resizer"></div>\n\n<div class="worksheet_cell_list" id...'
     2229        """
     2230        ncols = self.notebook().conf()['word_wrap_cols']
     2231        cells_html = ""
    22142232        if self.is_published():
    22152233            try:
    22162234                return self.__html
    22172235            except AttributeError:
    2218                 s = self.html_worksheet_body(do_print=True)
    2219                 s += self.javascript_for_jsmath_rendering()
     2236                for cell in self.cell_list():
     2237                    cells_html += cell.html(ncols, do_print=True) + '\n'
     2238                s = template("worksheet/published_worksheet.html", ncols = ncols,
     2239                             cells_html = cells_html)
    22202240                self.__html = s
    22212241                return s
    2222                
    2223         s = ''
    2224            
    2225         s += self.html_worksheet_body(do_print=do_print)
    2226 
    2227         if do_print:
    2228             s += self.javascript_for_jsmath_rendering()
    2229         else:
    2230             s += self.javascript_for_being_active_worksheet()
    2231 
    2232         if not do_print and confirm_before_leave:
    2233             s += self.javascript_confirm_before_leave()
    2234            
    2235         return s
     2242        for cell in self.cell_list():
     2243            cells_html += cell.html(ncols, do_print=do_print) + '\n'
     2244           
     2245        return template("worksheet/worksheet.html", published = self.is_published(),
     2246                        do_print = do_print, confirm_before_leave = confirm_before_leave,
     2247                        cells_html = cells_html,
     2248                        cell_id_list = self.compute_cell_id_list())
    22362249
    22372250    def truncated_name(self, max=30):
    22382251        name = self.name()
    class Worksheet: 
    22432256    def html_title(self, username='guest'):
    22442257        import cgi
    22452258        name = self.truncated_name()
    2246 
    22472259        warn = self.warn_about_other_person_editing(username, WARN_THRESHOLD)
    22482260       
    2249         s = ''
    2250         s += '<div class="worksheet_title">'
    2251         s += '<a id="worksheet_title" class="worksheet_title" onClick="rename_worksheet(); return false;" title="Click to rename this worksheet">%s</a>'%(cgi.escape(name))
    2252         s += '<br>' + self.html_time_last_edited()
    2253         if warn and username != 'guest' and not self.is_doc_worksheet():
    2254             s += '&nbsp;&nbsp;<span class="pingdown">(Someone else is viewing this worksheet)</span>'
    2255         s += '</div>'
    2256 
    2257         return s
     2261        return template("worksheet/title.html", worksheet = self,
     2262                        name = cgi.escape(self.truncated_name()),
     2263                        warn = warn, doc_worksheet = self.is_doc_worksheet(),
     2264                        username = username)
    22582265
    22592266    def is_doc_worksheet(self):
    22602267        try:
    class Worksheet: 
    22662273        self.__is_doc_worksheet = value
    22672274
    22682275    def html_save_discard_buttons(self):
    2269         if self.is_doc_worksheet():
    2270             return ''
    2271         return """
    2272         <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>
    2273         """
    2274 
     2276        r"""
     2277        OUTPUT:
     2278        - returns the html for the save, discard, etc. buttons
     2279
     2280        EXAMPLES::
     2281
     2282            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     2283            sage: W = nb.create_new_worksheet('Test', 'admin')
     2284            sage: W.html_save_discard_buttons()
     2285            '\n\n<button name="button_save" title="Save changes" onClick="save_worksheet();">Save<...'
     2286        """
     2287        return template("worksheet/save_discard_buttons.html", doc_worksheet = self.is_doc_worksheet())
     2288       
    22752289    def html_share_publish_buttons(self, select=None, backwards=False):
    2276         if self.is_doc_worksheet():
    2277             return ''
    2278         def cls(x):
    2279             if x == select:
    2280                 return "control-select"
    2281             else:
    2282                 return "control"
    2283         backwards = '../' if backwards else ''
    2284         return """
    2285 
    2286         <a  title="Print this worksheet" class="usercontrol" onClick="print_worksheet()"><img border=0 src="/images/icon_print.gif" alt="Print">Print</a>
    2287         <a class="%s" title="Interactively use this worksheet" onClick="edit_worksheet();">Worksheet</a>       
    2288         <a class="%s" title="Edit text version of this worksheet" href="%sedit">Edit</a>
    2289         <a class="%s" title="View plain text version of this worksheet" href="%stext">Text</a>
    2290         <a class="%s" href="%srevisions" title="View changes to this worksheet over time">Undo</a>
    2291         <a class="%s" href="%sshare" title="Let others edit this worksheet">Share</a>
    2292         <a class="%s" href="%spublish" title="Make this worksheet publicly viewable">Publish</a>
    2293         """%(cls('use'),cls('edit'),backwards,cls('text'),backwards,cls('revisions'),backwards,cls('share'),backwards,cls('publish'),backwards)
    2294 
    2295     def html_data_options_list(self):
    2296         D = self.attached_data_files()
    2297         D.sort()
    2298         x = '\n'.join(['<option value="datafile?name=%s">%s</option>'%(nm,nm) for nm in D])
    2299         return x
    2300 
    2301     def html_file_menu(self):
    2302 ##  <option title="Save this worksheet as an HTML web page" onClick="save_as('html');">Save as HTML (zipped) </option>
    2303 ##  <option title="Save this worksheet to LaTeX format" onClick="save_as('latex');">Save as LaTeX (zipped) </option>
    2304 ##  <option title="Save this worksheet as a PDF file" onClick="save_as('pdf');">Save as PDF</option>
    2305 ##  <option title="Save this worksheet as a text file" onClick="save_as('text');">Save as Text</option>
    2306 
    2307         if self.is_doc_worksheet():
    2308             system_select = ''
    2309             pretty_print_check = ''
    2310         else:
    2311             system_select = self.notebook().html_system_select_form_element(self)
    2312             pretty_print_check = self.notebook().html_pretty_print_check_form_element(self)
    2313 
    2314         data = self.html_data_options_list()
    2315        
    2316         return """
    2317 <select class="worksheet"  onchange="go_option(this);">
    2318 <option title="Select a file related function" value=""  selected>File...</option>
    2319  <option title="Load a new worksheet stored in a file" value="upload_worksheet_button();">Upload worksheet from a file</option>
    2320  <option title="Create a new worksheet" value="new_worksheet();">New worksheet</option>
    2321  <option title="Save this worksheet to an sws file" value="download_worksheet('%s');">Download to a file</option>
    2322  <option title="Print this worksheet" value="print_worksheet();">Print</option>
    2323  <option title="Rename this worksheet" value="rename_worksheet();">Rename worksheet</option>
    2324  <option title="Copy this worksheet" value="copy_worksheet();">Copy worksheet</option>
    2325  <option title="Move this worksheet to the trash" value="delete_worksheet('%s');">Delete worksheet</option>
    2326 </select>
    2327 
    2328 <select class="worksheet"  onchange="go_option(this);" >
    2329  <option title="Select a worksheet function" value="" selected>Action...</option>
    2330  <option title="Interrupt currently running calculations, if possible" value="interrupt();">Interrupt</option>
    2331  <option title="Restart the worksheet process" value="restart_sage();">Restart worksheet</option>
    2332  <option title="Quit the worksheet process" value="save_worksheet_and_close();">Save and quit worksheet</option>
    2333  <option value="">---------------------------</option>
    2334  <option title="Evaluate all input cells in the worksheet" value="evaluate_all();">Evaluate All</option>
    2335  <option title="Hide all output" value="hide_all();">Hide All Output</option>
    2336  <option title="Show all output" value="show_all();">Show All Output</option>
    2337  <option title="Delete all output" value="delete_all_output();">Delete All Output</option>
    2338  <option value="">---------------------------</option>
    2339  <option title="Switch to single-cell mode" value="slide_mode();">One Cell Mode</option>
    2340  <option title="Switch to multi-cell mode" value="cell_mode();">Multi Cell Mode</option>
    2341  </select>
    2342 
    2343 <select class="worksheet" onchange="handle_data_menu(this);" >
    2344  <option title="Select an attached file" value="" selected>Data...</option>
    2345  <option title="Upload or create a data file in a wide range of formats" value="__upload_data_file__">Upload or create file...</option>
    2346  <option value="">--------------------</option>
    2347 %s
    2348 </select>
    2349 
    2350  %s
    2351  %s
    2352  """%(_notebook.clean_name(self.name()), self.filename(),
    2353       data, system_select, pretty_print_check)
     2290        r"""
     2291        INPUT:
     2292        - select - a boolean
     2293        - backwards - a boolean
     2294
     2295        OUTPUT:
     2296        - returns the html for the share, publish, etc. buttons
     2297
     2298        EXAMPLES::
     2299
     2300            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     2301            sage: W = nb.create_new_worksheet('Test', 'admin')
     2302            sage: W.html_share_publish_buttons()
     2303            '\n\n\n\n\n<a title="Print this worksheet" class="usercontrol" onClick="print_worksheet()">...'
     2304        """
     2305        return template("worksheet/share_publish_buttons.html", worksheet = self, select = select, backwards = backwards)
     2306       
    23542307# <option title="Browse the data directory" value="data/">Browse data directory...</option>
    23552308# <option title="Browse the directory of output from cells" value="cells/">Browse cell output directories...</option>
    23562309
    23572310# <option title="Configure this worksheet" value="worksheet_settings();">Worksheet settings</option>
    23582311
    23592312    def html_menu(self):
    2360         name = self.filename()
    2361 
    2362         menu = '&nbsp;'*3 + self.html_file_menu()
    2363        
    2364         filename = os.path.split(self.filename())[-1]
    2365         download_name = _notebook.clean_name(self.name())
    2366        
    2367         #menu += '  </span>' #why is this here?  it isn't opened anywhere.
    2368 
    2369         return menu
     2313        """
     2314        OUTPUT:
     2315        - returns the html for the menus of the worksheet
     2316
     2317        EXAMPLES::
     2318       
     2319            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     2320            sage: W = nb.create_new_worksheet('Test', 'admin')
     2321            sage: W.html_menu()
     2322            '\n&nbsp;&nbsp;&nbsp;<select class="worksheet"  onchange="go_option(this);">\n    ...'
     2323        """
     2324        return template("worksheet/menu.html", name = _notebook.clean_name(self.name()),
     2325                        filename_ = self.filename(), data = self.attached_data_files().sort(),
     2326                        systems_enumerated = enumerate(self.notebook().systems()),
     2327                        system_names = self.notebook().system_names(),
     2328                        current_system_index = self.notebook().system_names().index(self.system()),
     2329                        pretty_print = self.pretty_print(),
     2330                        doc_worksheet = self.is_doc_worksheet())
    23702331
    23712332    def html_worksheet_body(self, do_print, publish=False):
    2372         n = len(self.cell_list())
     2333        """
     2334        INPUT:
     2335        - publish - a boolean stating whether the worksheet is published
     2336        - do_print - a boolean
     2337
     2338        OUTPUT:
     2339        - returns the html for the File menu of the worksheet
     2340
     2341        EXAMPLES::
     2342       
     2343            sage: nb = sage.server.notebook.notebook.Notebook(tmp_dir())
     2344            sage: W = nb.create_new_worksheet('Test', 'admin')
     2345            sage: W.html_worksheet_body(false)
     2346            '\n\n<div class="cell_input_active" id="cell_resizer"></div>\n\n<div class="worksheet_cell_list" id...'
     2347        """
    23732348        published = self.is_published() or publish
    2374 
    2375         s = '<div class="cell_input_active" id="cell_resizer"></div>'
    2376         D = self.notebook().conf()
    2377         ncols = D['word_wrap_cols']
    2378         if not published:
    2379             s += '<div class="worksheet_cell_list" id="worksheet_cell_list">\n'
    2380            
    2381         for i in range(n):
    2382             cell = self.cell_list()[i]
    2383             s += cell.html(ncols, do_print=do_print) + '\n'
    2384 
    2385         if not do_print and not published:
    2386             s += '\n</div>\n'
    2387             s += """<div class="insert_new_cell" id="insert_last_cell">
    2388                  </div>
    2389 <script type="text/javascript">
    2390 $("#insert_last_cell").plainclick(function(e) {insert_new_cell_after(cell_id_list[cell_id_list.length-1]);});
    2391 $("#insert_last_cell").shiftclick(function(e) {insert_new_text_cell_after(cell_id_list[cell_id_list.length-1]);});
    2392 </script>"""
    2393             s += '<div class="worksheet_bottom_padding"></div>\n'
    2394         return s
    2395 
    2396     def javascript_for_being_active_worksheet(self):
    2397         s =  '<script type="text/javascript">cell_id_list=%s;</script>'%self.compute_cell_id_list()
    2398         #s += 'for(i=0;i<cell_id_list.length;i++) prettify_cell(cell_id_list[i]);</script>\n'
    2399         return s
    2400 
    2401     def javascript_for_jsmath_rendering(self):
    2402         return '<script language=javascript>jsMath.ProcessBeforeShowing();</script>\n'
    2403 
    2404     def javascript_confirm_before_leave(self):
    2405         return """<script type="text/javascript">
    2406             window.onbeforeunload = confirmBrowseAway;
    2407             function confirmBrowseAway()
    2408             {
    2409             return "Unsubmitted cells will be lost.";
    2410             }
    2411             </script>
    2412             """
    2413 
     2349        ncols = self.notebook().conf()['word_wrap_cols']
     2350        cells_html = ""
     2351        for cell in self.cell_list():
     2352            cells_html += cell.html(ncols, do_print=do_print) + '\n'
     2353       
     2354        return template("worksheet/worksheet_body.html",
     2355                        cells_html = cells_html,
     2356                        published = published,
     2357                        do_print = do_print)
    24142358
    24152359
    24162360    ##########################################################
    class Worksheet: 
    24702414            user = self.last_to_edit()
    24712415            if user != username:
    24722416                return True, user
    2473         False
     2417        return False
    24742418       
    24752419    def html_time_since_last_edited(self):
    24762420        t = self.time_since_last_edited()
    24772421        tm = convert_seconds_to_meaningful_time_span(t)
    2478         who = ' by %s'%self.last_to_edit()
    2479         return '<span class="lastedit">%s ago%s</span>'%(tm, who)
     2422        return template("worksheet/time_since_last_edited.html",
     2423                        last_editor = self.last_to_edit(),
     2424                        time = tm)
    24802425
    24812426    def html_time_last_edited(self):
    2482         tm = convert_time_to_string(self.last_edited())
    2483         who = self.last_to_edit()
    2484         t = '<span class="lastedit">last edited on %s by %s</span>'%(tm, who)
    2485         return t
     2427        return template("worksheet/time_last_edited.html",
     2428                        time = convert_time_to_string(self.last_edited()),
     2429                        last_editor = self.last_to_edit())
    24862430
    24872431       
    24882432    ##########################################################
    class Worksheet: 
    38403784    # List of attached files.
    38413785    ##########################################################
    38423786    def attached_html(self):
    3843         s = ''
    3844         div = '<div class="attached_filename" onClick="inspect_attached_file(\'%s\')">'
    3845         A = self.attached_files()
    3846         D = self.DIR()
    3847         for F, tm in A.iteritems():
    3848             # uncomment this to remove some absolute path info...
    3849             # if F[:len(D)] == D: F = F[len(D)+1:]
    3850             s += div%F + '%s</div>'%F
    3851         return s
     3787        return template("worksheet/attached.html",
     3788                        attached_files = self.attached_files())
    38523789
    38533790    ##########################################################
    38543791    # Showing and hiding all cells
    def first_word(s): 
    40814018
    40824019
    40834020def format_completions_as_html(cell_id, completions):
     4021    """
     4022    INPUT:
     4023    - cell_id - id for the cell of the completions
     4024    - completions - list of completions in row-major order
     4025   
     4026    OUTPUT:
     4027    - html for the completions formatted in rows and columns
     4028    """
    40844029    if len(completions) == 0:
    40854030        return ''
    4086     lists = []
    4087 
    4088     # compute the width of each column
    4089     column_width = []
    4090     for i in range(len(completions[0])):
    4091         column_width.append(max([len(x[i]) for x in completions if i < len(x)]))
    4092 
    4093     for i in range(len(completions)):
    4094         row = completions[i]
    4095         for j in range(len(row)):
    4096             if len(lists) <= j:
    4097                 lists.append([])     
    4098             cell = """
    4099 <li id='completion%s_%s_%s' class='completion_menu_two'>
    4100 <a onClick='do_replacement(%s, "%s"); return false;'
    4101    onMouseOver='this.focus(); select_replacement(%s,%s);'
    4102 >%s</a>
    4103 </li>"""%(cell_id, i, j, cell_id, row[j], i,j,
    4104          row[j])
    4105          #row[j] + '&nbsp;'*(column_width[j]-len(row[j])) )
    4106 
    4107             lists[j].append(cell)
    4108 
    4109     grid = "<ul class='completion_menu_one'>"
    4110     for L in lists:
    4111         s = "\n   ".join(L)
    4112         grid += "\n <li class='completion_menu_one'>\n  <ul class='completion_menu_two'>\n%s\n  </ul>\n </li>"%s
    4113 
    4114     return grid + "\n</ul>"
     4031
     4032    return template("worksheet/completions.html", cell_id = cell_id,
     4033                    # Transpose and enumerate completions to column-major
     4034                    completions_enumerated = enumerate(map(list, zip(*completions))))
    41154035
    41164036
    41174037def extract_name(text):