forked from karpathy/arxiv-sanity-preserver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathas-common.js
246 lines (219 loc) · 10.1 KB
/
as-common.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// various JS utilities shared by all templates
// helper function so that we can access keys in url bar
var QueryString = function () {
// This function is anonymous, is executed immediately and
// the return value is assigned to QueryString!
var query_string = {};
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
// If first entry with this name
if (typeof query_string[pair[0]] === "undefined") {
query_string[pair[0]] = decodeURIComponent(pair[1]);
// If second entry with this name
} else if (typeof query_string[pair[0]] === "string") {
var arr = [ query_string[pair[0]],decodeURIComponent(pair[1]) ];
query_string[pair[0]] = arr;
// If third or later entry with this name
} else {
query_string[pair[0]].push(decodeURIComponent(pair[1]));
}
}
return query_string;
}();
function jq( myid ) { return myid.replace( /(:|\.|\[|\]|,)/g, "\\$1" ); } // for dealing with ids that have . in them
function build_ocoins_str(p) {
var ocoins_info = {
"ctx_ver": "Z39.88-2004",
"rft_val_fmt": "info:ofi/fmt:kev:mtx:journal",
"rfr_id": "info:sid/arxiv-sanity.com:arxiv-sanity",
"rft_id": p.link,
"rft.atitle": p.title,
"rft.jtitle": "arXiv:" + p.pid + " [" + p.category.substring(0, p.category.indexOf('.')) + "]",
"rft.date": p.published_time,
"rft.artnum": p.pid,
"rft.genre": "preprint",
// NB: Stolen from Dublin Core; Zotero understands this even though it's
// not part of COinS
"rft.description": p.abstract,
};
ocoins_info = $.param(ocoins_info);
ocoins_info += "&" + $.map(p.authors, function(a) {
return "rft.au=" + encodeURIComponent(a);
}).join("&");
return ocoins_info;
}
function build_authors_html(authors) {
var res = '';
for(var i=0,n=authors.length;i<n;i++) {
var link = '/search?q=' + authors[i].replace(/ /g, "+");
res += '<a href="' + link + '">' + authors[i] + '</a>';
if(i<n-1) res += ', ';
}
return res;
}
function build_categories_html(tags) {
var res = '';
for(var i=0,n=tags.length;i<n;i++) {
var link = '/search?q=' + tags[i].replace(/ /g, "+");
res += '<a href="' + link + '">' + tags[i] + '</a>';
if(i<n-1) res += ' | ';
}
return res;
}
function strip_version(pidv) {
var lst = pidv.split('v');
return lst[0];
}
// populate papers into #rtable
// we have some global state here, which is gross and we should get rid of later.
var pointer_ix = 0; // points to next paper in line to be added to #rtable
var showed_end_msg = false;
function addPapers(num, dynamic) {
if(papers.length === 0) { return true; } // nothing to display, and we're done
var root = d3.select("#rtable");
var base_ix = pointer_ix;
for(var i=0;i<num;i++) {
var ix = base_ix + i;
if(ix >= papers.length) {
if(!showed_end_msg) {
if (ix >= numresults){
var msg = 'Results complete.';
} else {
var msg = 'You hit the limit of number of papers to show in one result.';
}
root.append('div').classed('msg', true).html(msg);
showed_end_msg = true;
}
break;
}
pointer_ix++;
var p = papers[ix];
var div = root.append('div').classed('apaper', true).attr('id', p.pid);
// Generate OpenURL COinS metadata element -- readable by Zotero, Mendeley, etc.
var ocoins_span = div.append('span').classed('Z3988', true).attr('title', build_ocoins_str(p));
var tdiv = div.append('div').classed('paperdesc', true);
tdiv.append('span').classed('ts', true).append('a').attr('href', p.link).attr('target', '_blank').html(p.title);
tdiv.append('br');
tdiv.append('span').classed('as', true).html(build_authors_html(p.authors));
tdiv.append('br');
tdiv.append('span').classed('ds', true).html(p.published_time);
if(p.originally_published_time !== p.published_time) {
tdiv.append('span').classed('ds2', true).html('(v1: ' + p.originally_published_time + ')');
}
tdiv.append('span').classed('cs', true).html(build_categories_html(p.tags));
tdiv.append('br');
tdiv.append('span').classed('ccs', true).html(p.comment);
// action items for each paper
var ldiv = div.append('div').classed('dllinks', true);
// show raw arxiv id
ldiv.append('span').classed('spid', true).html(p.pid);
// access PDF of the paper
var pdf_link = p.link.replace("abs", "pdf"); // convert from /abs/ link to /pdf/ link. url hacking. slightly naughty
if(pdf_link === p.link) { var pdf_url = pdf_link } // replace failed, lets fall back on arxiv landing page
else { var pdf_url = pdf_link + '.pdf'; }
ldiv.append('a').attr('href', pdf_url).attr('target', '_blank').html('pdf');
// rank by tfidf similarity
ldiv.append('br');
var similar_span = ldiv.append('span').classed('sim', true).attr('id', 'sim'+p.pid).html('show similar');
similar_span.on('click', function(pid){ // attach a click handler to redirect for similarity search
return function() { window.location.replace('/' + pid); }
}(p.pid)); // closer over the paper id
// var review_span = ldiv.append('span').classed('sim', true).attr('style', 'margin-left:5px; padding-left: 5px; border-left: 1px solid black;').append('a').attr('href', 'http://www.shortscience.org/paper?bibtexKey='+p.pid).html('review');
var discuss_text = p.num_discussion === 0 ? 'discuss' : 'discuss [' + p.num_discussion + ']';
var discuss_color = p.num_discussion === 0 ? 'black' : 'red';
var review_span = ldiv.append('span').classed('sim', true).attr('style', 'margin-left:5px; padding-left: 5px; border-left: 1px solid black;')
.append('a').attr('href', 'discuss?id='+strip_version(p.pid)).attr('style', 'color:'+discuss_color).html(discuss_text);
ldiv.append('br');
var lib_state_img = p.in_library === 1 ? 'static/saved.png' : 'static/save.png';
var saveimg = ldiv.append('img').attr('src', lib_state_img)
.classed('save-icon', true)
.attr('title', 'toggle save paper to library (requires login)')
.attr('id', 'lib'+p.pid);
// attach a handler for in-library toggle
saveimg.on('click', function(pid, elt){
return function() {
if(username !== '') {
// issue the post request to the server
$.post("/libtoggle", {pid: pid})
.done(function(data){
// toggle state of the image to reflect the state of the server, as reported by response
if(data === 'ON') {
elt.attr('src', 'static/saved.png');
} else if(data === 'OFF') {
elt.attr('src', 'static/save.png');
}
});
} else {
alert('you must be logged in to save papers to library.')
}
}
}(p.pid, saveimg)); // close over the pid and handle to the image
div.append('div').attr('style', 'clear:both');
if(typeof p.img !== 'undefined') {
div.append('div').classed('animg', true).append('img').attr('src', p.img);
}
if(typeof p.abstract !== 'undefined') {
var abdiv = div.append('span').classed('tt', true).html(p.abstract);
if(dynamic) {
MathJax.Hub.Queue(["Typeset",MathJax.Hub,abdiv[0]]); //typeset the added paper
}
}
// in friends tab, list users who the user follows who had these papers in libary
if(render_format === 'friends') {
if(pid_to_users.hasOwnProperty(p.rawpid)) {
var usrtxt = pid_to_users[p.rawpid].join(', ');
div.append('div').classed('inlibsof', true).html('In libraries of: ' + usrtxt);
}
}
// create the tweets
if(ix < tweets.length) {
var ix_tweets = tweets[ix].tweets; // looks a little weird, i know
var tdiv = div.append('div').classed('twdiv', true);
var tcontentdiv = div.append('div').classed('twcont', true);
tdiv.append('div').classed('tweetcount', true).text(tweets[ix].num_tweets + ' tweets:');
for(var j=0,m=ix_tweets.length;j<m;j++) {
var t = ix_tweets[j];
var border_col = t.ok ? '#3c3' : '#fff'; // distinguish non-boring tweets visually making their border green
var timgdiv = tdiv.append('img').classed('twimg', true).attr('src', t.image_url)
.attr('style', 'border: 2px solid ' + border_col + ';');
var act_fun = function(elt, txt, tname, tid, imgelt){ // mouseover handler: show tweet text.
return function() {
elt.attr('style', 'display:block;'); // make visible
elt.html(''); // clear it
elt.append('div').append('a').attr('href', 'https://twitter.com/' + tname + '/status/' + tid).attr('target', '_blank')
.attr('style', 'font-weight:bold; color:#05f; text-decoration:none;').text('@' + tname + ':'); // show tweet source
elt.append('div').text(txt) // show tweet text
imgelt.attr('style', 'border: 2px solid #05f;');
}
}(tcontentdiv, t.text, t.screen_name, t.id, timgdiv)
timgdiv.on('mouseover', act_fun);
timgdiv.on('click', act_fun);
timgdiv.on('mouseout', function(elt, col){
return function() { elt.attr('style', 'border: 2px solid ' + col + ';'); }
}(timgdiv, border_col));
}
}
if(render_format == 'paper' && ix === 0) {
// lets insert a divider/message
div.append('div').classed('paperdivider', true).html('Most similar papers:');
}
}
return pointer_ix >= papers.length; // are we done?
}
function timeConverter(UNIX_timestamp){
var a = new Date(UNIX_timestamp * 1000);
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var year = a.getFullYear();
var month = months[a.getMonth()];
var date = a.getDate().toString();
var hour = a.getHours().toString();
var min = a.getMinutes().toString();
var sec = a.getSeconds().toString();
if(hour.length === 1) { hour = '0' + hour; }
if(min.length === 1) { min = '0' + min; }
if(sec.length === 1) { sec = '0' + sec; }
var time = date + ' ' + month + ' ' + year + ', ' + hour + ':' + min + ':' + sec ;
return time;
}