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 if (frame.document.createElement('dialog').show) {
56 this._x_edit_tags(frame, available_tags, message_id, tags);
61 function basename (element) {
63 if (!element.tagName) {
65 } else if (element.tagName.toLowerCase() == 'script') {
67 } else if (element.tagName.toLowerCase() == 'link') {
72 return url.replace(/.*\//, '');
76 var name = basename(this);
77 console.log('nmbug: loaded ' + name, this);
78 var index = needed.indexOf(name);
80 needed.splice(index, 1);
82 if (needed.length == 0) {
83 _this._x_edit_tags(frame, available_tags, message_id, tags);
87 function has_header (name) {
88 var nodes = frame.document.head.childNodes;
89 for (var i = 0; i < nodes.length; i++) {
90 if (basename(nodes[i]) == name) {
97 if (!has_header('dialog-polyfill.js')) {
98 needed.push('dialog-polyfill.js');
99 var script = frame.document.createElement('script');
100 script.type = 'text/javascript';
101 script.src = nmbug_server + '/static/dialog-polyfill/dialog-polyfill.js';
102 script.onload = onload;
103 console.log('nmbug: loading dialog-polyfill.js');
104 frame.document.head.appendChild(script);
107 if (!has_header('dialog-polyfill.css')) {
108 needed.push('dialog-polyfill.css');
109 var link = frame.document.createElement('link');
110 link.rel = 'stylesheet';
111 link.type = 'text/css';
112 link.href = nmbug_server + '/static/dialog-polyfill/dialog-polyfill.css';
113 link.onload = onload;
114 console.log('nmbug: loading dialog-polyfill.css');
115 frame.document.head.appendChild(link);
119 _x_edit_tags: function (frame, available_tags, message_id, tags) {
120 var dialog = frame.document.createElement('dialog');
121 if (!frame.document.createElement('dialog').show) {
122 frame.dialogPolyfill.registerDialog(dialog);
125 dialog.style.border = '1px solid rgba(0, 0, 0, 0.3)';
126 dialog.style.borderRadius = '6px';
127 dialog.style.boxShadow = '0 3px 7px rgba(0, 0, 0, 0.3)';
129 var content = frame.document.createElement('p');
130 content.innerHTML = 'Edit tags for ' + message_id;
131 dialog.appendChild(content);
133 var ul = frame.document.createElement('ul');
134 dialog.appendChild(ul);
135 for (var i = 0; i < available_tags.length; i++) {
136 var li = frame.document.createElement('li');
137 li.innerHTML = available_tags[i];
138 li.style.cursor = 'pointer';
139 if (tags.indexOf(available_tags[i]) >= 0) {
140 li.style.backgroundColor = 'lime';
142 li.onclick = this._toggle_tag.bind(
143 this, message_id, available_tags[i], li);
146 var close = frame.document.createElement('button');
147 close.innerHTML = 'Close';
148 close.onclick = function () {
151 dialog.appendChild(close);
153 frame.document.body.appendChild(dialog);
157 _toggle_tag: function (message_id, tag, li) {
159 if (li.style.backgroundColor == 'lime') {
160 prefix = '-'; /* unset */
161 li.style.backgroundColor = null;
163 prefix = '+'; /* set */
164 li.style.backgroundColor = 'lime';
169 encodeURIComponent(message_id),
171 console.log('nmbug: alter tags via ' + url);
172 var request = new XMLHttpRequest();
173 request.onload = function () {
174 if (this.status == 200) {
175 var tags = JSON.parse(this.response);
176 console.log('nmbug: got tags', tags);
178 throw 'Error posting to ' + url + ' (status ' + this.status + ')';
181 request.open('post', url, true);
182 request.setRequestHeader(
183 'Content-Type', 'application/json; charset=UTF-8');
184 request.send(JSON.stringify([prefix + tag]));
188 var _gmane_handler = {
189 regexp: /gmane[.]org/,
190 handle: function (callback) {
191 var frame = this._get_frame();
192 var article = this._article_from_url(frame.document.URL);
193 this._get_message_id(article, function (message_id) {
194 callback(message_id, frame);
197 _article_from_url: function (url) {
198 var regexp = new RegExp('http://article.gmane.org/([^/]+)/([0-9]+)');
199 var match = regexp.exec(url);
200 console.log('nmbug: get article from ' + url, match);
202 return {'group': match[1], 'id': parseInt(match[2])};
205 _get_frame: function () {
207 var article = this._article_from_url(frame.document.URL);
209 for (var i = 0; !article && i < window.frames.length; i++) {
210 frame = window.frames[i];
211 article = this._article_from_url(frame.document.URL);
214 throw "Cannot extract an article from Gmane's " + document.URL;
218 _get_message_id: function (article, callback) {
225 console.log('nmbug: get Message-ID from ' + url);
226 var request = new XMLHttpRequest();
227 request.onload = function () {
228 var message_id = this.responseText;
229 callback(message_id);
231 request.open('get', url, true);
240 function _check_handler(handler) {
241 var match = handler.regexp.test(document.URL);
242 console.log('nmbug: testing', handler, match);
244 console.log('nmbug: matched', handler);
245 handler.handle(nmbug.show.bind(nmbug));
247 return match; /* break after the first match */
251 var matched = handlers.some(_check_handler);
253 throw 'No handler for ' + document.URL;