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)';
108 dialog.style.marginLeft = '10em';
109 dialog.style.marginRight = '10em';
111 var content = frame.document.createElement('p');
112 content.innerHTML = 'Edit tags for ' + message_id;
113 dialog.appendChild(content);
115 var tag_list = frame.document.createElement('p');
116 dialog.appendChild(tag_list);
117 for (var i = 0; i < available_tags.length; i++) {
118 var tag = frame.document.createElement('a');
119 tag.innerHTML = available_tags[i];
120 tag.style.cursor = 'pointer';
121 if (tags.indexOf(available_tags[i]) >= 0) {
122 tag.style.backgroundColor = 'lime';
124 tag.onclick = this._toggle_tag.bind(
125 this, message_id, available_tags[i], tag);
126 tag_list.appendChild(tag);
127 tag_list.appendChild(frame.document.createTextNode(' '));
129 var close = frame.document.createElement('button');
130 close.innerHTML = 'Close';
131 close.onclick = function () {
134 dialog.appendChild(close);
136 frame.document.body.insertBefore(dialog, frame.document.body.firstChild);
140 _toggle_tag: function (message_id, tag, element) {
142 if (element.style.backgroundColor == 'lime') {
143 prefix = '-'; /* unset */
144 element.style.backgroundColor = null;
146 prefix = '+'; /* set */
147 element.style.backgroundColor = 'lime';
152 encodeURIComponent(message_id),
154 console.log('nmbug: alter tags via ' + url);
155 var request = new XMLHttpRequest();
156 request.onload = function () {
157 if (this.status == 200) {
158 var tags = JSON.parse(this.response);
159 console.log('nmbug: got tags', tags);
161 throw 'Error posting to ' + url + ' (status ' + this.status + ')';
164 request.open('post', url, true);
165 request.setRequestHeader(
166 'Content-Type', 'application/json; charset=UTF-8');
167 request.send(JSON.stringify([prefix + tag]));
171 var _gmane_handler = {
172 regexp: /gmane[.]org/,
173 handle: function (callback) {
174 var frame = this._get_frame();
175 var article = this._article_from_url(frame.document.URL);
176 this._get_message_id(article, function (message_id) {
177 callback(message_id, frame);
180 _article_from_url: function (url) {
181 var regexp = new RegExp('http://article.gmane.org/([^/]+)/([0-9]+)');
182 var match = regexp.exec(url);
183 console.log('nmbug: get article from ' + url, match);
185 return {'group': match[1], 'id': parseInt(match[2])};
188 _get_frame: function () {
190 var article = this._article_from_url(frame.document.URL);
192 for (var i = 0; !article && i < window.frames.length; i++) {
193 frame = window.frames[i];
194 article = this._article_from_url(frame.document.URL);
197 throw "Cannot extract an article from Gmane's " + document.URL;
201 _get_message_id: function (article, callback) {
208 console.log('nmbug: get Message-ID from ' + url);
209 var request = new XMLHttpRequest();
210 request.onload = function () {
211 var message_id = this.responseText;
212 callback(message_id);
214 request.open('get', url, true);
223 function _check_handler(handler) {
224 var match = handler.regexp.test(document.URL);
225 console.log('nmbug: testing', handler, match);
227 console.log('nmbug: matched', handler);
228 handler.handle(nmbug.show.bind(nmbug));
230 return match; /* break after the first match */
234 var matched = handlers.some(_check_handler);
236 throw 'No handler for ' + document.URL;