Commit 21cc578fca7a843b4e7ca548b198c192f4bf529c

  • avatar
  • arvind
  • Mon Jul 07 17:58:44 IST 2014
Integrating annotator with the application.
/annotate is the API endpoint for getting a web page with annotator
loaded.
  
66import config
77import requests
88import json
9import urllib2
9import StringIO
1010import imghdr
1111
1212app = flask.Flask(__name__)
5353@app.route('/annotate', methods=['GET'])
5454def annotate():
5555 print flask.request.args['where']
56 img = urllib2.urlopen(flask.request.args['where']).read()
57 if imghdr.what('ignore', img) is None:
58 root = lxml.html.parse(flask.request.args['where']).getroot()
56 # img = urllib2.urlopen(flask.request.args['where']).read()
57 request = requests.get(flask.request.args['where'])
58 content = request.text
59 if imghdr.what('ignore', content) is None:
60 root = lxml.html.parse(StringIO.StringIO(content)).getroot()
5961 root.make_links_absolute(flask.request.args['where'],
6062 resolve_base_href=True)
6163
8080 "css/annotator.min.css"))
8181 annotatorCSS.set("rel", "stylesheet")
8282 annotatorCSS.set("type", "text/css")
83
84 swtmakerCSS = root.makeelement('link')
85 root.body.append(swtmakerCSS)
86 swtmakerCSS.set("href", flask.url_for('static',
87 filename=
88 "css/swtmaker.css"))
89 swtmakerCSS.set("rel", "stylesheet")
90 swtmakerCSS.set("type", "text/css")
91
92 bootstrapCSS = root.makeelement('link')
93 root.body.append(bootstrapCSS)
94 bootstrapCSS.set("href", flask.url_for('static',
95 filename=
96 "css/bootstrap.min.css"))
97 bootstrapCSS.set("rel", "stylesheet")
98 bootstrapCSS.set("type", "text/css")
99
100 underscoreJS = root.makeelement('script')
101 root.body.append(underscoreJS)
102 underscoreJS.set("src", flask.url_for('static',
103 filename="js/lib/" +
104 "underscore-1.5.2.min.js"))
105 underscoreJS.set("type", "text/javascript")
106
107 backboneJS = root.makeelement('script')
108 root.body.append(backboneJS)
109 backboneJS.set("src", flask.url_for('static',
110 filename=
111 "js/lib/backbone-1.0.0.min.js"))
112 backboneJS.set("type", "text/javascript")
113
114 if 'auth_tok' in session:
115 auth_tok = session['auth_tok']
116 else:
117 auth_tok = {'access_token': '', 'refresh_token': ''}
118
119 configScript = root.makeelement('script')
120 root.body.append(configScript)
121 configScript.text = """window.swtr = window.swtr || {};
122 swtr.swtstoreURL = {}
123 swtr.endpoints = {}
124 'get': '/api/sweets/q',
125 'post': '/api/sweets',
126 'auth': '/oauth/authorize',
127 'login': '/auth/login',
128 'logout': '/auth/logout'
129 {};
130
131 swtr.access_token = '{}';
132 swtr.refresh_token = '{}';
133 swtr.app_id = '{}';swtr.app_secret = '{}';
134 swtr.oauth_redirect_uri = '{}';""".format(
135 '{}', 'function() {}return "{}"{}'.format('{',
136 config.swtstoreURL, '};'),
137 '{', '}', auth_tok['access_token'], auth_tok['refresh_token'],
138 config.app_id, config.app_secret,
139 config.redirect_uri)
140 configScript.set("type", "text/javascript")
141
142 # swtmakerScript = root.makeelement('script')
143 # root.body.append(swtmakerScript)
144 # swtmakerScript.set("src", flask.url_for('static',
145 # filename="js/swtmaker.js"))
146 # swtmakerScript.set("type", "text/javascript")
147
148 oAuthScript = root.makeelement('script')
149 root.body.append(oAuthScript)
150 oAuthScript.set("src", flask.url_for('static',
151 filename="js/oauth.js"))
152 oAuthScript.set("type", "text/javascript")
83153
84154 appScript = root.makeelement('script')
85155 root.body.append(appScript)
  
1(function() {
2 $(document).ready(function() {
3 var annotator = new Annotator(document.body);
4 annotator.addPlugin("Tags");
5 annotator.addPlugin("Filter");
1window.swtr = window.swtr || {};
2(function(swtr) {
3
4 swtr.handleOAuth = function() {
5 if(swtr.access_token) {
6 $('#signinview').html('Signing you in..');
7 $.ajax({
8 url: swtr.swtstoreURL()+'/api/users/me?access_token='+
9 swtr.access_token,
10 success: function(data) {
11 $('#signinview').html('Signed in as ' + data.username);
12 swtr.who = data.username;
13 $("#sign-in").hide();
14 },
15 error: function() {
16 // $('#signinview').html('Error signing in! Please try again');
17 $("#sign-in").show();
18 }
19 });
20 } else {
21 $('#signinview').html('Please sign in.');
22 }
23 };
24
25 var TxtAnnoSwt = Backbone.Model.extend({
26 defaults: {
27 'who': '',
28 'what': 'txt-anno',
29 'where': '',
30 'how': {}
31 },
32 initialize: function(options) {
33 this.set(options);
34 }
635 });
7})();
36
37 var TxtAnnoSwts = Backbone.Collection.extend({
38 model: TxtAnnoSwt,
39 url: function() {
40 return swtr.swtstoreURL() + '/sweets';
41 },
42 // get all sweets/annotations of type #img-anno for a particular URI
43 // (where)
44 // @options is a javascript object,
45 // @options.where : URI of the resource for which swts to be fetched
46 // @options.who: optional username to filter sweets
47 // @options.success: success callback to call
48 // @options.error: error callback to call
49 getAll: function(options) {
50 // error checking
51 if(!options.where) {
52 throw Error('"where" option must be passed to get sweets of a URI');
53 return false;
54 }
55 /*if(!swtr.access_token) {
56 throw new Error('Access Token required to get query that API');
57 }*/
58 // setting up params
59 var where = options.where,
60 who = options.who || null;
61 url = swtr.swtstoreURL() + swtr.endpoints.get + '?where=' +
62 encodeURIComponent(where) + '&access_token=' + swtr.access_token;
63 if(who) {
64 url += '&who=' + who;
65 }
66 // get them!
67 this.sync('read', this, {
68 url: url,
69 success: function() {
70 if(typeof options.success === 'function') {
71 options.success.apply(this, arguments);
72 }
73 },
74 error: function() {
75 if(typeof options.error === 'function') {
76 options.error.apply(this, arguments);
77 }
78 }
79 });
80 },
81 // post newly created sweets to a sweet store
82 // @options is a javascript object,
83 // @options.where : URI of the resource for which swts to be fetched
84 // @options.who: optional username to filter sweets
85 // @options.success: success callback to call
86 // @options.error: error callback to call,
87 post: function(options) {
88 var new_sweets = this.getNew();
89 var dummy_collection = new Backbone.Collection(new_sweets);
90
91 if(!swtr.access_token) {
92 throw new Error('Access Token is required to sweet');
93 return;
94 }
95
96 var url = swtr.swtstoreURL() + swtr.endpoints.post +
97 '?access_token=' + swtr.access_token;
98
99 this.sync('create', dummy_collection, {
100 url: url,
101 success: function() {
102 if(typeof options.success === 'function') {
103 options.success.apply(this, arguments);
104 }
105 },
106 error: function() {
107 if(typeof options.error === 'function') {
108 options.error.apply(this, arguments);
109 }
110 }
111 });
112 },
113 // return newly created models from the collection
114 getNew: function() {
115 var new_models = [];
116 this.each(function(model) {
117 if(model.isNew()) {
118 new_models.push(model);
119 }
120 });
121 return new_models;
122 },
123 // update part of the collection after a save on the server
124 update: function() {
125 }
126 });
127
128 var TxtAnnoView = Backbone.View.extend({
129 initialize: function() {
130 this.annotator = new Annotator(document.body);
131 swtr.anno = this.annotator;
132 this.annotator.addPlugin("Tags");
133 this.listenTo(this.collection, "add", this.loadAnno);
134 this.annotator.subscribe("annotationCreated", this.storeAnno);
135 },
136 storeAnno: function(annotation) {
137 var pageURL = window.location.search.split("=")[1];
138 if(!(swtr.who)) {
139 swtr.who = "Guest";
140 }
141 swtr.TxtAnnoSwts.add(new TxtAnnoSwt({how: annotation,
142 where: pageURL,
143 who: swtr.who}));
144 if($("#show-sweets").attr('disabled')) {
145 $("#show-sweets").removeAttr('disabled');
146 }
147 },
148 loadAnno: function(annotation) {
149 if(!(annotation.isNew())) {
150 swtr.anno.createAnnotation(annotation.get('how'));
151 swtr.anno.setupAnnotation(annotation.get('how'));
152 }
153 }
154 });
155
156 var AppView = Backbone.View.extend({
157 el: document.body,
158 events: {
159 "click #show-sweets": 'showSweets',
160 "click #sweet-cancel": 'cancelSweet',
161 "click #post-sweet": 'postSweet',
162 "click #sign-in": 'signIn'
163 },
164 oauth: new Oauth({
165 app_id: swtr.app_id,
166 app_secret: swtr.app_secret,
167 endpoint: swtr.swtstoreURL() + swtr.endpoints.auth,
168 redirect_uri: swtr.oauth_redirect_uri,
169 scopes: 'email,sweet'
170 }),
171 sweetTemplate: '<div id="sweet-list-wrapper">'+
172 '<h4>These are your sweet annotations!</h4>'+
173 '<ul id="sweet-list"></ul>'+
174 '<div class="btn-grp">'+
175 '<button class="btn btn-default" id="sweet-cancel">Cancel</button>'+
176 '<button class="btn btn-primary" id="post-sweet">Sweet</button>'+
177 '</div>'+
178 '</div>'+
179 '</div>',
180 initialize: function() {
181 swtr.TxtAnnoSwts = new TxtAnnoSwts();
182 var txtAnnoView = new TxtAnnoView({collection: swtr.TxtAnnoSwts});
183 swtr.TxtAnnoSwts.getAll({where: window.location.search.split("=")[1],
184 success: function(data) {
185 swtr.TxtAnnoSwts.add(data);
186 }});
187 swtr.handleOAuth();
188 $(this.el).append(this.sweetTemplate);
189 this.loadOverlayBar();
190 },
191 loadOverlayBar: function() {
192 var template = "<div id='overlayBar' class='navbar' style='background:grey;position:fixed; top:0px; left:0px;width:100%;'><div class='navbar-inner'><div class='container-fluid'>"+
193 "<a href='/' >Try a different website.</a>"+
194 "<button id='show-sweets' disabled='enabled' class='btn btn-default'>Sweets"+
195 "</button><button id='sign-in' class='btn btn-sm btn-primary'>Sign In</button><span id='signinview'></span></div></div></div>";
196 $(document.body).append(template);
197 },
198 signIn: function(e) {
199 this.oauth.authorize();
200 swtr.handleOAuth();
201 },
202 showSweets: function(e) {
203 $("#sweet-list-wrapper").show();
204 swtr.TxtAnnoSwts.each(function(model){
205 var templateStr ='<li class="sweet">'+
206 '<a href="#">@<%= who %></a> <strong>#<%= what %></strong> '+
207 '<a href="<%= where %>"><%= where.substr(0, 30) + "..." %></a> '+
208 '<p><%= how %></p>'+
209 '</li>';
210 var template = _.template(templateStr);
211 if(model.isNew()) {
212 $("#sweet-list").append(template({
213 'who': swtr.who,
214 'what': 'txt-anno',
215 'where': window.location.search.split("=")[1],
216 'how': JSON.stringify(model.get('how'))
217 }));
218 }
219 }, this);
220 $("#sweet-list-wrapper").focus();
221
222 },
223 cancelSweet: function(e) {
224 $("#sweet-list-wrapper").hide();
225 $("#sweet-list").html('');
226 },
227 postSweet: function(e) {
228 swtr.TxtAnnoSwts.post({success: function(data) {
229 alert("Your SWeets are posted!!");
230 },
231 error: function(data) {
232 alert("Failed to post your SWeets, please try again.");
233 }
234 });
235 }
236 });
237 new AppView;
238
239})(swtr);