This repository has been archived by the owner on Oct 5, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathsite.js
191 lines (152 loc) · 4.49 KB
/
site.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
;(function() {
// Micro templating
var render = function(string, data) {
for(var s in data) {
string = string.replace(new RegExp('{'+s+'}', 'g'), data[s])
}
return string
}
// Create a template function bound to a
// template string ready for rendering data
// Usage: var tmpl = template('Hi {name}')
// var rendered = tmpl({name: 'Johan'})
// => 'Hi Johan'
var template = function(string) {
return render.bind(this, string)
}
var getExercises = function() {
return $.getJSON('exercises.json').then(function(res) {
return res
})
}
var getReadmeForExercise = function(exercise) {
return $.get('exercises/' + exercise.name + '/README.html')
}
// Matches:
// Svårighetsgrad: <level>
// **Svårighetsgrad: **<level>
// Svårighetsgrad <level>
// etc.
var extractLevel = function(content) {
var matches = content.match(/Svårighetsgrad[\D]*(\d)/i)
return matches ? matches[1] : false
}
// Create a plain object for templating
var transformExercise = function(exercise, i) {
var content = exercise.readme
var files = exercise.files
var name = $(content).filter("h1").first().text()
// Include listing of attached files if there are any
if (files.length > 0) {
var items = []
files.forEach(function(file) {
items.push('<a href="exercises/' + exercise.name + '/' + file + '" download>' + file + '</a>')
})
var filesText = '\n<h2>Filer</h2>\n' + items.join(", ")
// Inject list of files before first h2, or at the end if there are none
var $html = $('<div />', { html: content })
h2s = $html.find('h2')
if (h2s.length > 0) {
h2s.first().before(filesText)
} else {
$html.append(filesText)
}
content = $html.html()
}
return {
order: i,
level: extractLevel(content) || 'Okänd',
text: name, // The first heading
content: content
}
}
// Comparator function for exercises
var sortByLevel = function(exercises) {
return exercises.sort(function(e1, e2) {
return (e1.level > e2.level) ? 1 :
(e1.level < e2.level) ? -1 : 0
})
}
// Build the list from an exercises object array
var renderReadmeList = function(exercises) {
var $container = $(".exercises-list"),
tmpl = template($("#exercise-template").html())
// Render each exercise with 'tmpl', whose only argument
// is a data object (given in Array.map).
return $container.html( exercises.map(tmpl).join("") )
}
// Custom function mimicing Q.all():
// returns a promise whose argument is
// an array with all data objects. Takes
// and array of promises
var whenAll = function(promises) {
var slice = Array.prototype.slice
return $.when.apply($, promises).then(function() {
return slice.call(arguments).map(function(r) {
// The first element is the data object
// The others are the status and the XHR promise itself.
return r[0]
})
})
}
// Fetch READMEs and build list
var fetchReadmes = function() {
// Fetch exercises
getExercises()
// Then for each exercise, fetch its README
.then(function(exercises) {
// Add readme to each exercise
// Could probably be done more elegantly
var dfd = $.Deferred()
// Modify exercise object when all README-fetches have settled
whenAll(exercises.map(getReadmeForExercise)).then(function(readmes) {
readmes.forEach(function(readme, i) {
exercises[i].readme = readme
})
dfd.resolve(exercises)
})
return dfd
})
// Transform each exercise (parse out relevant data for templating)
.then(function(exercises) {
return exercises.map(transformExercise)
})
// Sort by difficulty level
.then(sortByLevel)
// Render the exercises with README content
.then(renderReadmeList)
}
var buildNavigation = (function($) {
var defaults = {
container: "body",
nodes: "h1",
navigation: "[role='navigation'] ul"
}
return function(options) {
options = $.extend({}, defaults, options)
var headings = $(options.container).find(options.nodes),
frag = []
headings.each(function(i, item) {
if(!item.id) return;
var li = $("<li />"),
a = $("<a />", {
href: "#"+item.id,
text: $(item).text(),
"data-scroll": true
})
li.append(a)
frag.push(li)
})
$(options.navigation).html(frag)
}
})(jQuery)
$(function() {
fetchReadmes()
buildNavigation({
container: "[role='main']"
})
$("#accordion").on("shown.bs.collapse", function(evt) {
var panel = $(evt.target)
})
})
})()