1 var nmbug_server = 'http://localhost:5000';
4 show: function (message_id, frame) {
6 if (frame === undefined) {
9 this._get_available_tags(function (available_tags) {
12 _this._edit_tags.bind(_this, frame, available_tags, message_id));
15 _get_available_tags: function (callback) {
20 console.log('nmbug: get available tags from ' + url);
21 var request = new XMLHttpRequest();
22 request.onload = function () {
23 if (this.status == 200) {
24 var available_tags = JSON.parse(this.response);
25 console.log('nmbug: got available tags', available_tags);
26 callback(available_tags);
28 throw 'Error fetching ' + url + ' (status ' + this.status + ')';
31 request.open('get', url, true);
34 _get_tags: function (message_id, callback) {
38 encodeURIComponent(message_id),
40 console.log('nmbug: get tags from ' + url);
41 var request = new XMLHttpRequest();
42 request.onload = function () {
43 if (this.status == 200) {
44 var tags = JSON.parse(this.response);
45 console.log('nmbug: got tags', tags);
48 throw 'Error fetching ' + url + ' (status ' + this.status + ')';
51 request.open('get', url, true);
54 _edit_tags: function (frame, available_tags, message_id, tags) {
55 var have_dialog_polyfill;
57 have_dialog_polyfill = frame.dialogPolyfill !== undefined;
59 if (error.name == 'ReferenceError') {
60 have_dialog_polyfill = false;
63 if (frame.document.createElement('dialog').show || have_dialog_polyfill) {
64 this._x_edit_tags(frame, available_tags, message_id, tags);
66 var script = frame.document.createElement('script');
67 script.type = 'text/javascript';
68 script.src = nmbug_server + '/static/dialog-polyfill/dialog-polyfill.js';
70 console.log('nmbug: loading dialog-polyfill.js');
71 frame.document.head.appendChild(script);
73 var link = frame.document.createElement('link');
74 link.rel = 'stylesheet';
75 link.type = 'text/css';
76 link.href = nmbug_server + '/static/dialog-polyfill/dialog-polyfill.css';
78 console.log('nmbug: loading dialog-polyfill.css');
79 frame.document.head.appendChild(link);
82 function edit_tags_after_dialog_polyfill () {
84 have_dialog_polyfill = frame.dialogPolyfill !== undefined;
85 console.log('have dialogPolyfill');
87 _this._x_edit_tags.bind(_this), 200,
88 frame, available_tags, message_id, tags);
90 if (error.name == 'ReferenceError') {
91 console.log('waiting for dialogPolyfill');
92 window.setTimeout(edit_tags_after_dialog_polyfill, 200);
96 edit_tags_after_dialog_polyfill();
99 _x_edit_tags: function (frame, available_tags, message_id, tags) {
100 var dialog = frame.document.createElement('dialog');
101 if (!frame.document.createElement('dialog').show) {
102 frame.dialogPolyfill.registerDialog(dialog);
105 dialog.style.border = '1px solid rgba(0, 0, 0, 0.3)';
106 dialog.style.borderRadius = '6px';
107 dialog.style.boxShadow = '0 3px 7px rgba(0, 0, 0, 0.3)';
109 var content = frame.document.createElement('p');
110 content.innerHTML = 'Edit tags for ' + message_id;
111 dialog.appendChild(content);
113 var ul = frame.document.createElement('ul');
114 dialog.appendChild(ul);
115 for (var i = 0; i < available_tags.length; i++) {
116 var li = frame.document.createElement('li');
117 li.innerHTML = available_tags[i];
118 li.style.cursor = 'pointer';
119 if (tags.indexOf(available_tags[i]) >= 0) {
120 li.style.backgroundColor = 'lime';
122 li.onclick = this._toggle_tag.bind(
123 this, message_id, available_tags[i], li);
126 var close = frame.document.createElement('button');
127 close.innerHTML = 'Close';
128 close.onclick = function () {
131 dialog.appendChild(close);
133 frame.document.body.insertBefore(dialog, frame.document.body.firstChild);
137 _toggle_tag: function (message_id, tag, li) {
139 if (li.style.backgroundColor == 'lime') {
140 prefix = '-'; /* unset */
141 li.style.backgroundColor = null;
143 prefix = '+'; /* set */
144 li.style.backgroundColor = 'lime';
149 encodeURIComponent(message_id),
151 console.log('nmbug: alter tags via ' + url);
152 var request = new XMLHttpRequest();
153 request.onload = function () {
154 if (this.status == 200) {
155 var tags = JSON.parse(this.response);
156 console.log('nmbug: got tags', tags);
158 throw 'Error posting to ' + url + ' (status ' + this.status + ')';
161 request.open('post', url, true);
162 request.setRequestHeader(
163 'Content-Type', 'application/json; charset=UTF-8');
164 request.send(JSON.stringify([prefix + tag]));
168 var _gmane_handler = {
169 regexp: /gmane[.]org/,
170 handle: function (callback) {
171 var frame = this._get_frame();
172 var article = this._article_from_url(frame.document.URL);
173 this._get_message_id(article, function (message_id) {
174 callback(message_id, frame);
177 _article_from_url: function (url) {
178 var regexp = new RegExp('http://article.gmane.org/([^/]+)/([0-9]+)');
179 var match = regexp.exec(url);
180 console.log('nmbug: get article from ' + url, match);
182 return {'group': match[1], 'id': parseInt(match[2])};
185 _get_frame: function () {
187 var article = this._article_from_url(frame.document.URL);
189 for (var i = 0; !article && i < window.frames.length; i++) {
190 frame = window.frames[i];
191 article = this._article_from_url(frame.document.URL);
194 throw "Cannot extract an article from Gmane's " + document.URL;
198 _get_message_id: function (article, callback) {
205 console.log('nmbug: get Message-ID from ' + url);
206 var request = new XMLHttpRequest();
207 request.onload = function () {
208 var message_id = this.responseText;
209 callback(message_id);
211 request.open('get', url, true);
220 function _check_handler(handler) {
221 var match = handler.regexp.test(document.URL);
222 console.log('nmbug: testing', handler, match);
224 console.log('nmbug: matched', handler);
225 handler.handle(nmbug.show.bind(nmbug));
227 return match; /* break after the first match */
231 var matched = handlers.some(_check_handler);
233 throw 'No handler for ' + document.URL;