bower.json: Mention bookmarklet and server in the description
[nmhive.git] / nmbug.js
1 var nmbug_server = 'http://localhost:5000';
2
3 nmbug = {
4         show: function (message_id) {
5                 var _this = this;
6                 this._get_available_tags(function (available_tags) {
7                         _this._get_tags(
8                                 message_id,
9                                 _this._edit_tags.bind(_this, available_tags, message_id));
10                 });
11         },
12         _get_available_tags: function (callback) {
13                 var url = [
14                         nmbug_server,
15                         'tags',
16                         ].join('/');
17                 console.log('nmbug: get available tags from ' + url);
18                 var request = new XMLHttpRequest();
19                 request.onload = function () {
20                         if (this.status == 200) {
21                                 var available_tags = JSON.parse(this.response);
22                                 console.log('nmbug: got available tags', available_tags);
23                                 callback(available_tags);
24                         } else {
25                                 throw 'Error fetching ' + url + ' (status ' + this.status + ')';
26                         }
27                 };
28                 request.open('get', url, true);
29                 request.send();
30         },
31         _get_tags: function (message_id, callback) {
32                 var url = [
33                         nmbug_server,
34                         'mid',
35                         encodeURIComponent(message_id),
36                         ].join('/');
37                 console.log('nmbug: get tags from ' + url);
38                 var request = new XMLHttpRequest();
39                 request.onload = function () {
40                         if (this.status == 200) {
41                                 var tags = JSON.parse(this.response);
42                                 console.log('nmbug: got tags', tags);
43                                 callback(tags);
44                         } else {
45                                 throw 'Error fetching ' + url + ' (status ' + this.status + ')';
46                         }
47                 };
48                 request.open('get', url, true);
49                 request.send();
50         },
51         _edit_tags: function (available_tags, message_id, tags) {
52                 if (document.createElement('dialog').show) {
53                         this._x_edit_tags(available_tags, message_id, tags);
54                 } else {
55                         var _this = this;
56                         var dialog_polyfill_loaded = 0;
57
58                         function onload () {
59                                 dialog_polyfill_loaded++;
60                                 if (dialog_polyfill_loaded == 2) {
61                                         _this._x_edit_tags(available_tags, message_id, tags);
62                                 }
63                         }
64
65                         var script = document.createElement('script');
66                         script.type = 'text/javascript';
67                         script.src = nmbug_server + '/static/dialog-polyfill/dialog-polyfill.js';
68                         script.onload = onload;
69                         document.head.appendChild(script);
70
71                         var link = document.createElement('link');
72                         link.rel = 'stylesheet';
73                         link.type = 'text/css';
74                         link.href = nmbug_server + '/static/dialog-polyfill/dialog-polyfill.css';
75                         link.onload = onload;
76                         document.head.appendChild(link);
77                 }
78         },
79         _x_edit_tags: function (available_tags, message_id, tags) {
80                 var dialog = document.createElement('dialog');
81                 if (!document.createElement('dialog').show) {
82                         dialogPolyfill.registerDialog(dialog);
83                 }
84
85                 dialog.style.border = '1px solid rgba(0, 0, 0, 0.3)';
86                 dialog.style.borderRadius = '6px';
87                 dialog.style.boxShadow = '0 3px 7px rgba(0, 0, 0, 0.3)';
88
89                 var content = document.createElement('p');
90                 content.innerHTML = 'Edit tags for ' + message_id;
91                 dialog.appendChild(content);
92
93                 var ul = document.createElement('ul');
94                 dialog.appendChild(ul);
95                 for (var i = 0; i < available_tags.length; i++) {
96                         var li = document.createElement('li');
97                         li.innerHTML = available_tags[i];
98                         li.style.cursor = 'pointer';
99                         if (tags.indexOf(available_tags[i]) >= 0) {
100                                 li.style.backgroundColor = 'lime';
101                         }
102                         li.onclick = this._toggle_tag.bind(
103                                 this, message_id, available_tags[i], li);
104                         ul.appendChild(li);
105                 }
106                 var close = document.createElement('button');
107                 close.innerHTML = 'Close';
108                 close.onclick = function () {
109                         dialog.close();
110                 };
111                 dialog.appendChild(close);
112
113                 document.body.appendChild(dialog);
114
115                 dialog.show();
116         },
117         _toggle_tag: function (message_id, tag, li) {
118                 var prefix;
119                 if (li.style.backgroundColor == 'lime') {
120                         prefix = '-';  /* unset */
121                         li.style.backgroundColor = null;
122                 } else {
123                         prefix = '+';  /* set */
124                         li.style.backgroundColor = 'lime';
125                 }
126                 var url = [
127                         nmbug_server,
128                         'mid',
129                         encodeURIComponent(message_id),
130                         ].join('/');
131                 console.log('nmbug: alter tags via ' + url);
132                 var request = new XMLHttpRequest();
133                 request.onload = function () {
134                         if (this.status == 200) {
135                                 var tags = JSON.parse(this.response);
136                                 console.log('nmbug: got tags', tags);
137                         } else {
138                                 throw 'Error posting to ' + url + ' (status ' + this.status + ')';
139                         }
140                 };
141                 request.open('post', url, true);
142                 request.setRequestHeader(
143                         'Content-Type', 'application/json; charset=UTF-8');
144                 request.send(JSON.stringify([prefix + tag]));
145         },
146 };
147
148 var _gmane_handler = {
149         regexp: /gmane[.]org/,
150         handle: function (callback) {
151                 var article = this._get_article();
152                 this._get_message_id(article, callback);
153         },
154         _article_from_url: function (url) {
155                 var regexp = new RegExp('http://article.gmane.org/([^/]+)/([0-9]+)');
156                 var match = regexp.exec(url);
157                 console.log('nmbug: get article from ' + url, match);
158                 if (match) {
159                         return {'group': match[1], 'id': parseInt(match[2])};
160                 }
161         },
162         _get_article: function () {
163                 var article = this._article_from_url(document.URL);
164                 var i = 0;
165                 for (var i = 0; !article && i < window.frames.length; i++) {
166                         article = this._article_from_url(window.frames[i].document.URL);
167                 }
168                 if (!article) {
169                         throw "Cannot extract an article from Gmane's " + document.URL;
170                 }
171                 return article;
172         },
173         _get_message_id: function (article, callback) {
174                 var url = [
175                         nmbug_server,
176                         'gmane',
177                         article.group,
178                         article.id,
179                 ].join('/');
180                 console.log('nmbug: get Message-ID from ' + url);
181                 var request = new XMLHttpRequest();
182                 request.onload = function () {
183                         var message_id = this.responseText;
184                         callback(message_id);
185                 };
186                 request.open('get', url, true);
187                 request.send();
188         },
189 };
190
191 var handlers = [
192         _gmane_handler,
193 ];
194
195 function _check_handler(handler) {
196         var match = handler.regexp.test(document.URL);
197         console.log('nmbug: testing', handler, match);
198         if (match) {
199                 console.log('nmbug: matched', handler);
200                 handler.handle(nmbug.show.bind(nmbug));
201         }
202         return match;  /* break after the first match */
203 }
204
205 function run() {
206         var matched = handlers.some(_check_handler);
207         if (!matched) {
208                 throw 'No handler for ' + document.URL;
209         }
210 }