Author: Gustavo Carreno
(2011/01/01 04:57) Over 1 year ago
Forgot to copy code onto the new version.
5
org.gcarreno = {};
6
}
7
8
if (typeof org.gcarreno.StackOverflowBar == 'undefined') {
org.gcarreno.jSapiens = {
9
org.gcarreno.StackOverflowBar = {
_mainURL: "http://api.stackoverflow.com/",
10
searchHistory: Components.classes["@mozilla.org/satchel/form-history;1"]
_apiVer: "1.0",
11
.getService(Components.interfaces.nsIFormHistory2 || Components.interfaces.nsIFormHistory),
_key: "[PLEASE CHANGE ME!]",
12
oneTime: false,
13
Strings: {
_req: Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
14
Constants: {
.createInstance(Components.interfaces.nsIXMLHttpRequest),
15
Protocol: "http",
16
Host: "stackoverflow.com",
_console: Components.classes['@mozilla.org/consoleservice;1']
17
Ask: "/questions/ask",
.getService(Components.interfaces.nsIConsoleService),
18
Home: {
19
Active: "/?tab=active",
init: function(){
20
Featured: "/?tab=featured",
this.Log('init()');
21
Hot: "/?tab=hot",
this.answers._parent = this;
22
Week: "/?tab=week",
this.questions._parent = this;
23
Month: "/?tab=month"
this.users._parent = this;
24
},
return 0;
25
Questions: {
26
Newest: "/questions?sort=newest",
API: {
27
Featured: "/questions?sort=featured",
User: "/users",
28
Hot: "/questions?sort=hot",
UserQuestions: "",
29
Votes: "/questions?sort=votes",
UserAnswers: "",
30
Active: "/questions?sort=active"
UserFavorites: "",
31
UserReputation: "",
32
UnAnswered: {
UserRecent: "",
33
MyTags: "/unanswered/tagged?tab=mytags",
UserFlair: ""
34
Newest: "/unanswered/tagged?tab=newest",
35
Votes: "/unanswered/tagged?tab=votes"
36
answers: {
37
User: {
_parent: null,
38
Stats: "/users/%s?tab=stats#tab-top",
find: function(answerList) {
39
Activity: "/users/%s?tab=activity#tab-top",
this._parent.Log('answers.find(' + answerList + ')');
40
Reputation: "/users/%s?tab=reputationhistory#tab-top",
var text = null;
41
Favorites: "/users/%s?tab=favorites#tab-top",
if (answerList != 0 || answerList != null) {
42
Preferences: "/users/%s?tab=preferences#tab-top",
var url = this._parent._mainURL + this._parent._apiVer + "/answers/" + answerList;
43
Accounts: "/users/%s?tab=accounts#tab-top",
if (text = this._parent.Get(url)){
44
return this._parent.JSONDecode(text);
45
Recent: "/users/recent/%s?tab=summary#tab-top",
46
RecentRep: "/users/recent/%s?tab=reputation#tab-top",
47
Responses: "/users/recent/%s?tab=responses#tab-top",
48
Revisions: "/users/recent/%s?tab=revisions#tab-top",
49
Badges: "/users/recent/%s?tab=badges#tab-top"
50
51
52
Buttons: {
53
Search: "button_search",
54
Ask: "button_ask",
55
TabActive: "button_tab_active",
56
TabFeatured: "button_tab_featured",
57
TabHot: "button_tab_hot",
58
TabWeek: "button_tab_week",
59
TabMonth: "button_tab_month",
60
Featured: "button_featured",
61
New: "button_new",
62
Hot: "button_hot",
63
Votes: "button_votes",
64
Active: "button_active",
65
TabMyTags: "button_tab_mytags",
66
TabNewest: "button_tab_newest",
67
TabVotes: "button_tab_votes",
68
UserStats: "button_user_stats",
69
UserActivity: "button_user_actvity",
70
UserReputation: "button_user_reputation",
71
UserFavorites: "button_user_favorites",
72
UserPreferences: "button_user_preferences",
73
UserAccounts: "button_user_accounts",
74
75
UserRecentSummary: "button_user_recent_summary",
76
UserRecentReputation: "button_user_recent_reputation",
77
UserRecentResponses: "button_user_recent_responses",
78
UserRecentRevisions: "button_user_recent_revisions",
79
UserRecentBadges: "button_user_recent_badges",
80
ShowOptions: "button_show_options",
81
ShowOverview: "button_show_overview",
82
Test: "button_test"
83
84
Options: {
85
SearchInTab: "search_in_tab",
86
ButtonsInTab: "buttons_in_tab",
87
UseAPI: "use_api",
88
UserID: "user_id"
89
return this._parent.JSONDecode("{[]}");
90
91
Search: function (event, type) {
comments: function(anserList) {
92
this.Utils.Log('Entering Search: ' + type);
this._parent.Log('answers.comments(' + answerList + ')');
93
var URL = "";
94
var isEmpty = false;
95
var searchTerms = this.Utils.TrimString(this.GetTerms());
var url = this._parent._mainURL + this._parent._apiVer + "/answers/" + answerList + '/comments';
96
if (searchTerms.length == 0) {
97
isEmpty = true;
98
} else {
99
this.searchHistory.addEntry("SOB-SearchTerms-History", searchTerms);
100
searchTerms = this.Utils.ConvertTermsToURI(searchTerms);
101
102
103
switch(type)
104
{
105
case "sob_search":
106
if(!isEmpty) {
questions: {
107
URL = this.Strings.Constants.Protocol + "://" +
108
this.Strings.Constants.Host + "/search?q=" +
find: function(questionList) {
109
searchTerms;
this._parent.Log('questions.find(' + questionList + ')');
110
111
break;
if (questionList != 0 || questionList != null) {
112
var url = this._parent._mainURL + this._parent._apiVer + "/questions/" + questionList;
113
if (!isEmpty) {
114
this.Utils.LoadURL(URL, this.Utils.GetOption(this.Strings.Options.SearchInTab, "bool"));
115
116
117
SearchTermsTextEntered: function (param){
answers: function(questionList) {
118
this.Utils.Log('Entering SearchTermsTextEntered');
this._parent.Log('questions.answers(' + questionList + ')');
119
this.Search(null, 'sob_search');
var url = this._parent._mainURL + this._parent._apiVer + "/questions/" + questionList + '/answers';
users: {
find: function(userList){
this._parent.Log('users.find(' + userList + ')');
120
121
GetTerms: function () {
answers: function(userList){
122
this.Utils.Log('Entering GetTerms');
this._parent.Log('users.answers(' + userList + ')');
123
var terms = document.getElementById("SOB-SearchTerms");
124
return terms.value;
125
126
SetTerms: function (newTerms) {
timeline: function (userList){
127
this.Utils.Log('Entering SetTerms');
this._parent.Log('users.timeline(' + userList + ')');
128
129
terms.value = newTerms;
if (userList != 0 || userList != null) {
var url = this._parent._mainURL + this._parent._apiVer + "/users/" + userList + '/timeline';
Get: function(url){
this.Log('Get: "' + url + '"');
this._req.open('GET', url, false);
this._req.send(null);
if (this._req.status == 200) {
return this._req.responseText;
JSONDecode: function(json){
var JSON = Components.classes["@mozilla.org/dom/json;1"]
.createInstance(Components.interfaces.nsIJSON);
return JSON.decode(json);
Log: function (aMessage) {
130
this._console.logStringMessage('jSapiens: ' + aMessage);
131
132
133
134
135
136
137
_first_run: null,
138
JSON: null,
139
Preferences: null,
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
ButtonClick: function (buttonName) {
179
this.Utils.Log('Entering ButtonClick: ' + buttonName);
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
const buttons = this.Strings.Buttons;
202
const consts = this.Strings.Constants;
203
const homepage = consts.Home;
204
const questions = consts.Questions;
205
const unanswered = consts.UnAnswered;
206
const user = consts.User;
207
const opts = this.Strings.Options;
208
ShowOverview: "button_show_overview"
var loadURL = this.Utils.LoadURL;
var inNewTab = this.Utils.GetOption(opts.ButtonsInTab, "bool");
var userID = this.Utils.GetOption(opts.UserID, "string");
switch (buttonName) {
case buttons.Ask:
loadURL(consts.Protocol + "://" +
consts.Host + consts.Ask, inNewTab);
case buttons.TabActive:
consts.Host + homepage.Active, inNewTab);
case buttons.TabFeatured:
consts.Host + homepage.Featured, inNewTab);
case buttons.TabHot:
consts.Host + homepage.Hot, inNewTab);
case buttons.TabWeek:
consts.Host + homepage.Week, inNewTab);
case buttons.TabMonth:
consts.Host + homepage.Month, inNewTab);
case buttons.New:
consts.Host + questions.Newest, inNewTab);
case buttons.Featured:
consts.Host + questions.Featured, inNewTab);
case buttons.Hot:
consts.Host + questions.Hot, inNewTab);
case buttons.Votes:
consts.Host + questions.Votes, inNewTab);
case buttons.Active:
consts.Host + questions.Active, inNewTab);
case buttons.TabMyTags:
consts.Host + unanswered.MyTags, inNewTab);
case buttons.TabNewest:
consts.Host + unanswered.Newest, inNewTab);
case buttons.TabVotes:
consts.Host + unanswered.Votes, inNewTab);
case buttons.UserStats:
consts.Host + this.Utils.sprintf(user.Stats, userID), inNewTab);
case buttons.UserActivity:
209
210
consts.Host + this.Utils.sprintf(user.Activity, userID), inNewTab);
211
212
case buttons.UserReputation:
213
214
consts.Host + this.Utils.sprintf(user.Reputation, userID), inNewTab);
215
216
case buttons.UserFavorites:
217
218
consts.Host + this.Utils.sprintf(user.Favorites, userID), inNewTab);
219
220
case buttons.UserPreferences:
221
222
consts.Host + this.Utils.sprintf(user.Preferences, userID), inNewTab);
223
224
case buttons.UserAccounts:
225
226
consts.Host + this.Utils.sprintf(user.Accounts, userID), inNewTab);
227
228
case buttons.UserRecentSummary:
229
230
consts.Host + this.Utils.sprintf(user.Recent, userID), inNewTab);
231
232
case buttons.UserRecentReputation:
233
234
consts.Host + this.Utils.sprintf(user.RecentRep, userID), inNewTab);
235
236
case buttons.UserRecentResponses:
237
238
consts.Host + this.Utils.sprintf(user.Responses, userID), inNewTab);
239
240
case buttons.UserRecentRevisions:
241
242
consts.Host + this.Utils.sprintf(user.Revisions, userID), inNewTab);
243
244
case buttons.UserRecentBadges:
245
246
consts.Host + this.Utils.sprintf(user.Badges, userID), inNewTab);
247
248
case buttons.ShowOptions:
249
this.Utils.ShowOptions();
250
251
case buttons.ShowOverview:
252
this.Utils.ShowOverview();
253
254
case buttons.Test:
255
this.Utils.Test();
256
257
258
259
PrepareContextSearch: function (event, search) {
260
this.Utils.Log('Entering PrepareContextSearch');
261
// ****************************************
262
// Step 1: Get the selected text
263
264
265
var node = document.popupNode;
266
var selection = "";
267
var nodeLocalName = node.localName.toLowerCase();
268
269
if((nodeLocalName == "textarea") || (nodeLocalName == "input" && node.type == "text"))
270
selection = node.value.substring(node.selectionStart, node.selectionEnd);
271
else
272
273
var focusedWindow = document.commandDispatcher.focusedWindow;
274
selection = focusedWindow.getSelection().toString();
275
276
277
// Limit the selection length
278
if(selection.length >= 150)
279
selection = selection.substring(0, 149);
280
281
282
// Step 2: Clean up the selected text
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
selection = this.Utils.TrimString(selection); // Clean up whitespace
408
409
var selArray = selection.split(" ");
410
for(var i=0; i<selArray.length; i++)
411
412
selArray[i] = selArray[i].replace(/^(\&|\(|\)|\[|\]|\{|\}|\"|,|\.|!|\?|'|:|;)+/, "");
413
selArray[i] = selArray[i].replace(/(\&|\(|\)|\[|\]|\{|\}|\"|,|\.|!|\?|'|:|;)+$/, "");
414
415
416
selection = selArray.join(" ");
417
418
419
// Step 3: Update the search box
420
421
422
this.SetTerms(selection);
423
424
425
// Step 4: Perform the search
426
427
428
this.Search(event, search);
429
430
UpdateContextMenuVisibility: function () {
431
this.Utils.Log('Entering UpdateContextMenuVisibility');
432
//Todo
433
434
UpdateContextMenu: function () {
435
this.Utils.Log('Entering UpdateContextMenu');
436
var contextMenu = document.getElementById('SOB-Context');
437
438
439
440
441
442
443
444
445
446
447
this.Utils.Log('Selection: ' + selection);
448
if (selection.length == 0) {
449
contextMenu.setAttribute('disabled', 'true');
450
451
contextMenu.setAttribute('disabled', 'false');
452
453
return true;
454
455
ProgressListener: function () {
456
this.Utils.Log('Entering ProgressListener');
457
458
459
Init: function() {
460
this.Utils.Log('Entering Init');
461
462
this.Utils.Log('Importing Preferences.jsm');
463
try {
464
Components.utils.import("resource://stackoverflowbar/Preferences.jsm", org.gcarreno.StackOverflowBar);
465
this.Utils.Log("Module Preferences imported");
466
} catch(e) {
467
this.Utils.Log("Error: " + e.message);
468
469
470
org.gcarreno.jSapiens.init();
471
this.Database.init();
472
this.Overview.init();
473
this.Timeline.my_turn();
474
475
var mainItem = document.getElementById("SOB-Main-Item");
476
// Only initialize if the main toolbar item is present
477
if(mainItem)
478
479
this._first_run = this.Utils.GetOption('first_run', 'bool');
480
if (this._first_run) {
481
this.Utils.Log('First run');
482
this.Utils.SetOption('first_run', 'bool', false);
483
this.Database.CreateDB()
484
485
this.UpdateContextMenuVisibility(); // Todo
486
487
488
Finalise: function () {
489
this.Utils.Log('Entering Finalise');
490
//if (typeof window.getBrowser != 'undefined') {
491
// window.getBrowser().removeProgressListener(this.ProgressListener);
492
//}
493
494
Database: {
495
_sobU: null,
496
_file: "sob-database.db",
497
_dirS: Components.classes["@mozilla.org/file/directory_service;1"]
498
.getService(Components.interfaces.nsIProperties),
499
_dir: null,
500
501
_storage: Components.classes["@mozilla.org/storage/service;1"]
502
.getService(Components.interfaces.mozIStorageService),
503
504
505
506
507
_dbConn: null,
508
509
init: function() {
510
this.Log('Entering init');
511
512
this.Log('File: ' + this._file);
513
this._dir = this._dirS.get("ProfD", Components.interfaces.nsIFile);
514
this._dir.append("StackOverflowBar");
515
516
this.Log('Error: ' +e.message);
517
518
if (!this._dir.exists() || !this._dir.isDirectory) {
519
this.Log('Folder does not exist, creating');
520
this._dir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0774);
521
522
523
this._dir.append(this._file);
524
525
526
527
if (!this._dir.exists()) {
528
this.Log('File missing, will create on DB Connect');
529
530
531
this._dbConn =this._storage.openDatabase(this._dir);
532
533
534
535
536
537
CreateDB: function() {
538
this.Log('Creating Database');
539
this._dbConn.executeSimpleSQL("CREATE TABLE timeline (date INTEGER, type STRING)");
540
541
542
543
this._console.logStringMessage('StackOverflowBar.Database: ' + aMessage);
544
545
546
Timeline: {
547
548
549
Log: function(aMessage) {
550
this._console.logStringMessage('StackOverflowBar.Timeline: ' + aMessage);
551
552
my_turn: function() {
553
return;
554
var timeout = org.gcarreno.StackOverflowBar.Utils.GetOption('timeout');
555
window.setTimeout(function() {
556
org.gcarreno.StackOverflowBar.Timeline.my_turn();
557
}, timeout * 60 * 1000);
558
559
560
Overview : {
561
_sob: null,
562
563
_sobD: null,
564
_jSapiens: null,
565
566
567
568
569
this.Log('init');
570
if (typeof org.gcarreno.StackOverflowBar != 'undefined') {
571
this.Log('Can reach SOB');
572
this._sob = org.gcarreno.StackOverflowBar;
573
574
if (typeof org.gcarreno.StackOverflowBar.Database != 'undefined') {
575
this.Log('Can reach SOB.D');
576
this._sobD = org.gcarreno.StackOverflowBar.Database;
577
578
if (typeof org.gcarreno.StackOverflowBar.Utils != 'undefined') {
579
this.Log('Can reach SOB.U');
580
this._sobU = org.gcarreno.StackOverflowBar.Utils;
581
582
if (typeof org.gcarreno.jSapiens != 'undefined') {
583
this.Log('Can reach jSapiens');
584
this._jSapiens = org.gcarreno.jSapiens;
585
586
587
588
refresh: function () {
589
var contents = document.getElementById('SOB-overview-contents');
590
591
var api_answer = this._jSapiens.users.timeline(this._sobU.GetOption('user_id'));
592
var b_value = '';
593
594
b_value += 'User Timeline:\n';
595
b_value += '\tTotal: ' + api_answer.total + '\n';
596
if (this.oneTime == false) {
597
if (api_answer.total > 0) {
this.oneTime = true;
598
for (var x = 0; x < api_answer.user_timelines.length; x++) {
//window.getBrowser().addProgressListener(this.ProgressListener, Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
599
b_value += '\t\tUser: ' + api_answer.user_timelines[x].user_id + '\n';
600
b_value += '\t\t\ttype: ' + api_answer.user_timelines[x].timeline_type + '\n';
601
switch (api_answer.user_timelines[x].timeline_type) {
602
case "comment":
603
b_value += '\t\t\taction: ' + api_answer.user_timelines[x].action + '\n';
604
b_value += '\t\t\tdescription: ' + api_answer.user_timelines[x].description + '\n';
605
b_value += '\t\t\tdetail: ' + api_answer.user_timelines[x].detail + '\n';
606
607
case "revision":
608
609
610
611
612
case "badge":
613
614
615
616
617
case "accepted":
618
619
620
621
case "askoranswered":
622
623
624
625
626
var creation_date = new Date(api_answer.user_timelines[x].creation_date * 1000);
627
b_value += '\t\t\tDate: ' + creation_date + '\n';
628
//b_value += '\t\t\tviews: ' + api_answer.user_timelines[x].view_count + '\n';
629
630
631
632
contents.value = b_value;
633
634
635
636
this._console.logStringMessage('StackOverflowBar.Overview: ' + aMessage);
637
638
639
Utils: {
640
consoleService: Components.classes['@mozilla.org/consoleservice;1']
641
642
prefService: Components.classes["@mozilla.org/preferences-service;1"]
643
.getService(Components.interfaces.nsIPrefService),
644
645
_sob_prefs: null,
646
647
648
this.consoleService.logStringMessage('StackOverflowBar: ' + aMessage);
649
650
GetOption: function(optName, optType) {
651
if (this._sob_prefs == null) {
652
this._sob_prefs = new org.gcarreno.StackOverflowBar.Preferences("extensions.stackoverflowbar.");
653
654
var result = this._sob_prefs.get(optName);
655
656
this.Log('Prefs get: ' + optName + ': '+ result);
657
658
return result;
const branch = this.prefService.getBranch("extensions.stackoverflowbar.");
659
660
SetOption: function(optName, optType, optValue) {
661
662
663
664
this.Log('Prefs set: ' + optName + ': '+ optValue);
665
666
this._sob_prefs.set(optName, optValue);
667
668
LoadOptions: function () {
669
const options = org.gcarreno.StackOverflowBar.Strings.Options;
670
671
document.getElementById("SOB-Opt-SearchInTab").checked =
672
this.GetOption(options.SearchInTab, "bool");
673
document.getElementById("SOB-Opt-ButtonsInTab").checked =
674
this.GetOption(options.ButtonsInTab, "bool");
675
var result = null;
676
//document.getElementById("SOB-Opt-UseAPI").checked =
677
// this.GetOption(options.UseAPI, "bool");
678
switch (optType) {
679
document.getElementById("SOB-Opt-UserID").value =
case "bool":
680
this.GetOption(options.UserID, "string");
681
result = branch.getBoolPref(optName);
682
SaveOptions: function () {
} catch (e) {
683
result = false;
case "string":
result = branch.getCharPref(optName);
result = '';
case "int":
result = branch.getIntPref(optName);
result = 0;
branch.setBoolPref(optName, optValue);
branch.setCharPref(optName, optValue);
branch.setIntPref(optName, optValue);
684
this.SetOption(options.SearchInTab, "bool",
685
document.getElementById("SOB-Opt-SearchInTab").checked);
686
this.SetOption(options.ButtonsInTab, "bool",
687
document.getElementById("SOB-Opt-ButtonsInTab").checked);
688
//this.SetOption(options.UseAPI, "bool",
// document.getElementById("SOB-Opt-UseAPI").checked);
689
this.SetOption(options.UserID, "string",
690
document.getElementById("SOB-Opt-UserID").value);
691
692
ShowOptions: function () {
693
var flags = "chrome,centerscreen,modal";
694
window.openDialog("chrome://stackoverflowbar/content/options.xul", "Options", flags);
695
696
ShowOverview: function () {
697
var flags = "chrome,centerscreen,resizable";
698
window.openDialog("chrome://stackoverflowbar/content/options.xul", "&sobar.options.title;", flags);
window.openDialog("chrome://stackoverflowbar/content/overview.xul", "Overview", flags);
699
700
LoadURL: function (aURL, inNewTab) {
701
if(inNewTab)
702
window.openDialog("chrome://stackoverflowbar/content/overview.xul", "&sobar.overview.title;", flags);
703
var browser = window.getBrowser();
704
var newTab = browser.addTab(aURL);
705
browser.selectedTab = newTab;
706
707
708
709
710
711
712
713
var content = window.content;
714
content.document.location = aURL;
715
content.focus();
716
717
718
LoadHomepage: function (event) {
719
720
const consts = org.gcarreno.StackOverflowBar.Strings.Constants;
721
722
var inNewTab = this.GetOption(options.ButtonsInTab, "bool");
723
var URL = consts.Protocol + "://" + consts.Host;
724
this.LoadURL(URL, inNewTab);
725
event.stopPropagation();
726
727
LoadAboutURL: function (aWhere) {
728
var url = "";
729
switch(aWhere) {
730
case 'home':
731
url = 'http://guscarreno.blogspot.com/p/stack-overflow-bar.html'
732
733
case 'support':
734
url = 'http://www.assembla.com/spaces/StackOverflowBar'
735
736
737
738
var windowService = Components.classes["@mozilla.org/appshell/window-mediator;1"]
739
.getService(Components.interfaces.nsIWindowMediator);
740
var currentWindow = windowService.getMostRecentWindow("navigator:browser");
741
742
if(currentWindow)
743
744
745
currentWindow.delayedOpenTab(url);
746
747
currentWindow.loadURI(url);
748
749
750
751
window.open(url);
752
753
TrimString: function (string) {
754
if (!string) {
755
return "";
756
757
string = string.replace(/^\s+/, '');
758
string = string.replace(/\s+$/, '');
759
string = string.replace(/\s+/g, ' ');
760
return string;
761
762
ConvertTermsToURI: function (terms) {
763
var termArray = new Array();
764
termArray = terms.split(" ");
765
var result = "";
766
for (var i = 0; i < termArray.length; i++) {
767
if (i > 0) {
768
result += "+";
url = 'http://gcarreno.org/stackoverflowbar/'
769
770
result += encodeURIComponent(termArray[i]);
771
772
773
774
DoNothing: function () {},
Test: function(){
this.Log('Testing button');
var box = document.getElementById('SOB-Test-Box');
var strings = org.gcarreno.StackOverflowBar.Strings;
var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Components.interfaces.nsIXMLHttpRequest);
var url = this.sprintf(strings.Constants.Protocol + "://" +
strings.Constants.Host +
strings.API.UserFlair,
this.GetOption(strings.Options.UserID, 'string'));
box.value = '';
this.Log('Req: ' + url);
req.open('GET', url, false);
req.send(null);
if (req.status == 200) {
var flair = JSON.decode(req.responseText);
box.value = this.sprintf("Name: %s\nID: %s\n\n" + req.responseText, flair.displayName, flair.id);
box.value = 'Treta';
/**
775
* sprintf() for JavaScript v.0.4
776
*
777
* Copyright (c) 2007 Alexandru Marasteanu <http://alexei.417.ro/>
778
* Thanks to David Baird (unit test and patch).
779
780
* This program is free software; you can redistribute it and/or modify it under
781
* the terms of the GNU General Public License as published by the Free Software
782
* Foundation; either version 2 of the License, or (at your option) any later
783
* version.
784
785
* This program is distributed in the hope that it will be useful, but WITHOUT
786
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
787
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
788
* details.
789
790
* You should have received a copy of the GNU General Public License along with
791
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
792
* Place, Suite 330, Boston, MA 02111-1307 USA
793
*/
794
str_repeat: function (i, m) {
795
for (var o = []; m > 0; o[--m] = i); return(o.join(''));
796
797
sprintf: function () {
798
var i = 0, a, f = arguments[i++], o = [], m, p, c, x;
799
while (f) {
800
if (m = /^[^\x25]+/.exec(f)) o.push(m[0]);
801
else if (m = /^\x25{2}/.exec(f)) o.push('%');
802
else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) {
803
if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) throw("Too few arguments.");
804
if (/[^s]/.test(m[7]) && (typeof(a) != 'number'))
805
throw("Expecting number but found " + typeof(a));
806
switch (m[7]) {
807
case 'b': a = a.toString(2); break;
808
case 'c': a = String.fromCharCode(a); break;
809
case 'd': a = parseInt(a); break;
810
case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break;
811
case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break;
812
case 'o': a = a.toString(8); break;
813
case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break;
814
case 'u': a = Math.abs(a); break;
815
case 'x': a = a.toString(16); break;
816
case 'X': a = a.toString(16).toUpperCase(); break;
817
a = (/[def]/.test(m[7]) && m[2] && a > 0 ? '+' + a : a);
c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' ';
x = m[5] - String(a).length;
p = m[5] ? this.str_repeat(c, x) : '';
o.push(m[4] ? a + p : p + a);
else throw ("Huh ?!");
f = f.substring(m[0].length);
818
return o.join('');
819
820
821
822
823
824
825
826
827
828
829
830
831
832
window.addEventListener("load", function () { return org.gcarreno.StackOverflowBar.Init(); }, false);
833
window.addEventListener("load", function () {return org.gcarreno.StackOverflowBar.Init(); } , false);
window.addEventListener("unload", function () {return org.gcarreno.StackOverflowBar.Finalise(); } , false);
834
1
<?xml version="1.0" encoding="ISO-8859-1" ?>
2
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
3
<?xml-stylesheet href="chrome://stackoverflowbar/skin/stackoverflowbar.css"
<?xml-stylesheet href="chrome://stackoverflowbar/skin/stackoverflowbar.css" type="text/css"?>
4
type="text/css"?>
<?xul-overlay href="chrome://stackoverflowbar/content/toolbar.xul"?>
<?xul-overlay href="chrome://stackoverflowbar/content/contextmenu.xul"?>
...
<script type="application/x-javascript"
src="chrome://global/content/nsTransferable.js"/>
src="chrome://stackoverflowbar/content/stackoverflowbar.js" />
</overlay>
<!ENTITY sobar.options.tab.about "About">
<!ENTITY sobar.options.label.about "About the StackOverflow Bar">
<!ENTITY sobar.options.about.text1 "StackOverflow Bar v0.2.0.329">
<!ENTITY sobar.options.about.text1 "StackOverflow Bar v0.3.0.330">
<!ENTITY sobar.options.about.text2 "Gustavo Carreno <gcarreno@gcarreno.org>">
<!ENTITY sobar.options.about.text3 "Toolbar Site: ">
<!ENTITY sobar.options.about.text3.link "http://guscarreno.blogspot.com/p/stack-overflow-bar.html">
<!ENTITY sobar.options.tab.about "Sobre">
<!ENTITY sobar.options.label.about "Sobre a barra StackOverflow">
<!ENTITY sobar.options.about.text1 "Barra Stack Overflow v0.2.0.329">
<!ENTITY sobar.options.about.text1 "Barra Stack Overflow v0.3.0.330">
<!ENTITY sobar.options.about.text3 "Site da barra: ">
<RDF:Description RDF:about="urn:mozilla:install-manifest"
em:id="StackOverflowBar@gcarreno.org"
em:name="StackOverflow Bar"
em:version="0.2.0.329"
em:version="0.3.0.330"
em:creator="Gustavo Carreno"
em:description="StackOverflow Bar"
em:homepageURL="http://guscarreno.blogspot.com/p/stack-overflow-bar.html"
org.gcarreno = {};org.gcarreno = {};if (typeof org.gcarreno.StackOverflowBar == 'undefined') {org.gcarreno.jSapiens = {org.gcarreno.StackOverflowBar = {_mainURL: "http://api.stackoverflow.com/",searchHistory: Components.classes["@mozilla.org/satchel/form-history;1"]_apiVer: "1.0",.getService(Components.interfaces.nsIFormHistory2 || Components.interfaces.nsIFormHistory),_key: "[PLEASE CHANGE ME!]",oneTime: false,Strings: {_req: Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]Constants: {.createInstance(Components.interfaces.nsIXMLHttpRequest),Protocol: "http",Host: "stackoverflow.com",_console: Components.classes['@mozilla.org/consoleservice;1']Ask: "/questions/ask",.getService(Components.interfaces.nsIConsoleService),Home: {Active: "/?tab=active",init: function(){Featured: "/?tab=featured",this.Log('init()');Hot: "/?tab=hot",this.answers._parent = this;Week: "/?tab=week",this.questions._parent = this;Month: "/?tab=month"this.users._parent = this;},return 0;Questions: {},Newest: "/questions?sort=newest",API: {Featured: "/questions?sort=featured",User: "/users",Hot: "/questions?sort=hot",UserQuestions: "",Votes: "/questions?sort=votes",UserAnswers: "",Active: "/questions?sort=active"UserFavorites: "",},UserReputation: "",UnAnswered: {UserRecent: "",MyTags: "/unanswered/tagged?tab=mytags",UserFlair: ""Newest: "/unanswered/tagged?tab=newest",},Votes: "/unanswered/tagged?tab=votes"},answers: {User: {_parent: null,Stats: "/users/%s?tab=stats#tab-top",find: function(answerList) {Activity: "/users/%s?tab=activity#tab-top",this._parent.Log('answers.find(' + answerList + ')');Reputation: "/users/%s?tab=reputationhistory#tab-top",var text = null;Favorites: "/users/%s?tab=favorites#tab-top",if (answerList != 0 || answerList != null) {Preferences: "/users/%s?tab=preferences#tab-top",var url = this._parent._mainURL + this._parent._apiVer + "/answers/" + answerList;Accounts: "/users/%s?tab=accounts#tab-top",if (text = this._parent.Get(url)){return this._parent.JSONDecode(text);Recent: "/users/recent/%s?tab=summary#tab-top",RecentRep: "/users/recent/%s?tab=reputation#tab-top",Responses: "/users/recent/%s?tab=responses#tab-top",Revisions: "/users/recent/%s?tab=revisions#tab-top",Badges: "/users/recent/%s?tab=badges#tab-top"},Buttons: {Search: "button_search",Ask: "button_ask",TabActive: "button_tab_active",TabFeatured: "button_tab_featured",TabHot: "button_tab_hot",TabWeek: "button_tab_week",TabMonth: "button_tab_month",Featured: "button_featured",New: "button_new",Hot: "button_hot",Votes: "button_votes",Active: "button_active",TabMyTags: "button_tab_mytags",TabNewest: "button_tab_newest",TabVotes: "button_tab_votes",UserStats: "button_user_stats",UserActivity: "button_user_actvity",UserReputation: "button_user_reputation",UserFavorites: "button_user_favorites",UserPreferences: "button_user_preferences",UserAccounts: "button_user_accounts",UserRecentSummary: "button_user_recent_summary",UserRecentReputation: "button_user_recent_reputation",UserRecentResponses: "button_user_recent_responses",UserRecentRevisions: "button_user_recent_revisions",UserRecentBadges: "button_user_recent_badges",ShowOptions: "button_show_options",ShowOverview: "button_show_overview",Test: "button_test"},Options: {SearchInTab: "search_in_tab",ButtonsInTab: "buttons_in_tab",UseAPI: "use_api",UserID: "user_id"return this._parent.JSONDecode("{[]}");Search: function (event, type) {comments: function(anserList) {this.Utils.Log('Entering Search: ' + type);this._parent.Log('answers.comments(' + answerList + ')');var URL = "";var text = null;var isEmpty = false;if (answerList != 0 || answerList != null) {var searchTerms = this.Utils.TrimString(this.GetTerms());var url = this._parent._mainURL + this._parent._apiVer + "/answers/" + answerList + '/comments';if (searchTerms.length == 0) {if (text = this._parent.Get(url)){isEmpty = true;return this._parent.JSONDecode(text);} else {}this.searchHistory.addEntry("SOB-SearchTerms-History", searchTerms);searchTerms = this.Utils.ConvertTermsToURI(searchTerms);return this._parent.JSONDecode("{[]}");switch(type)}{},case "sob_search":if(!isEmpty) {questions: {URL = this.Strings.Constants.Protocol + "://" +_parent: null,this.Strings.Constants.Host + "/search?q=" +find: function(questionList) {searchTerms;this._parent.Log('questions.find(' + questionList + ')');}var text = null;break;if (questionList != 0 || questionList != null) {}var url = this._parent._mainURL + this._parent._apiVer + "/questions/" + questionList;if (!isEmpty) {if (text = this._parent.Get(url)){this.Utils.LoadURL(URL, this.Utils.GetOption(this.Strings.Options.SearchInTab, "bool"));return this._parent.JSONDecode(text);}return this._parent.JSONDecode("{[]}");SearchTermsTextEntered: function (param){answers: function(questionList) {this.Utils.Log('Entering SearchTermsTextEntered');this._parent.Log('questions.answers(' + questionList + ')');this.Search(null, 'sob_search');var text = null;if (questionList != 0 || questionList != null) {var url = this._parent._mainURL + this._parent._apiVer + "/questions/" + questionList + '/answers';if (text = this._parent.Get(url)){return this._parent.JSONDecode(text);}}return this._parent.JSONDecode("{[]}");}},users: {_parent: null,find: function(userList){this._parent.Log('users.find(' + userList + ')');return this._parent.JSONDecode("{[]}");GetTerms: function () {answers: function(userList){this.Utils.Log('Entering GetTerms');this._parent.Log('users.answers(' + userList + ')');var terms = document.getElementById("SOB-SearchTerms");return this._parent.JSONDecode("{[]}");return terms.value;SetTerms: function (newTerms) {timeline: function (userList){this.Utils.Log('Entering SetTerms');this._parent.Log('users.timeline(' + userList + ')');var terms = document.getElementById("SOB-SearchTerms");var text = null;terms.value = newTerms;if (userList != 0 || userList != null) {var url = this._parent._mainURL + this._parent._apiVer + "/users/" + userList + '/timeline';if (text = this._parent.Get(url)){return this._parent.JSONDecode(text);}}return this._parent.JSONDecode("{[]}");}},Get: function(url){this.Log('Get: "' + url + '"');this._req.open('GET', url, false);this._req.send(null);if (this._req.status == 200) {return this._req.responseText;}return 0;},JSONDecode: function(json){var JSON = Components.classes["@mozilla.org/dom/json;1"].createInstance(Components.interfaces.nsIJSON);return JSON.decode(json);},Log: function (aMessage) {this._console.logStringMessage('jSapiens: ' + aMessage);}}org.gcarreno.StackOverflowBar = {searchHistory: Components.classes["@mozilla.org/satchel/form-history;1"].getService(Components.interfaces.nsIFormHistory2 || Components.interfaces.nsIFormHistory),_first_run: null,JSON: null,Preferences: null,Strings: {Constants: {Protocol: "http",Host: "stackoverflow.com",Ask: "/questions/ask",Home: {Active: "/?tab=active",Featured: "/?tab=featured",Hot: "/?tab=hot",Week: "/?tab=week",Month: "/?tab=month"},Questions: {Newest: "/questions?sort=newest",Featured: "/questions?sort=featured",Hot: "/questions?sort=hot",Votes: "/questions?sort=votes",Active: "/questions?sort=active"},UnAnswered: {MyTags: "/unanswered/tagged?tab=mytags",Newest: "/unanswered/tagged?tab=newest",Votes: "/unanswered/tagged?tab=votes"},User: {Stats: "/users/%s?tab=stats#tab-top",Activity: "/users/%s?tab=activity#tab-top",Reputation: "/users/%s?tab=reputationhistory#tab-top",Favorites: "/users/%s?tab=favorites#tab-top",Preferences: "/users/%s?tab=preferences#tab-top",Accounts: "/users/%s?tab=accounts#tab-top",Recent: "/users/recent/%s?tab=summary#tab-top",RecentRep: "/users/recent/%s?tab=reputation#tab-top",Responses: "/users/recent/%s?tab=responses#tab-top",Revisions: "/users/recent/%s?tab=revisions#tab-top",Badges: "/users/recent/%s?tab=badges#tab-top"}ButtonClick: function (buttonName) {Buttons: {this.Utils.Log('Entering ButtonClick: ' + buttonName);Search: "button_search",Ask: "button_ask",TabActive: "button_tab_active",TabFeatured: "button_tab_featured",TabHot: "button_tab_hot",TabWeek: "button_tab_week",TabMonth: "button_tab_month",Featured: "button_featured",New: "button_new",Hot: "button_hot",Votes: "button_votes",Active: "button_active",TabMyTags: "button_tab_mytags",TabNewest: "button_tab_newest",TabVotes: "button_tab_votes",UserStats: "button_user_stats",UserActivity: "button_user_actvity",UserReputation: "button_user_reputation",UserFavorites: "button_user_favorites",UserPreferences: "button_user_preferences",UserAccounts: "button_user_accounts",const buttons = this.Strings.Buttons;UserRecentSummary: "button_user_recent_summary",const consts = this.Strings.Constants;UserRecentReputation: "button_user_recent_reputation",const homepage = consts.Home;UserRecentResponses: "button_user_recent_responses",const questions = consts.Questions;UserRecentRevisions: "button_user_recent_revisions",const unanswered = consts.UnAnswered;UserRecentBadges: "button_user_recent_badges",const user = consts.User;ShowOptions: "button_show_options",const opts = this.Strings.Options;ShowOverview: "button_show_overview"var loadURL = this.Utils.LoadURL;var inNewTab = this.Utils.GetOption(opts.ButtonsInTab, "bool");var userID = this.Utils.GetOption(opts.UserID, "string");switch (buttonName) {case buttons.Ask:loadURL(consts.Protocol + "://" +consts.Host + consts.Ask, inNewTab);break;case buttons.TabActive:loadURL(consts.Protocol + "://" +consts.Host + homepage.Active, inNewTab);break;case buttons.TabFeatured:loadURL(consts.Protocol + "://" +consts.Host + homepage.Featured, inNewTab);break;case buttons.TabHot:loadURL(consts.Protocol + "://" +consts.Host + homepage.Hot, inNewTab);break;case buttons.TabWeek:loadURL(consts.Protocol + "://" +consts.Host + homepage.Week, inNewTab);break;case buttons.TabMonth:loadURL(consts.Protocol + "://" +consts.Host + homepage.Month, inNewTab);break;case buttons.New:loadURL(consts.Protocol + "://" +consts.Host + questions.Newest, inNewTab);break;case buttons.Featured:loadURL(consts.Protocol + "://" +consts.Host + questions.Featured, inNewTab);break;case buttons.Hot:loadURL(consts.Protocol + "://" +consts.Host + questions.Hot, inNewTab);break;case buttons.Votes:loadURL(consts.Protocol + "://" +consts.Host + questions.Votes, inNewTab);break;case buttons.Active:loadURL(consts.Protocol + "://" +consts.Host + questions.Active, inNewTab);break;case buttons.TabMyTags:loadURL(consts.Protocol + "://" +consts.Host + unanswered.MyTags, inNewTab);break;case buttons.TabNewest:loadURL(consts.Protocol + "://" +consts.Host + unanswered.Newest, inNewTab);break;case buttons.TabVotes:loadURL(consts.Protocol + "://" +consts.Host + unanswered.Votes, inNewTab);break;case buttons.UserStats:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Stats, userID), inNewTab);break;case buttons.UserActivity:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Activity, userID), inNewTab);break;case buttons.UserReputation:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Reputation, userID), inNewTab);break;case buttons.UserFavorites:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Favorites, userID), inNewTab);break;case buttons.UserPreferences:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Preferences, userID), inNewTab);break;case buttons.UserAccounts:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Accounts, userID), inNewTab);break;case buttons.UserRecentSummary:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Recent, userID), inNewTab);break;case buttons.UserRecentReputation:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.RecentRep, userID), inNewTab);break;case buttons.UserRecentResponses:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Responses, userID), inNewTab);break;case buttons.UserRecentRevisions:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Revisions, userID), inNewTab);break;case buttons.UserRecentBadges:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Badges, userID), inNewTab);break;case buttons.ShowOptions:this.Utils.ShowOptions();break;case buttons.ShowOverview:this.Utils.ShowOverview();break;case buttons.Test:this.Utils.Test();break;}PrepareContextSearch: function (event, search) {Options: {this.Utils.Log('Entering PrepareContextSearch');SearchInTab: "search_in_tab",// ****************************************ButtonsInTab: "buttons_in_tab",// Step 1: Get the selected textUserID: "user_id"// ****************************************}},Search: function (event, type) {this.Utils.Log('Entering Search: ' + type);var URL = "";var isEmpty = false;var searchTerms = this.Utils.TrimString(this.GetTerms());if (searchTerms.length == 0) {isEmpty = true;} else {this.searchHistory.addEntry("SOB-SearchTerms-History", searchTerms);searchTerms = this.Utils.ConvertTermsToURI(searchTerms);}switch(type){case "sob_search":if(!isEmpty) {URL = this.Strings.Constants.Protocol + "://" +this.Strings.Constants.Host + "/search?q=" +searchTerms;}break;}if (!isEmpty) {this.Utils.LoadURL(URL, this.Utils.GetOption(this.Strings.Options.SearchInTab, "bool"));}},SearchTermsTextEntered: function (param){this.Utils.Log('Entering SearchTermsTextEntered');this.Search(null, 'sob_search');},GetTerms: function () {this.Utils.Log('Entering GetTerms');var terms = document.getElementById("SOB-SearchTerms");return terms.value;},SetTerms: function (newTerms) {this.Utils.Log('Entering SetTerms');var terms = document.getElementById("SOB-SearchTerms");terms.value = newTerms;},ButtonClick: function (buttonName) {this.Utils.Log('Entering ButtonClick: ' + buttonName);var node = document.popupNode;const buttons = this.Strings.Buttons;var selection = "";const consts = this.Strings.Constants;var nodeLocalName = node.localName.toLowerCase();const homepage = consts.Home;const questions = consts.Questions;const unanswered = consts.UnAnswered;const user = consts.User;const opts = this.Strings.Options;if((nodeLocalName == "textarea") || (nodeLocalName == "input" && node.type == "text"))var loadURL = this.Utils.LoadURL;selection = node.value.substring(node.selectionStart, node.selectionEnd);else{var focusedWindow = document.commandDispatcher.focusedWindow;selection = focusedWindow.getSelection().toString();}// Limit the selection lengthvar inNewTab = this.Utils.GetOption(opts.ButtonsInTab, "bool");if(selection.length >= 150)var userID = this.Utils.GetOption(opts.UserID, "string");selection = selection.substring(0, 149);// ****************************************switch (buttonName) {// Step 2: Clean up the selected textcase buttons.Ask:// ****************************************loadURL(consts.Protocol + "://" +consts.Host + consts.Ask, inNewTab);break;case buttons.TabActive:loadURL(consts.Protocol + "://" +consts.Host + homepage.Active, inNewTab);break;case buttons.TabFeatured:loadURL(consts.Protocol + "://" +consts.Host + homepage.Featured, inNewTab);break;case buttons.TabHot:loadURL(consts.Protocol + "://" +consts.Host + homepage.Hot, inNewTab);break;case buttons.TabWeek:loadURL(consts.Protocol + "://" +consts.Host + homepage.Week, inNewTab);break;case buttons.TabMonth:loadURL(consts.Protocol + "://" +consts.Host + homepage.Month, inNewTab);break;case buttons.New:loadURL(consts.Protocol + "://" +consts.Host + questions.Newest, inNewTab);break;case buttons.Featured:loadURL(consts.Protocol + "://" +consts.Host + questions.Featured, inNewTab);break;case buttons.Hot:loadURL(consts.Protocol + "://" +consts.Host + questions.Hot, inNewTab);break;case buttons.Votes:loadURL(consts.Protocol + "://" +consts.Host + questions.Votes, inNewTab);break;case buttons.Active:loadURL(consts.Protocol + "://" +consts.Host + questions.Active, inNewTab);break;case buttons.TabMyTags:loadURL(consts.Protocol + "://" +consts.Host + unanswered.MyTags, inNewTab);break;case buttons.TabNewest:loadURL(consts.Protocol + "://" +consts.Host + unanswered.Newest, inNewTab);break;case buttons.TabVotes:loadURL(consts.Protocol + "://" +consts.Host + unanswered.Votes, inNewTab);break;case buttons.UserStats:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Stats, userID), inNewTab);break;case buttons.UserActivity:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Activity, userID), inNewTab);break;case buttons.UserReputation:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Reputation, userID), inNewTab);break;case buttons.UserFavorites:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Favorites, userID), inNewTab);break;case buttons.UserPreferences:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Preferences, userID), inNewTab);break;case buttons.UserAccounts:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Accounts, userID), inNewTab);break;case buttons.UserRecentSummary:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Recent, userID), inNewTab);break;case buttons.UserRecentReputation:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.RecentRep, userID), inNewTab);break;case buttons.UserRecentResponses:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Responses, userID), inNewTab);break;case buttons.UserRecentRevisions:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Revisions, userID), inNewTab);break;case buttons.UserRecentBadges:loadURL(consts.Protocol + "://" +consts.Host + this.Utils.sprintf(user.Badges, userID), inNewTab);break;case buttons.ShowOptions:this.Utils.ShowOptions();break;case buttons.ShowOverview:this.Utils.ShowOverview();break;}},PrepareContextSearch: function (event, search) {this.Utils.Log('Entering PrepareContextSearch');// ****************************************// Step 1: Get the selected text// ****************************************var node = document.popupNode;var selection = "";var nodeLocalName = node.localName.toLowerCase();if((nodeLocalName == "textarea") || (nodeLocalName == "input" && node.type == "text"))selection = node.value.substring(node.selectionStart, node.selectionEnd);else{var focusedWindow = document.commandDispatcher.focusedWindow;selection = focusedWindow.getSelection().toString();}// Limit the selection lengthif(selection.length >= 150)selection = selection.substring(0, 149);// ****************************************// Step 2: Clean up the selected text// ****************************************selection = this.Utils.TrimString(selection); // Clean up whitespaceselection = this.Utils.TrimString(selection); // Clean up whitespacevar selArray = selection.split(" ");for(var i=0; i<selArray.length; i++)var selArray = selection.split(" ");{for(var i=0; i<selArray.length; i++)selArray[i] = selArray[i].replace(/^(\&|\(|\)|\[|\]|\{|\}|\"|,|\.|!|\?|'|:|;)+/, "");{selArray[i] = selArray[i].replace(/(\&|\(|\)|\[|\]|\{|\}|\"|,|\.|!|\?|'|:|;)+$/, "");selArray[i] = selArray[i].replace(/^(\&|\(|\)|\[|\]|\{|\}|\"|,|\.|!|\?|'|:|;)+/, "");}selArray[i] = selArray[i].replace(/(\&|\(|\)|\[|\]|\{|\}|\"|,|\.|!|\?|'|:|;)+$/, "");}selection = selArray.join(" ");// ****************************************// Step 3: Update the search box// ****************************************this.SetTerms(selection);// ****************************************// Step 4: Perform the search// ****************************************this.Search(event, search);},UpdateContextMenuVisibility: function () {this.Utils.Log('Entering UpdateContextMenuVisibility');//Todo},UpdateContextMenu: function () {this.Utils.Log('Entering UpdateContextMenu');var contextMenu = document.getElementById('SOB-Context');var node = document.popupNode;var selection = "";var nodeLocalName = node.localName.toLowerCase();if((nodeLocalName == "textarea") || (nodeLocalName == "input" && node.type == "text"))selection = node.value.substring(node.selectionStart, node.selectionEnd);else{var focusedWindow = document.commandDispatcher.focusedWindow;selection = focusedWindow.getSelection().toString();}this.Utils.Log('Selection: ' + selection);if (selection.length == 0) {contextMenu.setAttribute('disabled', 'true');} else {contextMenu.setAttribute('disabled', 'false');}return true;},ProgressListener: function () {this.Utils.Log('Entering ProgressListener');//Todo},Init: function() {this.Utils.Log('Entering Init');selection = selArray.join(" ");this.Utils.Log('Importing Preferences.jsm');try {Components.utils.import("resource://stackoverflowbar/Preferences.jsm", org.gcarreno.StackOverflowBar);this.Utils.Log("Module Preferences imported");} catch(e) {this.Utils.Log("Error: " + e.message);}org.gcarreno.jSapiens.init();this.Database.init();this.Overview.init();this.Timeline.my_turn();// ****************************************var mainItem = document.getElementById("SOB-Main-Item");// Step 3: Update the search box// Only initialize if the main toolbar item is present// ****************************************if(mainItem){this._first_run = this.Utils.GetOption('first_run', 'bool');if (this._first_run) {this.Utils.Log('First run');this.Utils.SetOption('first_run', 'bool', false);this.Database.CreateDB()}this.UpdateContextMenuVisibility(); // Todo}},Finalise: function () {this.Utils.Log('Entering Finalise');//if (typeof window.getBrowser != 'undefined') {// window.getBrowser().removeProgressListener(this.ProgressListener);//}},Database: {_sobU: null,_file: "sob-database.db",_dirS: Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties),_dir: null,this.SetTerms(selection);_storage: Components.classes["@mozilla.org/storage/service;1"].getService(Components.interfaces.mozIStorageService),_console: Components.classes['@mozilla.org/consoleservice;1'].getService(Components.interfaces.nsIConsoleService),_dbConn: null,// ****************************************init: function() {// Step 4: Perform the searchthis.Log('Entering init');// ****************************************try {this.Log('File: ' + this._file);this._dir = this._dirS.get("ProfD", Components.interfaces.nsIFile);this._dir.append("StackOverflowBar");} catch(e) {this.Log('Error: ' +e.message);}if (!this._dir.exists() || !this._dir.isDirectory) {this.Log('Folder does not exist, creating');this._dir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0774);}try {this._dir.append(this._file);} catch(e) {this.Log('Error: ' +e.message);}if (!this._dir.exists()) {this.Log('File missing, will create on DB Connect');}try {this._dbConn =this._storage.openDatabase(this._dir);} catch(e) {this.Log('Error: ' +e.message);}},this.Search(event, search);CreateDB: function() {this.Log('Creating Database');this._dbConn.executeSimpleSQL("CREATE TABLE timeline (date INTEGER, type STRING)");UpdateContextMenuVisibility: function () {this.Utils.Log('Entering UpdateContextMenuVisibility');Log: function (aMessage) {//Todothis._console.logStringMessage('StackOverflowBar.Database: ' + aMessage);}},Timeline: {_console: Components.classes['@mozilla.org/consoleservice;1'].getService(Components.interfaces.nsIConsoleService),Log: function(aMessage) {this._console.logStringMessage('StackOverflowBar.Timeline: ' + aMessage);UpdateContextMenu: function () {my_turn: function() {this.Utils.Log('Entering UpdateContextMenu');return;var contextMenu = document.getElementById('SOB-Context');var timeout = org.gcarreno.StackOverflowBar.Utils.GetOption('timeout');var node = document.popupNode;window.setTimeout(function() {var selection = "";org.gcarreno.StackOverflowBar.Timeline.my_turn();var nodeLocalName = node.localName.toLowerCase();}, timeout * 60 * 1000);if((nodeLocalName == "textarea") || (nodeLocalName == "input" && node.type == "text"))}selection = node.value.substring(node.selectionStart, node.selectionEnd);},elseOverview : {{_sob: null,var focusedWindow = document.commandDispatcher.focusedWindow;_sobU: null,selection = focusedWindow.getSelection().toString();_sobD: null,_jSapiens: null,_console: Components.classes['@mozilla.org/consoleservice;1'].getService(Components.interfaces.nsIConsoleService),init: function(){this.Log('init');if (typeof org.gcarreno.StackOverflowBar != 'undefined') {this.Log('Can reach SOB');this._sob = org.gcarreno.StackOverflowBar;this.Utils.Log('Selection: ' + selection);if (typeof org.gcarreno.StackOverflowBar.Database != 'undefined') {if (selection.length == 0) {this.Log('Can reach SOB.D');contextMenu.setAttribute('disabled', 'true');this._sobD = org.gcarreno.StackOverflowBar.Database;} else {contextMenu.setAttribute('disabled', 'false');return true;if (typeof org.gcarreno.StackOverflowBar.Utils != 'undefined') {this.Log('Can reach SOB.U');this._sobU = org.gcarreno.StackOverflowBar.Utils;}if (typeof org.gcarreno.jSapiens != 'undefined') {this.Log('Can reach jSapiens');this._jSapiens = org.gcarreno.jSapiens;}ProgressListener: function () {this.Utils.Log('Entering ProgressListener');refresh: function () {//Todovar contents = document.getElementById('SOB-overview-contents');},Init: function() {var api_answer = this._jSapiens.users.timeline(this._sobU.GetOption('user_id'));this.Utils.Log('Entering Init');var b_value = '';var mainItem = document.getElementById("SOB-Main-Item");// Only initialize if the main toolbar item is presentb_value += 'User Timeline:\n';if(mainItem)b_value += '\tTotal: ' + api_answer.total + '\n';{if (this.oneTime == false) {if (api_answer.total > 0) {this.oneTime = true;for (var x = 0; x < api_answer.user_timelines.length; x++) {//window.getBrowser().addProgressListener(this.ProgressListener, Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);b_value += '\t\tUser: ' + api_answer.user_timelines[x].user_id + '\n';this.UpdateContextMenuVisibility(); // Todob_value += '\t\t\ttype: ' + api_answer.user_timelines[x].timeline_type + '\n';switch (api_answer.user_timelines[x].timeline_type) {case "comment":b_value += '\t\t\taction: ' + api_answer.user_timelines[x].action + '\n';b_value += '\t\t\tdescription: ' + api_answer.user_timelines[x].description + '\n';b_value += '\t\t\tdetail: ' + api_answer.user_timelines[x].detail + '\n';break;case "revision":b_value += '\t\t\taction: ' + api_answer.user_timelines[x].action + '\n';b_value += '\t\t\tdescription: ' + api_answer.user_timelines[x].description + '\n';b_value += '\t\t\tdetail: ' + api_answer.user_timelines[x].detail + '\n';break;case "badge":b_value += '\t\t\taction: ' + api_answer.user_timelines[x].action + '\n';b_value += '\t\t\tdescription: ' + api_answer.user_timelines[x].description + '\n';b_value += '\t\t\tdetail: ' + api_answer.user_timelines[x].detail + '\n';break;case "accepted":b_value += '\t\t\taction: ' + api_answer.user_timelines[x].action + '\n';b_value += '\t\t\tdescription: ' + api_answer.user_timelines[x].description + '\n';break;case "askoranswered":b_value += '\t\t\taction: ' + api_answer.user_timelines[x].action + '\n';b_value += '\t\t\tdescription: ' + api_answer.user_timelines[x].description + '\n';break;}var creation_date = new Date(api_answer.user_timelines[x].creation_date * 1000);b_value += '\t\t\tDate: ' + creation_date + '\n';//b_value += '\t\t\tviews: ' + api_answer.user_timelines[x].view_count + '\n';Finalise: function () {this.Utils.Log('Entering Finalise');Log: function (aMessage) {//if (typeof window.getBrowser != 'undefined') {this._console.logStringMessage('StackOverflowBar.Overview: ' + aMessage);// window.getBrowser().removeProgressListener(this.ProgressListener);}//}},Utils: {consoleService: Components.classes['@mozilla.org/consoleservice;1'].getService(Components.interfaces.nsIConsoleService),prefService: Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService),_sob_prefs: null,Log: function (aMessage) {this.consoleService.logStringMessage('StackOverflowBar: ' + aMessage);Utils: {GetOption: function(optName, optType) {consoleService: Components.classes['@mozilla.org/consoleservice;1']if (this._sob_prefs == null) {.getService(Components.interfaces.nsIConsoleService),this._sob_prefs = new org.gcarreno.StackOverflowBar.Preferences("extensions.stackoverflowbar.");prefService: Components.classes["@mozilla.org/preferences-service;1"]}.getService(Components.interfaces.nsIPrefService),var result = this._sob_prefs.get(optName);Log: function (aMessage) {this.consoleService.logStringMessage('StackOverflowBar: ' + aMessage);this.Log('Prefs get: ' + optName + ': '+ result);},GetOption: function(optName, optType) {return result;const branch = this.prefService.getBranch("extensions.stackoverflowbar.");},SetOption: function(optName, optType, optValue) {if (this._sob_prefs == null) {this._sob_prefs = new org.gcarreno.StackOverflowBar.Preferences("extensions.stackoverflowbar.");}this.Log('Prefs set: ' + optName + ': '+ optValue);this._sob_prefs.set(optName, optValue);},LoadOptions: function () {const options = org.gcarreno.StackOverflowBar.Strings.Options;document.getElementById("SOB-Opt-SearchInTab").checked =this.GetOption(options.SearchInTab, "bool");document.getElementById("SOB-Opt-ButtonsInTab").checked =this.GetOption(options.ButtonsInTab, "bool");var result = null;//document.getElementById("SOB-Opt-UseAPI").checked =// this.GetOption(options.UseAPI, "bool");switch (optType) {document.getElementById("SOB-Opt-UserID").value =case "bool":this.GetOption(options.UserID, "string");try {},result = branch.getBoolPref(optName);SaveOptions: function () {} catch (e) {const options = org.gcarreno.StackOverflowBar.Strings.Options;result = false;}break;case "string":try {result = branch.getCharPref(optName);} catch (e) {result = '';}break;case "int":try {result = branch.getIntPref(optName);} catch (e) {result = 0;}break;}return result;},SetOption: function(optName, optType, optValue) {const branch = this.prefService.getBranch("extensions.stackoverflowbar.");switch (optType) {case "bool":branch.setBoolPref(optName, optValue);break;case "string":branch.setCharPref(optName, optValue);break;case "int":branch.setIntPref(optName, optValue);break;}},LoadOptions: function () {const options = org.gcarreno.StackOverflowBar.Strings.Options;document.getElementById("SOB-Opt-SearchInTab").checked =this.GetOption(options.SearchInTab, "bool");document.getElementById("SOB-Opt-ButtonsInTab").checked =this.GetOption(options.ButtonsInTab, "bool");//document.getElementById("SOB-Opt-UseAPI").checked =// this.GetOption(options.UseAPI, "bool");document.getElementById("SOB-Opt-UserID").value =this.GetOption(options.UserID, "string");},SaveOptions: function () {const options = org.gcarreno.StackOverflowBar.Strings.Options;this.SetOption(options.SearchInTab, "bool",document.getElementById("SOB-Opt-SearchInTab").checked);document.getElementById("SOB-Opt-SearchInTab").checked);this.SetOption(options.ButtonsInTab, "bool",document.getElementById("SOB-Opt-ButtonsInTab").checked);document.getElementById("SOB-Opt-ButtonsInTab").checked);//this.SetOption(options.UseAPI, "bool",// document.getElementById("SOB-Opt-UseAPI").checked);this.SetOption(options.UserID, "string",//this.SetOption(options.UseAPI, "bool",document.getElementById("SOB-Opt-UserID").value);// document.getElementById("SOB-Opt-UseAPI").checked);},ShowOptions: function () {this.SetOption(options.UserID, "string",var flags = "chrome,centerscreen,modal";document.getElementById("SOB-Opt-UserID").value);window.openDialog("chrome://stackoverflowbar/content/options.xul", "Options", flags);},},ShowOptions: function () {ShowOverview: function () {var flags = "chrome,centerscreen,modal";var flags = "chrome,centerscreen,resizable";window.openDialog("chrome://stackoverflowbar/content/options.xul", "&sobar.options.title;", flags);window.openDialog("chrome://stackoverflowbar/content/overview.xul", "Overview", flags);},},ShowOverview: function () {LoadURL: function (aURL, inNewTab) {var flags = "chrome,centerscreen,resizable";if(inNewTab)window.openDialog("chrome://stackoverflowbar/content/overview.xul", "&sobar.overview.title;", flags);{},var browser = window.getBrowser();LoadURL: function (aURL, inNewTab) {var newTab = browser.addTab(aURL);if(inNewTab)browser.selectedTab = newTab;{var browser = window.getBrowser();var newTab = browser.addTab(aURL);browser.selectedTab = newTab;}else{var content = window.content;content.document.location = aURL;content.focus();}},LoadHomepage: function (event) {const options = org.gcarreno.StackOverflowBar.Strings.Options;const consts = org.gcarreno.StackOverflowBar.Strings.Constants;var inNewTab = this.GetOption(options.ButtonsInTab, "bool");var URL = consts.Protocol + "://" + consts.Host;this.LoadURL(URL, inNewTab);event.stopPropagation();},LoadAboutURL: function (aWhere) {var url = "";switch(aWhere) {case 'home':url = 'http://guscarreno.blogspot.com/p/stack-overflow-bar.html'break;case 'support':url = 'http://www.assembla.com/spaces/StackOverflowBar'break;}var windowService = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);var currentWindow = windowService.getMostRecentWindow("navigator:browser");if(currentWindow){try {currentWindow.delayedOpenTab(url);} catch(e) {currentWindow.loadURI(url);else}{elsevar content = window.content;window.open(url);content.document.location = aURL;},content.focus();TrimString: function (string) {if (!string) {return "";},string = string.replace(/^\s+/, '');LoadHomepage: function (event) {string = string.replace(/\s+$/, '');const options = org.gcarreno.StackOverflowBar.Strings.Options;string = string.replace(/\s+/g, ' ');const consts = org.gcarreno.StackOverflowBar.Strings.Constants;return string;},var inNewTab = this.GetOption(options.ButtonsInTab, "bool");ConvertTermsToURI: function (terms) {var URL = consts.Protocol + "://" + consts.Host;var termArray = new Array();this.LoadURL(URL, inNewTab);termArray = terms.split(" ");event.stopPropagation();var result = "";},for (var i = 0; i < termArray.length; i++) {LoadAboutURL: function (aWhere) {if (i > 0) {var url = "";result += "+";switch(aWhere) {case 'home':url = 'http://gcarreno.org/stackoverflowbar/'break;case 'support':url = 'http://www.assembla.com/spaces/StackOverflowBar'break;result += encodeURIComponent(termArray[i]);var windowService = Components.classes["@mozilla.org/appshell/window-mediator;1"]}.getService(Components.interfaces.nsIWindowMediator);return result;var currentWindow = windowService.getMostRecentWindow("navigator:browser");},DoNothing: function () {},if(currentWindow){try {currentWindow.delayedOpenTab(url);} catch(e) {currentWindow.loadURI(url);}}elsewindow.open(url);},TrimString: function (string) {if (!string) {return "";}string = string.replace(/^\s+/, '');string = string.replace(/\s+$/, '');string = string.replace(/\s+/g, ' ');return string;},ConvertTermsToURI: function (terms) {var termArray = new Array();termArray = terms.split(" ");var result = "";for (var i = 0; i < termArray.length; i++) {if (i > 0) {result += "+";}result += encodeURIComponent(termArray[i]);}return result;},Test: function(){this.Log('Testing button');var box = document.getElementById('SOB-Test-Box');var strings = org.gcarreno.StackOverflowBar.Strings;var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);var url = this.sprintf(strings.Constants.Protocol + "://" +strings.Constants.Host +strings.API.UserFlair,this.GetOption(strings.Options.UserID, 'string'));box.value = '';this.Log('Req: ' + url);req.open('GET', url, false);req.send(null);if (req.status == 200) {var JSON = Components.classes["@mozilla.org/dom/json;1"].createInstance(Components.interfaces.nsIJSON);var flair = JSON.decode(req.responseText);box.value = this.sprintf("Name: %s\nID: %s\n\n" + req.responseText, flair.displayName, flair.id);} else {box.value = 'Treta';}},DoNothing: function () {},* sprintf() for JavaScript v.0.4** Copyright (c) 2007 Alexandru Marasteanu <http://alexei.417.ro/>* Thanks to David Baird (unit test and patch).** This program is free software; you can redistribute it and/or modify it under* the terms of the GNU General Public License as published by the Free Software* Foundation; either version 2 of the License, or (at your option) any later* version.** This program is distributed in the hope that it will be useful, but WITHOUT* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more* details.** You should have received a copy of the GNU General Public License along with* this program; if not, write to the Free Software Foundation, Inc., 59 Temple* Place, Suite 330, Boston, MA 02111-1307 USA*/str_repeat: function (i, m) {str_repeat: function (i, m) {for (var o = []; m > 0; o[--m] = i); return(o.join(''));for (var o = []; m > 0; o[--m] = i); return(o.join(''));},sprintf: function () {sprintf: function () {var i = 0, a, f = arguments[i++], o = [], m, p, c, x;while (f) {while (f) {if (m = /^[^\x25]+/.exec(f)) o.push(m[0]);else if (m = /^\x25{2}/.exec(f)) o.push('%');else if (m = /^\x25{2}/.exec(f)) o.push('%');else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) {else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) {if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) throw("Too few arguments.");if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) throw("Too few arguments.");if (/[^s]/.test(m[7]) && (typeof(a) != 'number'))throw("Expecting number but found " + typeof(a));throw("Expecting number but found " + typeof(a));switch (m[7]) {switch (m[7]) {case 'b': a = a.toString(2); break;case 'c': a = String.fromCharCode(a); break;case 'd': a = parseInt(a); break;case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break;case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break;case 'o': a = a.toString(8); break;case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break;case 'u': a = Math.abs(a); break;case 'x': a = a.toString(16); break;case 'X': a = a.toString(16).toUpperCase(); break;}a = (/[def]/.test(m[7]) && m[2] && a > 0 ? '+' + a : a);c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' ';x = m[5] - String(a).length;p = m[5] ? this.str_repeat(c, x) : '';o.push(m[4] ? a + p : p + a);}else throw ("Huh ?!");f = f.substring(m[0].length);return o.join('');a = (/[def]/.test(m[7]) && m[2] && a > 0 ? '+' + a : a);c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' ';x = m[5] - String(a).length;p = m[5] ? this.str_repeat(c, x) : '';o.push(m[4] ? a + p : p + a);}else throw ("Huh ?!");f = f.substring(m[0].length);return o.join('');window.addEventListener("load", function () { return org.gcarreno.StackOverflowBar.Init(); }, false);window.addEventListener("load", function () {return org.gcarreno.StackOverflowBar.Init(); } , false);window.addEventListener("unload", function () {return org.gcarreno.StackOverflowBar.Finalise(); } , false);window.addEventListener("unload", function () {return org.gcarreno.StackOverflowBar.Finalise(); } , false);<?xml-stylesheet href="chrome://stackoverflowbar/skin/stackoverflowbar.css" type="text/css"?>type="text/css"?><!ENTITY sobar.options.about.text1 "StackOverflow Bar v0.2.0.329"><!ENTITY sobar.options.about.text1 "StackOverflow Bar v0.3.0.330"><!ENTITY sobar.options.about.text1 "Barra Stack Overflow v0.2.0.329"><!ENTITY sobar.options.about.text1 "Barra Stack Overflow v0.3.0.330">em:version="0.2.0.329"em:version="0.3.0.330"