MobileBlur

Check-in [517f4aa073]
Login

Check-in [517f4aa073]

Overview
Comment:Made the app substantially prettier
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 517f4aa073cf39995af8c701e95bf90666d0d9e8
User & Date: spiffy on 2011-11-30 04:12:13
Other Links: manifest | tags
Context
2011-12-02
03:31
Made feed and story list divs clickable instead of just their text check-in: 7ff27f901d user: spiffy tags: trunk
2011-11-30
04:12
Made the app substantially prettier check-in: 517f4aa073 user: spiffy tags: trunk
02:49
Made the story title in the story view nicely styled. Put the 'mark story read' button inside the header check-in: dea6297b3d user: spiffy tags: develop, v0.4
2011-11-20
21:41
Added support for multiple users to use the site simultaneously check-in: 2ac904a27b user: spiffy tags: trunk, v0.2
Changes

Modified applications/mobileblur/controllers/default.py from [4edf6967cb] to [cdfea9e32e].

19
20
21
22
23
24
25
26
27
28
29

30
31







        Field("password", "password", requires=IS_NOT_EMPTY())
    )
    if login_form.accepts(request):
        try:
            results = newsblur.login(login_form.vars["username"], login_form.vars["password"])
            response.cookies["nb_cookie"] = newsblur.cookies["newsblur_sessionid"]
            response.cookies["nb_cookie"]["path"] = "/"
            print "cookie =", newsblur.cookies
            redirect(URL("index"))
        except Exception as ex:
            login_form.insert(-1, ex.message)


    return dict(login_form=login_form)














<



>


>
>
>
>
>
>
>
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35
36
37
38
        Field("password", "password", requires=IS_NOT_EMPTY())
    )
    if login_form.accepts(request):
        try:
            results = newsblur.login(login_form.vars["username"], login_form.vars["password"])
            response.cookies["nb_cookie"] = newsblur.cookies["newsblur_sessionid"]
            response.cookies["nb_cookie"]["path"] = "/"

            redirect(URL("index"))
        except Exception as ex:
            login_form.insert(-1, ex.message)
            login_form._class = "alert-message block-message error"

    return dict(login_form=login_form)


def logout():
    response.cookies["nb_cookie"] = ""
    response.cookies["nb_cookie"]["expires"] = -10
    response.cookies["nb_cookie"]["path"] = "/"
    redirect(URL("index"))

Modified applications/mobileblur/controllers/feeds.py from [b47f0eada4] to [30c965b149].

1
2
3

4
5


6







7



8




9
10

11

12
13
# -*- coding: utf-8 -*-

from pprint import pprint


def view():


    stories = newsblur.feed(request.args[0])["stories"]







    feeds = newsblur.feeds(flat=True)["feeds"]



    feed = [feed for feed in feeds.itervalues() if feed["id"]==int(request.args[0])][0]




    return dict(stories=stories, feed=feed)


def mark_read():

    newsblur.mark_feed_as_read(request.vars["feed"])
    redirect(URL("default", "index"))



>


>
>
|
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>


>

>
|

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# -*- coding: utf-8 -*-

from pprint import pprint
import time

def view():
    print ""
    s = time.time()
    feed = newsblur.feed(request.args[0])
    stories = feed["stories"]
    print time.time() - s

    print feed.keys()

    if not feed.has_key("feed_title"):
        s = time.time()
        feeds = newsblur.feeds(flat=True)["feeds"]
        print time.time() - s

        s = time.time()
        feed = [feed for feed in feeds.itervalues() if feed["id"]==int(request.args[0])][0]
        print time.time() - s

    response.title = feed["feed_title"]

    return dict(stories=stories, feed=feed)


def mark_read():
    if len(request.args) > 0:
        newsblur.mark_feed_as_read(request.args[0])
    redirect(URL("default", "index"))

Modified applications/mobileblur/controllers/stories.py from [59984e848a] to [fbf9de8ba7].

1
2
3
4
5
6
7
8




# -*- coding: utf-8 -*-

from pprint import pprint

def view():
    stories = newsblur.feed(request.vars["feed_id"])["stories"]
    story = [story for story in stories if story["id"]==request.vars["story"]][0]
    return dict(story=story)











|
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
# -*- coding: utf-8 -*-

from pprint import pprint

def view():
    stories = newsblur.feed(request.vars["feed_id"])["stories"]
    story = [story for story in stories if story["id"]==request.vars["story"]][0]
    return dict(story=story, feed_id=request.vars["feed_id"])

def mark_read():
    results = newsblur.mark_story_as_read(request.vars["story_id"], request.vars["feed_id"])
    redirect(URL("default", "index"))

Modified applications/mobileblur/models/0_helpers.py from [c67dbf684a] to [8ed26c507d].

1
2
3
4
5
6
7
8
9
10
11
12
newsblur = local_import("newsblur")
newsblur = newsblur.NewsBlur()

threshold = 0
thresholds = ["nt", "ps", "ng"]  # indices -1, 0, 1 for negative, neutral, and positive intelligence filters

print request.cookies
if [request.application, request.controller, request.function] != [request.application, "default", "login"]:
    if "nb_cookie" not in request.cookies.keys():
        redirect(URL("default", "login"))
    else:
        newsblur.cookies["newsblur_sessionid"] = request.cookies["nb_cookie"].value






<





1
2
3
4
5
6

7
8
9
10
11
newsblur = local_import("newsblur")
newsblur = newsblur.NewsBlur()

threshold = 0
thresholds = ["nt", "ps", "ng"]  # indices -1, 0, 1 for negative, neutral, and positive intelligence filters


if [request.application, request.controller, request.function] != [request.application, "default", "login"]:
    if "nb_cookie" not in request.cookies.keys():
        redirect(URL("default", "login"))
    else:
        newsblur.cookies["newsblur_sessionid"] = request.cookies["nb_cookie"].value

Modified applications/mobileblur/modules/newsblur.py from [a487a766ef] to [df40c3d1a1].

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
        Login as an existing user.
        If a user has no password set, you cannot just send any old password. 
        Required parameters, username and password, must be of string type.
        '''

        url = nb_url + 'api/login'
        results = requests.post(url, data={"username": username, "password": password})
        print "results.cookies =", results.cookies
        print type(results.cookies)
        self.cookies = results.cookies
        results = simplejson.loads(results.content)
        if results["authenticated"] is False:
            raise Exception("The newsblur credentials you provided are invalid")
        return results

    def logout(self, ):







<
<







19
20
21
22
23
24
25


26
27
28
29
30
31
32
        Login as an existing user.
        If a user has no password set, you cannot just send any old password. 
        Required parameters, username and password, must be of string type.
        '''

        url = nb_url + 'api/login'
        results = requests.post(url, data={"username": username, "password": password})


        self.cookies = results.cookies
        results = simplejson.loads(results.content)
        if results["authenticated"] is False:
            raise Exception("The newsblur credentials you provided are invalid")
        return results

    def logout(self, ):

Modified applications/mobileblur/static/css/base.css from [0353986da0] to [c4d6d0ed8b].

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
- always indent the first line and add space below paragraphs
- bullets and numbers style and indent
- form and table padding
- code blocks
- left and right padding to quoted text
- page layout alignment, width and padding (change this for spaces)
- column widths (change this to use left_sidebar and right_sidebar)
- backrgound images and colors (change this for colors)
- web2py specific (.flash, .error)

Notice:
- even if you use a different layout/css you may need classes .flash and .error
- this is all color neutral except for #349C01 (header, links, lines)
- there are two backrgound images: images/background.png and images/header.png

License: This file is released under BSD and MIT

*/

/*     
  credit is left where credit is due.







|





|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
- always indent the first line and add space below paragraphs
- bullets and numbers style and indent
- form and table padding
- code blocks
- left and right padding to quoted text
- page layout alignment, width and padding (change this for spaces)
- column widths (change this to use left_sidebar and right_sidebar)
- background images and colors (change this for colors)
- web2py specific (.flash, .error)

Notice:
- even if you use a different layout/css you may need classes .flash and .error
- this is all color neutral except for #349C01 (header, links, lines)
- there are two background images: images/background.png and images/header.png

License: This file is released under BSD and MIT

*/

/*     
  credit is left where credit is due.
141
142
143
144
145
146
147
148
149
150

151
152
153
154
155
156
157
h1,h2,h3,h4,h5,h6 { font-weight: bold; }

/* always force a scrollbar in non-IE */ 
html { overflow-y: scroll; }
 
/* Accessible focus treatment: people.opera.com/patrickl/experiments/keyboard/test */
a:hover, a:active { outline: none; }

a, a:active, a:visited { color:#607890; }
a:hover { color:#036; }


ul, ol { margin-left: 1.8em; }
ol { list-style-type: decimal; }

/* Remove margins for navigation lists */
nav ul, nav li { margin: 0; } 








|


>







141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
h1,h2,h3,h4,h5,h6 { font-weight: bold; }

/* always force a scrollbar in non-IE */ 
html { overflow-y: scroll; }
 
/* Accessible focus treatment: people.opera.com/patrickl/experiments/keyboard/test */
a:hover, a:active { outline: none; }
/*
a, a:active, a:visited { color:#607890; }
a:hover { color:#036; }
*/

ul, ol { margin-left: 1.8em; }
ol { list-style-type: decimal; }

/* Remove margins for navigation lists */
nav ul, nav li { margin: 0; } 

325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
}

fieldset { border: 1px solid #dedede; padding: 6px; }
legend { font-weight: bold; }

input:focus, textarea:focus { background: #fafafa; }

p {text-indent:30px;}

p, blockquote {    
    margin-bottom: 10px;
}

h1,h2,h3,h4,h5,h6 { line-height: 170%; }
h1 {font-size: 2.0em;}
h2 {font-size: 1.8em;}
h3 {font-size: 1.4em;}
h4 {font-size: 1.2em;}
h5 {font-size: 1.0em;}
h6 {font-size: 0.8em;}

/*********** page layout alignment, width and padding ***********/
/*body {background-color: #000;}*/
#container, #header, #page, #content, #statusbar,
#footer, #wrapper { display:block; line-height: 170%; }
#wrapper {width: 900px;}
#container {
    margin: 0 auto;
    padding: 0;
}
#wrapper {margin: 0 auto;} 
#wrapper {background-color: #fff; padding: 5px;} 
#statusbar { margin: 5px 0px 20px 0px;}
#footer {    
    margin-top: 30px;    
    padding: 5px;    
}
#statusbar, #footer {    
    background: #eaeaea; 
    border-top: 1px #aaa solid;    
}
#logo {
    width: 68px;
    height: 62px;
    background: url(../images/logo.png);
}
#appname {
    color: #cccccc;
}

#right_sidebar { width: 160px; float:right; display: none; }
#left_sidebar { width: 160px; float:left; display: none; }
#content { float: left; /*width: 740px;*//*width: 63%;*/ /*width: 640px; float:left;*/ } /* uncomment this if you are going to use sidebars */
 
.auth_navbar {
   top: 0px;
   float: right;
   padding: 3px 10px 3px 10px; 
}

/*********** web2py specific ***********/
div.flash {
    font-weight: bold;
    display: none;
    position: fixed;    
    padding: 10px;
    top: 40px;







<
<
<
<
<
<








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







326
327
328
329
330
331
332






333
334
335
336
337
338
339
340







































341
342
343
344
345
346
347
}

fieldset { border: 1px solid #dedede; padding: 6px; }
legend { font-weight: bold; }

input:focus, textarea:focus { background: #fafafa; }







h1,h2,h3,h4,h5,h6 { line-height: 170%; }
h1 {font-size: 2.0em;}
h2 {font-size: 1.8em;}
h3 {font-size: 1.4em;}
h4 {font-size: 1.2em;}
h5 {font-size: 1.0em;}
h6 {font-size: 0.8em;}








































/*********** web2py specific ***********/
div.flash {
    font-weight: bold;
    display: none;
    position: fixed;    
    padding: 10px;
    top: 40px;
531
532
533
534
535
536
537





538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556













































































  
  
  /* Uncomment if you don't want iOS and WinMobile to mobile-optimize the text for you
     j.mp/textsizeadjust 
  html { -webkit-text-size-adjust:none; -ms-text-size-adjust:none; } */
}







/* 
 * print styles
 * inlined to avoid required HTTP connection www.phpied.com/delay-loading-your-print-css/ 
 */
@media print {
  * { background: transparent !important; color: #444 !important; text-shadow: none !important; }
  a, a:visited { color: #444 !important; text-decoration: underline; }
  a:after { content: " (" attr(href) ")"; } 
  abbr:after { content: " (" attr(title) ")"; }
  .ir a:after { content: ""; }  /* Don't show links for images */
  pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
  thead { display: table-header-group; } /* css-discuss.incutio.com/wiki/Printing_Tables */ 
  tr, img { page-break-inside: avoid; }
  @page { margin: 0.5cm; }
  p, h2, h3 { orphans: 3; widows: 3; }
  h2, h3{ page-break-after: avoid; }
}





















































































>
>
>
>
>



















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
  
  
  /* Uncomment if you don't want iOS and WinMobile to mobile-optimize the text for you
     j.mp/textsizeadjust 
  html { -webkit-text-size-adjust:none; -ms-text-size-adjust:none; } */
}

@media handheld {
    body {
    }
}


/* 
 * print styles
 * inlined to avoid required HTTP connection www.phpied.com/delay-loading-your-print-css/ 
 */
@media print {
  * { background: transparent !important; color: #444 !important; text-shadow: none !important; }
  a, a:visited { color: #444 !important; text-decoration: underline; }
  a:after { content: " (" attr(href) ")"; } 
  abbr:after { content: " (" attr(title) ")"; }
  .ir a:after { content: ""; }  /* Don't show links for images */
  pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
  thead { display: table-header-group; } /* css-discuss.incutio.com/wiki/Printing_Tables */ 
  tr, img { page-break-inside: avoid; }
  @page { margin: 0.5cm; }
  p, h2, h3 { orphans: 3; widows: 3; }
  h2, h3{ page-break-after: avoid; }
}

body {
/*    background-color: #f2c84b;*/
    color: #493F3E
}

header {
    background-color: #95392E;
    padding: 1%;
    border-bottom: 1px solid #95392E;
    color: white;
}
header > h1 > a {
    text-decoration: none;
    color: white;
    font-weight: bold;
}

#story > header > a {
    color: white;
}

header > a> h2 {
/*    border-top: 1px solid white;*/
    color: white;
}

#story-list {
/*    background-color: #f2c84b;*/
}

#story-list > .story > a, .feed > a {
    text-decoration: none;
    font-weight: bold;
    margin-top: 0;
}
#story-list > .story > p {
    font-size: .75em;
}

#story-list > .story > .read {
    color: #D99B48;
}
#story-list > .story > .unread, .feed > a {
    color: #C57E3C;
}

#story-list > .story, .feed {
    padding: .5%;
    border-top: 1px solid #95392E;
    margin-top: .33%;
}

span.ps, span.nt, span.ng {
    padding: .05em;
    border-radius: 5px;
}
span.ps {
    background-color: #ABAA7A;
}
span.nt {
    background-color: #D99B48;
}
span.ng {
    background-color: red;
}

footer {
    background-color: #95392E;
    padding: 1%;
    border-top: 1px solid #95392E;
    color: white;
}
footer > a {
    text-decoration: none;
    color: white;
    font-weight: bold;
}

Modified applications/mobileblur/views/default/index.html from [1ac89d52bc] to [de8ac0789f].

1
2
3
4

5
6
7
8

9
10
11
12
{{left_sidebar_enabled=right_sidebar_enabled=False}}
{{extend 'layout.html'}}

{{ for feed in feeds.itervalues(): }}

    {{ if threshold == -1 and feed["ng"] > 0: }} <span class='ng'>[ {{= feed["ng"] }} ]</span> {{ pass }}
    {{ if threshold <= 0 and feed["nt"] > 0: }} <span class='nt'>[ {{= feed["nt"] }} ]</span> {{ pass }}
    {{if feed["ps"] > 0: }}<span class='ps'>[ {{= feed["ps"] }} ]</span> {{ pass }}
    <a href="{{= URL(c="feeds", f="view", args=[feed["id"]]) }}">{{= feed["feed_title"] }}</a><br />

{{ pass }}

{{block left_sidebar}}New Left Sidebar Content{{end}}
{{block right_sidebar}}New Right Sidebar Content{{end}}
<



>
|
|
|
|
>

<
<
<

1
2
3
4
5
6
7
8
9
10




{{extend 'layout.html'}}

{{ for feed in feeds.itervalues(): }}
    <div class="feed">
        {{ if threshold == -1 and feed["ng"] > 0: }} <span class='ng'>{{= feed["ng"] }}</span> {{ pass }}
        {{ if threshold <= 0 and feed["nt"] > 0: }} <span class='nt'>{{= feed["nt"] }}</span> {{ pass }}
        {{if feed["ps"] > 0: }}<span class='ps'>{{= feed["ps"] }}</span> {{ pass }}
        <a href="{{= URL(c="feeds", f="view", args=[feed["id"]]) }}">{{= feed["feed_title"] }}</a><br />
    </div>
{{ pass }}



Modified applications/mobileblur/views/feeds/view.html from [3646a45d79] to [6526673ca3].

1
2
3

4
5

6






7






8




9
10
11
12

{{left_sidebar_enabled=right_sidebar_enabled=False}}
{{extend 'layout.html'}}


<h1>{{= feed["feed_title"] }}</h1>
<a href="{{= URL("mark_read", vars=dict(feed=feed["id"])) }}"> Mark feed as read</a>








{{ for story in stories: }}






    <a href="{{= URL(c="stories", f="view", vars=dict(story=story["id"], feed_id=feed["id"])) }}"><h2>{{= story["story_title"] }}</h2></a>




{{ pass }}

{{block left_sidebar}}New Left Sidebar Content{{end}}
{{block right_sidebar}}New Right Sidebar Content{{end}}

<


>
|
|
>

>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
|
|
<
<
>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27


28

{{extend 'layout.html'}}

{{ block header_bonus }}
    <h2>{{= feed["feed_title"] }}</h2>
    <a href="{{= URL("mark_read", args=[feed["id"]]) }}" class="button">Mark feed as read</a>
{{ end }}

<section id="story-list">
{{
import time 
s = time.time()
}}
    {{ 
        for story in stories: 
        if sum([v for k,v in story["intelligence"].iteritems()]) < threshold:
            continue
    }}

        {{ print story["read_status"] }}
        <div class="story">
            <a href="{{= URL(c="stories", f="view", vars=dict(story=story["id"], feed_id=feed["id"])) }}" class="{{= "unread" if story["read_status"] == 0 else "read" }}">
                {{= story["story_title"] }}
            </a>
            <p>{{= story["story_date"] }}</p>
        </div>
    {{ pass }}
{{ print time.time() - s }}


</section>

Modified applications/mobileblur/views/layout.html from [78b7d8a5ef] to [2dc8430c3d].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="{{=T.accepted_language or 'en'}}" class="no-js"><!-- no-js need it for modernzr -->
  <head>
    
    <meta charset="utf-8" />	  	
    <!-- www.phpied.com/conditional-comments-block-downloads/ -->
    <!--[if IE]><![endif]-->    
    <!-- Always force latest IE rendering engine 
	 (even in intranet) & Chrome Frame 
	 Remove this if you use the .htaccess -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    
    <title>{{=response.title or request.application}}</title>
    
    <!-- http://dev.w3.org/html5/markup/meta.name.html -->
    <meta name="application-name" content="{{=request.application}}" />	
    
    <!-- Speaking of Google, don't forget to set your site up: 
	 http://google.com/webmasters -->
    <meta name="google-site-verification" content="" />
    
    <!--  Mobile Viewport Fix
	  j.mp/mobileviewport & davidbcalhoun.com/2010/viewport-metatag 
	  device-width: Occupy full width of the screen in its current orientation
	  initial-scale = 1.0 retains dimensions instead of zooming out if page height > device height
	  maximum-scale = 1.0 retains dimensions instead of zooming in if page width < device width
      -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
    
    <!-- Place favicon.ico and apple-touch-icon.png in the root of your domain and delete these references -->
    <link rel="shortcut icon" href="{{=URL('static','favicon.ico')}}" type="image/x-icon">
    <link rel="apple-touch-icon" href="{{=URL('static','favicon.png')}}">

    <!-- For the less-enabled mobile browsers like Opera Mini -->
    <link rel="stylesheet" media="handheld" href="{{=URL('static','css/handheld.css')}}">












|














|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="{{=T.accepted_language or 'en'}}" class="no-js"><!-- no-js need it for modernzr -->
  <head>
    
    <meta charset="utf-8" />	  	
    <!-- www.phpied.com/conditional-comments-block-downloads/ -->
    <!--[if IE]><![endif]-->    
    <!-- Always force latest IE rendering engine 
	 (even in intranet) & Chrome Frame 
	 Remove this if you use the .htaccess -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    
    <title>{{ block title }}{{= " - ".join([response.title, request.application]) }}{{ end }}</title>
    
    <!-- http://dev.w3.org/html5/markup/meta.name.html -->
    <meta name="application-name" content="{{=request.application}}" />	
    
    <!-- Speaking of Google, don't forget to set your site up: 
	 http://google.com/webmasters -->
    <meta name="google-site-verification" content="" />
    
    <!--  Mobile Viewport Fix
	  j.mp/mobileviewport & davidbcalhoun.com/2010/viewport-metatag 
	  device-width: Occupy full width of the screen in its current orientation
	  initial-scale = 1.0 retains dimensions instead of zooming out if page height > device height
	  maximum-scale = 1.0 retains dimensions instead of zooming in if page width < device width
      -->
    <meta name="viewport" content="width=320" />
    
    <!-- Place favicon.ico and apple-touch-icon.png in the root of your domain and delete these references -->
    <link rel="shortcut icon" href="{{=URL('static','favicon.ico')}}" type="image/x-icon">
    <link rel="apple-touch-icon" href="{{=URL('static','favicon.png')}}">

    <!-- For the less-enabled mobile browsers like Opera Mini -->
    <link rel="stylesheet" media="handheld" href="{{=URL('static','css/handheld.css')}}">
55
56
57
58
59
60
61


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
    else: width_content='100%'
    if left_sidebar_enabled: left_sidebar_style = 'style="display: block;"'
    else: left_sidebar_style = 'style="display: none;"'
    if right_sidebar_enabled: right_sidebar_style = 'style="display: block;"'
    else: right_sidebar_style = 'style="display: none;"'
    style_content = 'style="width: %s"' % width_content
    }}


  </head>
  
  <!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->	
  <!--[if lt IE 7 ]> <body class="ie6"> <![endif]-->
  <!--[if IE 7 ]>    <body class="ie7"> <![endif]-->
  <!--[if IE 8 ]>    <body class="ie8"> <![endif]-->
  <!--[if IE 9 ]>    <body class="ie9"> <![endif]-->
  <!--[if (gt IE 9)|!(IE)]><!--> <body> <!--<![endif]-->
    
    <div class="flash">{{=response.flash or ''}}</div> <!-- notification div -->
    
    <div id="container">	      		      	
      
      <div id="wrapper">		
	
	<div id="header"> <!-- header and login nav -->
	  {{block header}} <!-- this is default header -->
	  {{try:}}{{=auth.navbar(action=URL('default','user'))}}{{except:pass}}		          
	  <h1><span id="appname">{{=request.application.capitalize()}}</span>App</h1>
	  <div style="clear: both;"></div><!-- Clear the divs -->
	  {{end}}				  					  
	</div><!-- header  -->
	
	<div id="statusbar"><!-- statusbar is menu zone -->
	  {{block statusbar}} <!-- this is default statusbar -->
	  {{#------ superfish menu ------}}
	  {{=MENU(response.menu,_class='sf-menu')}}
	  <script type="text/javascript">
	    jQuery(document).ready(function(){
	    jQuery('ul.sf-menu').superfish();});
	  </script>
	  <div style="clear: both;"></div><!-- Clear the divs -->	
	  {{end}}				
	</div><!-- statusbar -->
	
	<div id="page"> <!-- Here my central body -->	  

	  {{if left_sidebar_enabled:}}
          <div id="left_sidebar" {{=XML(left_sidebar_style)}} >
            <div style="padding: 4px;">
	      {{block left_sidebar}}Content Left Sidebar{{end}}		  
            </div>
          </div><!-- left_sidebar -->
	  {{pass}}

	  <!-- content -->
	  <div id="content" {{=XML(style_content)}} >
	    {{include}}	
	  </div>
	  <!-- content -->

	  {{if right_sidebar_enabled:}}
          <div id="right_sidebar" {{=XML(right_sidebar_style)}} >
            <div style="padding: 4px;">
              {{block right_sidebar}}Content Right Sidebar{{end}}
            </div>
	  </div><!-- right_sidebar -->
          {{pass}}


	  <div style="clear: both;"></div><!-- Clear the divs -->
	  
	</div><!-- page -->							
	
	<div id="footer">
	  {{block footer}} <!-- this is default footer -->
	  <a href="http://www.web2py.com/" style="float: left; padding-right: 6px;">
	    <img src="{{=URL('static','images/poweredby.png')}}"/>
	  </a>
	  {{=T('Copyright')}} &#169; 2010				
	  <div style="clear: both;"></div><!-- Clear the divs -->
	  {{end}}

	</div><!-- footer -->			
      </div><!-- wrapper -->
    </div><!-- container -->		
    
    <!--[if lt IE 7 ]>
	<script src="{{=URL('static','js/dd_belatedpng.js')}}"></script>
	<script> DD_belatedPNG.fix('img, .png_bg'); //fix any <img> or .png_bg background-images </script>
	<![endif]-->
    
    <!-- asynchronous google analytics: mathiasbynens.be/notes/async-analytics-snippet 
	 change the UA-XXXXX-X to be your site's ID -->
    <!--   
	   <script>
	     var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_trackPageview']];
	     (function(d, t) {
	     var g = d.createElement(t),
	     s = d.getElementsByTagName(t)[0];
	     g.async = true;
	     g.src = '//www.google-analytics.com/ga.js';
	     s.parentNode.insertBefore(g, s);
	     })(document, 'script');
	   </script>
	   -->    
  </body>
</html>







>
>











<
|
<
<
<

<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
|
<
|
<
|
<
<
<
<
<
<
<
|
<
|
|
<
<
|
<
<
<
<
<
<
<

<
<
<
<
<
|
<
<
<
<
<
<
<
|
|
<
<








<

|








<


55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

75



76





77









78

79

80







81

82
83


84







85





86







87
88


89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104
105
106

107
108
    else: width_content='100%'
    if left_sidebar_enabled: left_sidebar_style = 'style="display: block;"'
    else: left_sidebar_style = 'style="display: none;"'
    if right_sidebar_enabled: right_sidebar_style = 'style="display: block;"'
    else: right_sidebar_style = 'style="display: none;"'
    style_content = 'style="width: %s"' % width_content
    }}
<!--    <link rel="stylesheet" href="http://twitter.github.com/bootstrap/1.4.0/bootstrap.min.css">-->
    <link rel="stylesheet" href="{{= URL("static", "css/1140.css") }}">
  </head>
  
  <!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->	
  <!--[if lt IE 7 ]> <body class="ie6"> <![endif]-->
  <!--[if IE 7 ]>    <body class="ie7"> <![endif]-->
  <!--[if IE 8 ]>    <body class="ie8"> <![endif]-->
  <!--[if IE 9 ]>    <body class="ie9"> <![endif]-->
  <!--[if (gt IE 9)|!(IE)]><!--> <body> <!--<![endif]-->
    
    <div class="flash">{{=response.flash or ''}}</div> <!-- notification div -->
    

	<header>



	  {{block header}} <!-- this is default header -->





          <h1><a href="{{= URL("mobileblur", "default", "index") }}">MobileBlur</a></h1>









	  {{end}}

      {{ block header_bonus }}{{end}}

	</header>







	

    <section id="content" class-"container" {{=XML(style_content)}} >
        {{include}}	


    </section>













    <footer>







        <a href="{{= URL("default", "logout") }}">Log out</a>
    </footer>


    
    <!--[if lt IE 7 ]>
	<script src="{{=URL('static','js/dd_belatedpng.js')}}"></script>
	<script> DD_belatedPNG.fix('img, .png_bg'); //fix any <img> or .png_bg background-images </script>
	<![endif]-->
    
    <!-- asynchronous google analytics: mathiasbynens.be/notes/async-analytics-snippet 
	 change the UA-XXXXX-X to be your site's ID -->

	   <script>
	     var _gaq = [['_setAccount', 'UA-27222314-1'], ['_trackPageview']];
	     (function(d, t) {
	     var g = d.createElement(t),
	     s = d.getElementsByTagName(t)[0];
	     g.async = true;
	     g.src = '//www.google-analytics.com/ga.js';
	     s.parentNode.insertBefore(g, s);
	     })(document, 'script');
	   </script>

  </body>
</html>

Modified applications/mobileblur/views/stories/view.html from [859afcf521] to [bcfec0acca].

1
2
3

4
5






6
7
8
9
{{left_sidebar_enabled=right_sidebar_enabled=False}}
{{extend 'layout.html'}}


<a href="{{= story["story_permalink"] }}"><h1>{{= story["story_title"] }}</h1></a>







{{= XML(story["story_content"]) }}

{{block left_sidebar}}New Left Sidebar Content{{end}}
{{block right_sidebar}}New Right Sidebar Content{{end}}
<


>
|
|
>
>
>
>
>
>
|
|
<
<

1
2
3
4
5
6
7
8
9
10
11
12
13



{{extend 'layout.html'}}

{{ block header_bonus }}
    <a href="{{= story["story_permalink"] }}">
        <h2>{{= story["story_title"] }}</h2>
    </a>
    <a href="{{= URL("mark_read", vars=dict(story_id=story["id"], feed_id=feed_id)) }}" class="button">
        Mark story as read
    </a>
{{ end }}
<section id="story">
    {{= XML(story["story_content"]) }}
</section>


Added routes.py version [b42c3be42e].













































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#!/usr/bin/python
# -*- coding: utf-8 -*-

# default_application, default_controller, default_function
# are used when the respective element is missing from the
# (possibly rewritten) incoming URL
#
default_application = 'mobileblur'    # ordinarily set in base routes.py
default_controller = 'default'  # ordinarily set in app-specific routes.py
default_function = 'index'      # ordinarily set in app-specific routes.py

# routes_app is a tuple of tuples.  The first item in each is a regexp that will
# be used to match the incoming request URL. The second item in the tuple is
# an applicationname.  This mechanism allows you to specify the use of an
# app-specific routes.py. This entry is meaningful only in the base routes.py.
#
# Example: support welcome, admin, app and myapp, with myapp the default:


routes_app = ((r'/(?P<app>welcome|admin|app)\b.*', r'\g<app>'),
              (r'(.*)', r'myapp'),
              (r'/?(.*)', r'myapp'))

# routes_in is a tuple of tuples.  The first item in each is a regexp that will
# be used to match the incoming request URL. The second item in the tuple is
# what it will be replaced with.  This mechanism allows you to redirect incoming
# routes to different web2py locations
#
# Example: If you wish for your entire website to use init's static directory:
#
#   routes_in=( (r'/static/(?P<file>[\w./-]+)', r'/init/static/\g<file>') )
#

routes_in = ((r'.*:/favicon.ico', r'/examples/static/favicon.ico'),
             (r'.*:/robots.txt', r'/examples/static/robots.txt'),
             ((r'.*http://otherdomain.com.* (?P<any>.*)', r'/app/ctr\g<any>')))

# routes_out, like routes_in translates URL paths created with the web2py URL()
# function in the same manner that route_in translates inbound URL paths.
#

routes_out = ((r'.*http://otherdomain.com.* /app/ctr(?P<any>.*)', r'\g<any>'),
              (r'/app(?P<any>.*)', r'\g<any>'))

# Error-handling redirects all HTTP errors (status codes >= 400) to a specified
# path.  If you wish to use error-handling redirects, uncomment the tuple
# below.  You can customize responses by adding a tuple entry with the first
# value in 'appName/HTTPstatusCode' format. ( Only HTTP codes >= 400 are
# routed. ) and the value as a path to redirect the user to.  You may also use
# '*' as a wildcard.
#
# The error handling page is also passed the error code and ticket as
# variables.  Traceback information will be stored in the ticket.
#
# routes_onerror = [
#     (r'init/400', r'/init/default/login')
#    ,(r'init/*', r'/init/static/fail.html')
#    ,(r'*/404', r'/init/static/cantfind.html')
#    ,(r'*/*', r'/init/error/index')
# ]

# specify action in charge of error handling
#
# error_handler = dict(application='error',
#                      controller='default',
#                      function='index')

# In the event that the error-handling page itself returns an error, web2py will
# fall back to its old static responses.  You can customize them here.
# ErrorMessageTicket takes a string format dictionary containing (only) the
# "ticket" key.

# error_message = '<html><body><h1>%s</h1></body></html>'
# error_message_ticket = '<html><body><h1>Internal error</h1>Ticket issued: <a href="/admin/default/ticket/%(ticket)s" target="_blank">%(ticket)s</a></body></html>'

# specify a list of apps that bypass args-checking and use request.raw_args
#
#routes_apps_raw=['myapp']
#routes_apps_raw=['myapp', 'myotherapp']

def __routes_doctest():
    '''
    Dummy function for doctesting routes.py.

    Use filter_url() to test incoming or outgoing routes;
    filter_err() for error redirection.

    filter_url() accepts overrides for method and remote host:
        filter_url(url, method='get', remote='0.0.0.0', out=False)

    filter_err() accepts overrides for application and ticket:
        filter_err(status, application='app', ticket='tkt')

    >>> import os
    >>> import gluon.main
    >>> from gluon.rewrite import regex_select, load, filter_url, regex_filter_out, filter_err, compile_regex
    >>> regex_select()
    >>> load(routes=os.path.basename(__file__))

    >>> os.path.relpath(filter_url('http://domain.com/favicon.ico'))
    'applications/examples/static/favicon.ico'
    >>> os.path.relpath(filter_url('http://domain.com/robots.txt'))
    'applications/examples/static/robots.txt'
    >>> filter_url('http://domain.com')
    '/init/default/index'
    >>> filter_url('http://domain.com/')
    '/init/default/index'
    >>> filter_url('http://domain.com/init/default/fcn')
    '/init/default/fcn'
    >>> filter_url('http://domain.com/init/default/fcn/')
    '/init/default/fcn'
    >>> filter_url('http://domain.com/app/ctr/fcn')
    '/app/ctr/fcn'
    >>> filter_url('http://domain.com/app/ctr/fcn/arg1')
    "/app/ctr/fcn ['arg1']"
    >>> filter_url('http://domain.com/app/ctr/fcn/arg1/')
    "/app/ctr/fcn ['arg1']"
    >>> filter_url('http://domain.com/app/ctr/fcn/arg1//')
    "/app/ctr/fcn ['arg1', '']"
    >>> filter_url('http://domain.com/app/ctr/fcn//arg1')
    "/app/ctr/fcn ['', 'arg1']"
    >>> filter_url('HTTP://DOMAIN.COM/app/ctr/fcn')
    '/app/ctr/fcn'
    >>> filter_url('http://domain.com/app/ctr/fcn?query')
    '/app/ctr/fcn ?query'
    >>> filter_url('http://otherdomain.com/fcn')
    '/app/ctr/fcn'
    >>> regex_filter_out('/app/ctr/fcn')
    '/ctr/fcn'
    >>> filter_url('https://otherdomain.com/app/ctr/fcn', out=True)
    '/ctr/fcn'
    >>> filter_url('https://otherdomain.com/app/ctr/fcn/arg1//', out=True)
    '/ctr/fcn/arg1//'
    >>> filter_url('http://otherdomain.com/app/ctr/fcn', out=True)
    '/fcn'
    >>> filter_url('http://otherdomain.com/app/ctr/fcn?query', out=True)
    '/fcn?query'
    >>> filter_url('http://otherdomain.com/app/ctr/fcn#anchor', out=True)
    '/fcn#anchor'
    >>> filter_err(200)
    200
    >>> filter_err(399)
    399
    >>> filter_err(400)
    400
    >>> filter_url('http://domain.com/welcome', app=True)
    'welcome'
    >>> filter_url('http://domain.com/', app=True)
    'myapp'
    >>> filter_url('http://domain.com', app=True)
    'myapp'
    >>> compile_regex('.*http://otherdomain.com.* (?P<any>.*)', '/app/ctr\g<any>')[0].pattern
    '^.*http://otherdomain.com.* (?P<any>.*)$'
    >>> compile_regex('.*http://otherdomain.com.* (?P<any>.*)', '/app/ctr\g<any>')[1]
    '/app/ctr\\\\g<any>'
    >>> compile_regex('/$c/$f', '/init/$c/$f')[0].pattern
    '^.*?:https?://[^:/]+:[a-z]+ /(?P<c>\\\\w+)/(?P<f>\\\\w+)$'
    >>> compile_regex('/$c/$f', '/init/$c/$f')[1]
    '/init/\\\\g<c>/\\\\g<f>'
    '''
    pass

if __name__ == '__main__':
    import doctest
    doctest.testmod()