45862d01bdb1c12cad8d98f404d0574d5f852b11
[mdref/mdref] / public / index.js
1 "use strict";
2
3 $(function() {
4 var mdref = {
5 log: function log() {
6 console.log.apply(console, arguments);
7 },
8 is_constant: function is_constant(s) {
9 s = s.replace(/v\d+(_\d+)?$/, "");
10 if (s.length < 2) {
11 return false;
12 }
13 return s.toUpperCase(s) === s;
14 },
15 is_variable: function is_variable(s) {
16 return s.substring(0,1) === "$";
17 },
18 type: function type(s, nn) {
19 var i, j, t;
20 // mdref.log("type", s);
21 // nothing
22 if (!s.match(/[a-zA-Z]/)) {
23 return;
24 }
25
26 switch (s) {
27 // types
28 case "void":
29 case "bool":
30 case "int":
31 case "float":
32 case "string":
33 case "resource":
34 case "array":
35 case "object":
36 case "callable":
37 case "mixed":
38 // Zend/SPL
39 case "stdClass":
40 case "Exception":
41 case "ErrorException":
42 case "RuntimeException":
43 case "UnexpectedValueException":
44 case "DomainException":
45 case "InvalidArgumentException":
46 case "BadMethodCallException":
47 case "Closure":
48 case "Generator":
49 case "Countable":
50 case "Serializable":
51 case "Traversable":
52 case "Iterator":
53 case "IteratorAggregate":
54 case "ArrayAccess":
55 case "ArrayObject":
56 case "ArrayIterator":
57 case "RecursiveArrayIterator":
58 case "SeekableIterator":
59 case "SplObserver":
60 case "SplSubject":
61 case "SplObjectStorage":
62 case "JsonSerializable":
63 return "<code>";
64
65 // keywords
66 case "is":
67 if (nn !== "H1") {
68 return;
69 }
70 case "extends":
71 case "implements":
72 if (nn === "H1") {
73 return "<br>&nbsp;<em>";
74 }
75 case "class":
76 case "interface":
77 case "namespace":
78 case "public":
79 case "protected":
80 case "private":
81 case "static":
82 case "final":
83 case "abstract":
84 case "self":
85 case "parent":
86 // phrases
87 case "Optional":
88 case "optional":
89 return "<em>";
90 }
91
92 // class members
93 if (-1 !== (i = s.indexOf("::"))) {
94 t = s.substring(i+2);
95 if (!mdref.is_constant(t) && !mdref.is_variable(t)) {
96 // methods
97 return "<a href=\"" + s.replace(/::|\\/g, "/") + "\">";
98 }
99 }
100 if (-1 !== (j = s.lastIndexOf("\\")) && s.substr(j+1,1) !== "n") {
101 t = s.substring(j+1);
102 if (!mdref.is_constant(t) || s.match(/\\/g).length <= 1) {
103 return "<a href=\"" + s.replace(/\\/g, "/").replace(/::/, "#") + "\">";
104 }
105 return "<a href=\"" + s.substring(0,j).replace(/\\/g, "/") + "#" + t + "\">";
106 }
107
108 switch (s.toLowerCase()) {
109 // variables
110 default:
111 if (!mdref.is_variable(s)) {
112 break;
113 }
114 // special constants
115 case "null":
116 case "true":
117 case "false":
118 return "<span class=\"var\">";
119 }
120
121 // constants
122 if (mdref.is_constant(s)) {
123 return "<span class=\"constant\">";
124 }
125 },
126 wrap: function wrap(n, nn) {
127 var $n = $(n)
128 var a = [];
129
130 $n.text().split(/([^a-zA-Z0-9_\\\$:]+)/).forEach(function(v) {
131 var t;
132
133 if ((t = mdref.type(v.replace(/:$/, ""), nn))) {
134 a.push($(t).text(v));
135 } else if (a.length && a[a.length-1].nodeName === "#text") {
136 /* if we already have a text node and the next is also gonna be a text
137 * node, then join them, becuase chrome v30+ or something eats whitespace
138 * for breakfast, lunch and dinner!
139 */
140 a[a.length-1].textContent += v;
141 } else {
142 a.push(document.createTextNode(v));
143 }
144 });
145 $n.replaceWith(a);
146 },
147 walk: function walk(i, e) {
148 // mdref.log("walk", i, e);
149
150 switch (e.nodeName) {
151 case "H1":
152 case "H2":
153 case "H3":
154 case "H4":
155 case "H5":
156 case "H6":
157 if (e.id.length) {
158 var href = document.location.pathname;
159 var perm = $("<a class=\"permalink\" href=\""+href+"#\">#</a>");
160 if (e.nodeName === "H1") {
161 perm.prependTo(e);
162 } else {
163 perm.attr("href", function(i, href) {
164 return href + e.id;
165 });
166 perm.appendTo(e);
167 }
168 }
169 break;
170 }
171
172 $.each($.makeArray(e.childNodes), function(i, n) {
173 switch (n.nodeName) {
174 case "A":
175 case "BR":
176 case "HR":
177 case "EM":
178 case "CODE":
179 case "SPAN":
180 break;
181 case "#text":
182 mdref.wrap(n, e.nodeName);
183 break;
184 default:
185 mdref.walk(-1, n);
186 break;
187 }
188 });
189 },
190 blink: function blink(c) {
191 var $c = $(c);
192
193 $c.fadeOut("fast").queue(function(next) {
194 this.style.color = "red";
195 next();
196 }).fadeIn("fast").fadeOut("slow").queue(function(next) {
197 this.style.color = "";
198 next();
199 }).fadeIn("slow");
200 },
201 hashchange: function hashchange() {
202 if (location.hash.length > 1) {
203 var e;
204 if ((e = document.getElementById(location.hash.substring(1)))) {
205 mdref.blink(e);
206 } else {
207 var hash = location.hash.substring(1);
208 var name = mdref.is_variable(hash) ? ".var" : ".constant";
209 var scrolled = false;
210
211 $(name).each(hash.substring(hash.length-1) === "_" ? function(i, c) {
212 if (c.textContent.substring(0, hash.length) === hash) {
213 if (!scrolled) {
214 $(window).scrollTop($(c).offset().top - 100);
215 scrolled = true;
216 }
217 mdref.blink(c);
218 }
219 } : function(i, c) {
220 if (c.textContent === hash) {
221 $(window).scrollTop($(c).offset().top - 100);
222 mdref.blink(c);
223 return false;
224 }
225 });
226 }
227 }
228 }
229 };
230
231 $("h1,h2,h3,h4,h5,h6,p,li,code,td").each(mdref.walk);
232 $(window).on("hashchange", mdref.hashchange);
233 mdref.hashchange();
234
235 $("#disqus_activator").on("click", function() {
236 var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
237 dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
238 (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
239 });
240 $.ajax("https://disqus.com/api/3.0/threads/details.json?thread:ident="+(disqus_identifier||"index")+"&forum=mdref&api_key=VmhVG4z5jjtY8SCaMstOjfUuwniMv43Xy9FCU9YfEzhsrl95dNz1epykXSJn8jt9"). then(function(json) {
241 if (json && json.response) {
242 $("#disqus_activator span").text(json.response.posts);
243 }
244 });
245 setTimeout(function() {
246 $("footer").addClass("hidden");
247 }, 1000);
248 });