mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-17 05:50:25 +01:00
Compare commits
552 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48a7c48f7b | ||
|
|
7a919fbac4 | ||
|
|
181220621e | ||
|
|
249c45dfe2 | ||
|
|
b19d84f1a7 | ||
|
|
865edb70c2 | ||
|
|
e78369f0fa | ||
|
|
d40a6a5c3f | ||
|
|
cb7768d095 | ||
|
|
4290516d29 | ||
|
|
6a7a2301ee | ||
|
|
9a79c58e33 | ||
|
|
4c39c1ec30 | ||
|
|
571cb8b44f | ||
|
|
4207792ffd | ||
|
|
9f67282a79 | ||
|
|
ee71c1cf0d | ||
|
|
06f2284bcd | ||
|
|
8cbe79655a | ||
|
|
a4c1d733b7 | ||
|
|
839649d42f | ||
|
|
504e2aac4a | ||
|
|
eafb41602c | ||
|
|
2dcc4172c4 | ||
|
|
f96a711298 | ||
|
|
ad28b9b339 | ||
|
|
8dd8536f6b | ||
|
|
7bf5b2ec57 | ||
|
|
aa731aa894 | ||
|
|
c58cb257dc | ||
|
|
06f59cf853 | ||
|
|
83b4b5434f | ||
|
|
9de5214a2f | ||
|
|
f08067bab2 | ||
|
|
1160f39cb0 | ||
|
|
d633ecd160 | ||
|
|
4cea313060 | ||
|
|
9b7f8076eb | ||
|
|
571259f241 | ||
|
|
607ee8bbc1 | ||
|
|
36d2f74887 | ||
|
|
cdaf409a99 | ||
|
|
fba487d8a2 | ||
|
|
3ab7306199 | ||
|
|
2e4e94d5f8 | ||
|
|
3348ed3524 | ||
|
|
942a21b4be | ||
|
|
9c14618d55 | ||
|
|
7d50551392 | ||
|
|
f2c1a92513 | ||
|
|
fe6595cd2a | ||
|
|
c2aac916aa | ||
|
|
e161b5387b | ||
|
|
585e5cd88f | ||
|
|
1637ffc5dc | ||
|
|
a28797ee03 | ||
|
|
49e28f9d1e | ||
|
|
4a7cd664fd | ||
|
|
253e11d55b | ||
|
|
eb1c1c78d4 | ||
|
|
0b0d64b52e | ||
|
|
1ae51ef5ea | ||
|
|
de1e3230f5 | ||
|
|
1fbc038e64 | ||
|
|
cd63dd429b | ||
|
|
fbfdf561fc | ||
|
|
83d5a84edd | ||
|
|
5abf02c6d1 | ||
|
|
b8037845d6 | ||
|
|
c80e2552b2 | ||
|
|
1a1fea535b | ||
|
|
5c7da4b686 | ||
|
|
b6ee89a6d8 | ||
|
|
2d8e6bd980 | ||
|
|
a173d61464 | ||
|
|
8f04a136c8 | ||
|
|
b7675e1ec7 | ||
|
|
964fbfe2bb | ||
|
|
8fb8956c0d | ||
|
|
c11920ac08 | ||
|
|
9a4eb26246 | ||
|
|
0d9958afe7 | ||
|
|
d6dd74b50a | ||
|
|
d5437ca8fa | ||
|
|
14720057c2 | ||
|
|
170ed8cc01 | ||
|
|
25576eb35a | ||
|
|
66cb1fb6ad | ||
|
|
bcc65fd879 | ||
|
|
99440585e6 | ||
|
|
290d69d14a | ||
|
|
4fce06677f | ||
|
|
f53cd8b5b6 | ||
|
|
da59f47624 | ||
|
|
521586f08f | ||
|
|
f39a7ada7c | ||
|
|
bae9f46d8b | ||
|
|
d7ea24e218 | ||
|
|
e621d7e601 | ||
|
|
aa6eff4c54 | ||
|
|
f36583e676 | ||
|
|
0a0a91d4b2 | ||
|
|
6c70f9e308 | ||
|
|
b25c3d8b67 | ||
|
|
bade99d069 | ||
|
|
776b51fef7 | ||
|
|
da2d014f00 | ||
|
|
7fdf83089d | ||
|
|
043aafd7b7 | ||
|
|
3254979568 | ||
|
|
6fd202fe36 | ||
|
|
5f00f1e18e | ||
|
|
c940ce3329 | ||
|
|
2366e2b209 | ||
|
|
2b7fd3c9d1 | ||
|
|
d3e37d1716 | ||
|
|
d2b858c997 | ||
|
|
de34c7580f | ||
|
|
bcb492751c | ||
|
|
e26cc79819 | ||
|
|
98cb2d4c17 | ||
|
|
2fc569715c | ||
|
|
3eb594df43 | ||
|
|
8243019a60 | ||
|
|
5a10f7fcfe | ||
|
|
5e89caf358 | ||
|
|
35b40ef650 | ||
|
|
56b7d6cb7c | ||
|
|
8b8a890ac9 | ||
|
|
5645bcee2d | ||
|
|
a631707db4 | ||
|
|
451ffafb9e | ||
|
|
b5274a0d91 | ||
|
|
db4dc03abc | ||
|
|
6be5bcc4c8 | ||
|
|
21efda4a84 | ||
|
|
082375f129 | ||
|
|
1204859263 | ||
|
|
c8b5d1561e | ||
|
|
6912e77d25 | ||
|
|
d84d096e7e | ||
|
|
29c17fd32e | ||
|
|
d721320af5 | ||
|
|
efef9c864c | ||
|
|
27cb837b08 | ||
|
|
047fcbe63f | ||
|
|
dbe0b1551b | ||
|
|
8f7b047b7a | ||
|
|
a38ace0df9 | ||
|
|
0b0b06e8b9 | ||
|
|
f83b61903a | ||
|
|
881fa41bb7 | ||
|
|
f9442db96f | ||
|
|
64521494ce | ||
|
|
e75e3399ab | ||
|
|
e5ef498164 | ||
|
|
24e4be77d8 | ||
|
|
0d55f2ef32 | ||
|
|
8ec3371139 | ||
|
|
ccca4d2914 | ||
|
|
28704a6164 | ||
|
|
cf4ba9d1d3 | ||
|
|
c69e30c146 | ||
|
|
fd32d75d3b | ||
|
|
afa228fd91 | ||
|
|
a01a7ae5fc | ||
|
|
64b071f277 | ||
|
|
af246ad0d7 | ||
|
|
56a87329ec | ||
|
|
eddddc694d | ||
|
|
ce61138351 | ||
|
|
564662ee00 | ||
|
|
678db837fd | ||
|
|
c789f4230d | ||
|
|
1b9e451a6f | ||
|
|
1780b343b4 | ||
|
|
aea3181d27 | ||
|
|
c44461e33f | ||
|
|
221b9bc149 | ||
|
|
dc41c6bc0d | ||
|
|
828d937dec | ||
|
|
cf889cfe25 | ||
|
|
6bab2523d5 | ||
|
|
d714b5c592 | ||
|
|
08316496cd | ||
|
|
d5fd985f0d | ||
|
|
eab7839195 | ||
|
|
18717dd6f5 | ||
|
|
d249f411f8 | ||
|
|
b85e2545d6 | ||
|
|
79280b195e | ||
|
|
4a18728e19 | ||
|
|
b7498416fa | ||
|
|
49b201db0f | ||
|
|
be4d6761b1 | ||
|
|
c01ba1a3cb | ||
|
|
af59ff3209 | ||
|
|
b0a37c6ac5 | ||
|
|
8b3fd9d1e9 | ||
|
|
95b16690e0 | ||
|
|
f6b865a052 | ||
|
|
d1c756306a | ||
|
|
ad5af8e123 | ||
|
|
ba89285c74 | ||
|
|
43c0c2ec2a | ||
|
|
a277104ad5 | ||
|
|
84afffc761 | ||
|
|
5e5680fd13 | ||
|
|
727da38fb6 | ||
|
|
79096cfdce | ||
|
|
a848f82b8f | ||
|
|
71bdd4608b | ||
|
|
f04a948152 | ||
|
|
15be3e52ae | ||
|
|
b1003e954e | ||
|
|
f2b9a7ff0c | ||
|
|
19ad9ab224 | ||
|
|
8eae8a4fb5 | ||
|
|
85fbe38e71 | ||
|
|
e896fd1fd6 | ||
|
|
916150de01 | ||
|
|
732204f11b | ||
|
|
1df50ff855 | ||
|
|
11042858b8 | ||
|
|
89ca2319f5 | ||
|
|
2f4fd310bd | ||
|
|
6d7919ad85 | ||
|
|
59467c906d | ||
|
|
def871ac89 | ||
|
|
6fe5a93a73 | ||
|
|
7796c9269c | ||
|
|
ec150d4a4c | ||
|
|
49abff1609 | ||
|
|
be59c16aad | ||
|
|
f1144f3a7e | ||
|
|
9ebff816dc | ||
|
|
4c3eacd745 | ||
|
|
325e402d0f | ||
|
|
251587cb86 | ||
|
|
9fb1f8acf8 | ||
|
|
cffbc76da1 | ||
|
|
be51025048 | ||
|
|
ae6f9fc87c | ||
|
|
e61a7bff65 | ||
|
|
bb14881b63 | ||
|
|
a7f1bfa7c9 | ||
|
|
7b3384a6be | ||
|
|
efa8717fc5 | ||
|
|
9e42cee87c | ||
|
|
9fe30b905b | ||
|
|
2fc9afa4f4 | ||
|
|
732c8b1f7f | ||
|
|
19be3bc55c | ||
|
|
8a7e2577aa | ||
|
|
e32494879c | ||
|
|
ac4803961a | ||
|
|
de8d6d3c8c | ||
|
|
392b80fe14 | ||
|
|
9fa75a8b45 | ||
|
|
b19097ab8f | ||
|
|
31624b32e9 | ||
|
|
b8b6558f53 | ||
|
|
a53e75aeaa | ||
|
|
7798004568 | ||
|
|
63873575a5 | ||
|
|
9845df4d1b | ||
|
|
462d5f5d05 | ||
|
|
1d860923d0 | ||
|
|
c9a3fac654 | ||
|
|
a1c9685b49 | ||
|
|
c16c4aac44 | ||
|
|
e80ff9c551 | ||
|
|
3176ccc6e3 | ||
|
|
b24196be36 | ||
|
|
52365a9755 | ||
|
|
41bea9f50c | ||
|
|
3416c7bb3c | ||
|
|
ce126b11fb | ||
|
|
99db8fc3fe | ||
|
|
780cec2596 | ||
|
|
d3b4cb71c0 | ||
|
|
1758c3e3f2 | ||
|
|
995fa7d6fd | ||
|
|
87abe426d8 | ||
|
|
bec0b46a2c | ||
|
|
a88ddc2a4d | ||
|
|
1f60578a63 | ||
|
|
2f70489e22 | ||
|
|
3b75734672 | ||
|
|
ff4b35d6f1 | ||
|
|
e5b26fdad0 | ||
|
|
bcbcf40eae | ||
|
|
661fdfb43e | ||
|
|
31f08c49e7 | ||
|
|
2999d61ac9 | ||
|
|
ca72a4b0fc | ||
|
|
164977972e | ||
|
|
b6fbfcc814 | ||
|
|
418700ce3f | ||
|
|
1d52557562 | ||
|
|
45e24c54ce | ||
|
|
abd909d23b | ||
|
|
f39932ece7 | ||
|
|
03fb649274 | ||
|
|
54e9e95076 | ||
|
|
201fb4d73e | ||
|
|
e0cc35ba66 | ||
|
|
d3818e888e | ||
|
|
a2af4a3e91 | ||
|
|
02a02fa64c | ||
|
|
9fae0d2505 | ||
|
|
e23198bbcc | ||
|
|
0a8c43901d | ||
|
|
e9054301d1 | ||
|
|
caaede7e84 | ||
|
|
3ed9e1dd51 | ||
|
|
207eccc505 | ||
|
|
45d5524df7 | ||
|
|
1f08e407d1 | ||
|
|
2c215afe33 | ||
|
|
d1d2b03dfd | ||
|
|
c1a41c6605 | ||
|
|
d1a17b39ea | ||
|
|
bf365bedfd | ||
|
|
6a1ab47a08 | ||
|
|
5fdaa6b0ee | ||
|
|
a6b0c2638a | ||
|
|
a671d08f0b | ||
|
|
5e869a5e5c | ||
|
|
0e6109ff2b | ||
|
|
0bff6ee504 | ||
|
|
7cbe429be9 | ||
|
|
09b578522f | ||
|
|
40897d0be6 | ||
|
|
f49bc088fc | ||
|
|
7795a9ead2 | ||
|
|
2c238f49e0 | ||
|
|
599789634a | ||
|
|
77359f7b83 | ||
|
|
7cff55a160 | ||
|
|
8d26eb4e07 | ||
|
|
ad5e3ebce3 | ||
|
|
2deb0e1708 | ||
|
|
b2f383f095 | ||
|
|
22ababd87a | ||
|
|
167c1fa348 | ||
|
|
3b1bf67436 | ||
|
|
d2eb73df96 | ||
|
|
4d075efcd3 | ||
|
|
8a53c56a46 | ||
|
|
73d4152d1d | ||
|
|
c0a90bd677 | ||
|
|
106157a951 | ||
|
|
ab9cf6d036 | ||
|
|
54ba6efc93 | ||
|
|
85ac4aac94 | ||
|
|
691b6611d0 | ||
|
|
1b33b4425b | ||
|
|
41defbcf9c | ||
|
|
928594fc7c | ||
|
|
cc1f668308 | ||
|
|
f2b8813fb9 | ||
|
|
5ed7c31278 | ||
|
|
13b456bffd | ||
|
|
938dee481b | ||
|
|
a69140faa9 | ||
|
|
6a5ebdb1ef | ||
|
|
ece4d083a5 | ||
|
|
96688a8ffe | ||
|
|
e9b0aa537f | ||
|
|
4052c3e817 | ||
|
|
4a6e838b18 | ||
|
|
3773f6b44f | ||
|
|
a19e836d63 | ||
|
|
aa5e5f9cc0 | ||
|
|
6647e75c77 | ||
|
|
f85a514ee3 | ||
|
|
619dd84d81 | ||
|
|
f9fdfab19e | ||
|
|
ca46d0f8e1 | ||
|
|
bb8f75b4be | ||
|
|
0db599a478 | ||
|
|
902e60fab2 | ||
|
|
87f48e2cc9 | ||
|
|
cc55073107 | ||
|
|
96c43b4607 | ||
|
|
f1b4367168 | ||
|
|
4416f8530d | ||
|
|
4e48ab2363 | ||
|
|
b5a26696f8 | ||
|
|
4307229ae0 | ||
|
|
b681f01be9 | ||
|
|
c262027728 | ||
|
|
6a08fedf18 | ||
|
|
e471b4edf5 | ||
|
|
dd86812822 | ||
|
|
ac311ab75d | ||
|
|
c9387313e2 | ||
|
|
97641dbcda | ||
|
|
54fdbcd947 | ||
|
|
7636e09284 | ||
|
|
7666ed3010 | ||
|
|
e82a9ec37a | ||
|
|
770d9e5b7c | ||
|
|
5f0e0c993e | ||
|
|
7be69b0b54 | ||
|
|
251beb7f9b | ||
|
|
1c27cbd90a | ||
|
|
4b4b26651a | ||
|
|
1a6ba8c230 | ||
|
|
06904506d4 | ||
|
|
62a28825f8 | ||
|
|
c6c693acd2 | ||
|
|
8d04454457 | ||
|
|
aeb831eeff | ||
|
|
67db78ad66 | ||
|
|
06809ab5fc | ||
|
|
08ba911738 | ||
|
|
59f4b6788a | ||
|
|
a317a4d689 | ||
|
|
6e164e61aa | ||
|
|
2098bf84a1 | ||
|
|
860a83ba90 | ||
|
|
abce5fd120 | ||
|
|
0243e9c5be | ||
|
|
8a4a0154f6 | ||
|
|
469a5221ed | ||
|
|
f251b9c6c5 | ||
|
|
c4228be86c | ||
|
|
94e565aa00 | ||
|
|
cc6e028b1d | ||
|
|
d4d4c3cc92 | ||
|
|
33a69abece | ||
|
|
3a12ba177a | ||
|
|
6a4947533f | ||
|
|
28e1538fdb | ||
|
|
879a31f51e | ||
|
|
eed66c099b | ||
|
|
49fc87e295 | ||
|
|
ece2edf579 | ||
|
|
1961f01cab | ||
|
|
fe89f1f096 | ||
|
|
346681ba27 | ||
|
|
4a214b6ef0 | ||
|
|
dda429ab5d | ||
|
|
15feaafd68 | ||
|
|
14e7907e06 | ||
|
|
b4b483b35a | ||
|
|
79c9bdba7f | ||
|
|
a6837a7869 | ||
|
|
0a485a7ff6 | ||
|
|
bca1602474 | ||
|
|
96ee0a2017 | ||
|
|
25550e18d0 | ||
|
|
154d0160bc | ||
|
|
aefa56221b | ||
|
|
dd40cbc139 | ||
|
|
23db2e5c9e | ||
|
|
eff1b174c0 | ||
|
|
545069b069 | ||
|
|
13e13cd5a8 | ||
|
|
f767535ce5 | ||
|
|
aeebd069e2 | ||
|
|
0f8aad52b2 | ||
|
|
b6a5cbf956 | ||
|
|
d2aa2a9a29 | ||
|
|
a482d4db5f | ||
|
|
d7eb30ccbd | ||
|
|
9bc12f28b4 | ||
|
|
4d11fba20a | ||
|
|
df15dceaef | ||
|
|
cb6f587f24 | ||
|
|
9f2e192993 | ||
|
|
c647793512 | ||
|
|
d62f36c6a0 | ||
|
|
2427724868 | ||
|
|
9b35d8f8e1 | ||
|
|
a859f4524c | ||
|
|
8be896aebb | ||
|
|
a008cf971d | ||
|
|
caa057ff4d | ||
|
|
43152bdaf9 | ||
|
|
4cdb7ff32b | ||
|
|
7cbb01a78a | ||
|
|
555eddff83 | ||
|
|
a3cab53b73 | ||
|
|
454d5827fd | ||
|
|
186c426691 | ||
|
|
5e1e1ecf6f | ||
|
|
2d3d0f688a | ||
|
|
7975844e4d | ||
|
|
f2b138510e | ||
|
|
1c95ef4060 | ||
|
|
b43e12a42a | ||
|
|
316077fffb | ||
|
|
4373037071 | ||
|
|
24e81c873c | ||
|
|
9e4a3905a0 | ||
|
|
b54b4a6580 | ||
|
|
f33a9c3941 | ||
|
|
d792798963 | ||
|
|
e5af4f6299 | ||
|
|
ef5bd9dc61 | ||
|
|
8834feac65 | ||
|
|
2f70dd732d | ||
|
|
3f793ae902 | ||
|
|
ac56f3a30a | ||
|
|
e2ffac74bc | ||
|
|
1c08ca54c5 | ||
|
|
f1547a7b1f | ||
|
|
746fa93c80 | ||
|
|
5ab1758d28 | ||
|
|
2e4e1df3d9 | ||
|
|
eded61d66e | ||
|
|
d9360da9a5 | ||
|
|
2b7a1b7515 | ||
|
|
1e66116e1d | ||
|
|
a95582b382 | ||
|
|
7860cfdec3 | ||
|
|
30bbea9c74 | ||
|
|
481105d6be | ||
|
|
f939a632a6 | ||
|
|
c05f56d28c | ||
|
|
b844251587 | ||
|
|
b9bd907a6b | ||
|
|
17d86a2a35 | ||
|
|
c70c67394a | ||
|
|
92d3559146 | ||
|
|
0e9a3c3a9f | ||
|
|
41263f0332 | ||
|
|
3747427538 | ||
|
|
b65554ca15 | ||
|
|
00cb15d3c8 | ||
|
|
6690f49c4e | ||
|
|
ff805a704d | ||
|
|
f83be710a0 | ||
|
|
3933549659 | ||
|
|
4993b74c23 | ||
|
|
76e7a98c88 | ||
|
|
999e98e43d | ||
|
|
74af205426 | ||
|
|
9ad82f4907 | ||
|
|
2e6b37e018 | ||
|
|
67070e335e | ||
|
|
22536e694c | ||
|
|
929282a2f7 | ||
|
|
b0092b68c6 | ||
|
|
91446378bd | ||
|
|
dceec0ce46 | ||
|
|
1856e394f3 | ||
|
|
8dc7a0dbbf | ||
|
|
6e17ff7981 |
4
.editorconfig
Normal file
4
.editorconfig
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*.js, *.css, *.tpl]
|
||||||
|
indent_style = tab
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -6,9 +6,13 @@ npm-debug.log
|
|||||||
node_modules/
|
node_modules/
|
||||||
sftp-config.json
|
sftp-config.json
|
||||||
config.json
|
config.json
|
||||||
|
public/src/nodebb.min.js
|
||||||
public/config.json
|
public/config.json
|
||||||
public/css/*.css
|
public/css/*.css
|
||||||
public/themes/*
|
public/themes/*
|
||||||
|
!/public/themes/vanilla
|
||||||
|
!/public/themes/cerulean
|
||||||
|
!/public/themes/modern
|
||||||
*.sublime-project
|
*.sublime-project
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
plugins/*
|
plugins/*
|
||||||
|
|||||||
17
.jsbeautifyrc
Normal file
17
.jsbeautifyrc
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"indent_size": 4,
|
||||||
|
"indent_char": " ",
|
||||||
|
"indent_level": 0,
|
||||||
|
"indent_with_tabs": true,
|
||||||
|
"preserve_newlines": true,
|
||||||
|
"max_preserve_newlines": 10,
|
||||||
|
"jslint_happy": true,
|
||||||
|
"brace_style": "collapse",
|
||||||
|
"keep_array_indentation": false,
|
||||||
|
"keep_function_indentation": false,
|
||||||
|
"space_before_conditional": true,
|
||||||
|
"break_chained_methods": false,
|
||||||
|
"eval_code": false,
|
||||||
|
"unescape_strings": false,
|
||||||
|
"wrap_line_length": 0
|
||||||
|
}
|
||||||
86
.jshintrc
Normal file
86
.jshintrc
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
{
|
||||||
|
// JSHint Default Configuration File (as on JSHint website)
|
||||||
|
// See http://jshint.com/docs/ for more details
|
||||||
|
|
||||||
|
"maxerr" : 50, // {int} Maximum error before stopping
|
||||||
|
|
||||||
|
// Enforcing
|
||||||
|
"bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
|
||||||
|
"camelcase" : false, // true: Identifiers must be in camelCase
|
||||||
|
"curly" : true, // true: Require {} for every new block or scope
|
||||||
|
"eqeqeq" : true, // true: Require triple equals (===) for comparison
|
||||||
|
"forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
|
||||||
|
"immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
|
||||||
|
"indent" : 4, // {int} Number of spaces to use for indentation
|
||||||
|
"latedef" : false, // true: Require variables/functions to be defined before being used
|
||||||
|
"newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()`
|
||||||
|
"noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
|
||||||
|
"noempty" : true, // true: Prohibit use of empty blocks
|
||||||
|
"nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment)
|
||||||
|
"plusplus" : false, // true: Prohibit use of `++` & `--`
|
||||||
|
"quotmark" : false, // Quotation mark consistency:
|
||||||
|
// false : do nothing (default)
|
||||||
|
// true : ensure whatever is used is consistent
|
||||||
|
// "single" : require single quotes
|
||||||
|
// "double" : require double quotes
|
||||||
|
"undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
|
||||||
|
"unused" : false, // true: Require all defined variables be used TODO: Set this to true, update codebase.
|
||||||
|
"strict" : true, // true: Requires all functions run in ES5 Strict Mode
|
||||||
|
"trailing" : false, // true: Prohibit trailing whitespaces
|
||||||
|
"maxparams" : false, // {int} Max number of formal params allowed per function
|
||||||
|
"maxdepth" : false, // {int} Max depth of nested blocks (within functions)
|
||||||
|
"maxstatements" : false, // {int} Max number statements per function
|
||||||
|
"maxcomplexity" : false, // {int} Max cyclomatic complexity per function
|
||||||
|
"maxlen" : false, // {int} Max number of characters per line
|
||||||
|
|
||||||
|
// Relaxing
|
||||||
|
"asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
|
||||||
|
"boss" : false, // true: Tolerate assignments where comparisons would be expected
|
||||||
|
"debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
|
||||||
|
"eqnull" : false, // true: Tolerate use of `== null`
|
||||||
|
"es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
|
||||||
|
"esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
|
||||||
|
"moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
|
||||||
|
// (ex: `for each`, multiple try/catch, function expression…)
|
||||||
|
"evil" : false, // true: Tolerate use of `eval` and `new Function()`
|
||||||
|
"expr" : false, // true: Tolerate `ExpressionStatement` as Programs
|
||||||
|
"funcscope" : false, // true: Tolerate defining variables inside control statements"
|
||||||
|
"globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
|
||||||
|
"iterator" : false, // true: Tolerate using the `__iterator__` property
|
||||||
|
"lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
|
||||||
|
"laxbreak" : false, // true: Tolerate possibly unsafe line breakings
|
||||||
|
"laxcomma" : false, // true: Tolerate comma-first style coding
|
||||||
|
"loopfunc" : false, // true: Tolerate functions being defined in loops
|
||||||
|
"multistr" : false, // true: Tolerate multi-line strings
|
||||||
|
"proto" : false, // true: Tolerate using the `__proto__` property
|
||||||
|
"scripturl" : false, // true: Tolerate script-targeted URLs
|
||||||
|
"smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
|
||||||
|
"shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
|
||||||
|
"sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
|
||||||
|
"supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
|
||||||
|
"validthis" : false, // true: Tolerate using this in a non-constructor function
|
||||||
|
|
||||||
|
// Environments
|
||||||
|
"browser" : true, // Web Browser (window, document, etc)
|
||||||
|
"couch" : false, // CouchDB
|
||||||
|
"devel" : true, // Development/debugging (alert, confirm, etc)
|
||||||
|
"dojo" : false, // Dojo Toolkit
|
||||||
|
"jquery" : true, // jQuery
|
||||||
|
"mootools" : false, // MooTools
|
||||||
|
"node" : true, // Node.js
|
||||||
|
"nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
|
||||||
|
"prototypejs" : false, // Prototype and Scriptaculous
|
||||||
|
"rhino" : false, // Rhino
|
||||||
|
"worker" : false, // Web Workers
|
||||||
|
"wsh" : false, // Windows Scripting Host
|
||||||
|
"yui" : false, // Yahoo User Interface
|
||||||
|
|
||||||
|
// Legacy
|
||||||
|
"nomen" : false, // true: Prohibit dangling `_` in variables
|
||||||
|
"onevar" : false, // true: Allow only one `var` statement per function
|
||||||
|
"passfail" : false, // true: Stop on first error
|
||||||
|
"white" : false, // true: Check against strict whitespace and indentation rules
|
||||||
|
|
||||||
|
// Custom Globals
|
||||||
|
"globals" : {} // additional predefined global variables
|
||||||
|
}
|
||||||
22
README.md
22
README.md
@@ -1,23 +1,29 @@
|
|||||||
Please support NodeBB development! Check out our IndieGoGo campaign and like, share, and follow us :)
|
|
||||||
[NodeBB Homepage](http://www.nodebb.org/ "NodeBB") # [IndieGoGo campaign](https://www.indiegogo.com/projects/nodebb-the-discussion-platform-of-the-future/ "IndieGoGo") # [Follow on Twitter](http://www.twitter.com/NodeBB/ "NodeBB Twitter") # [Like us on Facebook](http://www.facebook.com/NodeBB/ "NodeBB Facebook")
|
|
||||||
|
|
||||||
# NodeBB
|
# NodeBB
|
||||||
**NodeBB** is a robust Node.js driven forum built on a redis database. It is powered by web sockets, and is compatible down to IE8.
|
**NodeBB** is a robust Node.js driven forum built on a redis database. It is powered by web sockets, and is compatible down to IE8.
|
||||||
|
|
||||||

|
* [NodeBB Homepage](http://www.nodebb.org/ "NodeBB")
|
||||||
|
* [Follow on Twitter](http://www.twitter.com/NodeBB/ "NodeBB Twitter")
|
||||||
|
* [Like us on Facebook](http://www.facebook.com/NodeBB/ "NodeBB Facebook")
|
||||||
|
* [Join us on IRC](https://kiwiirc.com/client/irc.freenode.net/nodebb) - #nodebb on Freenode
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## How can I follow along/contribute?
|
## How can I follow along/contribute?
|
||||||
|
|
||||||
* Our [Indiegogo campaign](https://www.indiegogo.com/projects/nodebb-the-discussion-platform-of-the-future/) is accepting contributions until August 17th, 2013
|
|
||||||
* Our feature roadmap is hosted on the project wiki's [Version History / Roadmap](https://github.com/designcreateplay/NodeBB/wiki/Version-History-%26-Roadmap)
|
* Our feature roadmap is hosted on the project wiki's [Version History / Roadmap](https://github.com/designcreateplay/NodeBB/wiki/Version-History-%26-Roadmap)
|
||||||
* If you are a developer, feel free to check out the source and submit pull requests.
|
* If you are a developer, feel free to check out the source and submit pull requests.
|
||||||
* If you are a designer, NodeBB needs themes! NodeBB will accept any LESS or CSS file and use it in place of the default Twitter Bootstrap theme. Consider extending Bootstrap themes by extending the base bootstrap LESS file.
|
* If you are a designer, NodeBB needs themes! NodeBB will accept any LESS or CSS file and use it in place of the default Twitter Bootstrap theme. Consider extending Bootstrap themes by extending the base bootstrap LESS file.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
NodeBB requires a version of Node.js at least 0.8 or greater, and a Redis version 2.6 or greater.
|
NodeBB requires the following software to be installed:
|
||||||
|
|
||||||
|
* A version of Node.js at least 0.8 or greater
|
||||||
|
* Redis, version 2.6 or greater.
|
||||||
|
* nginx, version 1.3.13 or greater (**only if** intending to use nginx to proxy requests to a NodeBB)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -55,3 +61,7 @@ NodeBB can also be started with helper programs, such as `supervisor` and `forev
|
|||||||
*(Optional)* Some server configurations may install the node binary as `nodejs` instead of `node`. You can re-map it (so as to not break compatibility with `node-supervisor`) by running the following command:
|
*(Optional)* Some server configurations may install the node binary as `nodejs` instead of `node`. You can re-map it (so as to not break compatibility with `node-supervisor`) by running the following command:
|
||||||
|
|
||||||
# update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10
|
# update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10
|
||||||
|
|
||||||
|
## Upgrading NodeBB
|
||||||
|
|
||||||
|
Detailed upgrade instructions are listed in [Upgrading NodeBB](https://github.com/designcreateplay/NodeBB/wiki/Upgrading-NodeBB)
|
||||||
178
app.js
178
app.js
@@ -16,127 +16,125 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var fs = require('fs'),
|
(function () {
|
||||||
nconf = require('nconf'),
|
"use strict";
|
||||||
|
|
||||||
|
// Configuration setup
|
||||||
|
var nconf = require('nconf');
|
||||||
|
nconf.argv().env();
|
||||||
|
|
||||||
|
var fs = require('fs'),
|
||||||
|
async = require('async'),
|
||||||
|
winston = require('winston'),
|
||||||
pkg = require('./package.json'),
|
pkg = require('./package.json'),
|
||||||
url = require('url');
|
path = require('path'),
|
||||||
|
meta;
|
||||||
|
|
||||||
// Runtime environment
|
// Runtime environment
|
||||||
global.env = process.env.NODE_ENV || 'production',
|
global.env = process.env.NODE_ENV || 'production';
|
||||||
|
|
||||||
// Configuration setup
|
winston.remove(winston.transports.Console);
|
||||||
nconf.argv().file({ file: __dirname + '/config.json'});
|
winston.add(winston.transports.Console, {
|
||||||
|
colorize: true
|
||||||
|
});
|
||||||
|
|
||||||
// Log GNU copyright info along with server info
|
winston.add(winston.transports.File, {
|
||||||
console.log('Info: NodeBB v' + pkg.version + ' Copyright (C) 2013 DesignCreatePlay Inc.');
|
filename: 'error.log',
|
||||||
console.log('Info: This program comes with ABSOLUTELY NO WARRANTY.');
|
level: 'error'
|
||||||
console.log('Info: This is free software, and you are welcome to redistribute it under certain conditions.');
|
});
|
||||||
console.log('Info: ===');
|
|
||||||
|
|
||||||
if(nconf.get('upgrade')) {
|
// TODO: remove once https://github.com/flatiron/winston/issues/280 is fixed
|
||||||
require('./src/upgrade').upgrade();
|
winston.err = function (err) {
|
||||||
} else if (!nconf.get('setup') && nconf.get('base_url')) {
|
winston.error(err.stack);
|
||||||
nconf.set('url', nconf.get('base_url') + (nconf.get('use_port') ? ':' + nconf.get('port') : '') + nconf.get('relative_path') + '/');
|
|
||||||
nconf.set('upload_url', nconf.get('url') + 'uploads/');
|
|
||||||
global.nconf = nconf;
|
|
||||||
|
|
||||||
console.log('Info: Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.');
|
|
||||||
console.log('Info: Base Configuration OK.');
|
|
||||||
|
|
||||||
// TODO: Replace this with nconf-redis
|
|
||||||
var meta = require('./src/meta.js');
|
|
||||||
global.config = {};
|
|
||||||
meta.config.get(function(config) {
|
|
||||||
for(c in config) {
|
|
||||||
if (config.hasOwnProperty(c)) {
|
|
||||||
global.config[c] = config[c];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var categories = require('./src/categories.js'),
|
|
||||||
RDB = require('./src/redis.js'),
|
|
||||||
templates = require('./public/src/templates.js'),
|
|
||||||
webserver = require('./src/webserver.js'),
|
|
||||||
websockets = require('./src/websockets.js'),
|
|
||||||
plugins = require('./src/plugins'),
|
|
||||||
admin = {
|
|
||||||
'categories': require('./src/admin/categories.js')
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DEVELOPMENT = true;
|
// Log GNU copyright info along with server info
|
||||||
|
winston.info('NodeBB v' + pkg.version + ' Copyright (C) 2013 DesignCreatePlay Inc.');
|
||||||
|
winston.info('This program comes with ABSOLUTELY NO WARRANTY.');
|
||||||
|
winston.info('This is free software, and you are welcome to redistribute it under certain conditions.');
|
||||||
|
winston.info('');
|
||||||
|
|
||||||
|
|
||||||
|
if (fs.existsSync(__dirname + '/config.json') && (!nconf.get('setup') && !nconf.get('upgrade'))) {
|
||||||
|
// Load server-side configs
|
||||||
|
nconf.file({
|
||||||
|
file: __dirname + '/config.json'
|
||||||
|
});
|
||||||
|
meta = require('./src/meta.js');
|
||||||
|
|
||||||
|
nconf.set('url', nconf.get('base_url') + (nconf.get('use_port') ? ':' + nconf.get('port') : '') + nconf.get('relative_path') + '/');
|
||||||
|
nconf.set('upload_url', nconf.get('url') + 'uploads/');
|
||||||
|
|
||||||
|
winston.info('Initializing NodeBB v' + pkg.version + ', on port ' + nconf.get('port') + ', using Redis store at ' + nconf.get('redis:host') + ':' + nconf.get('redis:port') + '.');
|
||||||
|
winston.info('NodeBB instance bound to: ' + (nconf.get('bind_address') || 'Any address'));
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
winston.info('Base Configuration OK.');
|
||||||
|
}
|
||||||
|
|
||||||
|
meta.configs.init(function () {
|
||||||
|
// Initial setup for Redis & Reds
|
||||||
|
var reds = require('reds'),
|
||||||
|
RDB = require('./src/redis.js');
|
||||||
|
|
||||||
|
reds.createClient = function () {
|
||||||
|
return reds.client || (reds.client = RDB);
|
||||||
|
};
|
||||||
|
|
||||||
|
var templates = require('./public/src/templates.js'),
|
||||||
|
translator = require('./public/src/translator.js'),
|
||||||
|
webserver = require('./src/webserver.js'),
|
||||||
|
SocketIO = require('socket.io').listen(global.server, { log: false, transports: ['websocket', 'xhr-polling', 'jsonp-polling', 'flashsocket']}),
|
||||||
|
websockets = require('./src/websockets.js'),
|
||||||
|
plugins = require('./src/plugins'); // Don't remove this - plugins initializes itself
|
||||||
|
|
||||||
|
websockets.init(SocketIO);
|
||||||
|
|
||||||
global.configuration = {};
|
|
||||||
global.templates = {};
|
global.templates = {};
|
||||||
|
global.translator = translator;
|
||||||
|
|
||||||
(function(config) {
|
translator.loadServer();
|
||||||
config['ROOT_DIRECTORY'] = __dirname;
|
|
||||||
|
|
||||||
|
// todo: replace below with read directory code, derp.
|
||||||
templates.init([
|
templates.init([
|
||||||
'header', 'footer', 'logout', 'outgoing', 'admin/header', 'admin/footer', 'admin/index',
|
'header', 'footer', 'logout', 'outgoing', 'admin/header', 'admin/footer', 'admin/index',
|
||||||
'emails/reset', 'emails/reset_plaintext', 'emails/email_confirm', 'emails/email_confirm_plaintext',
|
'emails/reset', 'emails/reset_plaintext', 'emails/email_confirm', 'emails/email_confirm_plaintext',
|
||||||
'emails/header', 'emails/footer', 'install/header', 'install/footer', 'install/redis',
|
'emails/header', 'emails/footer',
|
||||||
|
|
||||||
'noscript/header', 'noscript/home', 'noscript/category', 'noscript/topic'
|
'noscript/header', 'noscript/home', 'noscript/category', 'noscript/topic'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
templates.ready(webserver.init);
|
templates.ready(webserver.init);
|
||||||
|
|
||||||
//setup scripts to be moved outside of the app in future.
|
|
||||||
function setup_categories() {
|
|
||||||
console.log('Info: Checking categories...');
|
|
||||||
categories.getAllCategories(function(data) {
|
|
||||||
if (data.categories.length === 0) {
|
|
||||||
console.log('Info: Setting up default categories...');
|
|
||||||
|
|
||||||
fs.readFile(config.ROOT_DIRECTORY + '/install/data/categories.json', function(err, default_categories) {
|
|
||||||
default_categories = JSON.parse(default_categories);
|
|
||||||
|
|
||||||
for (var category in default_categories) {
|
|
||||||
admin.categories.create(default_categories[category]);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
} else if (nconf.get('upgrade')) {
|
||||||
|
meta = require('./src/meta.js');
|
||||||
|
|
||||||
console.log('Info: Hardcoding uid 1 as an admin');
|
meta.configs.init(function () {
|
||||||
var user = require('./src/user.js');
|
require('./src/upgrade').upgrade();
|
||||||
user.makeAdministrator(1);
|
});
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.log('Info: Categories OK. Found ' + data.categories.length + ' categories.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setup_categories();
|
|
||||||
}(global.configuration));
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// New install, ask setup questions
|
// New install, ask setup questions
|
||||||
if (nconf.get('setup')) console.log('Info: NodeBB Setup Triggered via Command Line');
|
if (nconf.get('setup')) {
|
||||||
else console.log('Info: Configuration not found, starting NodeBB setup');
|
winston.info('NodeBB Setup Triggered via Command Line');
|
||||||
|
} else {
|
||||||
|
winston.warn('Configuration not found, starting NodeBB setup');
|
||||||
|
}
|
||||||
|
|
||||||
var install = require('./src/install');
|
var install = require('./src/install');
|
||||||
|
|
||||||
process.stdout.write(
|
winston.info('Welcome to NodeBB!');
|
||||||
"\nWelcome to NodeBB!\nThis looks like a new installation, so you'll have to answer a " +
|
winston.info('This looks like a new installation, so you\'ll have to answer a few questions about your environment before we can proceed.');
|
||||||
"few questions about your environment before we can proceed.\n\n" +
|
winston.info('Press enter to accept the default setting (shown in brackets).');
|
||||||
"Press enter to accept the default setting (shown in brackets).\n\n\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
install.setup(function(err) {
|
install.setup(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log('Error: There was a problem completing NodeBB setup: ', err.message);
|
winston.error('There was a problem completing NodeBB setup: ', err.message);
|
||||||
} else {
|
} else {
|
||||||
if (!nconf.get('setup')) {
|
winston.info('NodeBB Setup Completed.');
|
||||||
process.stdout.write(
|
|
||||||
"Please start NodeBB again and register a new user. This user will automatically become an administrator.\n\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
process.exit();
|
process.exit();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}());
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "Announcements",
|
"name": "Announcements",
|
||||||
"description": "A place to talk about whateeeever you want",
|
"description": "Announcements regarding our community",
|
||||||
"blockclass": "category-blue",
|
"blockclass": "category-blue",
|
||||||
"icon" : "icon-bullhorn"
|
"icon" : "icon-bullhorn"
|
||||||
},
|
},
|
||||||
@@ -13,61 +13,61 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "NodeBB Development",
|
"name": "NodeBB Development",
|
||||||
"description": "Bugs? Dont worry, we dont read this thread, so post them here.",
|
"description": "NodeBB development news and announcements",
|
||||||
"blockclass": "category-blue",
|
"blockclass": "category-blue",
|
||||||
"icon" : "icon-github"
|
"icon" : "icon-github"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Blogs",
|
"name": "Blogs",
|
||||||
"description": "In future an example of how a hidden category should look like.",
|
"description": "Blog posts from individual members",
|
||||||
"blockclass": "category-blue",
|
"blockclass": "category-blue",
|
||||||
"icon" : "icon-pencil"
|
"icon" : "icon-pencil"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Feature Requests",
|
"name": "Feature Requests",
|
||||||
"description": "In future an example of how a hidden category should look like.",
|
"description": "Got a feature request you'd like to see? Give us a shout here.",
|
||||||
"blockclass": "category-purple",
|
"blockclass": "category-purple",
|
||||||
"icon" : "icon-lightbulb"
|
"icon" : "icon-lightbulb"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Bug Reports",
|
"name": "Bug Reports",
|
||||||
"description": "In future an example of how a hidden category should look like.",
|
"description": "Having trouble with NodeBB? Let us know...",
|
||||||
"blockclass": "category-purple",
|
"blockclass": "category-purple",
|
||||||
"icon" : "icon-cogs"
|
"icon" : "icon-cogs"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "NodeBB Addons",
|
"name": "NodeBB Plugins",
|
||||||
"description": "In future an example of how a hidden category should look like.",
|
"description": "Enhance your NodeBB with plugins!",
|
||||||
"blockclass": "category-purple",
|
"blockclass": "category-purple",
|
||||||
"icon" : "icon-plus-sign"
|
"icon" : "icon-plus-sign"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "NodeBB Link Exchange",
|
"name": "NodeBB Link Exchange",
|
||||||
"description": "In future an example of how a hidden category should look like.",
|
"description": "Link exchange",
|
||||||
"blockclass": "category-purple",
|
"blockclass": "category-purple",
|
||||||
"icon" : "icon-exchange"
|
"icon" : "icon-exchange"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "News",
|
"name": "News",
|
||||||
"description": "In future an example of how a hidden category should look like.",
|
"description": "News from around the world",
|
||||||
"blockclass": "category-darkblue",
|
"blockclass": "category-darkblue",
|
||||||
"icon" : "icon-globe"
|
"icon" : "icon-globe"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Movies",
|
"name": "Movies",
|
||||||
"description": "In future an example of how a hidden category should look like.",
|
"description": "Discuss the latest movies here",
|
||||||
"blockclass": "category-darkblue",
|
"blockclass": "category-darkblue",
|
||||||
"icon" : "icon-film"
|
"icon" : "icon-film"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Games",
|
"name": "Games",
|
||||||
"description": "In future an example of how a hidden category should look like.",
|
"description": "Discuss the latest games here",
|
||||||
"blockclass": "category-darkblue",
|
"blockclass": "category-darkblue",
|
||||||
"icon" : "icon-screenshot"
|
"icon" : "icon-screenshot"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Random",
|
"name": "Random",
|
||||||
"description": "In future an example of how a hidden category should look like.",
|
"description": "Anything and (almost) everything welcome!",
|
||||||
"blockclass": "category-darkblue",
|
"blockclass": "category-darkblue",
|
||||||
"icon" : "icon-beer"
|
"icon" : "icon-beer"
|
||||||
}
|
}
|
||||||
|
|||||||
19
package.json
19
package.json
@@ -2,7 +2,7 @@
|
|||||||
"name": "nodebb",
|
"name": "nodebb",
|
||||||
"license": "GPLv3 or later",
|
"license": "GPLv3 or later",
|
||||||
"description": "NodeBB Forum",
|
"description": "NodeBB Forum",
|
||||||
"version": "0.0.5",
|
"version": "0.0.7",
|
||||||
"homepage": "http://www.nodebb.org",
|
"homepage": "http://www.nodebb.org",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -10,10 +10,10 @@
|
|||||||
},
|
},
|
||||||
"main": "app.js",
|
"main": "app.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"socket.io": "0.9.14",
|
"socket.io": "~0.9.16",
|
||||||
"redis": "0.8.3",
|
"redis": "0.8.3",
|
||||||
"express": "3.2.0",
|
"express": "3.2.0",
|
||||||
"express-namespace": "0.1.1",
|
"express-namespace": "~0.1.1",
|
||||||
"emailjs": "0.3.4",
|
"emailjs": "0.3.4",
|
||||||
"cookie": "0.0.6",
|
"cookie": "0.0.6",
|
||||||
"connect-redis": "1.4.5",
|
"connect-redis": "1.4.5",
|
||||||
@@ -27,13 +27,22 @@
|
|||||||
"bcrypt": "0.7.5",
|
"bcrypt": "0.7.5",
|
||||||
"async": "0.2.8",
|
"async": "0.2.8",
|
||||||
"node-imagemagick": "0.1.8",
|
"node-imagemagick": "0.1.8",
|
||||||
"node-rss": "1.0.1",
|
|
||||||
"gravatar": "1.0.6",
|
"gravatar": "1.0.6",
|
||||||
"nconf": "~0.6.7",
|
"nconf": "~0.6.7",
|
||||||
"sitemap": "~0.6.0",
|
"sitemap": "~0.6.0",
|
||||||
"cheerio": "~0.12.0",
|
"cheerio": "~0.12.0",
|
||||||
"request": "~2.25.0",
|
"request": "~2.25.0",
|
||||||
"reds": "~0.2.4"
|
"reds": "~0.2.4",
|
||||||
|
"winston": "~0.7.2",
|
||||||
|
"nodebb-plugin-mentions": "~0.1.0",
|
||||||
|
"nodebb-plugin-markdown": "~0.1.0",
|
||||||
|
"rss": "~0.2.0",
|
||||||
|
"prompt": "~0.2.11",
|
||||||
|
"uglify-js": "~2.4.0",
|
||||||
|
"validator": "~1.5.1"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"hiredis": "~0.1.15"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/designcreateplay/NodeBB/issues"
|
"url": "https://github.com/designcreateplay/NodeBB/issues"
|
||||||
|
|||||||
@@ -1,5 +1 @@
|
|||||||
@import "style";
|
@import "../themes/cerulean/cerulean.less";
|
||||||
|
|
||||||
@import "topic";
|
|
||||||
@import "category";
|
|
||||||
@import "noscript";
|
|
||||||
@@ -1,846 +0,0 @@
|
|||||||
@import "mixins";
|
|
||||||
|
|
||||||
body {
|
|
||||||
/*background: #fdfdfd;*/ // port to default theme when it is implemented.
|
|
||||||
-webkit-transition: margin-bottom 250ms ease;
|
|
||||||
-moz-transition: margin-bottom 250ms ease;
|
|
||||||
-ms-transition: margin-bottom 250ms ease;
|
|
||||||
-o-transition: margin-bottom 250ms ease;
|
|
||||||
transition: margin-bottom 250ms ease;
|
|
||||||
|
|
||||||
&.composing {
|
|
||||||
margin-bottom: 350px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 979px)
|
|
||||||
{
|
|
||||||
padding-top: 70px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 979px)
|
|
||||||
{
|
|
||||||
padding-bottom: 50px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button, a {
|
|
||||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.none {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.block, .show {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.badge {
|
|
||||||
vertical-align: 17%;
|
|
||||||
}
|
|
||||||
.nav .badge {
|
|
||||||
vertical-align: 10%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#alert_window {
|
|
||||||
position: fixed;
|
|
||||||
right: 20px;
|
|
||||||
top: 60px;
|
|
||||||
width: 300px;
|
|
||||||
height: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toaster-alert {
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer.footer {
|
|
||||||
color: #555;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #222;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#post_window {
|
|
||||||
width: 100%;
|
|
||||||
position: fixed;
|
|
||||||
height: 350px;
|
|
||||||
left: 0px;
|
|
||||||
bottom: 0px;
|
|
||||||
background: white;
|
|
||||||
z-index: 1500;
|
|
||||||
|
|
||||||
input {
|
|
||||||
width: 100%;
|
|
||||||
height: 30px;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
width: 100%;
|
|
||||||
background: #222;
|
|
||||||
height: 220px;
|
|
||||||
resize: none;
|
|
||||||
border-radius: 0;
|
|
||||||
border: 1px solid #111;
|
|
||||||
font-size: 16px;
|
|
||||||
color: #bebebe;
|
|
||||||
outline: 0;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: 0;
|
|
||||||
border:none !important;
|
|
||||||
box-shadow:none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-title-container {
|
|
||||||
opacity: 0.8;
|
|
||||||
height: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-content-container {
|
|
||||||
opacity: 0.8;
|
|
||||||
background: #000;
|
|
||||||
width: 100%;
|
|
||||||
height: 300px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#user_label { //belongs in header.less
|
|
||||||
img {
|
|
||||||
border: 1px solid #454;
|
|
||||||
margin-right: 8px;
|
|
||||||
margin-top: -2px;
|
|
||||||
float: left;
|
|
||||||
width:24px;
|
|
||||||
height:24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #ded;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#reply_title {
|
|
||||||
font-size: 17px;
|
|
||||||
padding-top: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alt-logins {
|
|
||||||
margin: 0 0 0 1em;
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
li {
|
|
||||||
vertical-align: top;
|
|
||||||
background: transparent;
|
|
||||||
display: none;
|
|
||||||
margin: 0.25em;
|
|
||||||
.pointer;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
.inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
i {
|
|
||||||
-webkit-transition: color 100ms linear;
|
|
||||||
-moz-transition: color 100ms linear;
|
|
||||||
-ms-transition: color 100ms linear;
|
|
||||||
-o-transition: color 100ms linear;
|
|
||||||
transition: color 100ms linear;
|
|
||||||
|
|
||||||
&.icon-twitter-sign:hover {
|
|
||||||
color: #4099FF;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.icon-facebook-sign:hover {
|
|
||||||
color: #3b5999;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.icon-google-plus-sign:hover {
|
|
||||||
color: #d34836;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#thread_active_users {
|
|
||||||
float: right;
|
|
||||||
color: rgb(153,153,153);
|
|
||||||
|
|
||||||
strong {
|
|
||||||
color: rgb(100,100,100);
|
|
||||||
font-weight: 600;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.account-username-box{
|
|
||||||
border-bottom:1px solid #e3e3e3;
|
|
||||||
margin-bottom:10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account-sub-links a{
|
|
||||||
margin-left:10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account-username{
|
|
||||||
font-size:20px;
|
|
||||||
font-weight:bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account-picture-block{
|
|
||||||
display:inline-block;
|
|
||||||
vertical-align:top;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account-online-status {
|
|
||||||
.icon-circle-blank {
|
|
||||||
color:red;
|
|
||||||
}
|
|
||||||
.icon-circle {
|
|
||||||
color:green;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-profile-picture {
|
|
||||||
width:128px;
|
|
||||||
margin-bottom:10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-picture-label {
|
|
||||||
font-size:20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account-bio-block{
|
|
||||||
display:inline-block;
|
|
||||||
vertical-align:top;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account-bio-label{
|
|
||||||
display:inline-block;
|
|
||||||
width:100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-recent-posts {
|
|
||||||
div {
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
p {
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
span {
|
|
||||||
padding-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-icon {
|
|
||||||
width: 100%;
|
|
||||||
height: 90px;
|
|
||||||
text-align: center;
|
|
||||||
border-radius: 0px;
|
|
||||||
margin: 0;
|
|
||||||
padding-top:25px;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
border-radius: 5px;
|
|
||||||
overflow:hidden;
|
|
||||||
}
|
|
||||||
.category-row h4 {
|
|
||||||
font-weight: 700;
|
|
||||||
text-align: left;
|
|
||||||
/*color: #555;*/ // NOTE: color for cat/topic header links should be grey in the default theme when we get around to it.
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
.category-row a {
|
|
||||||
text-decoration: none;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-purple {
|
|
||||||
@color: #ab1290;
|
|
||||||
background: @color;
|
|
||||||
color: white;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: lighten(@color, 10%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-darkblue {
|
|
||||||
@color: #004C66;
|
|
||||||
background: @color;
|
|
||||||
color: white;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: lighten(@color, 10%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-blue {
|
|
||||||
@color: #0059B2;
|
|
||||||
background: @color;
|
|
||||||
color: white;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: lighten(@color, 10%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-darkgreen {
|
|
||||||
@color: #004000;
|
|
||||||
background: @color;
|
|
||||||
color: white;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: lighten(@color, 10%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.category-orange {
|
|
||||||
@color: #FF7A4D;
|
|
||||||
color: white;
|
|
||||||
background: @color;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: lighten(@color, 10%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-list {
|
|
||||||
li {
|
|
||||||
.inline-block;
|
|
||||||
.pointer;
|
|
||||||
padding: 0.5em 0;
|
|
||||||
text-align: center;
|
|
||||||
margin: 0.5em;
|
|
||||||
-webkit-border-radius: 5px;
|
|
||||||
-moz-border-radius: 5px;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 0.5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-unit {
|
|
||||||
background: #56BCDA;
|
|
||||||
color: white;
|
|
||||||
padding: 30px;
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
.users-box{
|
|
||||||
display: inline-block;
|
|
||||||
margin-top: 20px;
|
|
||||||
text-align: center;
|
|
||||||
vertical-align: top;
|
|
||||||
max-width: 104px;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width:80px;
|
|
||||||
height:80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
margin:5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover, .btn-link:hover, .btn-link:active, .btn-link:focus {
|
|
||||||
text-decoration:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.formatting-bar {
|
|
||||||
.no-select;
|
|
||||||
|
|
||||||
span:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.breadcrumb {
|
|
||||||
li {
|
|
||||||
max-width: 35%;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow:ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body .navbar .nodebb-inline-block {
|
|
||||||
display:inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
#right-menu{
|
|
||||||
float:right;
|
|
||||||
}
|
|
||||||
|
|
||||||
#admin-redis-info {
|
|
||||||
span {
|
|
||||||
display:inline-block;
|
|
||||||
width:220px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-signature {
|
|
||||||
color: #666;
|
|
||||||
font-size: 12px;
|
|
||||||
border-top: 1px solid #ddd;
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
img {
|
|
||||||
max-width:200px;
|
|
||||||
max-height:60px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.username-field {
|
|
||||||
.icon-circle {
|
|
||||||
font-size: 12px;
|
|
||||||
color: green;
|
|
||||||
margin-right:3px;
|
|
||||||
}
|
|
||||||
.icon-circle-blank {
|
|
||||||
font-size: 12px;
|
|
||||||
color: red;
|
|
||||||
margin-right:3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#chat-content {
|
|
||||||
width:95%;
|
|
||||||
height:200px;
|
|
||||||
resize:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#chat-message-input {
|
|
||||||
width:95%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#content{
|
|
||||||
padding-bottom:20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-toggle {
|
|
||||||
i {
|
|
||||||
font-size: 12px;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
color: #558;
|
|
||||||
text-shadow: 0 0 1em #aaf, 0 0 1em #aaf, 0 0 1em #aaf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#notif-list {
|
|
||||||
li {
|
|
||||||
font-size: 12px;
|
|
||||||
width: 300px;
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
a {
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.unread {
|
|
||||||
background: #eceff5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.taskbar {
|
|
||||||
display: none;
|
|
||||||
-moz-opacity: 0.5;
|
|
||||||
opacity: 0.5;
|
|
||||||
margin-top: 0;
|
|
||||||
-webkit-transition: opacity 250ms ease-in;
|
|
||||||
-moz-transition: opacity 250ms ease-in;
|
|
||||||
-ms-transition: opacity 250ms ease-in;
|
|
||||||
-o-transition: opacity 250ms ease-in;
|
|
||||||
transition: opacity 250ms ease-in;
|
|
||||||
|
|
||||||
&[data-active="1"] {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
-moz-opacity: 1;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
a > span {
|
|
||||||
.inline-block;
|
|
||||||
max-width: 200px;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 24px;
|
|
||||||
max-height: 24px;
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.pulse {
|
|
||||||
-webkit-animation: pulsate 2500ms linear;
|
|
||||||
-webkit-animation-iteration-count: infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes pulsate {
|
|
||||||
0% { background: none; }
|
|
||||||
50% { background: #e5e5e5; }
|
|
||||||
100% { background: none; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-window {
|
|
||||||
position: fixed;
|
|
||||||
display: none;
|
|
||||||
height: 350px;
|
|
||||||
visibility: hidden;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
position: absolute;
|
|
||||||
height: 100%;
|
|
||||||
background: rgba(64, 64, 64, 0.6);
|
|
||||||
visibility: visible;
|
|
||||||
|
|
||||||
.btn-toolbar {
|
|
||||||
width: 90%;
|
|
||||||
margin: 0 auto;
|
|
||||||
|
|
||||||
span {
|
|
||||||
color: white;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
width: 98%;
|
|
||||||
text-align: center;
|
|
||||||
border: none;
|
|
||||||
padding: 0.5em 0;
|
|
||||||
-webkit-border-radius: 0px;
|
|
||||||
-moz-border-radius: 0px;
|
|
||||||
border-radius: 0px;
|
|
||||||
margin: 1% 1% 2% 1%;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
background: rgba(64, 64, 64, 0.95);
|
|
||||||
border: none;
|
|
||||||
padding: 0.5em;
|
|
||||||
display: block;
|
|
||||||
width: 90%;
|
|
||||||
margin: 0.5em auto;
|
|
||||||
resize: none;
|
|
||||||
color: white;
|
|
||||||
height: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#imagedrop {
|
|
||||||
text-align:center;
|
|
||||||
color:white;
|
|
||||||
position: absolute;
|
|
||||||
top: 0px;
|
|
||||||
left: 0px;
|
|
||||||
width: 100%;
|
|
||||||
height:230px;
|
|
||||||
line-height:230px;
|
|
||||||
font-size:20px;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
#imagelist {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 5px;
|
|
||||||
left: 0px;
|
|
||||||
padding-left:2em;
|
|
||||||
|
|
||||||
div {
|
|
||||||
margin-right:5px;
|
|
||||||
}
|
|
||||||
span {
|
|
||||||
line-height:20px;
|
|
||||||
float:left;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
padding-left:5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 979px) {
|
|
||||||
.post-window {
|
|
||||||
position: relative;
|
|
||||||
bottom: 0px !important;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
position: static;
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#mobile-menu {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0px;
|
|
||||||
height: 50px;
|
|
||||||
background: #333;
|
|
||||||
width: 100%;
|
|
||||||
left: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#mobile-menu, #mobile-menu-overlay {
|
|
||||||
z-index: 999;
|
|
||||||
|
|
||||||
@media (min-width: 979px)
|
|
||||||
{
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.btn-none,
|
|
||||||
.btn-none:active,
|
|
||||||
.btn-none[disabled] {
|
|
||||||
background-color: transparent;
|
|
||||||
background-image: none;
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
-moz-box-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-none {
|
|
||||||
cursor: pointer;
|
|
||||||
border-color: transparent;
|
|
||||||
-webkit-border-radius: 0;
|
|
||||||
-moz-border-radius: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-none:hover,
|
|
||||||
.btn-none:focus {
|
|
||||||
text-decoration: none;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-none[disabled]:hover,
|
|
||||||
.btn-none[disabled]:focus {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-none {
|
|
||||||
.icon-white {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#mobile-menu {
|
|
||||||
button {
|
|
||||||
color: #eee;
|
|
||||||
padding: 10px;
|
|
||||||
text-shadow: none;
|
|
||||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#mobile-menu-overlay {
|
|
||||||
|
|
||||||
background: rgba(0, 0, 0, 0.85);
|
|
||||||
position: fixed;
|
|
||||||
top: 0px;
|
|
||||||
left: 0px;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
//margin-top: 50px;
|
|
||||||
padding-top: 20px;
|
|
||||||
opacity: 0;
|
|
||||||
|
|
||||||
-webkit-transition: opacity 150ms ease;
|
|
||||||
-moz-transition: opacity 150ms ease;
|
|
||||||
-ms-transition: opacity 150ms ease;
|
|
||||||
-o-transition: opacity 150ms ease;
|
|
||||||
transition: opacity 150ms ease;
|
|
||||||
z-index: -1;
|
|
||||||
&.menu-visible {
|
|
||||||
z-index: 99;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile-menu-icon {
|
|
||||||
color: white;
|
|
||||||
width: 20%;
|
|
||||||
min-width: 85px;
|
|
||||||
height: auto;
|
|
||||||
text-align: center;
|
|
||||||
padding: 10px;
|
|
||||||
display: inline-block;
|
|
||||||
cursor: pointer;
|
|
||||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
|
||||||
|
|
||||||
-webkit-transition: margin-top 250ms ease;
|
|
||||||
-moz-transition: margin-top 250ms ease;
|
|
||||||
-ms-transition: margin-top 250ms ease;
|
|
||||||
-o-transition: margin-top 250ms ease;
|
|
||||||
transition: margin-top 250ms ease;
|
|
||||||
|
|
||||||
margin-top: 20%;
|
|
||||||
|
|
||||||
|
|
||||||
&.menu-visible {
|
|
||||||
margin-top: 0%;
|
|
||||||
}
|
|
||||||
|
|
||||||
i {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#mobile-sidebar {
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
left: 100%;
|
|
||||||
top: 0px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-top: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-box {
|
|
||||||
height:90px;
|
|
||||||
|
|
||||||
.post-preview {
|
|
||||||
padding-left:10px;
|
|
||||||
padding-right:10px;
|
|
||||||
text-align:left;
|
|
||||||
img {
|
|
||||||
width:60px;
|
|
||||||
height:60px;
|
|
||||||
padding-right:5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow:ellipsis;
|
|
||||||
height:60px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#mark-allread-btn {
|
|
||||||
margin-bottom:15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes scroll-2 /* Safari and Chrome */
|
|
||||||
{
|
|
||||||
0% {top: 0px;}
|
|
||||||
25% {top: -90px;}
|
|
||||||
50% {top: -180px;}
|
|
||||||
75% {top: -270px;}
|
|
||||||
100% {top: -360px;}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes scroll-2
|
|
||||||
{
|
|
||||||
0% {top: 0px;}
|
|
||||||
25% {top: -90px;}
|
|
||||||
50% {top: -180px;}
|
|
||||||
75% {top: -270px;}
|
|
||||||
100% {top: -360px;}
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes scroll-1 /* Safari and Chrome */
|
|
||||||
{
|
|
||||||
0% {top: 0px;}
|
|
||||||
33% {top: -90px;}
|
|
||||||
66% {top: -180px;}
|
|
||||||
100% {top: -270px;}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes scroll-1
|
|
||||||
{
|
|
||||||
0% {top: 0px;}
|
|
||||||
33% {top: -90px;}
|
|
||||||
66% {top: -180px;}
|
|
||||||
100% {top: -270px;}
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes scroll-0 /* Safari and Chrome */
|
|
||||||
{
|
|
||||||
0% {top: 0px;}
|
|
||||||
50% {top: -90px;}
|
|
||||||
100% {top: -180px;}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes scroll-0
|
|
||||||
{
|
|
||||||
0% {top: 0px;}
|
|
||||||
50% {top: -90px;}
|
|
||||||
100% {top: -180px;}
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-slider-2:hover {
|
|
||||||
position:relative;
|
|
||||||
|
|
||||||
-webkit-animation: scroll-2 10s ease 0.5s infinite normal;
|
|
||||||
animation: scroll-2 10s ease 0.5s infinite normal;/* Safari and Chrome: */
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-slider-1:hover {
|
|
||||||
position:relative;
|
|
||||||
|
|
||||||
-webkit-animation: scroll-1 8s ease 0.5s infinite normal;
|
|
||||||
animation: scroll-1 8s ease 0.5s infinite normal;/* Safari and Chrome: */
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-slider-0:hover {
|
|
||||||
position:relative;
|
|
||||||
|
|
||||||
-webkit-animation: scroll-0 6s ease 0.5s infinite normal;
|
|
||||||
animation: scroll-0 6s ease 0.5s infinite normal;/* Safari and Chrome: */
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-search {
|
|
||||||
float: left;
|
|
||||||
margin-top: 5px;
|
|
||||||
margin-bottom:0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-result-post {
|
|
||||||
width: 100%;
|
|
||||||
line-height: 16px;
|
|
||||||
padding: 5px;
|
|
||||||
overflow:hidden;
|
|
||||||
img {
|
|
||||||
display: block;
|
|
||||||
float: left;
|
|
||||||
width:48px;
|
|
||||||
height:48px;
|
|
||||||
padding-right:10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,193 +0,0 @@
|
|||||||
|
|
||||||
.post-container {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
clear: both;
|
|
||||||
|
|
||||||
.profile-image-block {
|
|
||||||
display: inline-block;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 12px;
|
|
||||||
|
|
||||||
.stats {
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
padding-bottom: 15px;
|
|
||||||
|
|
||||||
&.deleted {
|
|
||||||
-moz-opacity: 0.30;
|
|
||||||
opacity: 0.30;
|
|
||||||
height:30px;
|
|
||||||
overflow-y:hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.deleted-expanded {
|
|
||||||
height:100%;
|
|
||||||
overflow-y:default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-block, .post-block {
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.06);
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 10px;
|
|
||||||
|
|
||||||
p {
|
|
||||||
line-height: 1.75em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-block {
|
|
||||||
background: rgba(0, 0, 0, 0.02);
|
|
||||||
margin-right: -11px;
|
|
||||||
margin-left: -11px;
|
|
||||||
margin-bottom: -11px;
|
|
||||||
margin-top: 15px;
|
|
||||||
border-radius: 0 0 5px 5px;
|
|
||||||
font-size: 10px;
|
|
||||||
line-height: 18px;
|
|
||||||
padding: 5px;
|
|
||||||
padding-left: 10px;
|
|
||||||
|
|
||||||
img.hidden-desktop {
|
|
||||||
max-width: 10px;
|
|
||||||
max-height: 10px;
|
|
||||||
padding-top: 5px;
|
|
||||||
margin-right: 5px;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.post-content {
|
|
||||||
min-height: 50px;
|
|
||||||
padding: 2px 5px 0 5px;
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-images{
|
|
||||||
padding: 2px 5px 0 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-block {
|
|
||||||
.post-buttons {
|
|
||||||
font-size: 12px;
|
|
||||||
float: right;
|
|
||||||
margin-right: 5px;
|
|
||||||
|
|
||||||
button, a {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 0px 15px;
|
|
||||||
border: none;
|
|
||||||
border-left: 1px solid rgba(0, 0, 0, 0.06);
|
|
||||||
cursor: pointer;
|
|
||||||
background: none;
|
|
||||||
font-size: 12px;
|
|
||||||
height: 20px;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-star {
|
|
||||||
//theme this to make it yellow eventually
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.deleted {
|
|
||||||
-moz-opacity: 0.30;
|
|
||||||
opacity: 0.30;
|
|
||||||
}
|
|
||||||
/*http://stackoverflow.com/questions/11037517/bootstrap-making-responsive-changes-to-layout*/
|
|
||||||
@media (max-width: 979px) {
|
|
||||||
.span12-tablet {
|
|
||||||
width: 100% !important;
|
|
||||||
margin-left:0px;
|
|
||||||
*width: 100% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-post {
|
|
||||||
h3 {
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
.topic-title {
|
|
||||||
width: auto;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow:ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
padding-top: 5px;
|
|
||||||
margin-bottom: -5px;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-avatar {
|
|
||||||
color: white;
|
|
||||||
position: relative;
|
|
||||||
float: left;
|
|
||||||
margin-right: 25px;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
padding-bottom: 0px;
|
|
||||||
text-align: center;
|
|
||||||
width:80px;
|
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-avatar:hover .hover-overlay {
|
|
||||||
opacity: 0.75;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover-overlay {
|
|
||||||
margin: 5px;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0px;
|
|
||||||
height: 35px;
|
|
||||||
padding-top: 2px;
|
|
||||||
width: 80px;
|
|
||||||
font-size: 13px;
|
|
||||||
line-height: 16px;
|
|
||||||
background: #000;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-content {
|
|
||||||
min-height: 80px;
|
|
||||||
}
|
|
||||||
hr {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-right: 10px;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
.post-block {
|
|
||||||
.post-buttons {
|
|
||||||
div {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.favourite {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.btn {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.topic-buttons {
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
3
public/language/TODO
Normal file
3
public/language/TODO
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
NPM INSTALL
|
||||||
|
For now, language packs will be stored here. Eventually, will be moved to server side to allow for npm install-ability.
|
||||||
|
When that happens, server code will generate compressed JSON language files in this folder.
|
||||||
7
public/language/en/category.json
Normal file
7
public/language/en/category.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"new_topic_button": "New Topic",
|
||||||
|
"no_topics": "<strong>There are no topics in this category.</strong><br />Why don't you try posting one?",
|
||||||
|
"sidebar.recent_replies": "Recent Replies",
|
||||||
|
"sidebar.active_participants": "Active Participants",
|
||||||
|
"sidebar.moderators": "Moderators"
|
||||||
|
}
|
||||||
9
public/language/en/footer.json
Normal file
9
public/language/en/footer.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"chat.chatting_with": "Chat with <span id='chat-with-name'></span>",
|
||||||
|
"chat.placeholder": "type chat message, here press enter to send",
|
||||||
|
"chat.send": "Send",
|
||||||
|
"stats.online": "Online",
|
||||||
|
"stats.users": "Users",
|
||||||
|
"stats.topics": "Topics",
|
||||||
|
"stats.posts": "Posts"
|
||||||
|
}
|
||||||
17
public/language/en/global.json
Normal file
17
public/language/en/global.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"home": "Home",
|
||||||
|
"search": "Search",
|
||||||
|
"buttons.close": "Close",
|
||||||
|
"403.title": "Access Denied",
|
||||||
|
"403.message": "You seem to have stumbled upon a page that you do not have access to. Perhaps you should <a href='/login'>try logging in</a>?",
|
||||||
|
"404.title": "Not Found",
|
||||||
|
"404.message": "You seem to have stumbled upon a page that does not exist. Return to the <a href='/''>home page</a>.",
|
||||||
|
"logout": "Logout",
|
||||||
|
"logout.title": "You are now logged out.",
|
||||||
|
"logout.message": "You have successfully logged out of NodeBB",
|
||||||
|
"header.recent": "Recent",
|
||||||
|
"header.unread": "Unread",
|
||||||
|
"header.users": "Users",
|
||||||
|
"header.search": "Search",
|
||||||
|
"notifications.loading": "Loading Notifications"
|
||||||
|
}
|
||||||
10
public/language/en/login.json
Normal file
10
public/language/en/login.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"login": "Login",
|
||||||
|
"username": "Username",
|
||||||
|
"password": "Password",
|
||||||
|
"remember_me": "Remember Me?",
|
||||||
|
"forgot_password": "Forgot Password?",
|
||||||
|
"alternative_logins": "Alternative Logins",
|
||||||
|
"failed_login_attempt": "Failed login attempt, please try again.",
|
||||||
|
"login_successful": "You have successfully logged in!"
|
||||||
|
}
|
||||||
16
public/language/en/register.json
Normal file
16
public/language/en/register.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"register": "Register",
|
||||||
|
"help.email": "By default, your email will be hidden from the public.",
|
||||||
|
"help.username_restrictions": "A unique username between %1 and %2 characters. Others can mention you with @<span id='yourUsername'>username</span>.",
|
||||||
|
"help.minimum_password_length": "Your password's length must be at least %1 characters.",
|
||||||
|
"email_address": "Email Address",
|
||||||
|
"email_address_placeholder": "Enter Email Address",
|
||||||
|
"username": "Username",
|
||||||
|
"username_placeholder": "Enter Username",
|
||||||
|
"password": "Password",
|
||||||
|
"password_placeholder": "Enter Password",
|
||||||
|
"confirm_password": "Confirm Password",
|
||||||
|
"confirm_password_placeholder": "Confirm Password",
|
||||||
|
"register_now_button": "Register Now",
|
||||||
|
"alternative_registration": "Alternative Registration"
|
||||||
|
}
|
||||||
22
public/language/en/topic.json
Normal file
22
public/language/en/topic.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"profile": "Profile",
|
||||||
|
"posted_by": "Posted by",
|
||||||
|
"chat": "Chat",
|
||||||
|
"notify_me": "Be notified of new replies in this topic",
|
||||||
|
"favourite": "Favourite",
|
||||||
|
"quote": "Quote",
|
||||||
|
"reply": "Reply",
|
||||||
|
"edit": "Edit",
|
||||||
|
"delete": "Delete",
|
||||||
|
"banned": "banned",
|
||||||
|
"link": "Link",
|
||||||
|
"thread_tools.title": "Thread Tools",
|
||||||
|
"thread_tools.pin": "Pin Thread",
|
||||||
|
"thread_tools.lock": "Lock Thread",
|
||||||
|
"thread_tools.move": "Move Thread",
|
||||||
|
"thread_tools.delete": "Delete Thread",
|
||||||
|
"load_categories": "Loading Categories",
|
||||||
|
"confirm_move": "Move",
|
||||||
|
"favourites.not_logged_in.title": "Not Logged In",
|
||||||
|
"favourites.not_logged_in.message": "Please log in in order to favourite this post"
|
||||||
|
}
|
||||||
5
public/language/en/unread.json
Normal file
5
public/language/en/unread.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"no_unread_topics": "There are no unread topics.",
|
||||||
|
"mark_all_read": "Mark all as Read",
|
||||||
|
"load_more": "Load More"
|
||||||
|
}
|
||||||
9
public/language/en/users.json
Normal file
9
public/language/en/users.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"latest_users": "Latest Users",
|
||||||
|
"top_posters": "Top Posters",
|
||||||
|
"most_reputation": "Most Reputation",
|
||||||
|
"online": "Online",
|
||||||
|
"search": "Search",
|
||||||
|
"enter_username": "Enter a username to search",
|
||||||
|
"load_more": "Load More"
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
2
public/socket.io/socket.io.min.js
vendored
2
public/socket.io/socket.io.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,7 +1,8 @@
|
|||||||
var ajaxify = {};
|
var ajaxify = {};
|
||||||
|
|
||||||
|
|
||||||
(function($) {
|
(function ($) {
|
||||||
|
/*global app, templates, utils*/
|
||||||
|
|
||||||
var location = document.location || window.location,
|
var location = document.location || window.location,
|
||||||
rootUrl = location.protocol + '//' + (location.hostname || location.host) + (location.port ? ':' + location.port : ''),
|
rootUrl = location.protocol + '//' + (location.hostname || location.host) + (location.port ? ':' + location.port : ''),
|
||||||
@@ -11,8 +12,8 @@ var ajaxify = {};
|
|||||||
var executed = {};
|
var executed = {};
|
||||||
|
|
||||||
var events = [];
|
var events = [];
|
||||||
ajaxify.register_events = function(new_page_events) {
|
ajaxify.register_events = function (new_page_events) {
|
||||||
for (var i = 0, ii = events.length; i<ii; i++) {
|
for (var i = 0, ii = events.length; i < ii; i++) {
|
||||||
socket.removeAllListeners(events[i]); // optimize this to user removeListener(event, listener) instead.
|
socket.removeAllListeners(events[i]); // optimize this to user removeListener(event, listener) instead.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,27 +21,36 @@ var ajaxify = {};
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
window.onpopstate = function(event) {
|
window.onpopstate = function (event) {
|
||||||
// "quiet": If set to true, will not call pushState
|
// "quiet": If set to true, will not call pushState
|
||||||
if (event !== null && event.state && event.state.url !== undefined) ajaxify.go(event.state.url, null, null, true);
|
if (event !== null && event.state && event.state.url !== undefined) ajaxify.go(event.state.url, null, null, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
ajaxify.go = function(url, callback, template, quiet) {
|
var pagination;
|
||||||
// leave room and join global
|
|
||||||
|
ajaxify.go = function (url, callback, template, quiet) {
|
||||||
|
// start: the following should be set like so: ajaxify.onchange(function(){}); where the code actually belongs
|
||||||
|
$(window).off('scroll');
|
||||||
app.enter_room('global');
|
app.enter_room('global');
|
||||||
|
|
||||||
var url = url.replace(/\/$/, "");
|
pagination = pagination || document.getElementById('pagination');
|
||||||
|
if (pagination) pagination.parentNode.style.display = 'none';
|
||||||
|
window.onscroll = null;
|
||||||
|
// end
|
||||||
|
|
||||||
|
// Remove trailing slash
|
||||||
|
url = url.replace(/\/$/, "");
|
||||||
|
|
||||||
var hash = window.location.hash;
|
var hash = window.location.hash;
|
||||||
|
|
||||||
if(url.indexOf(RELATIVE_PATH.slice(1)) !== -1) {
|
if (url.indexOf(RELATIVE_PATH.slice(1)) !== -1) {
|
||||||
url = url.slice(RELATIVE_PATH.length);
|
url = url.slice(RELATIVE_PATH.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
var tpl_url = templates.get_custom_map(url.split('?')[0]);
|
var tpl_url = templates.get_custom_map(url.split('?')[0]);
|
||||||
|
|
||||||
if (tpl_url == false && !templates[url]) {
|
if (tpl_url == false && !templates[url]) {
|
||||||
if(url === '' || url === '/') {
|
if (url === '' || url === '/') {
|
||||||
tpl_url = 'home';
|
tpl_url = 'home';
|
||||||
} else {
|
} else {
|
||||||
tpl_url = url.split('/')[0].split('?')[0];
|
tpl_url = url.split('/')[0].split('?')[0];
|
||||||
@@ -52,75 +62,87 @@ var ajaxify = {};
|
|||||||
|
|
||||||
if (templates.is_available(tpl_url) && !templates.force_refresh(tpl_url)) {
|
if (templates.is_available(tpl_url) && !templates.force_refresh(tpl_url)) {
|
||||||
if (quiet !== true) {
|
if (quiet !== true) {
|
||||||
|
if (window.history && window.history.pushState) {
|
||||||
window.history.pushState({
|
window.history.pushState({
|
||||||
"url": url
|
"url": url
|
||||||
}, url, RELATIVE_PATH + "/" + url);
|
}, url, RELATIVE_PATH + "/" + url);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
translator.load(tpl_url);
|
||||||
|
|
||||||
jQuery('#footer, #content').fadeOut(100);
|
jQuery('#footer, #content').fadeOut(100);
|
||||||
|
|
||||||
templates.flush();
|
templates.flush();
|
||||||
templates.load_template(function() {
|
templates.load_template(function () {
|
||||||
exec_body_scripts(content);
|
exec_body_scripts(content);
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
app.process_page();
|
jQuery('#content, #footer').stop(true, true).fadeIn(200, function () {
|
||||||
|
|
||||||
jQuery('#content, #footer').stop(true, true).fadeIn(200, function() {
|
app.process_page();
|
||||||
if(window.location.hash)
|
if (window.location.hash)
|
||||||
hash = window.location.hash;
|
hash = window.location.hash;
|
||||||
if(hash)
|
if (hash)
|
||||||
app.scrollToPost(hash.substr(1));
|
app.scrollToPost(hash.substr(1));
|
||||||
});
|
});
|
||||||
|
|
||||||
}, url, template);
|
utils.refreshTitle(url);
|
||||||
|
|
||||||
socket.emit('api:meta.buildTitle', url, function(title) {
|
}, url, template);
|
||||||
document.title = title;
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
$('document').ready(function() {
|
$('document').ready(function () {
|
||||||
if (!window.history || !window.history.pushState) return; // no ajaxification for old browsers
|
if (!window.history || !window.history.pushState) return; // no ajaxification for old browsers
|
||||||
|
|
||||||
content = content || document.getElementById('content');
|
content = content || document.getElementById('content');
|
||||||
|
|
||||||
// Enhancing all anchors to ajaxify...
|
// Enhancing all anchors to ajaxify...
|
||||||
$(document.body).on('click', 'a', function(e) {
|
$(document.body).on('click', 'a', function (e) {
|
||||||
if (this.href == window.location.href + "#") return;
|
function hrefEmpty(href) {
|
||||||
if(this.href.slice(-1) === "#") return;
|
return href == 'javascript:;' || href == window.location.href + "#" || href.slice(-1) === "#";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hrefEmpty(this.href) || this.target !== '' || this.protocol === 'javascript:')
|
||||||
|
return;
|
||||||
|
|
||||||
var url = this.href.replace(rootUrl +'/', '');
|
app.previousUrl = window.location.href;
|
||||||
|
|
||||||
if (this.target !== '') return;
|
|
||||||
|
|
||||||
if (!e.ctrlKey && e.which === 1) {
|
if (!e.ctrlKey && e.which === 1) {
|
||||||
|
if (this.host === window.location.host) {
|
||||||
|
// Internal link
|
||||||
|
var url = this.href.replace(rootUrl + '/', '');
|
||||||
|
|
||||||
if (ajaxify.go(url)) {
|
if (ajaxify.go(url)) {
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
} else if (window.location.pathname !== '/outgoing') {
|
||||||
|
// External Link
|
||||||
|
ajaxify.go('outgoing?url=' + encodeURIComponent(this.href));
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function exec_body_scripts(body_el) {
|
function exec_body_scripts(body_el) {
|
||||||
// modified from http://stackoverflow.com/questions/2592092/executing-script-elements-inserted-with-innerhtml
|
// modified from http://stackoverflow.com/questions/2592092/executing-script-elements-inserted-with-innerhtml
|
||||||
|
|
||||||
function nodeName(elem, name) {
|
function nodeName(elem, name) {
|
||||||
return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
|
return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
|
||||||
};
|
}
|
||||||
|
|
||||||
function evalScript(elem) {
|
function evalScript(elem) {
|
||||||
var data = (elem.text || elem.textContent || elem.innerHTML || "" ),
|
var data = (elem.text || elem.textContent || elem.innerHTML || ""),
|
||||||
head = document.getElementsByTagName("head")[0] ||
|
head = document.getElementsByTagName("head")[0] ||
|
||||||
document.documentElement,
|
document.documentElement,
|
||||||
script = document.createElement("script");
|
script = document.createElement("script");
|
||||||
@@ -128,7 +150,7 @@ var ajaxify = {};
|
|||||||
script.type = "text/javascript";
|
script.type = "text/javascript";
|
||||||
try {
|
try {
|
||||||
script.appendChild(document.createTextNode(data));
|
script.appendChild(document.createTextNode(data));
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
script.text = data;
|
script.text = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,17 +161,17 @@ var ajaxify = {};
|
|||||||
head.insertBefore(script, head.firstChild);
|
head.insertBefore(script, head.firstChild);
|
||||||
//TODO: remove from head before inserting?, doing this breaks scripts in safari so commented out for now
|
//TODO: remove from head before inserting?, doing this breaks scripts in safari so commented out for now
|
||||||
//head.removeChild(script);
|
//head.removeChild(script);
|
||||||
};
|
}
|
||||||
|
|
||||||
var scripts = [],
|
var scripts = [],
|
||||||
script,
|
script,
|
||||||
children_nodes = body_el.childNodes,
|
children_nodes = $(body_el).children(),
|
||||||
child,
|
child,
|
||||||
i;
|
i;
|
||||||
|
|
||||||
for (i = 0; children_nodes[i]; i++) {
|
for (i = 0; children_nodes[i]; i++) {
|
||||||
child = children_nodes[i];
|
child = children_nodes[i];
|
||||||
if (nodeName(child, "script" ) &&
|
if (nodeName(child, "script") &&
|
||||||
(!child.type || child.type.toLowerCase() === "text/javascript")) {
|
(!child.type || child.type.toLowerCase() === "text/javascript")) {
|
||||||
scripts.push(child);
|
scripts.push(child);
|
||||||
}
|
}
|
||||||
@@ -162,6 +184,6 @@ var ajaxify = {};
|
|||||||
}
|
}
|
||||||
evalScript(scripts[i]);
|
evalScript(scripts[i]);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
}(jQuery));
|
}(jQuery));
|
||||||
@@ -1,88 +1,68 @@
|
|||||||
var socket,
|
var socket,
|
||||||
config,
|
config,
|
||||||
app = {},
|
app = {};
|
||||||
API_URL = null;
|
|
||||||
|
|
||||||
|
(function () {
|
||||||
(function() {
|
|
||||||
var showWelcomeMessage = false;
|
var showWelcomeMessage = false;
|
||||||
|
|
||||||
function loadConfig() {
|
app.loadConfig = function() {
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: RELATIVE_PATH + '/api/config',
|
url: RELATIVE_PATH + '/api/config',
|
||||||
success: function(data) {
|
success: function (data) {
|
||||||
API_URL = data.api_url;
|
|
||||||
|
|
||||||
config = data;
|
config = data;
|
||||||
socket = io.connect(config.socket.address + (config.socket.port ? ':' + config.socket.port : ''));
|
if(socket) {
|
||||||
|
socket.disconnect();
|
||||||
|
setTimeout(function() {
|
||||||
|
socket.socket.connect();
|
||||||
|
}, 200);
|
||||||
|
} else {
|
||||||
|
socket = io.connect(config.socket.address);
|
||||||
|
|
||||||
var reconnecting = false;
|
var reconnecting = false,
|
||||||
var reconnectTries = 0;
|
reconnectEl, reconnectTimer;
|
||||||
|
|
||||||
socket.on('event:connect', function(data) {
|
socket.on('event:connect', function (data) {
|
||||||
console.log('connected to nodebb socket: ', data);
|
|
||||||
app.username = data.username;
|
app.username = data.username;
|
||||||
app.showLoginMessage();
|
app.showLoginMessage();
|
||||||
|
socket.emit('api:updateHeader', {
|
||||||
|
fields: ['username', 'picture', 'userslug']
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('event:alert', function(data) {
|
socket.on('event:alert', function (data) {
|
||||||
app.alert(data);
|
app.alert(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('event:consolelog', function(data) {
|
socket.on('connect', function (data) {
|
||||||
console.log(data);
|
if (reconnecting) {
|
||||||
});
|
reconnectEl.html('<i class="icon-ok"></i> Connected!');
|
||||||
|
|
||||||
socket.on('connect', function(data){
|
|
||||||
if(reconnecting) {
|
|
||||||
setTimeout(function(){
|
|
||||||
app.alert({
|
|
||||||
alert_id: 'connection_alert',
|
|
||||||
title: 'Connected',
|
|
||||||
message: 'Connection successful.',
|
|
||||||
type: 'success',
|
|
||||||
timeout: 5000
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
reconnecting = false;
|
reconnecting = false;
|
||||||
reconnectTries = 0;
|
|
||||||
socket.emit('api:updateHeader', { fields: ['username', 'picture', 'userslug'] });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('reconnecting', function(data) {
|
setTimeout(function() {
|
||||||
function showDisconnectModal() {
|
reconnectEl.removeClass('active');
|
||||||
$('#disconnect-modal').modal({
|
}, 3000);
|
||||||
backdrop:'static',
|
|
||||||
show:true
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#reload-button').on('click',function(){
|
|
||||||
$('#disconnect-modal').modal('hide');
|
|
||||||
window.location.reload();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
socket.emit('api:updateHeader', {
|
||||||
|
fields: ['username', 'picture', 'userslug']
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('event:disconnect', function() {
|
||||||
|
socket.socket.connect();
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('reconnecting', function (data) {
|
||||||
|
if (!reconnectEl) reconnectEl = $('#reconnect');
|
||||||
reconnecting = true;
|
reconnecting = true;
|
||||||
reconnectTries++;
|
|
||||||
|
|
||||||
if(reconnectTries > 4) {
|
reconnectEl.addClass('active');
|
||||||
showDisconnectModal();
|
reconnectEl.html('<i class="icon-spinner icon-spin"></i> Reconnecting...');
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
app.alert({
|
|
||||||
alert_id: 'connection_alert',
|
|
||||||
title: 'Reconnecting',
|
|
||||||
message: 'You have disconnected from NodeBB, we will try to reconnect you. <br/><i class="icon-refresh icon-spin"></i>',
|
|
||||||
type: 'notify',
|
|
||||||
timeout: 5000
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:user.get_online_users', function(users) {
|
socket.on('api:user.get_online_users', function (users) {
|
||||||
jQuery('.username-field').each(function() {
|
jQuery('a.username-field').each(function () {
|
||||||
if (this.processed === true)
|
if (this.processed === true)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -97,25 +77,40 @@ var socket,
|
|||||||
el.prepend('<i class="icon-circle-blank"></i>');
|
el.prepend('<i class="icon-circle-blank"></i>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
el.processed = true;
|
||||||
|
});
|
||||||
|
jQuery('button .username-field').each(function () {
|
||||||
|
//DRY FAIL
|
||||||
|
if (this.processed === true)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var el = jQuery(this),
|
||||||
|
uid = el.parents('li').attr('data-uid');
|
||||||
|
|
||||||
|
if (uid && jQuery.inArray(uid, users) !== -1) {
|
||||||
|
el.parent().addClass('btn-success');
|
||||||
|
} else {
|
||||||
|
el.parent().addClass('btn-danger');
|
||||||
|
}
|
||||||
|
|
||||||
el.processed = true;
|
el.processed = true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.enter_room('global');
|
app.enter_room('global');
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
async: false
|
async: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// takes a string like 1000 and returns 1,000
|
// takes a string like 1000 and returns 1,000
|
||||||
app.addCommas = function(text) {
|
app.addCommas = function (text) {
|
||||||
return text.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
|
return text.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Willingly stolen from: http://phpjs.org/functions/strip_tags/
|
// Willingly stolen from: http://phpjs.org/functions/strip_tags/
|
||||||
app.strip_tags = function(input, allowed) {
|
app.strip_tags = function (input, allowed) {
|
||||||
allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
|
allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
|
||||||
var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
|
var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
|
||||||
commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
|
commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
|
||||||
@@ -131,14 +126,14 @@ var socket,
|
|||||||
// message = alert message content
|
// message = alert message content
|
||||||
// timeout default = permanent
|
// timeout default = permanent
|
||||||
// location : alert_window (default) or content
|
// location : alert_window (default) or content
|
||||||
app.alert = function(params) {
|
app.alert = function (params) {
|
||||||
var alert_id = 'alert_button_' + ((params.alert_id) ? params.alert_id : new Date().getTime());
|
var alert_id = 'alert_button_' + ((params.alert_id) ? params.alert_id : new Date().getTime());
|
||||||
|
|
||||||
var alert = $('#'+alert_id);
|
var alert = $('#' + alert_id);
|
||||||
|
|
||||||
function startTimeout(div, timeout) {
|
function startTimeout(div, timeout) {
|
||||||
var timeoutId = setTimeout(function() {
|
var timeoutId = setTimeout(function () {
|
||||||
$(div).fadeOut(1000, function() {
|
$(div).fadeOut(1000, function () {
|
||||||
$(this).remove();
|
$(this).remove();
|
||||||
});
|
});
|
||||||
}, timeout);
|
}, timeout);
|
||||||
@@ -146,15 +141,14 @@ var socket,
|
|||||||
$(div).attr('timeoutId', timeoutId);
|
$(div).attr('timeoutId', timeoutId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(alert.length > 0) {
|
if (alert.length > 0) {
|
||||||
alert.find('strong').html(params.title);
|
alert.find('strong').html(params.title);
|
||||||
alert.find('p').html(params.message);
|
alert.find('p').html(params.message);
|
||||||
alert.attr('class', "alert toaster-alert " + ((params.type=='warning') ? '' : "alert-" + params.type));
|
alert.attr('class', "alert toaster-alert " + "alert-" + params.type);
|
||||||
|
|
||||||
clearTimeout(alert.attr('timeoutId'));
|
clearTimeout(alert.attr('timeoutId'));
|
||||||
startTimeout(alert, params.timeout);
|
startTimeout(alert, params.timeout);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
var div = document.createElement('div'),
|
var div = document.createElement('div'),
|
||||||
button = document.createElement('button'),
|
button = document.createElement('button'),
|
||||||
strong = document.createElement('strong'),
|
strong = document.createElement('strong'),
|
||||||
@@ -163,7 +157,7 @@ var socket,
|
|||||||
p.innerHTML = params.message;
|
p.innerHTML = params.message;
|
||||||
strong.innerHTML = params.title;
|
strong.innerHTML = params.title;
|
||||||
|
|
||||||
div.className = "alert toaster-alert " + ((params.type=='warning') ? '' : "alert-" + params.type);
|
div.className = "alert toaster-alert " + "alert-" + params.type;
|
||||||
|
|
||||||
div.setAttribute('id', alert_id);
|
div.setAttribute('id', alert_id);
|
||||||
div.appendChild(button);
|
div.appendChild(button);
|
||||||
@@ -172,23 +166,23 @@ var socket,
|
|||||||
|
|
||||||
button.className = 'close';
|
button.className = 'close';
|
||||||
button.innerHTML = '×';
|
button.innerHTML = '×';
|
||||||
button.onclick = function(ev) {
|
button.onclick = function (ev) {
|
||||||
div.parentNode.removeChild(div);
|
div.parentNode.removeChild(div);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.location == null)
|
if (params.location == null)
|
||||||
params.location = 'alert_window';
|
params.location = 'alert_window';
|
||||||
|
|
||||||
jQuery('#'+params.location).prepend(jQuery(div).fadeIn('100'));
|
jQuery('#' + params.location).prepend(jQuery(div).fadeIn('100'));
|
||||||
|
|
||||||
if (params.timeout) {
|
if (params.timeout) {
|
||||||
startTimeout(div, params.timeout);
|
startTimeout(div, params.timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.clickfn) {
|
if (params.clickfn) {
|
||||||
div.onclick = function() {
|
div.onclick = function () {
|
||||||
params.clickfn();
|
params.clickfn();
|
||||||
jQuery(div).fadeOut(500, function() {
|
jQuery(div).fadeOut(500, function () {
|
||||||
this.remove();
|
this.remove();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -196,8 +190,8 @@ var socket,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app.alertSuccess = function(message, timeout) {
|
app.alertSuccess = function (message, timeout) {
|
||||||
if(!timeout)
|
if (!timeout)
|
||||||
timeout = 2000;
|
timeout = 2000;
|
||||||
|
|
||||||
app.alert({
|
app.alert({
|
||||||
@@ -208,22 +202,21 @@ var socket,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
app.alertError = function(message, timeout) {
|
app.alertError = function (message, timeout) {
|
||||||
if(!timeout)
|
if (!timeout)
|
||||||
timeout = 2000;
|
timeout = 2000;
|
||||||
|
|
||||||
app.alert({
|
app.alert({
|
||||||
title: 'Error',
|
title: 'Error',
|
||||||
message: message,
|
message: message,
|
||||||
type: 'error',
|
type: 'danger',
|
||||||
timeout: timeout
|
timeout: timeout
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
app.current_room = null;
|
app.current_room = null;
|
||||||
app.enter_room = function(room) {
|
app.enter_room = function (room) {
|
||||||
|
if (socket) {
|
||||||
if(socket) {
|
|
||||||
if (app.current_room === room)
|
if (app.current_room === room)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -236,20 +229,20 @@ var socket,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
app.populate_online_users = function() {
|
app.populate_online_users = function () {
|
||||||
var uids = [];
|
var uids = [];
|
||||||
|
|
||||||
jQuery('.post-row').each(function() {
|
jQuery('.post-row').each(function () {
|
||||||
uids.push(this.getAttribute('data-uid'));
|
uids.push(this.getAttribute('data-uid'));
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.emit('api:user.get_online_users', uids);
|
socket.emit('api:user.get_online_users', uids);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.process_page = function() {
|
app.process_page = function () {
|
||||||
|
|
||||||
// here is where all modules' onNavigate should be called, I think.
|
// here is where all modules' onNavigate should be called, I think.
|
||||||
require(['mobileMenu'], function(mobileMenu) {
|
require(['mobileMenu'], function (mobileMenu) {
|
||||||
mobileMenu.onNavigate();
|
mobileMenu.onNavigate();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -257,13 +250,13 @@ var socket,
|
|||||||
|
|
||||||
var url = window.location.href,
|
var url = window.location.href,
|
||||||
parts = url.split('/'),
|
parts = url.split('/'),
|
||||||
active = parts[parts.length-1];
|
active = parts[parts.length - 1];
|
||||||
|
|
||||||
jQuery('#main-nav li').removeClass('active');
|
jQuery('#main-nav li').removeClass('active');
|
||||||
if(active) {
|
if (active) {
|
||||||
jQuery('#main-nav li a').each(function() {
|
jQuery('#main-nav li a').each(function () {
|
||||||
var href = this.getAttribute('href');
|
var href = this.getAttribute('href');
|
||||||
if(active.match(/^users/))
|
if (active == "sort-posts" || active == "sort-reputation" || active == "search" || active == "latest" || active == "online")
|
||||||
active = 'users';
|
active = 'users';
|
||||||
if (href && href.match(active)) {
|
if (href && href.match(active)) {
|
||||||
jQuery(this.parentNode).addClass('active');
|
jQuery(this.parentNode).addClass('active');
|
||||||
@@ -272,12 +265,15 @@ var socket,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(function() {
|
$('span.timeago').timeago();
|
||||||
|
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
window.scrollTo(0, 1); // rehide address bar on mobile after page load completes.
|
window.scrollTo(0, 1); // rehide address bar on mobile after page load completes.
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.showLoginMessage = function() {
|
app.showLoginMessage = function () {
|
||||||
function showAlert() {
|
function showAlert() {
|
||||||
app.alert({
|
app.alert({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
@@ -287,9 +283,9 @@ var socket,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(showWelcomeMessage) {
|
if (showWelcomeMessage) {
|
||||||
showWelcomeMessage = false;
|
showWelcomeMessage = false;
|
||||||
if(document.readyState !== 'complete') {
|
if (document.readyState !== 'complete') {
|
||||||
$(document).ready(showAlert);
|
$(document).ready(showAlert);
|
||||||
} else {
|
} else {
|
||||||
showAlert();
|
showAlert();
|
||||||
@@ -297,23 +293,36 @@ var socket,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app.addCommasToNumbers = function() {
|
app.addCommasToNumbers = function () {
|
||||||
$('.formatted-number').each(function(index, element) {
|
$('.formatted-number').each(function (index, element) {
|
||||||
$(element).html(app.addCommas($(element).html()));
|
$(element).html(app.addCommas($(element).html()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
app.createNewPosts = function(data) {
|
app.openChat = function (username, touid) {
|
||||||
|
require(['chat'], function (chat) {
|
||||||
|
var chatModal;
|
||||||
|
if (!chat.modalExists(touid)) {
|
||||||
|
chatModal = chat.createModal(username, touid);
|
||||||
|
} else {
|
||||||
|
chatModal = chat.getModal(touid);
|
||||||
|
}
|
||||||
|
chat.load(chatModal.attr('UUID'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
app.createNewPosts = function (data) {
|
||||||
data.posts[0].display_moderator_tools = 'none';
|
data.posts[0].display_moderator_tools = 'none';
|
||||||
var html = templates.prepare(templates['topic'].blocks['posts']).parse(data),
|
var html = templates.prepare(templates['topic'].blocks['posts']).parse(data);
|
||||||
uniqueid = new Date().getTime(),
|
translator.translate(html, function(translatedHTML) {
|
||||||
|
var uniqueid = new Date().getTime(),
|
||||||
tempContainer = jQuery('<div id="' + uniqueid + '"></div>')
|
tempContainer = jQuery('<div id="' + uniqueid + '"></div>')
|
||||||
.appendTo("#post-container")
|
.appendTo("#post-container")
|
||||||
.hide()
|
.hide()
|
||||||
.append(html)
|
.append(translatedHTML)
|
||||||
.fadeIn('slow');
|
.fadeIn('slow');
|
||||||
|
|
||||||
for(var x=0,numPosts=data.posts.length;x<numPosts;x++) {
|
for (var x = 0, numPosts = data.posts.length; x < numPosts; x++) {
|
||||||
socket.emit('api:post.privileges', data.posts[x].pid);
|
socket.emit('api:post.privileges', data.posts[x].pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,112 +331,97 @@ var socket,
|
|||||||
|
|
||||||
app.populate_online_users();
|
app.populate_online_users();
|
||||||
app.addCommasToNumbers();
|
app.addCommasToNumbers();
|
||||||
|
$('span.timeago').timeago();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
app.infiniteLoaderActive = false;
|
app.infiniteLoaderActive = false;
|
||||||
|
|
||||||
app.loadMorePosts = function(tid, callback) {
|
app.loadMorePosts = function (tid, callback) {
|
||||||
if(app.infiniteLoaderActive)
|
if (app.infiniteLoaderActive)
|
||||||
return;
|
return;
|
||||||
app.infiniteLoaderActive = true;
|
app.infiniteLoaderActive = true;
|
||||||
|
|
||||||
|
if ($('#loading-indicator').attr('done') === '0')
|
||||||
|
$('#loading-indicator').removeClass('hide');
|
||||||
|
|
||||||
socket.emit('api:topic.loadMore', {
|
socket.emit('api:topic.loadMore', {
|
||||||
tid: tid,
|
tid: tid,
|
||||||
after: document.querySelectorAll('#post-container li[data-pid]').length
|
after: document.querySelectorAll('#post-container li[data-pid]').length
|
||||||
}, function(data) {
|
}, function (data) {
|
||||||
app.infiniteLoaderActive = false;
|
app.infiniteLoaderActive = false;
|
||||||
if(data.posts.length) {
|
if (data.posts.length) {
|
||||||
|
$('#loading-indicator').attr('done', '0');
|
||||||
app.createNewPosts(data);
|
app.createNewPosts(data);
|
||||||
if(callback)
|
} else {
|
||||||
callback();
|
$('#loading-indicator').attr('done', '1');
|
||||||
}
|
}
|
||||||
|
$('#loading-indicator').addClass('hide');
|
||||||
|
if (callback)
|
||||||
|
callback(data.posts);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
app.scrollToPost = function(pid) {
|
app.scrollToTop = function () {
|
||||||
if(!pid)
|
$('body,html').animate({
|
||||||
|
scrollTop: 0
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
app.scrollToBottom = function () {
|
||||||
|
$('body,html').animate({
|
||||||
|
scrollTop: $('html').height() - 100
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
app.scrollToPost = function (pid) {
|
||||||
|
|
||||||
|
if (!pid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var container = $(document.body),
|
var container = $(document.body),
|
||||||
|
scrollTo = $('#post_anchor_' + pid),
|
||||||
|
tid = $('#post-container').attr('data-tid');
|
||||||
|
|
||||||
|
function animateScroll() {
|
||||||
|
$('body,html').animate({
|
||||||
|
scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop() - $('#header-menu').height()
|
||||||
|
}, 400);
|
||||||
|
//$('body,html').scrollTop(scrollTo.offset().top - container.offset().top + container.scrollTop() - $('#header-menu').height());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!scrollTo.length && tid) {
|
||||||
|
|
||||||
|
var intervalID = setInterval(function () {
|
||||||
|
app.loadMorePosts(tid, function (posts) {
|
||||||
scrollTo = $('#post_anchor_' + pid);
|
scrollTo = $('#post_anchor_' + pid);
|
||||||
|
|
||||||
if(!scrollTo.length) {
|
if (tid && scrollTo.length) {
|
||||||
var tid = $('#post-container').attr('data-tid');
|
animateScroll();
|
||||||
app.loadMorePosts(tid, function() {
|
|
||||||
app.scrollToPost(pid);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
container.animate({
|
if (!posts.length || scrollTo.length)
|
||||||
scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop() - $('#header-menu').height()
|
clearInterval(intervalID);
|
||||||
});
|
});
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
} else if (tid) {
|
||||||
|
animateScroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery('document').ready(function() {
|
}
|
||||||
addTouchEvents();
|
|
||||||
|
|
||||||
$('#search-form').on('submit', function() {
|
jQuery('document').ready(function () {
|
||||||
|
$('#search-form').on('submit', function () {
|
||||||
var input = $(this).find('input');
|
var input = $(this).find('input');
|
||||||
ajaxify.go("search/"+input.val(), null, "search");
|
ajaxify.go("search/" + input.val(), null, "search");
|
||||||
input.val('');
|
input.val('');
|
||||||
return false;
|
return false;
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
showWelcomeMessage = location.href.indexOf('loggedin') !== -1;
|
showWelcomeMessage = location.href.indexOf('loggedin') !== -1;
|
||||||
|
|
||||||
loadConfig();
|
app.loadConfig();
|
||||||
|
|
||||||
|
|
||||||
function addTouchEvents() {
|
|
||||||
return; // later.
|
|
||||||
|
|
||||||
|
|
||||||
// click simulation just for testing/sanity purposes.
|
|
||||||
|
|
||||||
var el = jQuery("#content"),
|
|
||||||
sidebar = jQuery('#mobile-sidebar'),
|
|
||||||
width = el.width();
|
|
||||||
|
|
||||||
function onTouchMove(ev) {
|
|
||||||
var coordinates = window.event ? window.event.touches[0] : ev.touches[0];
|
|
||||||
|
|
||||||
el.css({
|
|
||||||
marginLeft: -parseInt(width - coordinates.pageX) + 'px',
|
|
||||||
paddingRight: parseInt(width - coordinates.pageX) + 'px'});
|
|
||||||
|
|
||||||
sidebar.css({
|
|
||||||
marginLeft: -parseInt(width - coordinates.pageX) + 'px',
|
|
||||||
width: parseInt(width - coordinates.pageX) + 'px'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMouseMove(ev) {
|
|
||||||
ev.touches = [{pageX: ev.pageX, pageY: ev.pageY}];
|
|
||||||
onTouchMove(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onTouchEnd() {
|
|
||||||
el.css({
|
|
||||||
marginLeft: '0px',
|
|
||||||
paddingRight: '0px'
|
|
||||||
});
|
|
||||||
|
|
||||||
sidebar.css({
|
|
||||||
marginLeft: '0px',
|
|
||||||
width: '0px'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
el.on('touchmove', onTouchMove);
|
|
||||||
el.on('mousedown', function() {
|
|
||||||
el.on('mousemove', onMouseMove);
|
|
||||||
});
|
|
||||||
|
|
||||||
el.on('touchend', onTouchEnd);
|
|
||||||
el.on('mouseup', function() {
|
|
||||||
el.off('mousemove');
|
|
||||||
onTouchEnd();
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}());
|
}());
|
||||||
@@ -4,30 +4,32 @@
|
|||||||
isFollowing = templates.get('isFollowing');
|
isFollowing = templates.get('isFollowing');
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
var username = $('.account-username a').html();
|
||||||
|
app.enter_room('user/' + theirid);
|
||||||
|
|
||||||
var rep = $('#reputation');
|
app.addCommasToNumbers();
|
||||||
rep.html(app.addCommas(rep.html()));
|
|
||||||
|
|
||||||
var postcount = $('#postcount');
|
|
||||||
postcount.html(app.addCommas(postcount.html()));
|
|
||||||
|
|
||||||
var followBtn = $('#follow-btn');
|
var followBtn = $('#follow-btn');
|
||||||
var unfollowBtn = $('#unfollow-btn');
|
var unfollowBtn = $('#unfollow-btn');
|
||||||
|
|
||||||
if(yourid !== theirid) {
|
if (yourid !== theirid) {
|
||||||
if(isFollowing) {
|
if (isFollowing) {
|
||||||
followBtn.hide();
|
followBtn.hide();
|
||||||
unfollowBtn.show();
|
unfollowBtn.show();
|
||||||
} else {
|
} else {
|
||||||
followBtn.show();
|
followBtn.show();
|
||||||
unfollowBtn.hide();
|
unfollowBtn.hide();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
followBtn.hide();
|
||||||
|
unfollowBtn.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
followBtn.on('click', function() {
|
followBtn.on('click', function() {
|
||||||
socket.emit('api:user.follow', {uid: theirid}, function(success) {
|
socket.emit('api:user.follow', {
|
||||||
var username = $('.account-username a').html();
|
uid: theirid
|
||||||
if(success) {
|
}, function(success) {
|
||||||
|
if (success) {
|
||||||
followBtn.hide();
|
followBtn.hide();
|
||||||
unfollowBtn.show();
|
unfollowBtn.show();
|
||||||
app.alertSuccess('You are now following ' + username + '!');
|
app.alertSuccess('You are now following ' + username + '!');
|
||||||
@@ -39,9 +41,10 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
unfollowBtn.on('click', function() {
|
unfollowBtn.on('click', function() {
|
||||||
socket.emit('api:user.unfollow', {uid: theirid}, function(success) {
|
socket.emit('api:user.unfollow', {
|
||||||
var username = $('.account-username a').html();
|
uid: theirid
|
||||||
if(success) {
|
}, function(success) {
|
||||||
|
if (success) {
|
||||||
followBtn.show();
|
followBtn.show();
|
||||||
unfollowBtn.hide();
|
unfollowBtn.hide();
|
||||||
app.alertSuccess('You are no longer following ' + username + '!');
|
app.alertSuccess('You are no longer following ' + username + '!');
|
||||||
@@ -58,17 +61,24 @@
|
|||||||
|
|
||||||
var onlineStatus = $('.account-online-status');
|
var onlineStatus = $('.account-online-status');
|
||||||
|
|
||||||
socket.on('api:user.isOnline', function(online) {
|
function handleUserOnline(data) {
|
||||||
if(online) {
|
if (data.online) {
|
||||||
onlineStatus.find('span span').text('online');
|
onlineStatus.find('span span').text('online');
|
||||||
onlineStatus.find('i').attr('class', 'icon-circle');
|
onlineStatus.find('i').attr('class', 'icon-circle');
|
||||||
} else {
|
} else {
|
||||||
onlineStatus.find('span span').text('offline');
|
onlineStatus.find('span span').text('offline');
|
||||||
onlineStatus.find('i').attr('class', 'icon-circle-blank');
|
onlineStatus.find('i').attr('class', 'icon-circle-blank');
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
socket.emit('api:user.isOnline', theirid);
|
socket.on('api:user.isOnline', handleUserOnline);
|
||||||
|
|
||||||
|
socket.emit('api:user.isOnline', theirid, handleUserOnline);
|
||||||
|
|
||||||
|
socket.on('event:new_post', function(data) {
|
||||||
|
var html = templates.prepare(templates['account'].blocks['posts']).parse(data);
|
||||||
|
$('.user-recent-posts').prepend(html);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
var gravatarPicture = templates.get('gravatarpicture');
|
var gravatarPicture = templates.get('gravatarpicture');
|
||||||
var uploadedPicture = templates.get('uploadedpicture');
|
var uploadedPicture = templates.get('uploadedpicture');
|
||||||
|
|
||||||
@@ -12,8 +10,9 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
$('#upload-progress-bar').css('width', '0%');
|
$('#upload-progress-bar').css('width', '0%');
|
||||||
$('#upload-progress-box').show();
|
$('#upload-progress-box').show();
|
||||||
|
$('#upload-progress-box').removeClass('hide');
|
||||||
|
|
||||||
if(!$('#userPhotoInput').val()) {
|
if (!$('#userPhotoInput').val()) {
|
||||||
error('select an image to upload!');
|
error('select an image to upload!');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -27,13 +26,14 @@ $(document).ready(function() {
|
|||||||
error('Error: ' + xhr.status);
|
error('Error: ' + xhr.status);
|
||||||
},
|
},
|
||||||
|
|
||||||
uploadProgress : function(event, position, total, percent) {
|
uploadProgress: function(event, position, total, percent) {
|
||||||
$('#upload-progress-bar').css('width', percent+'%');
|
console.log(percent);
|
||||||
|
$('#upload-progress-bar').css('width', percent + '%');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
if(response.error) {
|
if (response.error) {
|
||||||
error(response.error);
|
error(response.error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,9 @@ $(document).ready(function() {
|
|||||||
$('#upload-picture-modal').modal('hide');
|
$('#upload-picture-modal').modal('hide');
|
||||||
}, 750);
|
}, 750);
|
||||||
|
|
||||||
socket.emit('api:updateHeader', { fields: ['username', 'picture', 'userslug'] });
|
socket.emit('api:updateHeader', {
|
||||||
|
fields: ['username', 'picture', 'userslug']
|
||||||
|
});
|
||||||
success('File uploaded successfully!');
|
success('File uploaded successfully!');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -59,25 +61,25 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function hideAlerts() {
|
function hideAlerts() {
|
||||||
$('#alert-status').hide();
|
$('#alert-status').addClass('hide');
|
||||||
$('#alert-success').hide();
|
$('#alert-success').addClass('hide');
|
||||||
$('#alert-error').hide();
|
$('#alert-error').addClass('hide');
|
||||||
$('#upload-progress-box').hide();
|
$('#upload-progress-box').addClass('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
function status(message) {
|
function status(message) {
|
||||||
hideAlerts();
|
hideAlerts();
|
||||||
$('#alert-status').text(message).show();
|
$('#alert-status').text(message).removeClass('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
function success(message) {
|
function success(message) {
|
||||||
hideAlerts();
|
hideAlerts();
|
||||||
$('#alert-success').text(message).show();
|
$('#alert-success').text(message).removeClass('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
function error(message) {
|
function error(message) {
|
||||||
hideAlerts();
|
hideAlerts();
|
||||||
$('#alert-error').text(message).show();
|
$('#alert-error').text(message).removeClass('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeUserPicture(type) {
|
function changeUserPicture(type) {
|
||||||
@@ -86,7 +88,7 @@ $(document).ready(function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
socket.emit('api:user.changePicture', userData, function(success) {
|
socket.emit('api:user.changePicture', userData, function(success) {
|
||||||
if(!success) {
|
if (!success) {
|
||||||
app.alertError('There was an error changing picture!');
|
app.alertError('There was an error changing picture!');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -94,31 +96,31 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
var selectedImageType = '';
|
var selectedImageType = '';
|
||||||
|
|
||||||
$('#submitBtn').on('click',function(){
|
$('#submitBtn').on('click', function() {
|
||||||
|
|
||||||
var userData = {
|
var userData = {
|
||||||
uid:$('#inputUID').val(),
|
uid: $('#inputUID').val(),
|
||||||
email:$('#inputEmail').val(),
|
email: $('#inputEmail').val(),
|
||||||
fullname:$('#inputFullname').val(),
|
fullname: $('#inputFullname').val(),
|
||||||
website:$('#inputWebsite').val(),
|
website: $('#inputWebsite').val(),
|
||||||
birthday:$('#inputBirthday').val(),
|
birthday: $('#inputBirthday').val(),
|
||||||
location:$('#inputLocation').val(),
|
location: $('#inputLocation').val(),
|
||||||
signature:$('#inputSignature').val()
|
signature: $('#inputSignature').val()
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.emit('api:user.updateProfile', userData, function(data) {
|
socket.emit('api:user.updateProfile', userData, function(err, data) {
|
||||||
if(data.success) {
|
if (data.success) {
|
||||||
app.alertSuccess('Your profile has been updated successfully!');
|
app.alertSuccess('Your profile has been updated successfully!');
|
||||||
if(data.picture) {
|
if (data.picture) {
|
||||||
$('#user-current-picture').attr('src', data.picture);
|
$('#user-current-picture').attr('src', data.picture);
|
||||||
$('#user_label img').attr('src', data.picture);
|
$('#user_label img').attr('src', data.picture);
|
||||||
}
|
}
|
||||||
if(data.gravatarpicture) {
|
if (data.gravatarpicture) {
|
||||||
$('#user-gravatar-picture').attr('src', data.gravatarpicture);
|
$('#user-gravatar-picture').attr('src', data.gravatarpicture);
|
||||||
gravatarPicture = data.gravatarpicture;
|
gravatarPicture = data.gravatarpicture;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
app.alertError('There was an error updating your profile!');
|
app.alertError('There was an error updating your profile! ' + err.error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
@@ -127,27 +129,25 @@ $(document).ready(function() {
|
|||||||
function updateImages() {
|
function updateImages() {
|
||||||
var currentPicture = $('#user-current-picture').attr('src');
|
var currentPicture = $('#user-current-picture').attr('src');
|
||||||
|
|
||||||
if(gravatarPicture) {
|
if (gravatarPicture) {
|
||||||
$('#user-gravatar-picture').attr('src', gravatarPicture);
|
$('#user-gravatar-picture').attr('src', gravatarPicture);
|
||||||
$('#gravatar-box').show();
|
$('#gravatar-box').show();
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
$('#gravatar-box').hide();
|
$('#gravatar-box').hide();
|
||||||
|
|
||||||
if(uploadedPicture) {
|
if (uploadedPicture) {
|
||||||
$('#user-uploaded-picture').attr('src', uploadedPicture);
|
$('#user-uploaded-picture').attr('src', uploadedPicture);
|
||||||
$('#uploaded-box').show();
|
$('#uploaded-box').show();
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
$('#uploaded-box').hide();
|
$('#uploaded-box').hide();
|
||||||
|
|
||||||
|
|
||||||
if(currentPicture == gravatarPicture)
|
if (currentPicture == gravatarPicture)
|
||||||
$('#gravatar-box .icon-ok').show();
|
$('#gravatar-box .icon-ok').show();
|
||||||
else
|
else
|
||||||
$('#gravatar-box .icon-ok').hide();
|
$('#gravatar-box .icon-ok').hide();
|
||||||
|
|
||||||
if(currentPicture == uploadedPicture)
|
if (currentPicture == uploadedPicture)
|
||||||
$('#uploaded-box .icon-ok').show();
|
$('#uploaded-box .icon-ok').show();
|
||||||
else
|
else
|
||||||
$('#uploaded-box .icon-ok').hide();
|
$('#uploaded-box .icon-ok').hide();
|
||||||
@@ -159,17 +159,18 @@ $(document).ready(function() {
|
|||||||
updateImages();
|
updateImages();
|
||||||
|
|
||||||
$('#change-picture-modal').modal('show');
|
$('#change-picture-modal').modal('show');
|
||||||
|
$('#change-picture-modal').removeClass('hide');
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#gravatar-box').on('click', function(){
|
$('#gravatar-box').on('click', function() {
|
||||||
$('#gravatar-box .icon-ok').show();
|
$('#gravatar-box .icon-ok').show();
|
||||||
$('#uploaded-box .icon-ok').hide();
|
$('#uploaded-box .icon-ok').hide();
|
||||||
selectedImageType = 'gravatar';
|
selectedImageType = 'gravatar';
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#uploaded-box').on('click', function(){
|
$('#uploaded-box').on('click', function() {
|
||||||
$('#gravatar-box .icon-ok').hide();
|
$('#gravatar-box .icon-ok').hide();
|
||||||
$('#uploaded-box .icon-ok').show();
|
$('#uploaded-box .icon-ok').show();
|
||||||
selectedImageType = 'uploaded';
|
selectedImageType = 'uploaded';
|
||||||
@@ -178,12 +179,12 @@ $(document).ready(function() {
|
|||||||
$('#savePictureChangesBtn').on('click', function() {
|
$('#savePictureChangesBtn').on('click', function() {
|
||||||
$('#change-picture-modal').modal('hide');
|
$('#change-picture-modal').modal('hide');
|
||||||
|
|
||||||
if(selectedImageType) {
|
if (selectedImageType) {
|
||||||
changeUserPicture(selectedImageType);
|
changeUserPicture(selectedImageType);
|
||||||
|
|
||||||
if(selectedImageType == 'gravatar')
|
if (selectedImageType == 'gravatar')
|
||||||
$('#user-current-picture').attr('src', gravatarPicture);
|
$('#user-current-picture').attr('src', gravatarPicture);
|
||||||
else if(selectedImageType == 'uploaded')
|
else if (selectedImageType == 'uploaded')
|
||||||
$('#user-current-picture').attr('src', uploadedPicture);
|
$('#user-current-picture').attr('src', uploadedPicture);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,10 +194,11 @@ $(document).ready(function() {
|
|||||||
$('#userPhotoInput').val('');
|
$('#userPhotoInput').val('');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#uploadPictureBtn').on('click', function(){
|
$('#uploadPictureBtn').on('click', function() {
|
||||||
|
|
||||||
$('#change-picture-modal').modal('hide');
|
$('#change-picture-modal').modal('hide');
|
||||||
$('#upload-picture-modal').modal('show');
|
$('#upload-picture-modal').modal('show');
|
||||||
|
$('#upload-picture-modal').removeClass('hide');
|
||||||
|
|
||||||
hideAlerts();
|
hideAlerts();
|
||||||
|
|
||||||
@@ -219,50 +221,62 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
function onPasswordChanged() {
|
function onPasswordChanged() {
|
||||||
passwordvalid = utils.isPasswordValid(password.val());
|
passwordvalid = utils.isPasswordValid(password.val());
|
||||||
if (password.val().length < 6) {
|
if (password.val().length < config.minimumPasswordLength) {
|
||||||
password_notify.html('Password too short');
|
password_notify.html('Password too short');
|
||||||
password_notify.attr('class', 'label label-important');
|
password_notify.attr('class', 'alert alert-danger');
|
||||||
} else if(!passwordvalid) {
|
password_notify.removeClass('hide');
|
||||||
|
} else if (!passwordvalid) {
|
||||||
password_notify.html('Invalid password');
|
password_notify.html('Invalid password');
|
||||||
password_notify.attr('class', 'label label-important');
|
password_notify.attr('class', 'alert alert-danger');
|
||||||
|
password_notify.removeClass('hide');
|
||||||
} else {
|
} else {
|
||||||
password_notify.html('OK!');
|
password_notify.html('OK!');
|
||||||
password_notify.attr('class', 'label label-success');
|
password_notify.attr('class', 'alert alert-success');
|
||||||
|
password_notify.removeClass('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
onPasswordConfirmChanged();
|
onPasswordConfirmChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPasswordConfirmChanged() {
|
function onPasswordConfirmChanged() {
|
||||||
if(password.val() !== password_confirm.val()) {
|
if (password_notify.hasClass('alert-danger') || !password_confirm.val()) {
|
||||||
|
password_confirm_notify.addClass('hide');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (password.val() !== password_confirm.val()) {
|
||||||
password_confirm_notify.html('Passwords must match!');
|
password_confirm_notify.html('Passwords must match!');
|
||||||
password_confirm_notify.attr('class', 'label label-important');
|
password_confirm_notify.attr('class', 'alert alert-danger');
|
||||||
|
password_confirm_notify.removeClass('hide');
|
||||||
passwordsmatch = false;
|
passwordsmatch = false;
|
||||||
} else {
|
} else {
|
||||||
password_confirm_notify.html('OK!');
|
password_confirm_notify.html('OK!');
|
||||||
password_confirm_notify.attr('class', 'label label-success');
|
password_confirm_notify.attr('class', 'alert alert-success');
|
||||||
|
password_confirm_notify.removeClass('hide');
|
||||||
passwordsmatch = true;
|
passwordsmatch = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
password.on('keyup', onPasswordChanged);
|
password.on('blur', onPasswordChanged);
|
||||||
password_confirm.on('keyup', onPasswordConfirmChanged);
|
password_confirm.on('blur', onPasswordConfirmChanged);
|
||||||
|
|
||||||
$('#changePasswordBtn').on('click', function() {
|
$('#changePasswordBtn').on('click', function() {
|
||||||
|
|
||||||
if(passwordvalid && passwordsmatch && currentPassword.val()) {
|
if (passwordvalid && passwordsmatch && currentPassword.val()) {
|
||||||
socket.emit('api:user.changePassword', {'currentPassword': currentPassword.val(),'newPassword': password.val() }, function(data) {
|
socket.emit('api:user.changePassword', {
|
||||||
|
'currentPassword': currentPassword.val(),
|
||||||
|
'newPassword': password.val()
|
||||||
|
}, function(err) {
|
||||||
|
|
||||||
currentPassword.val('');
|
currentPassword.val('');
|
||||||
password.val('');
|
password.val('');
|
||||||
password_confirm.val('');
|
password_confirm.val('');
|
||||||
password_notify.html('');
|
password_notify.addClass('hide');
|
||||||
password_confirm_notify.html('');
|
password_confirm_notify.addClass('hide');
|
||||||
passwordsmatch = false;
|
passwordsmatch = false;
|
||||||
passwordvalid = false;
|
passwordvalid = false;
|
||||||
|
|
||||||
if(data.err) {
|
if (err) {
|
||||||
app.alertError(data.err);
|
app.alertError(err.error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,19 +2,41 @@
|
|||||||
var yourid = templates.get('yourid'),
|
var yourid = templates.get('yourid'),
|
||||||
theirid = templates.get('theirid');
|
theirid = templates.get('theirid');
|
||||||
|
|
||||||
|
|
||||||
|
function createMenu() {
|
||||||
|
var userslug = $('.account-username-box').attr('data-userslug');
|
||||||
|
var links = $('<div class="account-sub-links inline-block pull-right">\
|
||||||
|
<span id="settingsLink" class="pull-right"><a href="/user/' + userslug + '/settings">settings</a></span>\
|
||||||
|
<span id="favouritesLink" class="pull-right"><a href="/user/' + userslug + '/favourites">favourites</a></span>\
|
||||||
|
<span class="pull-right"><a href="/user/' + userslug + '/followers">followers</a></span>\
|
||||||
|
<span class="pull-right"><a href="/user/' + userslug + '/following">following</a></span>\
|
||||||
|
<span id="editLink" class="pull-right"><a href="/user/' + userslug + '/edit">edit</a></span>\
|
||||||
|
</div>');
|
||||||
|
|
||||||
|
$('.account-username-box').append(links);
|
||||||
|
}
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
createMenu();
|
||||||
|
|
||||||
var editLink = $('#editLink');
|
var editLink = $('#editLink');
|
||||||
var settingsLink = $('#settingsLink');
|
var settingsLink = $('#settingsLink');
|
||||||
|
var favouritesLink = $('#favouritesLink');
|
||||||
|
|
||||||
if(yourid === "0") {
|
if (yourid === "0" || yourid !== theirid) {
|
||||||
editLink.hide();
|
editLink.hide();
|
||||||
settingsLink.hide();
|
settingsLink.hide();
|
||||||
|
favouritesLink.hide();
|
||||||
}
|
}
|
||||||
else if(yourid !== theirid) {
|
|
||||||
editLink.hide();
|
jQuery('.account-sub-links span a').removeClass('bold').each(function() {
|
||||||
settingsLink.hide();
|
var href = this.getAttribute('href');
|
||||||
|
if (window.location.href.indexOf(href) !== -1) {
|
||||||
|
jQuery(this).addClass('bold');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
}());
|
}());
|
||||||
@@ -1,16 +1,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
$('#submitBtn').on('click', function() {
|
$('#submitBtn').on('click', function() {
|
||||||
|
|
||||||
var settings = {
|
var settings = {
|
||||||
showemail: $('#showemailCheckBox').is(':checked')?1:0
|
showemail: $('#showemailCheckBox').is(':checked') ? 1 : 0
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.emit('api:user.saveSettings', settings, function(success) {
|
socket.emit('api:user.saveSettings', settings, function(success) {
|
||||||
if(success) {
|
if (success) {
|
||||||
app.alertSuccess('Settings saved!');
|
app.alertSuccess('Settings saved!');
|
||||||
} else {
|
} else {
|
||||||
app.alertError('There was an error saving settings!');
|
app.alertError('There was an error saving settings!');
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
|
|
||||||
var modified_categories = {};
|
var modified_categories = {};
|
||||||
|
|
||||||
function modified(el) {
|
function modified(el) {
|
||||||
var cid = $(el).parents('li').attr('data-cid');
|
var cid = $(el).parents('li').attr('data-cid');
|
||||||
|
|
||||||
modified_categories[cid] = modified_categories[cid] || {};
|
modified_categories[cid] = modified_categories[cid] || {};
|
||||||
modified_categories[cid][el.getAttribute('data-name')] = el.value;
|
modified_categories[cid][$(el).attr('data-name')] = $(el).val();
|
||||||
}
|
}
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
@@ -14,25 +13,28 @@ function save() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function select_icon(el) {
|
function select_icon(el) {
|
||||||
var selected = el.className.replace(' icon-2x', '');
|
var selected = el.attr('class').replace(' icon-2x', '');
|
||||||
jQuery('#icons .selected').removeClass('selected');
|
jQuery('#icons .selected').removeClass('selected');
|
||||||
|
if (selected)
|
||||||
jQuery('#icons .' + selected).parent().addClass('selected');
|
jQuery('#icons .' + selected).parent().addClass('selected');
|
||||||
|
|
||||||
|
|
||||||
bootbox.confirm('<h2>Select an icon.</h2>' + document.getElementById('icons').innerHTML, function(confirm) {
|
bootbox.confirm('<h2>Select an icon.</h2>' + document.getElementById('icons').innerHTML, function(confirm) {
|
||||||
if (confirm) {
|
if (confirm) {
|
||||||
var iconClass = jQuery('.bootbox .selected').children(':first').attr('class');
|
var iconClass = jQuery('.bootbox .selected').children(':first').attr('class');
|
||||||
el.className = iconClass + ' icon icon-2x';
|
el.attr('class', iconClass + ' icon-2x');
|
||||||
el.value = iconClass;
|
el.val(iconClass);
|
||||||
|
|
||||||
modified(el);
|
modified(el);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
jQuery('.bootbox .span3').on('click', function() {
|
setTimeout(function() { //bootbox was rewritten for BS3 and I had to add this timeout for the previous code to work. TODO: to look into
|
||||||
|
jQuery('.bootbox .col-md-3').on('click', function() {
|
||||||
jQuery('.bootbox .selected').removeClass('selected');
|
jQuery('.bootbox .selected').removeClass('selected');
|
||||||
jQuery(this).addClass('selected');
|
jQuery(this).addClass('selected');
|
||||||
});
|
});
|
||||||
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -48,10 +50,42 @@ jQuery('.blockclass').each(function() {
|
|||||||
|
|
||||||
//DRY Failure. this needs to go into an ajaxify onready style fn. Currently is copy pasted into every single function so after ACP is off the ground fix asap
|
//DRY Failure. this needs to go into an ajaxify onready style fn. Currently is copy pasted into every single function so after ACP is off the ground fix asap
|
||||||
(function() {
|
(function() {
|
||||||
|
function showCreateCategoryModal() {
|
||||||
|
$('#new-category-modal').modal();
|
||||||
|
}
|
||||||
|
|
||||||
|
function createNewCategory() {
|
||||||
|
var category = {
|
||||||
|
name: $('#inputName').val(),
|
||||||
|
description: $('#inputDescription').val(),
|
||||||
|
icon: $('#new-category-modal i').attr('value'),
|
||||||
|
blockclass: $('#inputBlockclass').val()
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.emit('api:admin.categories.create', category, function(err, data) {
|
||||||
|
if (!err) {
|
||||||
|
app.alert({
|
||||||
|
alert_id: 'category_created',
|
||||||
|
title: 'Created',
|
||||||
|
message: 'Category successfully created!',
|
||||||
|
type: 'success',
|
||||||
|
timeout: 2000
|
||||||
|
});
|
||||||
|
|
||||||
|
var html = templates.prepare(templates['admin/categories'].blocks['categories']).parse({
|
||||||
|
categories: [data]
|
||||||
|
});
|
||||||
|
$('#entry-container').append(html);
|
||||||
|
|
||||||
|
$('#new-category-modal').modal('hide');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
jQuery('document').ready(function() {
|
jQuery('document').ready(function() {
|
||||||
var url = window.location.href,
|
var url = window.location.href,
|
||||||
parts = url.split('/'),
|
parts = url.split('/'),
|
||||||
active = parts[parts.length-1];
|
active = parts[parts.length - 1];
|
||||||
|
|
||||||
jQuery('.nav-pills li').removeClass('active');
|
jQuery('.nav-pills li').removeClass('active');
|
||||||
jQuery('.nav-pills li a').each(function() {
|
jQuery('.nav-pills li a').each(function() {
|
||||||
@@ -62,9 +96,11 @@ jQuery('.blockclass').each(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
jQuery('#save').on('click', save);
|
jQuery('#save').on('click', save);
|
||||||
|
jQuery('#addNew').on('click', showCreateCategoryModal);
|
||||||
|
jQuery('#create-category-btn').on('click', createNewCategory);
|
||||||
|
|
||||||
jQuery('.icon').on('click', function(ev) {
|
jQuery('#entry-container').on('click', '.icon', function(ev) {
|
||||||
select_icon(ev.target);
|
select_icon($(this).find('i'));
|
||||||
});
|
});
|
||||||
|
|
||||||
jQuery('.blockclass').on('change', function(ev) {
|
jQuery('.blockclass').on('change', function(ev) {
|
||||||
@@ -77,7 +113,7 @@ jQuery('.blockclass').each(function() {
|
|||||||
|
|
||||||
jQuery('.entry-row button').each(function(index, element) {
|
jQuery('.entry-row button').each(function(index, element) {
|
||||||
var disabled = $(element).attr('data-disabled');
|
var disabled = $(element).attr('data-disabled');
|
||||||
if(disabled == "0" || disabled == "")
|
if (disabled == "0" || disabled == "")
|
||||||
$(element).html('Disable');
|
$(element).html('Disable');
|
||||||
else
|
else
|
||||||
$(element).html('Enable');
|
$(element).html('Enable');
|
||||||
@@ -89,7 +125,7 @@ jQuery('.blockclass').each(function() {
|
|||||||
var categoryRow = btn.parents('li');
|
var categoryRow = btn.parents('li');
|
||||||
var cid = categoryRow.attr('data-cid');
|
var cid = categoryRow.attr('data-cid');
|
||||||
|
|
||||||
var disabled = btn.html() == "Disable" ? "1":"0";
|
var disabled = btn.html() == "Disable" ? "1" : "0";
|
||||||
categoryRow.remove();
|
categoryRow.remove();
|
||||||
modified_categories[cid] = modified_categories[cid] || {};
|
modified_categories[cid] = modified_categories[cid] || {};
|
||||||
modified_categories[cid]['disabled'] = disabled;
|
modified_categories[cid]['disabled'] = disabled;
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
var nodebb_admin = (function(nodebb_admin) {
|
var nodebb_admin = (function(nodebb_admin) {
|
||||||
|
|
||||||
nodebb_admin.config = undefined;
|
nodebb_admin.config = undefined;
|
||||||
@@ -19,12 +16,12 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
numFields = fields.length,
|
numFields = fields.length,
|
||||||
saveBtn = document.getElementById('save'),
|
saveBtn = document.getElementById('save'),
|
||||||
x, key, inputType;
|
x, key, inputType;
|
||||||
for(x=0;x<numFields;x++) {
|
for (x = 0; x < numFields; x++) {
|
||||||
key = fields[x].getAttribute('data-field');
|
key = fields[x].getAttribute('data-field');
|
||||||
inputType = fields[x].getAttribute('type');
|
inputType = fields[x].getAttribute('type');
|
||||||
if (fields[x].nodeName === 'INPUT') {
|
if (fields[x].nodeName === 'INPUT') {
|
||||||
if (nodebb_admin.config[key]) {
|
if (nodebb_admin.config[key]) {
|
||||||
switch(inputType) {
|
switch (inputType) {
|
||||||
case 'text':
|
case 'text':
|
||||||
case 'textarea':
|
case 'textarea':
|
||||||
case 'number':
|
case 'number':
|
||||||
@@ -45,11 +42,11 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
var key, value;
|
var key, value;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
for(x=0;x<numFields;x++) {
|
for (x = 0; x < numFields; x++) {
|
||||||
key = fields[x].getAttribute('data-field');
|
key = fields[x].getAttribute('data-field');
|
||||||
if (fields[x].nodeName === 'INPUT') {
|
if (fields[x].nodeName === 'INPUT') {
|
||||||
inputType = fields[x].getAttribute('type');
|
inputType = fields[x].getAttribute('type');
|
||||||
switch(inputType) {
|
switch (inputType) {
|
||||||
case 'text':
|
case 'text':
|
||||||
case 'number':
|
case 'number':
|
||||||
value = fields[x].value;
|
value = fields[x].value;
|
||||||
@@ -63,7 +60,10 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
value = fields[x].value;
|
value = fields[x].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.emit('api:config.set', { key: key, value: value });
|
socket.emit('api:config.set', {
|
||||||
|
key: key,
|
||||||
|
value: value
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
menuEl.addEventListener('click', function(e) {
|
menuEl.addEventListener('click', function(e) {
|
||||||
parentEl = e.target.parentNode;
|
parentEl = e.target.parentNode;
|
||||||
if (parentEl.nodeName === 'LI') {
|
if (parentEl.nodeName === 'LI') {
|
||||||
for(var x=0,numLis=liEls.length;x<numLis;x++) {
|
for (var x = 0, numLis = liEls.length; x < numLis; x++) {
|
||||||
if (liEls[x] !== parentEl) jQuery(liEls[x]).removeClass('active');
|
if (liEls[x] !== parentEl) jQuery(liEls[x]).removeClass('active');
|
||||||
else jQuery(parentEl).addClass('active');
|
else jQuery(parentEl).addClass('active');
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
alert_id: 'config_status',
|
alert_id: 'config_status',
|
||||||
timeout: 2500,
|
timeout: 2500,
|
||||||
title: 'Changes Saved',
|
title: 'Changes Saved',
|
||||||
message: 'Your changes to the NodeBB configuration have been saved. You may have to restart NodeBB to see the changes.',
|
message: 'Your changes to the NodeBB configuration have been saved.',
|
||||||
type: 'success'
|
type: 'success'
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -111,7 +111,7 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
timeout: 2500,
|
timeout: 2500,
|
||||||
title: 'Changes Not Saved',
|
title: 'Changes Not Saved',
|
||||||
message: 'NodeBB encountered a problem saving your changes',
|
message: 'NodeBB encountered a problem saving your changes',
|
||||||
type: 'error'
|
type: 'danger'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -119,4 +119,3 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
return nodebb_admin;
|
return nodebb_admin;
|
||||||
|
|
||||||
}(nodebb_admin || {}));
|
}(nodebb_admin || {}));
|
||||||
|
|
||||||
|
|||||||
194
public/src/forum/admin/groups.js
Normal file
194
public/src/forum/admin/groups.js
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
$(document).ready(function() {
|
||||||
|
var createEl = document.getElementById('create'),
|
||||||
|
createModal = $('#create-modal'),
|
||||||
|
createSubmitBtn = document.getElementById('create-modal-go'),
|
||||||
|
createNameEl = $('#create-group-name'),
|
||||||
|
detailsModal = $('#group-details-modal'),
|
||||||
|
detailsSearch = detailsModal.find('#group-details-search'),
|
||||||
|
searchResults = detailsModal.find('#group-details-search-results'),
|
||||||
|
groupMembersEl = detailsModal.find('ul.current_members'),
|
||||||
|
detailsModalSave = detailsModal.find('.btn-primary'),
|
||||||
|
searchDelay = undefined,
|
||||||
|
listEl = $('#groups-list');
|
||||||
|
|
||||||
|
createEl.addEventListener('click', function() {
|
||||||
|
createModal.modal('show');
|
||||||
|
setTimeout(function() {
|
||||||
|
createNameEl.focus();
|
||||||
|
}, 250);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
createSubmitBtn.addEventListener('click', function() {
|
||||||
|
var submitObj = {
|
||||||
|
name: createNameEl.val(),
|
||||||
|
description: $('#create-group-desc').val()
|
||||||
|
},
|
||||||
|
errorEl = $('#create-modal-error'),
|
||||||
|
errorText;
|
||||||
|
|
||||||
|
socket.emit('api:groups.create', submitObj, function(err, data) {
|
||||||
|
if (err) {
|
||||||
|
switch (err) {
|
||||||
|
case 'group-exists':
|
||||||
|
errorText = '<strong>Please choose another name</strong><p>There seems to be a group with this name already.</p>';
|
||||||
|
break;
|
||||||
|
case 'name-too-short':
|
||||||
|
errorText = '<strong>Please specify a grou name</strong><p>A group name is required for administrative purposes.</p>';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorText = '<strong>Uh-Oh</strong><p>There was a problem creating your group. Please try again later!</p>';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorEl.html(errorText).removeClass('hide');
|
||||||
|
} else {
|
||||||
|
createModal.modal('hide');
|
||||||
|
errorEl.addClass('hide');
|
||||||
|
createNameEl.val('');
|
||||||
|
ajaxify.go('admin/groups');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
listEl.on('click', 'button[data-action]', function() {
|
||||||
|
var action = this.getAttribute('data-action'),
|
||||||
|
gid = $(this).parents('li[data-gid]').attr('data-gid');
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case 'delete':
|
||||||
|
bootbox.confirm('Are you sure you wish to delete this group?', function(confirm) {
|
||||||
|
if (confirm) {
|
||||||
|
socket.emit('api:groups.delete', gid, function(err, data) {
|
||||||
|
if (data === 'OK') ajaxify.go('admin/groups');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'members':
|
||||||
|
socket.emit('api:groups.get', gid, function(err, groupObj) {
|
||||||
|
var formEl = detailsModal.find('form'),
|
||||||
|
nameEl = formEl.find('#change-group-name'),
|
||||||
|
descEl = formEl.find('#change-group-desc'),
|
||||||
|
memberIcon = document.createElement('li'),
|
||||||
|
numMembers = groupObj.members.length,
|
||||||
|
membersFrag = document.createDocumentFragment(),
|
||||||
|
memberIconImg, x;
|
||||||
|
|
||||||
|
|
||||||
|
nameEl.val(groupObj.name);
|
||||||
|
descEl.val(groupObj.description);
|
||||||
|
|
||||||
|
// Member list
|
||||||
|
memberIcon.innerHTML = '<img /><span></span>';
|
||||||
|
memberIconImg = memberIcon.querySelector('img');
|
||||||
|
memberIconLabel = memberIcon.querySelector('span');
|
||||||
|
if (numMembers > 0) {
|
||||||
|
for (x = 0; x < numMembers; x++) {
|
||||||
|
memberIconImg.src = groupObj.members[x].picture;
|
||||||
|
memberIconLabel.innerHTML = groupObj.members[x].username;
|
||||||
|
memberIcon.setAttribute('data-uid', groupObj.members[x].uid);
|
||||||
|
membersFrag.appendChild(memberIcon.cloneNode(true));
|
||||||
|
}
|
||||||
|
groupMembersEl.html('');
|
||||||
|
groupMembersEl[0].appendChild(membersFrag);
|
||||||
|
}
|
||||||
|
|
||||||
|
detailsModal.attr('data-gid', groupObj.gid);
|
||||||
|
detailsModal.modal('show');
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
detailsSearch.on('keyup', function() {
|
||||||
|
var searchEl = this;
|
||||||
|
|
||||||
|
if (searchDelay) clearTimeout(searchDelay);
|
||||||
|
|
||||||
|
searchDelay = setTimeout(function() {
|
||||||
|
var searchText = searchEl.value,
|
||||||
|
resultsEl = document.getElementById('group-details-search-results'),
|
||||||
|
foundUser = document.createElement('li'),
|
||||||
|
foundUserImg, foundUserLabel;
|
||||||
|
|
||||||
|
foundUser.innerHTML = '<img /><span></span>';
|
||||||
|
foundUserImg = foundUser.getElementsByTagName('img')[0];
|
||||||
|
foundUserLabel = foundUser.getElementsByTagName('span')[0];
|
||||||
|
|
||||||
|
socket.emit('api:admin.user.search', searchText, function(err, results) {
|
||||||
|
if (!err && results && results.length > 0) {
|
||||||
|
var numResults = results.length,
|
||||||
|
resultsSlug = document.createDocumentFragment(),
|
||||||
|
x;
|
||||||
|
if (numResults > 4) numResults = 4;
|
||||||
|
for (x = 0; x < numResults; x++) {
|
||||||
|
foundUserImg.src = results[x].picture;
|
||||||
|
foundUserLabel.innerHTML = results[x].username;
|
||||||
|
foundUser.setAttribute('title', results[x].username);
|
||||||
|
foundUser.setAttribute('data-uid', results[x].uid);
|
||||||
|
resultsSlug.appendChild(foundUser.cloneNode(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
resultsEl.innerHTML = '';
|
||||||
|
resultsEl.appendChild(resultsSlug);
|
||||||
|
} else resultsEl.innerHTML = '<li>No Users Found</li>';
|
||||||
|
});
|
||||||
|
}, 200);
|
||||||
|
});
|
||||||
|
|
||||||
|
searchResults.on('click', 'li[data-uid]', function() {
|
||||||
|
var userLabel = this,
|
||||||
|
uid = parseInt(this.getAttribute('data-uid')),
|
||||||
|
gid = detailsModal.attr('data-gid'),
|
||||||
|
members = [];
|
||||||
|
|
||||||
|
groupMembersEl.find('li[data-uid]').each(function() {
|
||||||
|
members.push(parseInt(this.getAttribute('data-uid')));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (members.indexOf(uid) === -1) {
|
||||||
|
socket.emit('api:groups.join', {
|
||||||
|
gid: gid,
|
||||||
|
uid: uid
|
||||||
|
}, function(err, data) {
|
||||||
|
if (!err) {
|
||||||
|
groupMembersEl.append(userLabel.cloneNode(true));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
groupMembersEl.on('click', 'li[data-uid]', function() {
|
||||||
|
var uid = this.getAttribute('data-uid'),
|
||||||
|
gid = detailsModal.attr('data-gid');
|
||||||
|
|
||||||
|
socket.emit('api:groups.leave', {
|
||||||
|
gid: gid,
|
||||||
|
uid: uid
|
||||||
|
}, function(err, data) {
|
||||||
|
if (!err) {
|
||||||
|
groupMembersEl.find('li[data-uid="' + uid + '"]').remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
detailsModalSave.on('click', function() {
|
||||||
|
var formEl = detailsModal.find('form'),
|
||||||
|
nameEl = formEl.find('#change-group-name'),
|
||||||
|
descEl = formEl.find('#change-group-desc'),
|
||||||
|
gid = detailsModal.attr('data-gid');
|
||||||
|
|
||||||
|
socket.emit('api:groups.update', {
|
||||||
|
gid: gid,
|
||||||
|
values: {
|
||||||
|
name: nameEl.val(),
|
||||||
|
description: descEl.val()
|
||||||
|
}
|
||||||
|
}, function(err) {
|
||||||
|
if (!err) {
|
||||||
|
detailsModal.modal('hide');
|
||||||
|
ajaxify.go('admin/groups');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
total = 0;
|
total = 0;
|
||||||
active_users.innerHTML = '';
|
active_users.innerHTML = '';
|
||||||
|
|
||||||
for(var room in data) {
|
for (var room in data) {
|
||||||
if (room !== '') {
|
if (room !== '') {
|
||||||
var count = data[room].length;
|
var count = data[room].length;
|
||||||
total += count;
|
total += count;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ var nodebb_admin = nodebb_admin || {};
|
|||||||
alert_id: 'plugin_toggled_' + status.id,
|
alert_id: 'plugin_toggled_' + status.id,
|
||||||
title: 'Plugin Enabled',
|
title: 'Plugin Enabled',
|
||||||
message: 'You may need to restart NodeBB in order for these changes to be reflected.',
|
message: 'You may need to restart NodeBB in order for these changes to be reflected.',
|
||||||
type: 'notify',
|
type: 'warning',
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
var nodebb_admin = (function(nodebb_admin) {
|
var nodebb_admin = (function(nodebb_admin) {
|
||||||
|
|
||||||
var themes = {};
|
var themes = {};
|
||||||
@@ -10,7 +8,7 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
themeContainer = document.querySelector('#bootstrap_themes'),
|
themeContainer = document.querySelector('#bootstrap_themes'),
|
||||||
numThemes = bootswatch.themes.length;
|
numThemes = bootswatch.themes.length;
|
||||||
|
|
||||||
for(var x=0;x<numThemes;x++) {
|
for (var x = 0; x < numThemes; x++) {
|
||||||
var theme = bootswatch.themes[x];
|
var theme = bootswatch.themes[x];
|
||||||
themeEl.setAttribute('data-css', theme.cssMin);
|
themeEl.setAttribute('data-css', theme.cssMin);
|
||||||
themeEl.setAttribute('data-theme', theme.name);
|
themeEl.setAttribute('data-theme', theme.name);
|
||||||
@@ -18,7 +16,7 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
'<div>' +
|
'<div>' +
|
||||||
'<div class="pull-right">' +
|
'<div class="pull-right">' +
|
||||||
'<button class="btn btn-primary" data-action="use">Use</button> ' +
|
'<button class="btn btn-primary" data-action="use">Use</button> ' +
|
||||||
'<button class="btn" data-action="preview">Preview</button>' +
|
'<button class="btn btn-default" data-action="preview">Preview</button>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<h4>' + theme.name + '</h4>' +
|
'<h4>' + theme.name + '</h4>' +
|
||||||
'<p>' + theme.description + '</p>' +
|
'<p>' + theme.description + '</p>' +
|
||||||
@@ -39,14 +37,14 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var scriptEl = document.createElement('script');
|
var scriptEl = document.createElement('script');
|
||||||
scriptEl.src = 'http://api.bootswatch.com/2/?callback=nodebb_admin.themes.render';
|
scriptEl.src = 'http://api.bootswatch.com/3/?callback=nodebb_admin.themes.render';
|
||||||
document.body.appendChild(scriptEl);
|
document.body.appendChild(scriptEl);
|
||||||
|
|
||||||
var bootstrapThemeContainer = document.querySelector('#bootstrap_themes'),
|
var bootstrapThemeContainer = document.querySelector('#bootstrap_themes'),
|
||||||
installedThemeContainer = document.querySelector('#installed_themes'),
|
installedThemeContainer = document.querySelector('#installed_themes'),
|
||||||
themeEvent = function(e) {
|
themeEvent = function(e) {
|
||||||
if (e.target.hasAttribute('data-action')) {
|
if (e.target.hasAttribute('data-action')) {
|
||||||
switch(e.target.getAttribute('data-action')) {
|
switch (e.target.getAttribute('data-action')) {
|
||||||
case 'preview':
|
case 'preview':
|
||||||
var cssSrc = $(e.target).parents('li').attr('data-css'),
|
var cssSrc = $(e.target).parents('li').attr('data-css'),
|
||||||
cssEl = document.getElementById('base-theme');
|
cssEl = document.getElementById('base-theme');
|
||||||
@@ -58,10 +56,12 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
cssSrc = parentEl.attr('data-css'),
|
cssSrc = parentEl.attr('data-css'),
|
||||||
cssName = parentEl.attr('data-theme');
|
cssName = parentEl.attr('data-theme');
|
||||||
socket.emit('api:config.set', {
|
socket.emit('api:config.set', {
|
||||||
key: 'theme:id', value: 'bootswatch:' + cssName
|
key: 'theme:id',
|
||||||
|
value: 'bootswatch:' + cssName
|
||||||
});
|
});
|
||||||
socket.emit('api:config.set', {
|
socket.emit('api:config.set', {
|
||||||
key: 'theme:src', value: cssSrc
|
key: 'theme:src',
|
||||||
|
value: cssSrc
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -87,14 +87,14 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
liEl = document.createElement('li');
|
liEl = document.createElement('li');
|
||||||
|
|
||||||
if (themes.length > 0) {
|
if (themes.length > 0) {
|
||||||
for(var x=0,numThemes=themes.length;x<numThemes;x++) {
|
for (var x = 0, numThemes = themes.length; x < numThemes; x++) {
|
||||||
liEl.setAttribute('data-theme', themes[x].id);
|
liEl.setAttribute('data-theme', themes[x].id);
|
||||||
liEl.setAttribute('data-css', themes[x].src);
|
liEl.setAttribute('data-css', themes[x].src);
|
||||||
liEl.innerHTML = '<img src="' + themes[x].screenshot + '" />' +
|
liEl.innerHTML = '<img src="' + themes[x].screenshot + '" />' +
|
||||||
'<div>' +
|
'<div>' +
|
||||||
'<div class="pull-right">' +
|
'<div class="pull-right">' +
|
||||||
'<button class="btn btn-primary" data-action="use">Use</button> ' +
|
'<button class="btn btn-primary" data-action="use">Use</button> ' +
|
||||||
'<button class="btn" data-action="preview">Preview</button>' +
|
'<button class="btn btn-default" data-action="preview">Preview</button>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<h4>' + themes[x].name + '</h4>' +
|
'<h4>' + themes[x].name + '</h4>' +
|
||||||
'<p>' +
|
'<p>' +
|
||||||
|
|||||||
@@ -7,18 +7,30 @@ $(document).ready(function() {
|
|||||||
action = this.getAttribute('data-action'),
|
action = this.getAttribute('data-action'),
|
||||||
tid = $this.parents('[data-tid]').attr('data-tid');
|
tid = $this.parents('[data-tid]').attr('data-tid');
|
||||||
|
|
||||||
switch(action) {
|
switch (action) {
|
||||||
case 'pin':
|
case 'pin':
|
||||||
if (!$this.hasClass('active')) socket.emit('api:topic.pin', { tid: tid });
|
if (!$this.hasClass('active')) socket.emit('api:topic.pin', {
|
||||||
else socket.emit('api:topic.unpin', { tid: tid });
|
tid: tid
|
||||||
|
});
|
||||||
|
else socket.emit('api:topic.unpin', {
|
||||||
|
tid: tid
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case 'lock':
|
case 'lock':
|
||||||
if (!$this.hasClass('active')) socket.emit('api:topic.lock', { tid: tid });
|
if (!$this.hasClass('active')) socket.emit('api:topic.lock', {
|
||||||
else socket.emit('api:topic.unlock', { tid: tid });
|
tid: tid
|
||||||
|
});
|
||||||
|
else socket.emit('api:topic.unlock', {
|
||||||
|
tid: tid
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case 'delete':
|
case 'delete':
|
||||||
if (!$this.hasClass('active')) socket.emit('api:topic.delete', { tid: tid });
|
if (!$this.hasClass('active')) socket.emit('api:topic.delete', {
|
||||||
else socket.emit('api:topic.restore', { tid: tid });
|
tid: tid
|
||||||
|
});
|
||||||
|
else socket.emit('api:topic.restore', {
|
||||||
|
tid: tid
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -56,7 +68,7 @@ $(document).ready(function() {
|
|||||||
// Resolve proper button state for all topics
|
// Resolve proper button state for all topics
|
||||||
var topicEls = topicsListEl.querySelectorAll('li'),
|
var topicEls = topicsListEl.querySelectorAll('li'),
|
||||||
numTopics = topicEls.length;
|
numTopics = topicEls.length;
|
||||||
for(var x=0;x<numTopics;x++) {
|
for (var x = 0; x < numTopics; x++) {
|
||||||
if (topicEls[x].getAttribute('data-pinned') === '1') topicEls[x].querySelector('[data-action="pin"]').className += ' active';
|
if (topicEls[x].getAttribute('data-pinned') === '1') topicEls[x].querySelector('[data-action="pin"]').className += ' active';
|
||||||
if (topicEls[x].getAttribute('data-locked') === '1') topicEls[x].querySelector('[data-action="lock"]').className += ' active';
|
if (topicEls[x].getAttribute('data-locked') === '1') topicEls[x].querySelector('[data-action="lock"]').className += ' active';
|
||||||
if (topicEls[x].getAttribute('data-deleted') === '1') topicEls[x].querySelector('[data-action="delete"]').className += ' active';
|
if (topicEls[x].getAttribute('data-deleted') === '1') topicEls[x].querySelector('[data-action="delete"]').className += ' active';
|
||||||
|
|||||||
@@ -1,76 +1,62 @@
|
|||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
function initUsers() {
|
var yourid = templates.get('yourid');
|
||||||
|
|
||||||
function isUserAdmin(element) {
|
function isUserAdmin(element) {
|
||||||
var parent = $(element).parents('.users-box');
|
var parent = $(element).parents('.users-box');
|
||||||
return (parent.attr('data-admin') !== "0");
|
return (parent.attr('data-admin') !== "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isUserBanned(element) {
|
||||||
|
var parent = $(element).parents('.users-box');
|
||||||
|
return (parent.attr('data-banned') !== "" && parent.attr('data-banned') !== "0");
|
||||||
|
}
|
||||||
|
|
||||||
function getUID(element) {
|
function getUID(element) {
|
||||||
var parent = $(element).parents('.users-box');
|
var parent = $(element).parents('.users-box');
|
||||||
return parent.attr('data-uid');
|
return parent.attr('data-uid');
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery('.admin-btn').each(function(index, element) {
|
function updateUserButtons() {
|
||||||
var adminBtn = $(element);
|
jQuery('.ban-btn').each(function(index, element) {
|
||||||
var isAdmin = isUserAdmin(adminBtn);
|
var banBtn = $(element);
|
||||||
|
var uid = getUID(banBtn);
|
||||||
if(isAdmin)
|
if (isUserAdmin(banBtn) || uid === yourid)
|
||||||
adminBtn.addClass('btn-success');
|
banBtn.addClass('disabled');
|
||||||
|
else if (isUserBanned(banBtn))
|
||||||
|
banBtn.addClass('btn-warning');
|
||||||
else
|
else
|
||||||
adminBtn.removeClass('btn-success');
|
banBtn.removeClass('btn-warning');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
jQuery('.delete-btn').each(function(index, element) {
|
|
||||||
var deleteBtn = $(element);
|
|
||||||
var isAdmin = isUserAdmin(deleteBtn);
|
|
||||||
|
|
||||||
if(isAdmin)
|
|
||||||
deleteBtn.addClass('disabled');
|
|
||||||
else
|
|
||||||
deleteBtn.show();
|
|
||||||
});
|
|
||||||
|
|
||||||
jQuery('.admin-btn').on('click', function() {
|
|
||||||
var adminBtn = $(this);
|
|
||||||
var isAdmin = isUserAdmin(adminBtn);
|
|
||||||
var parent = adminBtn.parents('.users-box');
|
|
||||||
var uid = getUID(adminBtn);
|
|
||||||
|
|
||||||
if(isAdmin) {
|
|
||||||
socket.emit('api:admin.user.removeAdmin', uid);
|
|
||||||
adminBtn.removeClass('btn-success');
|
|
||||||
parent.find('.delete-btn').removeClass('disabled');
|
|
||||||
parent.attr('data-admin', 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bootbox.confirm('Do you really want to make "' + parent.attr('data-username') +'" an admin?', function(confirm) {
|
|
||||||
if(confirm) {
|
|
||||||
socket.emit('api:admin.user.makeAdmin', uid);
|
|
||||||
adminBtn.addClass('btn-success');
|
|
||||||
parent.find('.delete-btn').addClass('disabled');
|
|
||||||
parent.attr('data-admin', 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
function initUsers() {
|
||||||
});
|
|
||||||
|
|
||||||
jQuery('.delete-btn').on('click', function() {
|
updateUserButtons();
|
||||||
var deleteBtn = $(this);
|
|
||||||
var isAdmin = isUserAdmin(deleteBtn);
|
|
||||||
var parent = deleteBtn.parents('.users-box');
|
|
||||||
var uid = getUID(deleteBtn);
|
|
||||||
|
|
||||||
if(!isAdmin) {
|
$('#users-container').on('click', '.ban-btn', function() {
|
||||||
bootbox.confirm('Do you really want to delete "' + parent.attr('data-username') +'"?', function(confirm) {
|
var banBtn = $(this);
|
||||||
socket.emit('api:admin.user.deleteUser', uid);
|
var isAdmin = isUserAdmin(banBtn);
|
||||||
|
var isBanned = isUserBanned(banBtn);
|
||||||
|
var parent = banBtn.parents('.users-box');
|
||||||
|
var uid = getUID(banBtn);
|
||||||
|
|
||||||
|
if (!isAdmin) {
|
||||||
|
if (isBanned) {
|
||||||
|
socket.emit('api:admin.user.unbanUser', uid);
|
||||||
|
banBtn.removeClass('btn-warning');
|
||||||
|
parent.attr('data-banned', 0);
|
||||||
|
} else {
|
||||||
|
bootbox.confirm('Do you really want to ban "' + parent.attr('data-username') + '"?', function(confirm) {
|
||||||
|
if (confirm) {
|
||||||
|
socket.emit('api:admin.user.banUser', uid);
|
||||||
|
banBtn.addClass('btn-warning');
|
||||||
|
parent.attr('data-banned', 1);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
@@ -79,13 +65,12 @@
|
|||||||
|
|
||||||
jQuery('document').ready(function() {
|
jQuery('document').ready(function() {
|
||||||
|
|
||||||
var yourid = templates.get('yourid'),
|
var timeoutId = 0,
|
||||||
timeoutId = 0,
|
|
||||||
loadingMoreUsers = false;
|
loadingMoreUsers = false;
|
||||||
|
|
||||||
var url = window.location.href,
|
var url = window.location.href,
|
||||||
parts = url.split('/'),
|
parts = url.split('/'),
|
||||||
active = parts[parts.length-1];
|
active = parts[parts.length - 1];
|
||||||
|
|
||||||
jQuery('.nav-pills li').removeClass('active');
|
jQuery('.nav-pills li').removeClass('active');
|
||||||
jQuery('.nav-pills li a').each(function() {
|
jQuery('.nav-pills li a').each(function() {
|
||||||
@@ -95,8 +80,8 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
jQuery('#search-user').on('keyup', function () {
|
jQuery('#search-user').on('keyup', function() {
|
||||||
if(timeoutId !== 0) {
|
if (timeoutId !== 0) {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
timeoutId = 0;
|
timeoutId = 0;
|
||||||
}
|
}
|
||||||
@@ -123,44 +108,46 @@
|
|||||||
userListEl.innerHTML = html;
|
userListEl.innerHTML = html;
|
||||||
jQuery('.icon-spinner').addClass('none');
|
jQuery('.icon-spinner').addClass('none');
|
||||||
|
|
||||||
if(data && data.length === 0) {
|
if (data && data.length === 0) {
|
||||||
$('#user-notfound-notify').html('User not found!')
|
$('#user-notfound-notify').html('User not found!')
|
||||||
.show()
|
.show()
|
||||||
.addClass('label-important')
|
.addClass('label-danger')
|
||||||
.removeClass('label-success');
|
.removeClass('label-success');
|
||||||
}
|
} else {
|
||||||
else {
|
$('#user-notfound-notify').html(data.length + ' user' + (data.length > 1 ? 's' : '') + ' found!')
|
||||||
$('#user-notfound-notify').html(data.length + ' user'+(data.length>1?'s':'') + ' found!')
|
|
||||||
.show()
|
.show()
|
||||||
.addClass('label-success')
|
.addClass('label-success')
|
||||||
.removeClass('label-important');
|
.removeClass('label-danger');
|
||||||
}
|
}
|
||||||
|
|
||||||
initUsers();
|
initUsers();
|
||||||
});
|
});
|
||||||
|
|
||||||
function onUsersLoaded(users) {
|
function onUsersLoaded(users) {
|
||||||
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({ users: users });
|
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({
|
||||||
|
users: users
|
||||||
|
});
|
||||||
$('#users-container').append(html);
|
$('#users-container').append(html);
|
||||||
|
updateUserButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadMoreUsers() {
|
function loadMoreUsers() {
|
||||||
var set = '';
|
var set = '';
|
||||||
if(active === 'latest') {
|
if (active === 'latest') {
|
||||||
set = 'users:joindate';
|
set = 'users:joindate';
|
||||||
} else if(active === 'sort-posts') {
|
} else if (active === 'sort-posts') {
|
||||||
set = 'users:postcount';
|
set = 'users:postcount';
|
||||||
} else if(active === 'sort-reputation') {
|
} else if (active === 'sort-reputation') {
|
||||||
set = 'users:reputation';
|
set = 'users:reputation';
|
||||||
}
|
}
|
||||||
|
|
||||||
if(set) {
|
if (set) {
|
||||||
loadingMoreUsers = true;
|
loadingMoreUsers = true;
|
||||||
socket.emit('api:users.loadMore', {
|
socket.emit('api:users.loadMore', {
|
||||||
set: set,
|
set: set,
|
||||||
after: $('#users-container').children().length
|
after: $('#users-container').children().length
|
||||||
}, function(data) {
|
}, function(data) {
|
||||||
if(data.users.length) {
|
if (data.users.length) {
|
||||||
onUsersLoaded(data.users);
|
onUsersLoaded(data.users);
|
||||||
}
|
}
|
||||||
loadingMoreUsers = false;
|
loadingMoreUsers = false;
|
||||||
@@ -171,9 +158,9 @@
|
|||||||
$('#load-more-users-btn').on('click', loadMoreUsers);
|
$('#load-more-users-btn').on('click', loadMoreUsers);
|
||||||
|
|
||||||
$(window).off('scroll').on('scroll', function() {
|
$(window).off('scroll').on('scroll', function() {
|
||||||
var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
|
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||||
|
|
||||||
if (document.body.scrollTop > bottom && !loadingMoreUsers) {
|
if ($(window).scrollTop() > bottom && !loadingMoreUsers) {
|
||||||
loadMoreUsers();
|
loadMoreUsers();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
(function() {
|
(function () {
|
||||||
var cid = templates.get('category_id'),
|
var cid = templates.get('category_id'),
|
||||||
room = 'category_' + cid,
|
room = 'category_' + cid,
|
||||||
twitterEl = document.getElementById('twitter-intent'),
|
twitterEl = document.getElementById('twitter-intent'),
|
||||||
@@ -11,22 +11,22 @@
|
|||||||
|
|
||||||
app.enter_room(room);
|
app.enter_room(room);
|
||||||
|
|
||||||
twitterEl.addEventListener('click', function() {
|
twitterEl.addEventListener('click', function () {
|
||||||
window.open(twitter_url, '_blank', 'width=550,height=420,scrollbars=no,status=no');
|
window.open(twitter_url, '_blank', 'width=550,height=420,scrollbars=no,status=no');
|
||||||
return false;
|
return false;
|
||||||
}, false);
|
}, false);
|
||||||
facebookEl.addEventListener('click', function() {
|
facebookEl.addEventListener('click', function () {
|
||||||
window.open(facebook_url, '_blank', 'width=626,height=436,scrollbars=no,status=no');
|
window.open(facebook_url, '_blank', 'width=626,height=436,scrollbars=no,status=no');
|
||||||
return false;
|
return false;
|
||||||
}, false);
|
}, false);
|
||||||
googleEl.addEventListener('click', function() {
|
googleEl.addEventListener('click', function () {
|
||||||
window.open(google_url, '_blank', 'width=500,height=570,scrollbars=no,status=no');
|
window.open(google_url, '_blank', 'width=500,height=570,scrollbars=no,status=no');
|
||||||
return false;
|
return false;
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
var new_post = document.getElementById('new_post');
|
var new_post = document.getElementById('new_post');
|
||||||
new_post.onclick = function() {
|
new_post.onclick = function () {
|
||||||
require(['composer'], function(cmp) {
|
require(['composer'], function (cmp) {
|
||||||
cmp.push(0, cid);
|
cmp.push(0, cid);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -36,37 +36,38 @@
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
function onNewTopic(data) {
|
function onNewTopic(data) {
|
||||||
|
var html = templates.prepare(templates['category'].blocks['topics']).parse({
|
||||||
var html = templates.prepare(templates['category'].blocks['topics']).parse({ topics: [data] }),
|
topics: [data]
|
||||||
topic = document.createElement('div'),
|
}),
|
||||||
container = document.getElementById('topics-container'),
|
topic = $(html),
|
||||||
topics = document.querySelectorAll('#topics-container a'),
|
container = $('#topics-container'),
|
||||||
numTopics = topics.length,
|
topics = $('#topics-container').children(),
|
||||||
x;
|
numTopics = topics.length;
|
||||||
|
|
||||||
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
|
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
|
||||||
jQuery('#category-no-topics').remove();
|
jQuery('#category-no-topics').remove();
|
||||||
|
|
||||||
topic.innerHTML = html;
|
|
||||||
topic = topic.querySelector('a');
|
|
||||||
|
|
||||||
if (numTopics > 0) {
|
if (numTopics > 0) {
|
||||||
for(x=0;x<numTopics;x++) {
|
for (var x = 0; x < numTopics; x++) {
|
||||||
if (topics[x].querySelector('.icon-pushpin')) continue;
|
if ($(topics[x]).find('.icon-pushpin').length)
|
||||||
container.insertBefore(topic, topics[x]);
|
continue;
|
||||||
$(topic).hide().fadeIn('slow');
|
topic.insertBefore(topics[x]);
|
||||||
|
topic.hide().fadeIn('slow');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
container.insertBefore(topic, null);
|
container.append(topic);
|
||||||
$(topic).hide().fadeIn('slow');
|
topic.hide().fadeIn('slow');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
socket.emit('api:categories.getRecentReplies', cid);
|
||||||
|
$('#topics-container span.timeago').timeago();
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.on('event:new_topic', onNewTopic);
|
socket.on('event:new_topic', onNewTopic);
|
||||||
|
|
||||||
socket.emit('api:categories.getRecentReplies', cid);
|
socket.emit('api:categories.getRecentReplies', cid);
|
||||||
socket.on('api:categories.getRecentReplies', function(posts) {
|
socket.on('api:categories.getRecentReplies', function (posts) {
|
||||||
if (!posts || posts.length === 0) {
|
if (!posts || posts.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -77,35 +78,39 @@
|
|||||||
|
|
||||||
var frag = document.createDocumentFragment(),
|
var frag = document.createDocumentFragment(),
|
||||||
li = document.createElement('li');
|
li = document.createElement('li');
|
||||||
for (var i=0,numPosts=posts.length; i<numPosts; i++) {
|
for (var i = 0, numPosts = posts.length; i < numPosts; i++) {
|
||||||
var dateString = utils.relativeTime(posts[i].timestamp);
|
|
||||||
li.setAttribute('data-pid', posts[i].pid);
|
li.setAttribute('data-pid', posts[i].pid);
|
||||||
|
|
||||||
|
|
||||||
li.innerHTML = '<a href="/users/' + posts[i].userslug + '"><img title="' + posts[i].username + '" style="width: 48px; height: 48px; /*temporary*/" class="img-polaroid" src="' + posts[i].picture + '" class="" /></a>' +
|
li.innerHTML = '<a href="/user/' + posts[i].userslug + '"><img title="' + posts[i].username + '" style="width: 48px; height: 48px; /*temporary*/" class="img-rounded" src="' + posts[i].picture + '" class="" /></a>' +
|
||||||
'<a href="/topic/'+ posts[i].topicSlug + '#' + posts[i].pid + '">' +
|
'<a href="/topic/' + posts[i].topicSlug + '#' + posts[i].pid + '">' +
|
||||||
'<p>' +
|
'<p>' +
|
||||||
'<strong>' + posts[i].username + '</strong>: ' + posts[i].content +
|
posts[i].content +
|
||||||
'</p>' +
|
'</p>' +
|
||||||
'<span>posted ' + utils.relativeTime(posts[i].timestamp) + ' ago</span>' +
|
'<p class="meta"><strong>' + posts[i].username + '</strong></span> -<span class="timeago" title="' + posts[i].relativeTime + '"></span></p>' +
|
||||||
'</a>';
|
'</a>';
|
||||||
|
|
||||||
frag.appendChild(li.cloneNode(true));
|
frag.appendChild(li.cloneNode(true));
|
||||||
recent_replies.appendChild(frag);
|
recent_replies.appendChild(frag);
|
||||||
}
|
}
|
||||||
|
$('#category_recent_replies span.timeago').timeago();
|
||||||
});
|
});
|
||||||
|
|
||||||
function onTopicsLoaded(topics) {
|
function onTopicsLoaded(topics) {
|
||||||
|
|
||||||
var html = templates.prepare(templates['category'].blocks['topics']).parse({ topics: topics }),
|
var html = templates.prepare(templates['category'].blocks['topics']).parse({
|
||||||
|
topics: topics
|
||||||
|
}),
|
||||||
container = $('#topics-container');
|
container = $('#topics-container');
|
||||||
|
|
||||||
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
|
jQuery('#topics-container, .category-sidebar').removeClass('hidden');
|
||||||
jQuery('#category-no-topics').remove();
|
jQuery('#category-no-topics').remove();
|
||||||
|
|
||||||
container.append(html);
|
container.append(html);
|
||||||
}
|
|
||||||
|
|
||||||
|
$('#topics-container span.timeago').timeago();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function loadMoreTopics(cid) {
|
function loadMoreTopics(cid) {
|
||||||
@@ -113,18 +118,18 @@
|
|||||||
socket.emit('api:category.loadMore', {
|
socket.emit('api:category.loadMore', {
|
||||||
cid: cid,
|
cid: cid,
|
||||||
after: $('#topics-container').children().length
|
after: $('#topics-container').children().length
|
||||||
}, function(data) {
|
}, function (data) {
|
||||||
if(data.topics.length) {
|
if (data.topics.length) {
|
||||||
onTopicsLoaded(data.topics);
|
onTopicsLoaded(data.topics);
|
||||||
}
|
}
|
||||||
loadingMoreTopics = false;
|
loadingMoreTopics = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$(window).off('scroll').on('scroll', function(ev) {
|
$(window).off('scroll').on('scroll', function (ev) {
|
||||||
var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
|
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||||
|
|
||||||
if (document.body.scrollTop > bottom && !loadingMoreTopics) {
|
if ($(window).scrollTop() > bottom && !loadingMoreTopics) {
|
||||||
loadMoreTopics(cid);
|
loadMoreTopics(cid);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
7
public/src/forum/favourites.js
Normal file
7
public/src/forum/favourites.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
(function() {
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('.user-favourite-posts .topic-row').on('click', function() {
|
||||||
|
ajaxify.go($(this).attr('topic-url'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}());
|
||||||
@@ -6,17 +6,11 @@
|
|||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
if(parseInt(followersCount, 10) === 0) {
|
if (parseInt(followersCount, 10) === 0) {
|
||||||
$('#no-followers-notice').show();
|
$('#no-followers-notice').removeClass('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.reputation').each(function(index, element) {
|
app.addCommasToNumbers();
|
||||||
$(element).html(app.addCommas($(element).html()));
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.postcount').each(function(index, element) {
|
|
||||||
$(element).html(app.addCommas($(element).html()));
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,22 +6,23 @@
|
|||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
if(parseInt(followingCount, 10) === 0) {
|
if (parseInt(followingCount, 10) === 0) {
|
||||||
$('#no-following-notice').show();
|
$('#no-following-notice').removeClass('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(yourid !== theirid) {
|
if (yourid !== theirid) {
|
||||||
$('.unfollow-btn').hide();
|
$('.unfollow-btn').hide();
|
||||||
}
|
} else {
|
||||||
else {
|
$('.unfollow-btn').on('click', function() {
|
||||||
$('.unfollow-btn').on('click',function() {
|
|
||||||
var unfollowBtn = $(this);
|
var unfollowBtn = $(this);
|
||||||
var followingUid = $(this).attr('followingUid');
|
var followingUid = $(this).attr('followingUid');
|
||||||
|
|
||||||
socket.emit('api:user.unfollow', {uid: followingUid}, function(success) {
|
socket.emit('api:user.unfollow', {
|
||||||
|
uid: followingUid
|
||||||
|
}, function(success) {
|
||||||
var username = unfollowBtn.attr('data-username');
|
var username = unfollowBtn.attr('data-username');
|
||||||
if(success) {
|
if (success) {
|
||||||
unfollowBtn.parent().remove();
|
unfollowBtn.parent().remove();
|
||||||
app.alertSuccess('You are no longer following ' + username + '!');
|
app.alertSuccess('You are no longer following ' + username + '!');
|
||||||
} else {
|
} else {
|
||||||
@@ -32,14 +33,7 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.reputation').each(function(index, element) {
|
app.addCommasToNumbers();
|
||||||
$(element).html(app.addCommas($(element).html()));
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.postcount').each(function(index, element) {
|
|
||||||
$(element).html(app.addCommas($(element).html()));
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,85 +1,93 @@
|
|||||||
(function() {
|
(function() {
|
||||||
var num_users = document.getElementById('number_of_users'),
|
var stats_users = document.getElementById('stats_users'),
|
||||||
post_stats = document.getElementById('post_stats'),
|
stats_topics = document.getElementById('stats_topics'),
|
||||||
latest_user = document.getElementById('latest_user'),
|
stats_posts = document.getElementById('stats_posts'),
|
||||||
active_users = document.getElementById('active_users'),
|
stats_online = document.getElementById('stats_online'),
|
||||||
user_label = document.getElementById('user_label'),
|
user_label = document.getElementById('user_label');
|
||||||
active_record = document.getElementById('active_record'),
|
|
||||||
right_menu = document.getElementById('right-menu');
|
|
||||||
|
|
||||||
socket.emit('user.count', {});
|
socket.emit('user.count', {});
|
||||||
socket.on('user.count', function(data) {
|
socket.on('user.count', function(data) {
|
||||||
num_users.innerHTML = "We currently have <b>" + data.count + "</b> registered users.";
|
stats_users.innerHTML = data.count;
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.emit('post.stats');
|
socket.emit('post.stats');
|
||||||
socket.on('post.stats', function(data) {
|
socket.on('post.stats', function(data) {
|
||||||
post_stats.innerHTML = "Our users have created <b>" + data.topics + "</b> topics and made <b>" + data.posts + "</b> posts.";
|
stats_topics.innerHTML = data.topics;
|
||||||
});
|
stats_posts.innerHTML = data.posts;
|
||||||
|
|
||||||
socket.emit('user.latest', {});
|
|
||||||
socket.on('user.latest', function(data) {
|
|
||||||
if (data.username == '') {
|
|
||||||
latest_user.innerHTML = '';
|
|
||||||
} else {
|
|
||||||
latest_user.innerHTML = "The most recent user to register is <b><a href='/users/"+data.userslug+"'>" + data.username + "</a></b>.";
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.emit('api:user.active.get');
|
socket.emit('api:user.active.get');
|
||||||
socket.on('api:user.active.get', function(data) {
|
socket.on('api:user.active.get', function(data) {
|
||||||
|
stats_online.innerHTML = data.users;
|
||||||
var plural_users = parseInt(data.users) !== 1,
|
|
||||||
plural_anon = parseInt(data.anon) !== 1;
|
|
||||||
|
|
||||||
active_users.innerHTML = 'There ' + (plural_users ? 'are' : 'is') + ' <strong>' + data.users + '</strong> user' + (plural_users ? 's' : '') + ' and <strong>' + data.anon + '</strong> guest' + (plural_anon ? 's' : '') + ' online';
|
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.emit('api:user.active.get_record');
|
socket.emit('api:updateHeader', {
|
||||||
socket.on('api:user.active.get_record', function(data) {
|
fields: ['username', 'picture', 'userslug']
|
||||||
active_record.innerHTML = "most users ever online was <strong>" + data.record + "</strong> on <strong>" + (new Date(parseInt(data.timestamp,10))).toUTCString() + "</strong>";
|
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.emit('api:updateHeader', { fields: ['username', 'picture', 'userslug'] });
|
|
||||||
|
|
||||||
socket.on('api:updateHeader', function(data) {
|
socket.on('api:updateHeader', function(data) {
|
||||||
|
jQuery('#search-button').on('click', function() {
|
||||||
|
jQuery('#search-fields').removeClass('hide').show();
|
||||||
|
jQuery(this).hide();
|
||||||
|
jQuery('#search-fields input').focus()
|
||||||
|
|
||||||
var rightMenu = $('#right-menu');
|
jQuery('#search-form').on('submit', function() {
|
||||||
if (data.uid > 0) {
|
jQuery('#search-fields').hide();
|
||||||
|
jQuery('#search-button').show();
|
||||||
|
});
|
||||||
|
|
||||||
var userLabel = rightMenu.find('#user_label');
|
$('#search-fields input').on('blur', function() {
|
||||||
if(userLabel.length) {
|
$('#search-fields').hide();
|
||||||
if(data['userslug'])
|
$('#search-button').show();
|
||||||
userLabel.attr('href','/users/' + data['userslug']);
|
});
|
||||||
if(data['picture'])
|
});
|
||||||
userLabel.find('img').attr('src',data['picture']);
|
|
||||||
if(data['username'])
|
var loggedInMenu = $('#logged-in-menu'),
|
||||||
|
isLoggedIn = data.uid > 0;
|
||||||
|
|
||||||
|
if (isLoggedIn) {
|
||||||
|
jQuery('.nodebb-loggedin').show();
|
||||||
|
jQuery('.nodebb-loggedout').hide();
|
||||||
|
|
||||||
|
$('#logged-out-menu').addClass('hide');
|
||||||
|
$('#logged-in-menu').removeClass('hide');
|
||||||
|
|
||||||
|
$('#search-button').show();
|
||||||
|
|
||||||
|
var userLabel = loggedInMenu.find('#user_label');
|
||||||
|
if (userLabel.length) {
|
||||||
|
if (data['userslug'])
|
||||||
|
userLabel.attr('href', '/user/' + data['userslug']);
|
||||||
|
if (data['picture'])
|
||||||
|
userLabel.find('img').attr('src', data['picture']);
|
||||||
|
if (data['username'])
|
||||||
userLabel.find('span').html(data['username']);
|
userLabel.find('span').html(data['username']);
|
||||||
}
|
|
||||||
else {
|
|
||||||
var userli = $('<li> \
|
|
||||||
<a id="user_label" href="/users/'+data['userslug']+'"> \
|
|
||||||
<img src="'+data['picture']+'"/> \
|
|
||||||
<span>'+data['username']+'</span> \
|
|
||||||
</a> \
|
|
||||||
</li>');
|
|
||||||
rightMenu.append(userli);
|
|
||||||
|
|
||||||
var logoutli = $('<li><a href="' + RELATIVE_PATH + '/logout">Log out</a></li>');
|
$('#logout-link').on('click', function() {
|
||||||
rightMenu.append(logoutli);
|
var csrf_token = $('#csrf_token').val();
|
||||||
|
|
||||||
|
$.post(RELATIVE_PATH + '/logout', {
|
||||||
|
_csrf: csrf_token
|
||||||
|
}, function() {
|
||||||
|
window.location = RELATIVE_PATH + '/';
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rightMenu.html('');
|
$('#search-button').hide();
|
||||||
|
|
||||||
var registerEl = document.createElement('li'),
|
jQuery('.nodebb-loggedin').hide();
|
||||||
loginEl = document.createElement('li');
|
jQuery('.nodebb-loggedout').show();
|
||||||
|
|
||||||
registerEl.innerHTML = '<a href="/register">Register</a>';
|
$('#logged-out-menu').removeClass('hide');
|
||||||
loginEl.innerHTML = '<a href="/login">Login</a>';
|
$('#logged-in-menu').addClass('hide');
|
||||||
|
|
||||||
right_menu.appendChild(registerEl);
|
|
||||||
right_menu.appendChild(loginEl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$('#main-nav a,#right-menu a').off('click').on('click', function() {
|
||||||
|
if($('.navbar .navbar-collapse').hasClass('in'))
|
||||||
|
$('.navbar-header button').click();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Notifications dropdown
|
// Notifications dropdown
|
||||||
@@ -90,26 +98,7 @@
|
|||||||
notifTrigger.addEventListener('click', function(e) {
|
notifTrigger.addEventListener('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (notifContainer.className.indexOf('open') === -1) {
|
if (notifContainer.className.indexOf('open') === -1) {
|
||||||
socket.emit('api:notifications.get');
|
socket.emit('api:notifications.get', null, function(data) {
|
||||||
socket.emit('api:notifications.mark_all_read', null, function() {
|
|
||||||
notifIcon.className = 'icon-circle-blank';
|
|
||||||
utils.refreshTitle();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
notifList.addEventListener('click', function(e) {
|
|
||||||
var target;
|
|
||||||
switch(e.target.nodeName) {
|
|
||||||
case 'SPAN': target = e.target.parentNode.parentNode; break;
|
|
||||||
case 'A': target = e.target.parentNode; break;
|
|
||||||
case 'li': target = e.target; break;
|
|
||||||
}
|
|
||||||
if (target) {
|
|
||||||
var nid = parseInt(target.getAttribute('data-nid'));
|
|
||||||
if (nid > 0) socket.emit('api:notifications.mark_read', nid);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
socket.on('api:notifications.get', function(data) {
|
|
||||||
var notifFrag = document.createDocumentFragment(),
|
var notifFrag = document.createDocumentFragment(),
|
||||||
notifEl = document.createElement('li'),
|
notifEl = document.createElement('li'),
|
||||||
numRead = data.read.length,
|
numRead = data.read.length,
|
||||||
@@ -117,13 +106,13 @@
|
|||||||
x;
|
x;
|
||||||
notifList.innerHTML = '';
|
notifList.innerHTML = '';
|
||||||
if ((data.read.length + data.unread.length) > 0) {
|
if ((data.read.length + data.unread.length) > 0) {
|
||||||
for(x=0;x<numUnread;x++) {
|
for (x = 0; x < numUnread; x++) {
|
||||||
notifEl.setAttribute('data-nid', data.unread[x].nid);
|
notifEl.setAttribute('data-nid', data.unread[x].nid);
|
||||||
notifEl.className = 'unread';
|
notifEl.className = 'unread';
|
||||||
notifEl.innerHTML = '<a href="' + data.unread[x].path + '"><span class="pull-right">' + utils.relativeTime(data.unread[x].datetime, true) + '</span>' + data.unread[x].text + '</a>';
|
notifEl.innerHTML = '<a href="' + data.unread[x].path + '"><span class="pull-right">' + utils.relativeTime(data.unread[x].datetime, true) + '</span>' + data.unread[x].text + '</a>';
|
||||||
notifFrag.appendChild(notifEl.cloneNode(true));
|
notifFrag.appendChild(notifEl.cloneNode(true));
|
||||||
}
|
}
|
||||||
for(x=0;x<numRead;x++) {
|
for (x = 0; x < numRead; x++) {
|
||||||
notifEl.setAttribute('data-nid', data.read[x].nid);
|
notifEl.setAttribute('data-nid', data.read[x].nid);
|
||||||
notifEl.className = '';
|
notifEl.className = '';
|
||||||
notifEl.innerHTML = '<a href="' + data.read[x].path + '"><span class="pull-right">' + utils.relativeTime(data.read[x].datetime, true) + '</span>' + data.read[x].text + '</a>';
|
notifEl.innerHTML = '<a href="' + data.read[x].path + '"><span class="pull-right">' + utils.relativeTime(data.read[x].datetime, true) + '</span>' + data.read[x].text + '</a>';
|
||||||
@@ -137,28 +126,62 @@
|
|||||||
|
|
||||||
if (data.unread.length > 0) notifIcon.className = 'icon-circle active';
|
if (data.unread.length > 0) notifIcon.className = 'icon-circle active';
|
||||||
else notifIcon.className = 'icon-circle-blank';
|
else notifIcon.className = 'icon-circle-blank';
|
||||||
|
|
||||||
|
socket.emit('api:notifications.mark_all_read', null, function() {
|
||||||
|
notifIcon.className = 'icon-circle-blank';
|
||||||
|
utils.refreshTitle();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
notifList.addEventListener('click', function(e) {
|
||||||
|
var target;
|
||||||
|
switch (e.target.nodeName) {
|
||||||
|
case 'SPAN':
|
||||||
|
target = e.target.parentNode.parentNode;
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
target = e.target.parentNode;
|
||||||
|
break;
|
||||||
|
case 'li':
|
||||||
|
target = e.target;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (target) {
|
||||||
|
var nid = parseInt(target.getAttribute('data-nid'));
|
||||||
|
if (nid > 0) socket.emit('api:notifications.mark_read', nid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
socket.on('event:new_notification', function() {
|
socket.on('event:new_notification', function() {
|
||||||
document.querySelector('.notifications a i').className = 'icon-circle active';
|
document.querySelector('.notifications a i').className = 'icon-circle active';
|
||||||
|
app.alert({
|
||||||
|
alert_id: 'new_notif',
|
||||||
|
title: 'New notification',
|
||||||
|
message: 'You have unread notifications.',
|
||||||
|
type: 'warning',
|
||||||
|
timeout: 2000
|
||||||
|
});
|
||||||
utils.refreshTitle();
|
utils.refreshTitle();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
socket.on('chatMessage', function(data) {
|
socket.on('chatMessage', function(data) {
|
||||||
var username = data.username;
|
|
||||||
var fromuid = data.fromuid;
|
|
||||||
var message = data.message;
|
|
||||||
|
|
||||||
require(['chat'], function(chat) {
|
require(['chat'], function(chat) {
|
||||||
var chatModal = chat.createModalIfDoesntExist(username, fromuid);
|
var modal = null;
|
||||||
chatModal.show();
|
if (chat.modalExists(data.fromuid)) {
|
||||||
chat.bringModalToTop(chatModal);
|
modal = chat.getModal(data.fromuid);
|
||||||
|
chat.appendChatMessage(modal, data.message, data.timestamp);
|
||||||
|
} else {
|
||||||
|
modal = chat.createModal(data.username, data.fromuid);
|
||||||
|
}
|
||||||
|
|
||||||
chat.appendChatMessage(chatModal, message);
|
chat.load(modal.attr('UUID'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
require(['mobileMenu'], function(mobileMenu) {
|
require(['mobileMenu'], function(mobileMenu) {
|
||||||
mobileMenu.init();
|
mobileMenu.init();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
// Alternate Logins
|
// Alternate Logins
|
||||||
var altLoginEl = document.querySelector('.alt-logins');
|
var altLoginEl = document.querySelector('.alt-logins');
|
||||||
altLoginEl.addEventListener('click', function(e) {
|
altLoginEl.addEventListener('click', function(e) {
|
||||||
var target;
|
var target;
|
||||||
switch(e.target.nodeName) {
|
switch (e.target.nodeName) {
|
||||||
case 'LI': target = e.target; break;
|
case 'LI':
|
||||||
case 'I': target = e.target.parentNode; break;
|
target = e.target;
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
target = e.target.parentNode;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (target) {
|
if (target) {
|
||||||
document.location.href = target.getAttribute('data-url');
|
document.location.href = target.getAttribute('data-url');
|
||||||
@@ -15,7 +17,6 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
$('#login').on('click', function() {
|
$('#login').on('click', function() {
|
||||||
|
|
||||||
var loginData = {
|
var loginData = {
|
||||||
'username': $('#username').val(),
|
'username': $('#username').val(),
|
||||||
'password': $('#password').val(),
|
'password': $('#password').val(),
|
||||||
@@ -27,11 +28,20 @@
|
|||||||
url: RELATIVE_PATH + '/login',
|
url: RELATIVE_PATH + '/login',
|
||||||
data: loginData,
|
data: loginData,
|
||||||
success: function(data, textStatus, jqXHR) {
|
success: function(data, textStatus, jqXHR) {
|
||||||
|
if (!data.success) {
|
||||||
|
$('#login-error-notify').show();
|
||||||
|
} else {
|
||||||
$('#login-error-notify').hide();
|
$('#login-error-notify').hide();
|
||||||
|
if(app.previousUrl.indexOf('/reset/') != -1)
|
||||||
window.location.replace(RELATIVE_PATH + "/?loggedin");
|
window.location.replace(RELATIVE_PATH + "/?loggedin");
|
||||||
|
else
|
||||||
|
window.location.replace(app.previousUrl + "?loggedin");
|
||||||
|
|
||||||
|
app.loadConfig();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
error : function(data, textStatus, jqXHR) {
|
error: function(data, textStatus, jqXHR) {
|
||||||
$('#login-error-notify').show().delay(1000).fadeOut(250);
|
$('#login-error-notify').show();
|
||||||
},
|
},
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
async: true,
|
async: true,
|
||||||
@@ -41,4 +51,10 @@
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#login-error-notify button').on('click', function() {
|
||||||
|
$('#login-error-notify').hide();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelector('#content input').focus();
|
||||||
}());
|
}());
|
||||||
@@ -8,7 +8,8 @@
|
|||||||
'event:new_post'
|
'event:new_post'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
var newTopicCount = 0, newPostCount = 0;
|
var newTopicCount = 0,
|
||||||
|
newPostCount = 0;
|
||||||
|
|
||||||
$('#new-topics-alert').on('click', function() {
|
$('#new-topics-alert').on('click', function() {
|
||||||
$(this).hide();
|
$(this).hide();
|
||||||
@@ -24,16 +25,16 @@
|
|||||||
function updateAlertText() {
|
function updateAlertText() {
|
||||||
var text = '';
|
var text = '';
|
||||||
|
|
||||||
if(newTopicCount > 1)
|
if (newTopicCount > 1)
|
||||||
text = 'There are ' + newTopicCount + ' new topics';
|
text = 'There are ' + newTopicCount + ' new topics';
|
||||||
else if(newTopicCount === 1)
|
else if (newTopicCount === 1)
|
||||||
text = 'There is 1 new topic';
|
text = 'There is 1 new topic';
|
||||||
else
|
else
|
||||||
text = 'There are no new topics';
|
text = 'There are no new topics';
|
||||||
|
|
||||||
if(newPostCount > 1)
|
if (newPostCount > 1)
|
||||||
text += ' and ' + newPostCount + ' new posts.';
|
text += ' and ' + newPostCount + ' new posts.';
|
||||||
else if(newPostCount === 1)
|
else if (newPostCount === 1)
|
||||||
text += ' and 1 new post.';
|
text += ' and 1 new post.';
|
||||||
else
|
else
|
||||||
text += ' and no new posts.';
|
text += ' and no new posts.';
|
||||||
@@ -50,7 +51,9 @@
|
|||||||
|
|
||||||
function onTopicsLoaded(topics) {
|
function onTopicsLoaded(topics) {
|
||||||
|
|
||||||
var html = templates.prepare(templates['recent'].blocks['topics']).parse({ topics: topics }),
|
var html = templates.prepare(templates['recent'].blocks['topics']).parse({
|
||||||
|
topics: topics
|
||||||
|
}),
|
||||||
container = $('#topics-container');
|
container = $('#topics-container');
|
||||||
|
|
||||||
$('#category-no-topics').remove();
|
$('#category-no-topics').remove();
|
||||||
@@ -60,8 +63,10 @@
|
|||||||
|
|
||||||
function loadMoreTopics() {
|
function loadMoreTopics() {
|
||||||
loadingMoreTopics = true;
|
loadingMoreTopics = true;
|
||||||
socket.emit('api:topics.loadMoreRecentTopics', {after:$('#topics-container').children().length}, function(data) {
|
socket.emit('api:topics.loadMoreRecentTopics', {
|
||||||
if(data.topics && data.topics.length) {
|
after: $('#topics-container').children().length
|
||||||
|
}, function(data) {
|
||||||
|
if (data.topics && data.topics.length) {
|
||||||
onTopicsLoaded(data.topics);
|
onTopicsLoaded(data.topics);
|
||||||
}
|
}
|
||||||
loadingMoreTopics = false;
|
loadingMoreTopics = false;
|
||||||
@@ -69,9 +74,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$(window).off('scroll').on('scroll', function() {
|
$(window).off('scroll').on('scroll', function() {
|
||||||
var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
|
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||||
|
|
||||||
if (document.body.scrollTop > bottom && !loadingMoreTopics) {
|
if ($(window).scrollTop() > bottom && !loadingMoreTopics) {
|
||||||
loadMoreTopics();
|
loadMoreTopics();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,157 +1,154 @@
|
|||||||
(function() {
|
(function() {
|
||||||
var username = document.getElementById('username'),
|
var username = $('#username'),
|
||||||
password = document.getElementById('password'),
|
password = $('#password'),
|
||||||
password_confirm = document.getElementById('password-confirm'),
|
password_confirm = $('#password-confirm'),
|
||||||
register = document.getElementById('register'),
|
register = $('#register'),
|
||||||
emailEl = document.getElementById('email'),
|
emailEl = $('#email'),
|
||||||
username_notify = document.getElementById('username-notify'),
|
username_notify = $('#username-notify'),
|
||||||
email_notify = document.getElementById('email-notify'),
|
email_notify = $('#email-notify'),
|
||||||
password_notify = document.getElementById('password-notify'),
|
password_notify = $('#password-notify'),
|
||||||
password_confirm_notify = document.getElementById('password-confirm-notify'),
|
password_confirm_notify = $('#password-confirm-notify'),
|
||||||
usernamevalid = false;
|
validationError = false,
|
||||||
emailexists = false,
|
successIcon = '<i class="icon icon-ok"></i>';
|
||||||
emailvalid = false,
|
|
||||||
userexists = false,
|
|
||||||
passwordsmatch = false,
|
|
||||||
passwordvalid = false;
|
|
||||||
|
|
||||||
$(username).on('keyup change', function() {
|
$('#referrer').val(app.previousUrl);
|
||||||
usernamevalid = utils.isUserNameValid(username.value);
|
|
||||||
|
|
||||||
|
function showError(element, msg) {
|
||||||
|
element.html(msg);
|
||||||
|
element.parent()
|
||||||
|
.removeClass('alert-success')
|
||||||
|
.addClass('alert-danger');
|
||||||
|
element.show();
|
||||||
|
validationError = true;
|
||||||
|
}
|
||||||
|
|
||||||
if(username.value.length < 3) {
|
function showSuccess(element, msg) {
|
||||||
username_notify.innerHTML = 'Username too short';
|
element.html(msg);
|
||||||
username_notify.className = 'label label-important';
|
element.parent()
|
||||||
} else if(username.value.length > 13) {
|
.removeClass('alert-danger')
|
||||||
username_notify.innerHTML = 'Username too long';
|
.addClass('alert-success');
|
||||||
username_notify.className = 'label label-important';
|
element.show();
|
||||||
} else if(!usernamevalid) {
|
}
|
||||||
username_notify.innerHTML = 'Invalid username';
|
|
||||||
username_notify.className = 'label label-important';
|
function validateEmail() {
|
||||||
|
if (!emailEl.val()) {
|
||||||
|
validationError = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!utils.isEmailValid(emailEl.val())) {
|
||||||
|
showError(email_notify, 'Invalid email address.');
|
||||||
|
} else
|
||||||
|
socket.emit('user.email.exists', {
|
||||||
|
email: emailEl.val()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
emailEl.on('blur', function() {
|
||||||
|
validateEmail();
|
||||||
|
});
|
||||||
|
|
||||||
|
function validateUsername() {
|
||||||
|
if (!username.val()) {
|
||||||
|
validationError = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (username.val().length < config.minimumUsernameLength) {
|
||||||
|
showError(username_notify, 'Username too short!');
|
||||||
|
} else if (username.val().length > config.maximumUsernameLength) {
|
||||||
|
showError(username_notify, 'Username too long!');
|
||||||
|
} else if (!utils.isUserNameValid(username.val())) {
|
||||||
|
showError(username_notify, 'Invalid username!');
|
||||||
} else {
|
} else {
|
||||||
socket.emit('user.exists', {username: username.value});
|
socket.emit('user.exists', {
|
||||||
|
username: username.val()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
username.on('keyup', function() {
|
||||||
|
jQuery('#yourUsername').html(this.value.length > 0 ? this.value : 'username');
|
||||||
|
});
|
||||||
|
username.on('blur', function() {
|
||||||
|
validateUsername();
|
||||||
});
|
});
|
||||||
|
|
||||||
$(emailEl).on('keyup change', function() {
|
function validatePassword() {
|
||||||
emailvalid = utils.isEmailValid(email.value);
|
if (!password.val()) {
|
||||||
|
validationError = true;
|
||||||
if(!emailvalid) {
|
return;
|
||||||
email_notify.innerHTML = 'Invalid email address';
|
|
||||||
email_notify.className = 'label label-important';
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
socket.emit('user.email.exists', { email: emailEl.value });
|
|
||||||
});
|
|
||||||
|
|
||||||
$(password).on('keyup', function() {
|
if (password.val().length < config.minimumPasswordLength) {
|
||||||
passwordvalid = utils.isPasswordValid(password.value);
|
showError(password_notify, 'Password too short!');
|
||||||
if (password.value.length < 6) {
|
} else if (!utils.isPasswordValid(password.val())) {
|
||||||
password_notify.innerHTML = 'Password too short';
|
showError(password_notify, 'Invalid password!');
|
||||||
password_notify.className = 'label label-important';
|
|
||||||
} else if(!passwordvalid) {
|
|
||||||
password_notify.innerHTML = 'Invalid password';
|
|
||||||
password_notify.className = 'label label-important';
|
|
||||||
} else {
|
} else {
|
||||||
password_notify.innerHTML = 'OK!';
|
showSuccess(password_notify, successIcon);
|
||||||
password_notify.className = 'label label-success';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(password.value !== password_confirm.value) {
|
if (password.val() !== password_confirm.val() && password_confirm.val() !== '') {
|
||||||
password_confirm_notify.innerHTML = 'Passwords must match!';
|
showError(password_confirm_notify, 'Passwords must match!');
|
||||||
password_confirm_notify.className = 'label label-important';
|
|
||||||
passwordsmatch = false;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(password).on('blur', function() {
|
||||||
|
validatePassword();
|
||||||
});
|
});
|
||||||
|
|
||||||
$(password_confirm).on('keyup', function() {
|
function validatePasswordConfirm() {
|
||||||
if(password.value !== password_confirm.value) {
|
if (!password.val() || password_notify.hasClass('alert-error')) {
|
||||||
password_confirm_notify.innerHTML = 'Passwords must match!';
|
return;
|
||||||
password_confirm_notify.className = 'label label-important';
|
|
||||||
passwordsmatch = false;
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
password_confirm_notify.innerHTML = 'OK!';
|
if (password.val() !== password_confirm.val()) {
|
||||||
password_confirm_notify.className = 'label label-success';
|
showError(password_confirm_notify, 'Passwords must match!');
|
||||||
passwordsmatch = true;
|
} else {
|
||||||
|
showSuccess(password_confirm_notify, successIcon);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(password_confirm).on('blur', function() {
|
||||||
|
validatePasswordConfirm();
|
||||||
});
|
});
|
||||||
|
|
||||||
ajaxify.register_events(['user.exists', 'user.email.exists']);
|
ajaxify.register_events(['user.exists', 'user.email.exists']);
|
||||||
|
|
||||||
socket.on('user.exists', function(data) {
|
socket.on('user.exists', function(data) {
|
||||||
userexists = data.exists;
|
|
||||||
if (data.exists === true) {
|
if (data.exists === true) {
|
||||||
username_notify.innerHTML = 'Username exists';
|
showError(username_notify, 'Username already taken!');
|
||||||
username_notify.className = 'label label-important';
|
|
||||||
} else {
|
} else {
|
||||||
username_notify.innerHTML = 'OK!';
|
showSuccess(username_notify, successIcon);
|
||||||
username_notify.className = 'label label-success';
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('user.email.exists', function(data) {
|
socket.on('user.email.exists', function(data) {
|
||||||
emailexists = data.exists;
|
|
||||||
|
|
||||||
if (data.exists === true) {
|
if (data.exists === true) {
|
||||||
email_notify.innerHTML = 'Email Address exists';
|
showError(email_notify, 'Email address already taken!');
|
||||||
email_notify.className = 'label label-important';
|
} else {
|
||||||
}
|
showSuccess(email_notify, successIcon);
|
||||||
else {
|
|
||||||
email_notify.innerHTML = 'OK!';
|
|
||||||
email_notify.className = 'label label-success';
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Alternate Logins
|
// Alternate Logins
|
||||||
var altLoginEl = document.querySelector('.alt-logins');
|
$('.alt-logins li').on('click', function(e) {
|
||||||
altLoginEl.addEventListener('click', function(e) {
|
document.location.href = $(this).attr('data-url');
|
||||||
var target;
|
|
||||||
switch(e.target.nodeName) {
|
|
||||||
case 'LI': target = e.target; break;
|
|
||||||
case 'I': target = e.target.parentNode; break;
|
|
||||||
}
|
|
||||||
if (target) {
|
|
||||||
document.location.href = target.getAttribute('data-url');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function validateForm() {
|
function validateForm() {
|
||||||
var validated = true;
|
validationError = false;
|
||||||
|
|
||||||
if (username.value.length < 2 || !usernamevalid) {
|
validateEmail();
|
||||||
username_notify.innerHTML = 'Invalid username';
|
validateUsername();
|
||||||
username_notify.className = 'label label-important';
|
validatePassword();
|
||||||
validated = false;
|
validatePasswordConfirm();
|
||||||
|
|
||||||
|
return validationError;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password.value.length < 5) {
|
register.on('click', function(e) {
|
||||||
password_notify.innerHTML = 'Password too short';
|
if (validateForm()) e.preventDefault();
|
||||||
validated = false;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
if(password.value !== password_confirm.value) {
|
|
||||||
password_confirm_notify.innerHTML = 'Passwords must match!';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!emailvalid) {
|
|
||||||
email_notify.innerHTML = 'Invalid email address';
|
|
||||||
validated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(emailexists) {
|
|
||||||
email_notify.innerHTML = 'Email Address exists';
|
|
||||||
validated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(userexists || !passwordsmatch || !passwordvalid)
|
|
||||||
validated = false;
|
|
||||||
|
|
||||||
return validated;
|
|
||||||
}
|
|
||||||
|
|
||||||
register.addEventListener('click', function(e) {
|
|
||||||
if (!validateForm()) e.preventDefault();
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
}());
|
}());
|
||||||
@@ -5,7 +5,9 @@
|
|||||||
|
|
||||||
document.getElementById('reset').onclick = function() {
|
document.getElementById('reset').onclick = function() {
|
||||||
if (inputEl.value.length > 0 && inputEl.value.indexOf('@') !== -1) {
|
if (inputEl.value.length > 0 && inputEl.value.indexOf('@') !== -1) {
|
||||||
socket.emit('user:reset.send', { email: inputEl.value });
|
socket.emit('user:reset.send', {
|
||||||
|
email: inputEl.value
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
jQuery('#success').hide();
|
jQuery('#success').hide();
|
||||||
jQuery(errorEl).show();
|
jQuery(errorEl).show();
|
||||||
@@ -26,7 +28,7 @@
|
|||||||
} else {
|
} else {
|
||||||
jQuery('#success').hide();
|
jQuery('#success').hide();
|
||||||
jQuery(errorEl).show();
|
jQuery(errorEl).show();
|
||||||
switch(data.message) {
|
switch (data.message) {
|
||||||
case 'invalid-email':
|
case 'invalid-email':
|
||||||
errorTextEl.innerHTML = 'The email you put in (<span>' + data.email + '</span>) is not registered with us. Please try again.';
|
errorTextEl.innerHTML = 'The email you put in (<span>' + data.email + '</span>) is not registered with us. Please try again.';
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -10,20 +10,30 @@
|
|||||||
if (password.value.length < 6) {
|
if (password.value.length < 6) {
|
||||||
$('#error').hide();
|
$('#error').hide();
|
||||||
noticeEl.querySelector('strong').innerHTML = 'Invalid Password';
|
noticeEl.querySelector('strong').innerHTML = 'Invalid Password';
|
||||||
noticeEl.querySelector('p').innerHTML = 'The password entered it too short, please pick a different password!';
|
noticeEl.querySelector('p').innerHTML = 'The password entered is too short, please pick a different password.';
|
||||||
noticeEl.style.display = 'block';
|
noticeEl.style.display = 'block';
|
||||||
} else if (password.value === repeat.value) {
|
} else if (password.value !== repeat.value) {
|
||||||
socket.emit('user:reset.commit', { code: reset_code, password: password.value });
|
$('#error').hide();
|
||||||
|
noticeEl.querySelector('strong').innerHTML = 'Invalid Password';
|
||||||
|
noticeEl.querySelector('p').innerHTML = 'The two passwords you\'ve entered do not match.';
|
||||||
|
noticeEl.style.display = 'block';
|
||||||
|
} else {
|
||||||
|
socket.emit('user:reset.commit', {
|
||||||
|
code: reset_code,
|
||||||
|
password: password.value
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
// Enable the form if the code is valid
|
// Enable the form if the code is valid
|
||||||
socket.emit('user:reset.valid', { code: reset_code });
|
socket.emit('user:reset.valid', {
|
||||||
|
code: reset_code
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
ajaxify.register_events(['user:reset.valid', 'user:reset.commit']);
|
ajaxify.register_events(['user:reset.valid', 'user:reset.commit']);
|
||||||
socket.on('user:reset.valid', function(data) {
|
socket.on('user:reset.valid', function(data) {
|
||||||
if (!!data.valid) resetEl.disabled = false;
|
if ( !! data.valid) resetEl.disabled = false;
|
||||||
else {
|
else {
|
||||||
var formEl = document.getElementById('reset-form');
|
var formEl = document.getElementById('reset-form');
|
||||||
// Show error message
|
// Show error message
|
||||||
|
|||||||
@@ -6,9 +6,19 @@
|
|||||||
$('.search-result-text').each(function() {
|
$('.search-result-text').each(function() {
|
||||||
var text = $(this).html();
|
var text = $(this).html();
|
||||||
var regex = new RegExp(searchQuery, 'gi');
|
var regex = new RegExp(searchQuery, 'gi');
|
||||||
text = text.replace(regex, '<span class="label label-success">'+searchQuery+'</span>');
|
text = text.replace(regex, '<span class="label label-success">' + searchQuery + '</span>');
|
||||||
$(this).html(text);
|
$(this).html(text);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$('#search-form input').val(searchQuery);
|
||||||
|
|
||||||
|
$('#mobile-search-form').off('submit').on('submit', function() {
|
||||||
|
var input = $(this).find('input');
|
||||||
|
ajaxify.go("search/" + input.val(), null, "search");
|
||||||
|
input.val('');
|
||||||
|
return false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
@@ -26,52 +26,61 @@
|
|||||||
if (thread_state.pinned === '1') set_pinned_state(true);
|
if (thread_state.pinned === '1') set_pinned_state(true);
|
||||||
|
|
||||||
if (expose_tools === '1') {
|
if (expose_tools === '1') {
|
||||||
var deleteThreadEl = document.getElementById('delete_thread'),
|
var moveThreadModal = $('#move_thread_modal');
|
||||||
lockThreadEl = document.getElementById('lock_thread'),
|
|
||||||
pinThreadEl = document.getElementById('pin_thread'),
|
|
||||||
moveThreadEl = document.getElementById('move_thread'),
|
|
||||||
moveThreadModal = $('#move_thread_modal');
|
|
||||||
|
|
||||||
adminTools.style.visibility = 'inherit';
|
adminTools.style.visibility = 'inherit';
|
||||||
|
|
||||||
// Add events to the thread tools
|
// Add events to the thread tools
|
||||||
deleteThreadEl.addEventListener('click', function(e) {
|
$('#delete_thread').on('click', function(e) {
|
||||||
e.preventDefault();
|
|
||||||
if (thread_state.deleted !== '1') {
|
if (thread_state.deleted !== '1') {
|
||||||
bootbox.confirm('Are you sure you want to delete this thread?', function(confirm) {
|
bootbox.confirm('Are you sure you want to delete this thread?', function(confirm) {
|
||||||
if (confirm) socket.emit('api:topic.delete', { tid: tid });
|
if (confirm) socket.emit('api:topic.delete', {
|
||||||
|
tid: tid
|
||||||
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
bootbox.confirm('Are you sure you want to restore this thread?', function(confirm) {
|
bootbox.confirm('Are you sure you want to restore this thread?', function(confirm) {
|
||||||
if (confirm) socket.emit('api:topic.restore', { tid: tid });
|
if (confirm) socket.emit('api:topic.restore', {
|
||||||
|
tid: tid
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, false);
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
lockThreadEl.addEventListener('click', function(e) {
|
$('#lock_thread').on('click', function(e) {
|
||||||
e.preventDefault();
|
|
||||||
if (thread_state.locked !== '1') {
|
if (thread_state.locked !== '1') {
|
||||||
socket.emit('api:topic.lock', { tid: tid });
|
socket.emit('api:topic.lock', {
|
||||||
|
tid: tid
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
socket.emit('api:topic.unlock', { tid: tid });
|
socket.emit('api:topic.unlock', {
|
||||||
|
tid: tid
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, false);
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
pinThreadEl.addEventListener('click', function(e) {
|
$('#pin_thread').on('click', function(e) {
|
||||||
e.preventDefault();
|
|
||||||
if (thread_state.pinned !== '1') {
|
if (thread_state.pinned !== '1') {
|
||||||
socket.emit('api:topic.pin', { tid: tid });
|
socket.emit('api:topic.pin', {
|
||||||
|
tid: tid
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
socket.emit('api:topic.unpin', { tid: tid });
|
socket.emit('api:topic.unpin', {
|
||||||
|
tid: tid
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, false);
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
moveThreadEl.addEventListener('click', function(e) {
|
$('#move_thread').on('click', function(e) {
|
||||||
e.preventDefault();
|
|
||||||
moveThreadModal.modal('show');
|
moveThreadModal.modal('show');
|
||||||
}, false);
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
moveThreadModal.on('shown.bs.modal', function() {
|
||||||
|
|
||||||
moveThreadModal.on('shown', function() {
|
|
||||||
var loadingEl = document.getElementById('categories-loading');
|
var loadingEl = document.getElementById('categories-loading');
|
||||||
if (loadingEl) {
|
if (loadingEl) {
|
||||||
socket.once('api:categories.get', function(data) {
|
socket.once('api:categories.get', function(data) {
|
||||||
@@ -88,7 +97,7 @@
|
|||||||
x, info, targetCid, targetCatLabel;
|
x, info, targetCid, targetCatLabel;
|
||||||
|
|
||||||
categoriesEl.className = 'category-list';
|
categoriesEl.className = 'category-list';
|
||||||
for(x=0;x<numCategories;x++) {
|
for (x = 0; x < numCategories; x++) {
|
||||||
info = data.categories[x];
|
info = data.categories[x];
|
||||||
categoryEl.className = info.blockclass;
|
categoryEl.className = info.blockclass;
|
||||||
categoryEl.innerHTML = '<i class="' + info.icon + '"></i> ' + info.name;
|
categoryEl.innerHTML = '<i class="' + info.icon + '"></i> ' + info.name;
|
||||||
@@ -128,14 +137,17 @@
|
|||||||
} else {
|
} else {
|
||||||
app.alert({
|
app.alert({
|
||||||
'alert_id': 'thread_move',
|
'alert_id': 'thread_move',
|
||||||
type: 'error',
|
type: 'danger',
|
||||||
title: 'Unable to Move Topic',
|
title: 'Unable to Move Topic',
|
||||||
message: 'This topic could not be moved to ' + targetCatLabel + '.<br />Please try again later',
|
message: 'This topic could not be moved to ' + targetCatLabel + '.<br />Please try again later',
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
socket.emit('api:topic.move', { tid: tid, cid: targetCid });
|
socket.emit('api:topic.move', {
|
||||||
|
tid: tid,
|
||||||
|
cid: targetCid
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -146,7 +158,7 @@
|
|||||||
|
|
||||||
// Fix delete state for this thread's posts
|
// Fix delete state for this thread's posts
|
||||||
var postEls = document.querySelectorAll('#post-container li[data-deleted]');
|
var postEls = document.querySelectorAll('#post-container li[data-deleted]');
|
||||||
for(var x=0,numPosts=postEls.length;x<numPosts;x++) {
|
for (var x = 0, numPosts = postEls.length; x < numPosts; x++) {
|
||||||
if (postEls[x].getAttribute('data-deleted') === '1') toggle_post_delete_state(postEls[x].getAttribute('data-pid'));
|
if (postEls[x].getAttribute('data-deleted') === '1') toggle_post_delete_state(postEls[x].getAttribute('data-pid'));
|
||||||
postEls[x].removeAttribute('data-deleted');
|
postEls[x].removeAttribute('data-deleted');
|
||||||
}
|
}
|
||||||
@@ -187,7 +199,7 @@
|
|||||||
if (data.status && data.status === 'ok') set_follow_state(data.follow);
|
if (data.status && data.status === 'ok') set_follow_state(data.follow);
|
||||||
else {
|
else {
|
||||||
app.alert({
|
app.alert({
|
||||||
type: 'error',
|
type: 'danger',
|
||||||
alert_id: 'topic_follow',
|
alert_id: 'topic_follow',
|
||||||
title: 'Please Log In',
|
title: 'Please Log In',
|
||||||
message: 'Please register or log in in order to subscribe to this topic',
|
message: 'Please register or log in in order to subscribe to this topic',
|
||||||
@@ -195,25 +207,37 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.emit('api:topic.followCheck', tid);
|
socket.emit('api:topic.followCheck', tid);
|
||||||
|
if (followEl[0]) {
|
||||||
followEl[0].addEventListener('click', function() {
|
followEl[0].addEventListener('click', function() {
|
||||||
socket.emit('api:topic.follow', tid);
|
socket.emit('api:topic.follow', tid);
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
// Infinite scrolling of posts
|
|
||||||
$(window).off('scroll').on('scroll', function() {
|
|
||||||
var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
|
|
||||||
|
|
||||||
if (document.body.scrollTop > bottom && !app.infiniteLoaderActive && $('#post-container').children().length) {
|
|
||||||
app.loadMorePosts(tid);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
$('.post-container').on('click', '.deleted', function(ev) {
|
enableInfiniteLoading();
|
||||||
|
|
||||||
|
var bookmark = localStorage.getItem('topic:' + tid + ':bookmark');
|
||||||
|
|
||||||
|
if(bookmark) {
|
||||||
|
app.scrollToPost(parseInt(bookmark, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#post-container').on('click', '.deleted', function(ev) {
|
||||||
$(this).toggleClass('deleted-expanded');
|
$(this).toggleClass('deleted-expanded');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function enableInfiniteLoading() {
|
||||||
|
$(window).off('scroll').on('scroll', function() {
|
||||||
|
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||||
|
|
||||||
|
if ($(window).scrollTop() > bottom && !app.infiniteLoaderActive && $('#post-container').children().length) {
|
||||||
|
app.loadMorePosts(tid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var reply_fn = function() {
|
var reply_fn = function() {
|
||||||
var selectionText = '',
|
var selectionText = '',
|
||||||
selection = window.getSelection() || document.getSelection();
|
selection = window.getSelection() || document.getSelection();
|
||||||
@@ -229,10 +253,10 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
$('.post-container').on('click', '.post_reply', reply_fn);
|
$('#post-container').on('click', '.post_reply', reply_fn);
|
||||||
$('#post_reply').on('click', reply_fn);
|
$('#post_reply').on('click', reply_fn);
|
||||||
|
|
||||||
$('.post-container').on('click', '.quote', function() {
|
$('#post-container').on('click', '.quote', function() {
|
||||||
if (thread_state.locked !== '1') {
|
if (thread_state.locked !== '1') {
|
||||||
var pid = $(this).parents('li').attr('data-pid');
|
var pid = $(this).parents('li').attr('data-pid');
|
||||||
|
|
||||||
@@ -243,60 +267,72 @@
|
|||||||
cmp.push(tid, null, null, quoted);
|
cmp.push(tid, null, null, quoted);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
socket.emit('api:posts.getRawPost', { pid: pid });
|
socket.emit('api:posts.getRawPost', {
|
||||||
|
pid: pid
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.post-container').on('click', '.favourite', function() {
|
$('#post-container').on('click', '.favourite', function() {
|
||||||
var ids = this.id.replace('favs_', '').split('_'),
|
var pid = $(this).parents('li').attr('data-pid');
|
||||||
pid = ids[0],
|
var uid = $(this).parents('li').attr('data-uid');
|
||||||
uid = ids[1];
|
|
||||||
|
|
||||||
var element = $(this).find('i');
|
var element = $(this).find('i');
|
||||||
if(element.attr('class') == 'icon-star-empty') {
|
if (element.attr('class') == 'icon-star-empty') {
|
||||||
element.attr('class', 'icon-star');
|
socket.emit('api:posts.favourite', {
|
||||||
socket.emit('api:posts.favourite', {pid: pid, room_id: app.current_room});
|
pid: pid,
|
||||||
}
|
room_id: app.current_room
|
||||||
else {
|
});
|
||||||
element.attr('class', 'icon-star-empty');
|
} else {
|
||||||
socket.emit('api:posts.unfavourite', {pid: pid, room_id: app.current_room});
|
socket.emit('api:posts.unfavourite', {
|
||||||
|
pid: pid,
|
||||||
|
room_id: app.current_room
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.post-container').delegate('.edit', 'click', function(e) {
|
$('#post-container').on('click', '.link', function() {
|
||||||
var pid = ($(this).attr('id') || $(this.parentNode).attr('id')).split('_')[1];
|
var pid = $(this).parents('li').attr('data-pid');
|
||||||
|
$('#post_' + pid + '_link').val(window.location.href + "#" + pid).stop(true, false).fadeIn().select();
|
||||||
|
$('#post_' + pid + '_link').off('blur').on('blur', function() {
|
||||||
|
$(this).fadeOut();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var main = $(this).parents('.main-post');
|
$('#post-container').delegate('.edit', 'click', function(e) {
|
||||||
|
var pid = $(this).parents('li').attr('data-pid'),
|
||||||
|
main = $(this).parents('.main-post');
|
||||||
|
|
||||||
require(['composer'], function(cmp) {
|
require(['composer'], function(cmp) {
|
||||||
cmp.push(null, null, pid);
|
cmp.push(null, null, pid);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.post-container').delegate('.delete', 'click', function(e) {
|
$('#post-container').delegate('.delete', 'click', function(e) {
|
||||||
var pid = ($(this).attr('id') || $(this.parentNode).attr('id')).split('_')[1],
|
var pid = $(this).parents('li').attr('data-pid'),
|
||||||
postEl = $(document.querySelector('#post-container li[data-pid="' + pid + '"]')),
|
postEl = $(document.querySelector('#post-container li[data-pid="' + pid + '"]')),
|
||||||
deleteAction = !postEl.hasClass('deleted') ? true : false,
|
deleteAction = !postEl.hasClass('deleted') ? true : false,
|
||||||
confirmDel = confirm((deleteAction ? 'Delete' : 'Restore') + ' this post?');
|
confirmDel = confirm((deleteAction ? 'Delete' : 'Restore') + ' this post?');
|
||||||
|
|
||||||
if (confirmDel) {
|
if (confirmDel) {
|
||||||
deleteAction ?
|
deleteAction ?
|
||||||
socket.emit('api:posts.delete', { pid: pid }) :
|
socket.emit('api:posts.delete', {
|
||||||
socket.emit('api:posts.restore', { pid: pid });
|
pid: pid
|
||||||
|
}) :
|
||||||
|
socket.emit('api:posts.restore', {
|
||||||
|
pid: pid
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.post-container').delegate('.chat', 'click', function(e) {
|
$('#post-container').on('click', '.chat', function(e) {
|
||||||
|
var username = $(this).parents('li.row').attr('data-username');
|
||||||
|
var touid = $(this).parents('li.row').attr('data-uid');
|
||||||
|
|
||||||
var username = $(this).parents('li').attr('data-username');
|
if (username === app.username || !app.username)
|
||||||
var touid = $(this).parents('li').attr('data-uid');
|
return;
|
||||||
|
|
||||||
require(['chat'], function(chat){
|
|
||||||
var chatModal = chat.createModalIfDoesntExist(username, touid);
|
|
||||||
chatModal.show();
|
|
||||||
chat.bringModalToTop(chatModal);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
app.openChat(username, touid);
|
||||||
});
|
});
|
||||||
|
|
||||||
ajaxify.register_events([
|
ajaxify.register_events([
|
||||||
@@ -310,7 +346,7 @@
|
|||||||
|
|
||||||
socket.on('api:get_users_in_room', function(data) {
|
socket.on('api:get_users_in_room', function(data) {
|
||||||
var activeEl = $('#thread_active_users');
|
var activeEl = $('#thread_active_users');
|
||||||
if(activeEl.length)
|
if (activeEl.length)
|
||||||
activeEl.html(data);
|
activeEl.html(data);
|
||||||
|
|
||||||
app.populate_online_users();
|
app.populate_online_users();
|
||||||
@@ -371,9 +407,9 @@
|
|||||||
socket.on('event:post_edited', function(data) {
|
socket.on('event:post_edited', function(data) {
|
||||||
var editedPostEl = document.getElementById('content_' + data.pid);
|
var editedPostEl = document.getElementById('content_' + data.pid);
|
||||||
|
|
||||||
var editedPostTitle = $('#topic_title_'+data.pid);
|
var editedPostTitle = $('#topic_title_' + data.pid);
|
||||||
|
|
||||||
if(editedPostTitle.length > 0) {
|
if (editedPostTitle.length > 0) {
|
||||||
editedPostTitle.fadeOut(250, function() {
|
editedPostTitle.fadeOut(250, function() {
|
||||||
editedPostTitle.html(data.title);
|
editedPostTitle.html(data.title);
|
||||||
editedPostTitle.fadeIn(250);
|
editedPostTitle.fadeIn(250);
|
||||||
@@ -384,12 +420,26 @@
|
|||||||
this.innerHTML = data.content;
|
this.innerHTML = data.content;
|
||||||
$(this).fadeIn(250);
|
$(this).fadeIn(250);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:posts.favourite', function(data) {
|
socket.on('api:posts.favourite', function(data) {
|
||||||
if (data.status !== 'ok' && data.pid) {
|
if (data.status === 'ok' && data.pid) {
|
||||||
var favEl = document.querySelector('.post_rep_' + data.pid).nextSibling;
|
var favEl = document.querySelector('.post_rep_' + data.pid).nextSibling;
|
||||||
if (favEl) favEl.className = 'icon-star-empty';
|
if (favEl) {
|
||||||
|
favEl.className = 'icon-star';
|
||||||
|
$(favEl).parent().addClass('btn-warning');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('api:posts.unfavourite', function(data) {
|
||||||
|
if (data.status === 'ok' && data.pid) {
|
||||||
|
var favEl = document.querySelector('.post_rep_' + data.pid).nextSibling;
|
||||||
|
if (favEl) {
|
||||||
|
favEl.className = 'icon-star-empty';
|
||||||
|
$(favEl).parent().removeClass('btn-warning');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -415,8 +465,8 @@
|
|||||||
ptotal += value;
|
ptotal += value;
|
||||||
utotal += value;
|
utotal += value;
|
||||||
|
|
||||||
post_rep.html(ptotal+ ' ');
|
post_rep.html(ptotal + ' ');
|
||||||
user_rep.html(utotal+ ' ');
|
user_rep.html(utotal + ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_locked_state(locked, alert) {
|
function set_locked_state(locked, alert) {
|
||||||
@@ -433,7 +483,7 @@
|
|||||||
lockThreadEl.innerHTML = '<i class="icon-unlock"></i> Unlock Thread';
|
lockThreadEl.innerHTML = '<i class="icon-unlock"></i> Unlock Thread';
|
||||||
threadReplyBtn.disabled = true;
|
threadReplyBtn.disabled = true;
|
||||||
threadReplyBtn.innerHTML = 'Locked <i class="icon-lock"></i>';
|
threadReplyBtn.innerHTML = 'Locked <i class="icon-lock"></i>';
|
||||||
for(x=0;x<numPosts;x++) {
|
for (x = 0; x < numPosts; x++) {
|
||||||
postReplyBtns[x].innerHTML = 'Locked <i class="icon-lock"></i>';
|
postReplyBtns[x].innerHTML = 'Locked <i class="icon-lock"></i>';
|
||||||
quoteBtns[x].style.display = 'none';
|
quoteBtns[x].style.display = 'none';
|
||||||
editBtns[x].style.display = 'none';
|
editBtns[x].style.display = 'none';
|
||||||
@@ -455,7 +505,7 @@
|
|||||||
lockThreadEl.innerHTML = '<i class="icon-lock"></i> Lock Thread';
|
lockThreadEl.innerHTML = '<i class="icon-lock"></i> Lock Thread';
|
||||||
threadReplyBtn.disabled = false;
|
threadReplyBtn.disabled = false;
|
||||||
threadReplyBtn.innerHTML = 'Reply';
|
threadReplyBtn.innerHTML = 'Reply';
|
||||||
for(x=0;x<numPosts;x++) {
|
for (x = 0; x < numPosts; x++) {
|
||||||
postReplyBtns[x].innerHTML = 'Reply <i class="icon-reply"></i>';
|
postReplyBtns[x].innerHTML = 'Reply <i class="icon-reply"></i>';
|
||||||
quoteBtns[x].style.display = 'inline-block';
|
quoteBtns[x].style.display = 'inline-block';
|
||||||
editBtns[x].style.display = 'inline-block';
|
editBtns[x].style.display = 'inline-block';
|
||||||
@@ -479,23 +529,23 @@
|
|||||||
function set_delete_state(deleted) {
|
function set_delete_state(deleted) {
|
||||||
var deleteThreadEl = document.getElementById('delete_thread'),
|
var deleteThreadEl = document.getElementById('delete_thread'),
|
||||||
deleteTextEl = deleteThreadEl.getElementsByTagName('span')[0],
|
deleteTextEl = deleteThreadEl.getElementsByTagName('span')[0],
|
||||||
threadEl = document.querySelector('.post-container'),
|
threadEl = $('#post-container'),
|
||||||
deleteNotice = document.getElementById('thread-deleted') || document.createElement('div');
|
deleteNotice = document.getElementById('thread-deleted') || document.createElement('div');
|
||||||
|
|
||||||
if (deleted) {
|
if (deleted) {
|
||||||
deleteTextEl.innerHTML = '<i class="icon-comment"></i> Restore Thread';
|
deleteTextEl.innerHTML = '<i class="icon-comment"></i> Restore Thread';
|
||||||
$(threadEl).addClass('deleted');
|
threadEl.addClass('deleted');
|
||||||
|
|
||||||
// Spawn a 'deleted' notice at the top of the page
|
// Spawn a 'deleted' notice at the top of the page
|
||||||
deleteNotice.setAttribute('id', 'thread-deleted');
|
deleteNotice.setAttribute('id', 'thread-deleted');
|
||||||
deleteNotice.className = 'alert';
|
deleteNotice.className = 'alert alert-warning';
|
||||||
deleteNotice.innerHTML = 'This thread has been deleted. Only users with thread management privileges can see it.';
|
deleteNotice.innerHTML = 'This thread has been deleted. Only users with thread management privileges can see it.';
|
||||||
document.getElementById('content').insertBefore(deleteNotice, threadEl);
|
threadEl.before(deleteNotice);
|
||||||
|
|
||||||
thread_state.deleted = '1';
|
thread_state.deleted = '1';
|
||||||
} else {
|
} else {
|
||||||
deleteTextEl.innerHTML = '<i class="icon-trash"></i> Delete Thread';
|
deleteTextEl.innerHTML = '<i class="icon-trash"></i> Delete Thread';
|
||||||
$(threadEl).removeClass('deleted');
|
threadEl.removeClass('deleted');
|
||||||
deleteNotice.parentNode.removeChild(deleteNotice);
|
deleteNotice.parentNode.removeChild(deleteNotice);
|
||||||
|
|
||||||
thread_state.deleted = '0';
|
thread_state.deleted = '0';
|
||||||
@@ -591,4 +641,76 @@
|
|||||||
deleteEl.addClass('none');
|
deleteEl.addClass('none');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var postAuthorImage, mobileAuthorOverlay, pagination;
|
||||||
|
var postcount = templates.get('postcount');
|
||||||
|
|
||||||
|
function updateHeader() {
|
||||||
|
if (pagination == null) {
|
||||||
|
jQuery('.pagination-block i:first').on('click', function() {
|
||||||
|
app.scrollToTop();
|
||||||
|
});
|
||||||
|
jQuery('.pagination-block i:last').on('click', function() {
|
||||||
|
app.scrollToBottom();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
jQuery('.mobile-author-overlay').css('bottom', '0px');
|
||||||
|
postAuthorImage = postAuthorImage || document.getElementById('mobile-author-image');
|
||||||
|
mobileAuthorOverlay = mobileAuthorOverlay || document.getElementById('mobile-author-overlay');
|
||||||
|
pagination = pagination || document.getElementById('pagination');
|
||||||
|
|
||||||
|
pagination.parentNode.style.display = 'block';
|
||||||
|
|
||||||
|
var windowHeight = jQuery(window).height();
|
||||||
|
var scrollTop = jQuery(window).scrollTop();
|
||||||
|
var scrollBottom = scrollTop + windowHeight;
|
||||||
|
|
||||||
|
if (scrollTop < 50 && postcount > 1) {
|
||||||
|
localStorage.removeItem("topic:" + tid + ":bookmark");
|
||||||
|
postAuthorImage.src = (jQuery('.main-post .avatar img').attr('src'));
|
||||||
|
mobileAuthorOverlay.innerHTML = 'Posted by ' + jQuery('.main-post').attr('data-username') + ', ' + jQuery('.main-post').find('.relativeTimeAgo').html();
|
||||||
|
pagination.innerHTML = '0 out of ' + postcount;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var count = 0, smallestNonNegative = 0;
|
||||||
|
|
||||||
|
jQuery('.sub-posts').each(function() {
|
||||||
|
count++;
|
||||||
|
this.postnumber = count;
|
||||||
|
|
||||||
|
|
||||||
|
var el = jQuery(this);
|
||||||
|
var elTop = el.offset().top;
|
||||||
|
var height = Math.floor(el.height());
|
||||||
|
var elBottom = elTop + (height < 300 ? height : 300);
|
||||||
|
|
||||||
|
var inView = ((elBottom >= scrollTop) && (elTop <= scrollBottom) && (elBottom <= scrollBottom) && (elTop >= scrollTop));
|
||||||
|
|
||||||
|
|
||||||
|
if (inView) {
|
||||||
|
if(elTop - scrollTop > smallestNonNegative) {
|
||||||
|
localStorage.setItem("topic:" + tid + ":bookmark", el.attr('data-pid'));
|
||||||
|
smallestNonNegative = Number.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pagination.innerHTML = this.postnumber + ' out of ' + postcount;
|
||||||
|
postAuthorImage.src = (jQuery(this).find('.profile-image-block img').attr('src'));
|
||||||
|
mobileAuthorOverlay.innerHTML = 'Posted by ' + jQuery(this).attr('data-username') + ', ' + jQuery(this).find('.relativeTimeAgo').html();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
if (scrollTop + windowHeight == jQuery(document).height()) {
|
||||||
|
pagination.innerHTML = postcount + ' out of ' + postcount;
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onscroll = updateHeader;
|
||||||
|
window.onload = updateHeader;
|
||||||
})();
|
})();
|
||||||
@@ -8,7 +8,8 @@
|
|||||||
'event:new_post'
|
'event:new_post'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
var newTopicCount = 0, newPostCount = 0;
|
var newTopicCount = 0,
|
||||||
|
newPostCount = 0;
|
||||||
|
|
||||||
$('#new-topics-alert').on('click', function() {
|
$('#new-topics-alert').on('click', function() {
|
||||||
$(this).hide();
|
$(this).hide();
|
||||||
@@ -24,16 +25,16 @@
|
|||||||
function updateAlertText() {
|
function updateAlertText() {
|
||||||
var text = '';
|
var text = '';
|
||||||
|
|
||||||
if(newTopicCount > 1)
|
if (newTopicCount > 1)
|
||||||
text = 'There are ' + newTopicCount + ' new topics';
|
text = 'There are ' + newTopicCount + ' new topics';
|
||||||
else if(newTopicCount === 1)
|
else if (newTopicCount === 1)
|
||||||
text = 'There is 1 new topic';
|
text = 'There is 1 new topic';
|
||||||
else
|
else
|
||||||
text = 'There are no new topics';
|
text = 'There are no new topics';
|
||||||
|
|
||||||
if(newPostCount > 1)
|
if (newPostCount > 1)
|
||||||
text += ' and ' + newPostCount + ' new posts.';
|
text += ' and ' + newPostCount + ' new posts.';
|
||||||
else if(newPostCount === 1)
|
else if (newPostCount === 1)
|
||||||
text += ' and 1 new post.';
|
text += ' and 1 new post.';
|
||||||
else
|
else
|
||||||
text += ' and no new posts.';
|
text += ' and no new posts.';
|
||||||
@@ -50,12 +51,16 @@
|
|||||||
|
|
||||||
$('#mark-allread-btn').on('click', function() {
|
$('#mark-allread-btn').on('click', function() {
|
||||||
var btn = $(this);
|
var btn = $(this);
|
||||||
socket.emit('api:topics.markAllRead', {} , function(success) {
|
socket.emit('api:topics.markAllRead', {}, function(success) {
|
||||||
if(success) {
|
if (success) {
|
||||||
btn.remove();
|
btn.remove();
|
||||||
$('#topics-container').empty();
|
$('#topics-container').empty();
|
||||||
$('#category-no-topics').removeClass('hidden');
|
$('#category-no-topics').removeClass('hidden');
|
||||||
app.alertSuccess('All topics marked as read!');
|
app.alertSuccess('All topics marked as read!');
|
||||||
|
$('#numUnreadBadge')
|
||||||
|
.removeClass('badge-important')
|
||||||
|
.addClass('badge-inverse')
|
||||||
|
.html('0');
|
||||||
} else {
|
} else {
|
||||||
app.alertError('There was an error marking topics read!');
|
app.alertError('There was an error marking topics read!');
|
||||||
}
|
}
|
||||||
@@ -64,7 +69,9 @@
|
|||||||
|
|
||||||
function onTopicsLoaded(topics) {
|
function onTopicsLoaded(topics) {
|
||||||
|
|
||||||
var html = templates.prepare(templates['unread'].blocks['topics']).parse({ topics: topics }),
|
var html = templates.prepare(templates['unread'].blocks['topics']).parse({
|
||||||
|
topics: topics
|
||||||
|
}),
|
||||||
container = $('#topics-container');
|
container = $('#topics-container');
|
||||||
|
|
||||||
$('#category-no-topics').remove();
|
$('#category-no-topics').remove();
|
||||||
@@ -74,25 +81,30 @@
|
|||||||
|
|
||||||
function loadMoreTopics() {
|
function loadMoreTopics() {
|
||||||
loadingMoreTopics = true;
|
loadingMoreTopics = true;
|
||||||
socket.emit('api:topics.loadMoreUnreadTopics', {after:parseInt($('#topics-container').attr('data-next-start'), 10)}, function(data) {
|
socket.emit('api:topics.loadMoreUnreadTopics', {
|
||||||
if(data.topics && data.topics.length) {
|
after: parseInt($('#topics-container').attr('data-next-start'), 10)
|
||||||
|
}, function(data) {
|
||||||
|
if (data.topics && data.topics.length) {
|
||||||
onTopicsLoaded(data.topics);
|
onTopicsLoaded(data.topics);
|
||||||
$('#topics-container').attr('data-next-start', data.nextStart);
|
$('#topics-container').attr('data-next-start', data.nextStart);
|
||||||
|
} else {
|
||||||
|
$('#load-more-btn').hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
loadingMoreTopics = false;
|
loadingMoreTopics = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$(window).off('scroll').on('scroll', function() {
|
$(window).off('scroll').on('scroll', function() {
|
||||||
var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
|
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||||
|
|
||||||
if (document.body.scrollTop > bottom && !loadingMoreTopics) {
|
if ($(window).scrollTop() > bottom && !loadingMoreTopics) {
|
||||||
loadMoreTopics();
|
loadMoreTopics();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
if($("body").height() <= $(window).height() && $('#topics-container').children().length)
|
if ($("body").height() <= $(window).height() && $('#topics-container').children().length >= 20)
|
||||||
$('#load-more-btn').show();
|
$('#load-more-btn').show();
|
||||||
|
|
||||||
$('#load-more-btn').on('click', function() {
|
$('#load-more-btn').on('click', function() {
|
||||||
|
|||||||
@@ -6,7 +6,11 @@
|
|||||||
|
|
||||||
var url = window.location.href,
|
var url = window.location.href,
|
||||||
parts = url.split('/'),
|
parts = url.split('/'),
|
||||||
active = parts[parts.length-1];
|
active = parts[parts.length - 1];
|
||||||
|
|
||||||
|
var lastSearch = null;
|
||||||
|
|
||||||
|
app.addCommasToNumbers();
|
||||||
|
|
||||||
jQuery('.nav-pills li').removeClass('active');
|
jQuery('.nav-pills li').removeClass('active');
|
||||||
jQuery('.nav-pills li a').each(function() {
|
jQuery('.nav-pills li a').each(function() {
|
||||||
@@ -16,8 +20,8 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
jQuery('#search-user').on('keyup', function () {
|
jQuery('#search-user').on('keyup', function() {
|
||||||
if(timeoutId !== 0) {
|
if (timeoutId !== 0) {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
timeoutId = 0;
|
timeoutId = 0;
|
||||||
}
|
}
|
||||||
@@ -25,93 +29,105 @@
|
|||||||
timeoutId = setTimeout(function() {
|
timeoutId = setTimeout(function() {
|
||||||
var username = $('#search-user').val();
|
var username = $('#search-user').val();
|
||||||
|
|
||||||
jQuery('.icon-spinner').removeClass('none');
|
if (username == '') {
|
||||||
|
jQuery('#user-notfound-notify').html('<i class="icon icon-circle-blank"></i>');
|
||||||
|
jQuery('#user-notfound-notify').parent().removeClass('btn-warning label-warning btn-success label-success');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastSearch === username) return;
|
||||||
|
lastSearch = username;
|
||||||
|
|
||||||
|
jQuery('#user-notfound-notify').html('<i class="icon-spinner icon-spin"></i>');
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
socket.emit('api:admin.user.search', username);
|
socket.emit('api:admin.user.search', username);
|
||||||
|
}, 500); //replace this with global throttling function/constant
|
||||||
|
|
||||||
}, 250);
|
}, 250);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.removeAllListeners('api:admin.user.search');
|
socket.removeAllListeners('api:admin.user.search');
|
||||||
|
|
||||||
socket.on('api:admin.user.search', function(data) {
|
socket.on('api:admin.user.search', function(data) {
|
||||||
|
if (data === null) {
|
||||||
jQuery('.icon-spinner').addClass('none');
|
$('#user-notfound-notify').html('You need to be logged in to search!');
|
||||||
|
$('#user-notfound-notify').parent().addClass('btn-warning label-warning');
|
||||||
if(data === null) {
|
|
||||||
$('#user-notfound-notify').html('You need to be logged in to search!')
|
|
||||||
.show()
|
|
||||||
.addClass('label-important')
|
|
||||||
.removeClass('label-success');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var html = templates.prepare(templates['users'].blocks['users']).parse({
|
var html = templates.prepare(templates['users'].blocks['users']).parse({
|
||||||
users: data
|
users: data
|
||||||
}),
|
}),
|
||||||
userListEl = document.querySelector('.users');
|
userListEl = document.querySelector('#users-container');
|
||||||
|
|
||||||
userListEl.innerHTML = html;
|
userListEl.innerHTML = html;
|
||||||
|
|
||||||
|
|
||||||
if(data && data.length === 0) {
|
if (data && data.length === 0) {
|
||||||
$('#user-notfound-notify').html('User not found!')
|
$('#user-notfound-notify').html('User not found!');
|
||||||
.show()
|
$('#user-notfound-notify').parent().addClass('btn-warning label-warning');
|
||||||
.addClass('label-important')
|
} else {
|
||||||
.removeClass('label-success');
|
$('#user-notfound-notify').html(data.length + ' user' + (data.length > 1 ? 's' : '') + ' found!');
|
||||||
}
|
$('#user-notfound-notify').parent().addClass('btn-success label-success');
|
||||||
else {
|
|
||||||
$('#user-notfound-notify').html(data.length + ' user'+(data.length>1?'s':'') + ' found!')
|
|
||||||
.show()
|
|
||||||
.addClass('label-success')
|
|
||||||
.removeClass('label-important');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.reputation').each(function(index, element) {
|
socket.on('api:user.isOnline', function(data) {
|
||||||
$(element).html(app.addCommas($(element).html()));
|
if(active == 'online' && !loadingMoreUsers) {
|
||||||
});
|
$('#users-container').empty();
|
||||||
|
startLoading('users:online', 0);
|
||||||
$('.postcount').each(function(index, element) {
|
}
|
||||||
$(element).html(app.addCommas($(element).html()));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function onUsersLoaded(users) {
|
function onUsersLoaded(users) {
|
||||||
var html = templates.prepare(templates['users'].blocks['users']).parse({ users: users });
|
var html = templates.prepare(templates['users'].blocks['users']).parse({
|
||||||
|
users: users
|
||||||
|
});
|
||||||
$('#users-container').append(html);
|
$('#users-container').append(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadMoreUsers() {
|
function loadMoreUsers() {
|
||||||
var set = '';
|
var set = '';
|
||||||
if(active === 'users-latest' || active === 'users') {
|
if (active === 'latest' || active === 'users') {
|
||||||
set = 'users:joindate';
|
set = 'users:joindate';
|
||||||
} else if(active === 'users-sort-posts') {
|
} else if (active === 'sort-posts') {
|
||||||
set = 'users:postcount';
|
set = 'users:postcount';
|
||||||
} else if(active === 'users-sort-reputation') {
|
} else if (active === 'sort-reputation') {
|
||||||
set = 'users:reputation';
|
set = 'users:reputation';
|
||||||
|
} else if (active === 'online') {
|
||||||
|
set = 'users:online';
|
||||||
}
|
}
|
||||||
|
|
||||||
if(set) {
|
if (set) {
|
||||||
|
startLoading(set, $('#users-container').children().length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function startLoading(set, after) {
|
||||||
loadingMoreUsers = true;
|
loadingMoreUsers = true;
|
||||||
socket.emit('api:users.loadMore', {
|
socket.emit('api:users.loadMore', {
|
||||||
set: set,
|
set: set,
|
||||||
after: $('#users-container').children().length
|
after: after
|
||||||
}, function(data) {
|
}, function(data) {
|
||||||
if(data.users.length) {
|
if (data.users.length) {
|
||||||
onUsersLoaded(data.users);
|
onUsersLoaded(data.users);
|
||||||
|
$('#load-more-users-btn').removeClass('disabled');
|
||||||
} else {
|
} else {
|
||||||
$('#load-more-users-btn').addClass('disabled');
|
$('#load-more-users-btn').addClass('disabled');
|
||||||
}
|
}
|
||||||
loadingMoreUsers = false;
|
loadingMoreUsers = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$('#load-more-users-btn').on('click', loadMoreUsers);
|
$('#load-more-users-btn').on('click', loadMoreUsers);
|
||||||
|
|
||||||
$(window).off('scroll').on('scroll', function() {
|
$(window).off('scroll').on('scroll', function() {
|
||||||
var bottom = (document.body.offsetHeight - $(window).height()) * 0.9;
|
var bottom = ($(document).height() - $(window).height()) * 0.9;
|
||||||
|
|
||||||
if (document.body.scrollTop > bottom && !loadingMoreUsers) {
|
if ($(window).scrollTop() > bottom && !loadingMoreUsers) {
|
||||||
loadMoreUsers();
|
loadMoreUsers();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ define(['taskbar'], function(taskbar) {
|
|||||||
|
|
||||||
var module = {};
|
var module = {};
|
||||||
|
|
||||||
|
|
||||||
module.bringModalToTop = function(chatModal) {
|
module.bringModalToTop = function(chatModal) {
|
||||||
var topZ = 0;
|
var topZ = 0;
|
||||||
$('.modal').each(function() {
|
$('.modal').each(function() {
|
||||||
@@ -11,26 +10,63 @@ define(['taskbar'], function(taskbar) {
|
|||||||
topZ = thisZ;
|
topZ = thisZ;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
chatModal.css('zIndex', topZ+1);
|
chatModal.css('zIndex', topZ + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.createModalIfDoesntExist = function(username, touid) {
|
module.getModal = function(touid) {
|
||||||
var chatModal = $('#chat-modal-'+touid);
|
return $('#chat-modal-' + touid);
|
||||||
|
}
|
||||||
|
|
||||||
if(!chatModal.length) {
|
module.modalExists = function(touid) {
|
||||||
var chatModal = $('#chat-modal').clone();
|
return $('#chat-modal-' + touid).length !== 0;
|
||||||
chatModal.attr('id','chat-modal-'+touid);
|
}
|
||||||
var uuid = utils.generateUUID();
|
|
||||||
|
function checkStatus(chatModal, callback) {
|
||||||
|
socket.emit('api:user.isOnline', chatModal.touid, function(data) {
|
||||||
|
if(data.online !== chatModal.online) {
|
||||||
|
if(data.online) {
|
||||||
|
module.appendChatMessage(chatModal, chatModal.username + ' is currently online.\n', data.timestamp);
|
||||||
|
} else {
|
||||||
|
module.appendChatMessage(chatModal, chatModal.username + ' is currently offline.\n', data.timestamp);
|
||||||
|
}
|
||||||
|
chatModal.online = data.online;
|
||||||
|
}
|
||||||
|
if(callback)
|
||||||
|
callback(data.online);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkOnlineStatus(chatModal) {
|
||||||
|
if(chatModal.intervalId === 0) {
|
||||||
|
chatModal.intervalId = setInterval(function() {
|
||||||
|
checkStatus(chatModal);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.createModal = function(username, touid, callback) {
|
||||||
|
|
||||||
|
var chatModal = $('#chat-modal').clone(),
|
||||||
|
uuid = utils.generateUUID();
|
||||||
|
|
||||||
|
chatModal.intervalId = 0;
|
||||||
|
chatModal.touid = touid;
|
||||||
|
chatModal.username = username;
|
||||||
|
|
||||||
|
chatModal.attr('id', 'chat-modal-' + touid);
|
||||||
chatModal.attr('UUID', uuid);
|
chatModal.attr('UUID', uuid);
|
||||||
chatModal.appendTo($('body'));
|
chatModal.appendTo($('body'));
|
||||||
chatModal.draggable({
|
chatModal.draggable({
|
||||||
start:function(){
|
start:function() {
|
||||||
module.bringModalToTop(chatModal);
|
module.bringModalToTop(chatModal);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
chatModal.find('#chat-with-name').html(username);
|
chatModal.find('#chat-with-name').html(username);
|
||||||
|
|
||||||
chatModal.find('.close').on('click',function(e){
|
chatModal.find('.close').on('click', function(e) {
|
||||||
|
clearInterval(chatModal.intervalId);
|
||||||
|
chatModal.intervalId = 0;
|
||||||
chatModal.hide();
|
chatModal.hide();
|
||||||
taskbar.discard('chat', uuid);
|
taskbar.discard('chat', uuid);
|
||||||
});
|
});
|
||||||
@@ -39,10 +75,13 @@ define(['taskbar'], function(taskbar) {
|
|||||||
module.bringModalToTop(chatModal);
|
module.bringModalToTop(chatModal);
|
||||||
});
|
});
|
||||||
|
|
||||||
addSendHandler(chatModal, touid);
|
addSendHandler(chatModal);
|
||||||
}
|
|
||||||
|
|
||||||
taskbar.push('chat', chatModal.attr('UUID'), {title:'chat with '+username});
|
getChatMessages(chatModal, function() {
|
||||||
|
checkOnlineStatus(chatModal);
|
||||||
|
});
|
||||||
|
|
||||||
|
taskbar.push('chat', chatModal.attr('UUID'), {title:'chat with ' + username});
|
||||||
return chatModal;
|
return chatModal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,43 +89,56 @@ define(['taskbar'], function(taskbar) {
|
|||||||
var chatModal = $('div[UUID="'+uuid+'"]');
|
var chatModal = $('div[UUID="'+uuid+'"]');
|
||||||
chatModal.show();
|
chatModal.show();
|
||||||
module.bringModalToTop(chatModal);
|
module.bringModalToTop(chatModal);
|
||||||
|
checkOnlineStatus(chatModal);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.minimize = function(uuid) {
|
module.minimize = function(uuid) {
|
||||||
var chatModal = $('div[UUID="'+uuid+'"]');
|
var chatModal = $('div[UUID="'+uuid+'"]');
|
||||||
chatModal.hide();
|
chatModal.hide();
|
||||||
taskbar.minimize('chat', uuid);
|
taskbar.minimize('chat', uuid);
|
||||||
|
clearInterval(chatModal.intervalId);
|
||||||
|
chatModal.intervalId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSendHandler(chatModal, touid) {
|
function getChatMessages(chatModal, callback) {
|
||||||
|
socket.emit('getChatMessages', {touid:chatModal.touid}, function(messages) {
|
||||||
|
for(var i = 0; i<messages.length; ++i) {
|
||||||
|
module.appendChatMessage(chatModal, messages[i].content, messages[i].timestamp);
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addSendHandler(chatModal) {
|
||||||
chatModal.find('#chat-message-input').off('keypress');
|
chatModal.find('#chat-message-input').off('keypress');
|
||||||
chatModal.find('#chat-message-input').on('keypress', function(e) {
|
chatModal.find('#chat-message-input').on('keypress', function(e) {
|
||||||
if(e.which === 13) {
|
if(e.which === 13) {
|
||||||
sendMessage(chatModal, touid);
|
sendMessage(chatModal);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
chatModal.find('#chat-message-send-btn').off('click');
|
chatModal.find('#chat-message-send-btn').off('click');
|
||||||
chatModal.find('#chat-message-send-btn').on('click', function(e){
|
chatModal.find('#chat-message-send-btn').on('click', function(e){
|
||||||
sendMessage(chatModal, touid);
|
sendMessage(chatModal);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendMessage(chatModal, touid) {
|
function sendMessage(chatModal) {
|
||||||
var msg = app.strip_tags(chatModal.find('#chat-message-input').val());
|
var msg = app.strip_tags(chatModal.find('#chat-message-input').val());
|
||||||
if(msg.length) {
|
if(msg.length) {
|
||||||
msg = msg +'\n';
|
msg = msg +'\n';
|
||||||
socket.emit('sendChatMessage', { touid:touid, message:msg});
|
socket.emit('sendChatMessage', { touid:chatModal.touid, message:msg});
|
||||||
chatModal.find('#chat-message-input').val('');
|
chatModal.find('#chat-message-input').val('');
|
||||||
module.appendChatMessage(chatModal, 'You : ' + msg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.appendChatMessage = function(chatModal, message, timestamp) {
|
||||||
module.appendChatMessage = function(chatModal, message){
|
|
||||||
var chatContent = chatModal.find('#chat-content');
|
var chatContent = chatModal.find('#chat-content');
|
||||||
chatContent.append(message);
|
|
||||||
|
var date = new Date(parseInt(timestamp, 10));
|
||||||
|
|
||||||
|
chatContent.append('[' + date.toLocaleTimeString() + '] ' + message);
|
||||||
chatContent.scrollTop(
|
chatContent.scrollTop(
|
||||||
chatContent[0].scrollHeight - chatContent.height()
|
chatContent[0].scrollHeight - chatContent.height()
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,12 +7,33 @@ define(['taskbar'], function(taskbar) {
|
|||||||
postContainer: undefined,
|
postContainer: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var uploadsInProgress = [];
|
||||||
|
|
||||||
|
function createImagePlaceholder(img) {
|
||||||
|
var text = $('.post-window textarea').val(),
|
||||||
|
textarea = $('.post-window textarea'),
|
||||||
|
imgText = "";
|
||||||
|
|
||||||
|
text += imgText;
|
||||||
|
textarea.val(text + " ");
|
||||||
|
uploadsInProgress.push(1);
|
||||||
|
socket.emit("api:posts.uploadImage", img, function(err, data) {
|
||||||
|
|
||||||
|
var currentText = textarea.val();
|
||||||
|
imgText = "";
|
||||||
|
|
||||||
|
if(!err)
|
||||||
|
textarea.val(currentText.replace(imgText, ""));
|
||||||
|
else
|
||||||
|
textarea.val(currentText.replace(imgText, ""));
|
||||||
|
uploadsInProgress.pop();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function loadFile(file) {
|
function loadFile(file) {
|
||||||
var reader = new FileReader();
|
var reader = new FileReader(),
|
||||||
var dropDiv = $('#imagedrop');
|
dropDiv = $('.post-window .imagedrop'),
|
||||||
var imagelist = $('#imagelist');
|
uuid = dropDiv.parents('[data-uuid]').attr('data-uuid');
|
||||||
var uuid = dropDiv.parents('[data-uuid]').attr('data-uuid');
|
|
||||||
var posts = composer.posts[uuid];
|
|
||||||
|
|
||||||
$(reader).on('loadend', function(e) {
|
$(reader).on('loadend', function(e) {
|
||||||
var bin = this.result;
|
var bin = this.result;
|
||||||
@@ -23,21 +44,8 @@ define(['taskbar'], function(taskbar) {
|
|||||||
data: bin
|
data: bin
|
||||||
};
|
};
|
||||||
|
|
||||||
posts.images.push(img);
|
createImagePlaceholder(img);
|
||||||
|
|
||||||
var imageLabel = $('<div class="label"><span>'+ file.name +'</span></div>');
|
|
||||||
var closeButton = $('<button class="close">×</button>');
|
|
||||||
closeButton.on('click', function(e) {
|
|
||||||
|
|
||||||
imageLabel.remove();
|
|
||||||
var index = posts.images.indexOf(img);
|
|
||||||
if(index !== -1) {
|
|
||||||
posts.images.splice(index, 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
imageLabel.append(closeButton);
|
|
||||||
imagelist.append(imageLabel);
|
|
||||||
dropDiv.hide();
|
dropDiv.hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -47,11 +55,28 @@ define(['taskbar'], function(taskbar) {
|
|||||||
function initializeFileReader() {
|
function initializeFileReader() {
|
||||||
jQuery.event.props.push( "dataTransfer" );
|
jQuery.event.props.push( "dataTransfer" );
|
||||||
|
|
||||||
if(window.FileReader) {
|
var draggingDocument = false;
|
||||||
var drop = $('#imagedrop');
|
|
||||||
|
|
||||||
$(composer.postContainer).on('dragenter dragover', function() {
|
if(window.FileReader) {
|
||||||
|
var drop = $('.post-window .imagedrop'),
|
||||||
|
textarea = $('.post-window textarea');
|
||||||
|
|
||||||
|
$(document).on('dragstart', function(e) {
|
||||||
|
draggingDocument = true;
|
||||||
|
}).on('dragend', function(e) {
|
||||||
|
draggingDocument = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
textarea.on('dragenter', function(e) {
|
||||||
|
if(draggingDocument)
|
||||||
|
return;
|
||||||
|
drop.css('top', textarea.position().top + 'px');
|
||||||
drop.show();
|
drop.show();
|
||||||
|
|
||||||
|
drop.on('dragleave', function(ev) {
|
||||||
|
drop.hide();
|
||||||
|
drop.off('dragleave');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function cancel(e) {
|
function cancel(e) {
|
||||||
@@ -64,19 +89,18 @@ define(['taskbar'], function(taskbar) {
|
|||||||
|
|
||||||
drop.on('drop', function(e) {
|
drop.on('drop', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var uuid = drop.parents('[data-uuid]').attr('data-uuid');
|
var uuid = drop.parents('[data-uuid]').attr('data-uuid'),
|
||||||
var posts = composer.posts[uuid];
|
dt = e.dataTransfer,
|
||||||
|
files = dt.files;
|
||||||
var dt = e.dataTransfer;
|
|
||||||
var files = dt.files;
|
|
||||||
|
|
||||||
for (var i=0; i<files.length; i++) {
|
for (var i=0; i<files.length; i++) {
|
||||||
loadFile(files[i]);
|
loadFile(files[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!files.length)
|
||||||
|
drop.hide();
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,25 +109,22 @@ define(['taskbar'], function(taskbar) {
|
|||||||
var taskbar = document.getElementById('taskbar');
|
var taskbar = document.getElementById('taskbar');
|
||||||
|
|
||||||
composer.postContainer = document.createElement('div');
|
composer.postContainer = document.createElement('div');
|
||||||
composer.postContainer.className = 'post-window row-fluid';
|
composer.postContainer.className = 'post-window row';
|
||||||
composer.postContainer.innerHTML = '<div class="span5">' +
|
composer.postContainer.innerHTML = '<div class="col-md-5">' +
|
||||||
'<input type="text" tabIndex="1" placeholder="Enter your topic title here..." />' +
|
'<input type="text" tabIndex="1" placeholder="Enter your topic title here..." />' +
|
||||||
'<div class="btn-toolbar">' +
|
'<div class="btn-toolbar formatting-bar">' +
|
||||||
'<div class="btn-group formatting-bar">' +
|
'<div class="btn-group">' +
|
||||||
'<span class="btn btn-link" tabindex="-1"><i class="icon-bold"></i></span>' +
|
'<span class="btn btn-link" tabindex="-1"><i class="icon-bold"></i></span>' +
|
||||||
'<span class="btn btn-link" tabindex="-1"><i class="icon-italic"></i></span>' +
|
'<span class="btn btn-link" tabindex="-1"><i class="icon-italic"></i></span>' +
|
||||||
'<span class="btn btn-link" tabindex="-1"><i class="icon-list"></i></span>' +
|
'<span class="btn btn-link" tabindex="-1"><i class="icon-list"></i></span>' +
|
||||||
'<span class="btn btn-link" tabindex="-1"><i class="icon-link"></i></span>' +
|
'<span class="btn btn-link" tabindex="-1"><i class="icon-link"></i></span>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div style="position:relative;">'+
|
|
||||||
'<div id="imagedrop" class=""><div>Drag and Drop Images Here</div></div>'+
|
|
||||||
'<textarea tabIndex="2"></textarea>' +
|
'<textarea tabIndex="2"></textarea>' +
|
||||||
'<div id="imagelist"></div>'+
|
'<div class="imagedrop"><div>Drag and Drop Images Here</div></div>'+
|
||||||
'</div>'+
|
'<div class="btn-toolbar action-bar">' +
|
||||||
'<div class="btn-toolbar">' +
|
'<div class="btn-group" style="float: right; margin-right: -8px">' +
|
||||||
'<div class="btn-group action-bar" style="float: right; margin-right: -8px">' +
|
'<button data-action="minimize" class="btn hidden-xs" tabIndex="4"><i class="icon-download-alt"></i> Minimize</button>' +
|
||||||
'<button data-action="minimize" class="btn hidden-phone" tabIndex="4"><i class="icon-download-alt"></i> Minimize</button>' +
|
|
||||||
'<button class="btn" data-action="discard" tabIndex="5"><i class="icon-remove"></i> Discard</button>' +
|
'<button class="btn" data-action="discard" tabIndex="5"><i class="icon-remove"></i> Discard</button>' +
|
||||||
'<button data-action="post" class="btn" tabIndex="3"><i class="icon-ok"></i> Submit</button>' +
|
'<button data-action="post" class="btn" tabIndex="3"><i class="icon-ok"></i> Submit</button>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
@@ -112,6 +133,7 @@ define(['taskbar'], function(taskbar) {
|
|||||||
|
|
||||||
document.body.insertBefore(composer.postContainer, taskbar);
|
document.body.insertBefore(composer.postContainer, taskbar);
|
||||||
|
|
||||||
|
if(config.imgurClientIDSet)
|
||||||
initializeFileReader();
|
initializeFileReader();
|
||||||
|
|
||||||
socket.on('api:composer.push', function(threadData) {
|
socket.on('api:composer.push', function(threadData) {
|
||||||
@@ -128,13 +150,12 @@ define(['taskbar'], function(taskbar) {
|
|||||||
cid: threadData.cid,
|
cid: threadData.cid,
|
||||||
pid: threadData.pid,
|
pid: threadData.pid,
|
||||||
title: threadData.title || '',
|
title: threadData.title || '',
|
||||||
body: threadData.body || '',
|
body: threadData.body || ''
|
||||||
images: []
|
|
||||||
};
|
};
|
||||||
composer.load(uuid);
|
composer.load(uuid);
|
||||||
} else {
|
} else {
|
||||||
app.alert({
|
app.alert({
|
||||||
type: 'error',
|
type: 'danger',
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
alert_id: 'post_error',
|
alert_id: 'post_error',
|
||||||
title: 'Please Log In to Post',
|
title: 'Please Log In to Post',
|
||||||
@@ -152,21 +173,32 @@ define(['taskbar'], function(taskbar) {
|
|||||||
|
|
||||||
// Post Window events
|
// Post Window events
|
||||||
var jPostContainer = $(composer.postContainer),
|
var jPostContainer = $(composer.postContainer),
|
||||||
postContentEl = composer.postContainer.querySelector('textarea')
|
postContentEl = composer.postContainer.querySelector('textarea');
|
||||||
|
|
||||||
jPostContainer.on('change', 'input, textarea', function() {
|
jPostContainer.on('change', 'input, textarea', function() {
|
||||||
var uuid = $(this).parents('.post-window')[0].getAttribute('data-uuid');
|
var uuid = $(this).parents('.post-window')[0].getAttribute('data-uuid');
|
||||||
if (this.nodeName === 'INPUT') composer.posts[uuid].title = this.value;
|
if (this.nodeName === 'INPUT') composer.posts[uuid].title = this.value;
|
||||||
else if (this.nodeName === 'TEXTAREA') composer.posts[uuid].body = this.value;
|
else if (this.nodeName === 'TEXTAREA') composer.posts[uuid].body = this.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
jPostContainer.on('click', '.action-bar button', function() {
|
jPostContainer.on('click', '.action-bar button', function() {
|
||||||
var action = this.getAttribute('data-action'),
|
var action = this.getAttribute('data-action'),
|
||||||
uuid = $(this).parents('.post-window').attr('data-uuid');
|
uuid = $(this).parents('.post-window').attr('data-uuid');
|
||||||
switch(action) {
|
switch(action) {
|
||||||
case 'post': composer.post(uuid); break;
|
case 'post': composer.post(uuid); break;
|
||||||
case 'minimize': composer.minimize(uuid); break;
|
case 'minimize': composer.minimize(uuid); break;
|
||||||
case 'discard': composer.discard(uuid); break;
|
case 'discard':
|
||||||
|
if (postContentEl.value.length > 0) {
|
||||||
|
bootbox.confirm('Are you sure you wish to discard this post?', function(discard) {
|
||||||
|
if (discard) composer.discard(uuid);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
composer.discard(uuid);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
jPostContainer.on('click', '.formatting-bar span', function() {
|
jPostContainer.on('click', '.formatting-bar span', function() {
|
||||||
var iconClass = this.querySelector('i').className,
|
var iconClass = this.querySelector('i').className,
|
||||||
cursorEnd = postContentEl.value.length,
|
cursorEnd = postContentEl.value.length,
|
||||||
@@ -242,12 +274,7 @@ define(['taskbar'], function(taskbar) {
|
|||||||
composer.load = function(post_uuid) {
|
composer.load = function(post_uuid) {
|
||||||
var post_data = composer.posts[post_uuid],
|
var post_data = composer.posts[post_uuid],
|
||||||
titleEl = composer.postContainer.querySelector('input'),
|
titleEl = composer.postContainer.querySelector('input'),
|
||||||
bodyEl = composer.postContainer.querySelector('textarea'),
|
bodyEl = composer.postContainer.querySelector('textarea');
|
||||||
dropDiv = $(composer.postContainer).find('#imagedrop'),
|
|
||||||
imagelist = $(composer.postContainer).find('#imagelist');
|
|
||||||
|
|
||||||
dropDiv.hide();
|
|
||||||
imagelist.empty();
|
|
||||||
|
|
||||||
composer.reposition(post_uuid);
|
composer.reposition(post_uuid);
|
||||||
composer.active = post_uuid;
|
composer.active = post_uuid;
|
||||||
@@ -264,7 +291,8 @@ define(['taskbar'], function(taskbar) {
|
|||||||
titleEl.value = post_data.title;
|
titleEl.value = post_data.title;
|
||||||
titleEl.readOnly = false;
|
titleEl.readOnly = false;
|
||||||
}
|
}
|
||||||
bodyEl.value = post_data.body
|
bodyEl.value = post_data.body;
|
||||||
|
|
||||||
|
|
||||||
// Direct user focus to the correct element
|
// Direct user focus to the correct element
|
||||||
if ((parseInt(post_data.tid) || parseInt(post_data.pid)) > 0) {
|
if ((parseInt(post_data.tid) || parseInt(post_data.pid)) > 0) {
|
||||||
@@ -277,7 +305,7 @@ define(['taskbar'], function(taskbar) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
composer.reposition = function(post_uuid) {
|
composer.reposition = function(post_uuid) {
|
||||||
var postWindowEl = composer.postContainer.querySelector('.span5'),
|
var postWindowEl = composer.postContainer.querySelector('.col-md-5'),
|
||||||
taskbarBtn = document.querySelector('#taskbar [data-uuid="' + post_uuid + '"]'),
|
taskbarBtn = document.querySelector('#taskbar [data-uuid="' + post_uuid + '"]'),
|
||||||
btnRect = taskbarBtn.getBoundingClientRect(),
|
btnRect = taskbarBtn.getBoundingClientRect(),
|
||||||
taskbarRect = document.getElementById('taskbar').getBoundingClientRect(),
|
taskbarRect = document.getElementById('taskbar').getBoundingClientRect(),
|
||||||
@@ -299,9 +327,19 @@ define(['taskbar'], function(taskbar) {
|
|||||||
titleEl.value = titleEl.value.trim();
|
titleEl.value = titleEl.value.trim();
|
||||||
bodyEl.value = bodyEl.value.trim();
|
bodyEl.value = bodyEl.value.trim();
|
||||||
|
|
||||||
|
if(uploadsInProgress.length) {
|
||||||
|
return app.alert({
|
||||||
|
type: 'warning',
|
||||||
|
timeout: 2000,
|
||||||
|
title: 'Still uploading',
|
||||||
|
message: "Please wait for uploads to complete.",
|
||||||
|
alert_id: 'post_error'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (titleEl.value.length < config.minimumTitleLength) {
|
if (titleEl.value.length < config.minimumTitleLength) {
|
||||||
return app.alert({
|
return app.alert({
|
||||||
type: 'error',
|
type: 'danger',
|
||||||
timeout: 2000,
|
timeout: 2000,
|
||||||
title: 'Title too short',
|
title: 'Title too short',
|
||||||
message: "Please enter a longer title. At least " + config.minimumTitleLength+ " characters.",
|
message: "Please enter a longer title. At least " + config.minimumTitleLength+ " characters.",
|
||||||
@@ -311,7 +349,7 @@ define(['taskbar'], function(taskbar) {
|
|||||||
|
|
||||||
if (bodyEl.value.length < config.minimumPostLength) {
|
if (bodyEl.value.length < config.minimumPostLength) {
|
||||||
return app.alert({
|
return app.alert({
|
||||||
type: 'error',
|
type: 'danger',
|
||||||
timeout: 2000,
|
timeout: 2000,
|
||||||
title: 'Content too short',
|
title: 'Content too short',
|
||||||
message: "Please enter a longer post. At least " + config.minimumPostLength + " characters.",
|
message: "Please enter a longer post. At least " + config.minimumPostLength + " characters.",
|
||||||
@@ -324,21 +362,18 @@ define(['taskbar'], function(taskbar) {
|
|||||||
socket.emit('api:topics.post', {
|
socket.emit('api:topics.post', {
|
||||||
'title' : titleEl.value,
|
'title' : titleEl.value,
|
||||||
'content' : bodyEl.value,
|
'content' : bodyEl.value,
|
||||||
'category_id' : postData.cid,
|
'category_id' : postData.cid
|
||||||
images: composer.posts[post_uuid].images
|
|
||||||
});
|
});
|
||||||
} else if (parseInt(postData.tid) > 0) {
|
} else if (parseInt(postData.tid) > 0) {
|
||||||
socket.emit('api:posts.reply', {
|
socket.emit('api:posts.reply', {
|
||||||
'topic_id' : postData.tid,
|
'topic_id' : postData.tid,
|
||||||
'content' : bodyEl.value,
|
'content' : bodyEl.value
|
||||||
images: composer.posts[post_uuid].images
|
|
||||||
});
|
});
|
||||||
} else if (parseInt(postData.pid) > 0) {
|
} else if (parseInt(postData.pid) > 0) {
|
||||||
socket.emit('api:posts.edit', {
|
socket.emit('api:posts.edit', {
|
||||||
pid: postData.pid,
|
pid: postData.pid,
|
||||||
content: bodyEl.value,
|
content: bodyEl.value,
|
||||||
title: titleEl.value,
|
title: titleEl.value
|
||||||
images: composer.posts[post_uuid].images
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,7 +382,7 @@ define(['taskbar'], function(taskbar) {
|
|||||||
|
|
||||||
composer.discard = function(post_uuid) {
|
composer.discard = function(post_uuid) {
|
||||||
if (composer.posts[post_uuid]) {
|
if (composer.posts[post_uuid]) {
|
||||||
$(composer.postContainer).find('#imagedrop').html('');
|
$(composer.postContainer).find('.imagedrop').hide();
|
||||||
delete composer.posts[post_uuid];
|
delete composer.posts[post_uuid];
|
||||||
composer.minimize();
|
composer.minimize();
|
||||||
taskbar.discard('composer', post_uuid);
|
taskbar.discard('composer', post_uuid);
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ define(function() {
|
|||||||
|
|
||||||
|
|
||||||
mobileMenu.init = function() {
|
mobileMenu.init = function() {
|
||||||
|
return; // disabling until this can be pluginified.
|
||||||
overlay = overlay || document.getElementById('mobile-menu-overlay');
|
overlay = overlay || document.getElementById('mobile-menu-overlay');
|
||||||
menuBtn = menuBtn || document.getElementById('mobile-menu-btn');
|
menuBtn = menuBtn || document.getElementById('mobile-menu-btn');
|
||||||
postBtn = postBtn || document.getElementById('mobile-post-btn');
|
postBtn = postBtn || document.getElementById('mobile-post-btn');
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ define(function() {
|
|||||||
|
|
||||||
taskbar.taskbar = document.createElement('div');
|
taskbar.taskbar = document.createElement('div');
|
||||||
var jTaskbar = $(taskbar.taskbar);
|
var jTaskbar = $(taskbar.taskbar);
|
||||||
taskbar.taskbar.innerHTML = '<div class="navbar-inner"><ul class="nav pull-right"></ul></div>';
|
taskbar.taskbar.innerHTML = '<div class="navbar-inner"><ul class="nav navbar-nav pull-right"></ul></div>';
|
||||||
taskbar.taskbar.className = 'taskbar navbar navbar-fixed-bottom';
|
taskbar.taskbar.className = 'taskbar navbar navbar-default navbar-fixed-bottom';
|
||||||
taskbar.taskbar.id = 'taskbar';
|
taskbar.taskbar.id = 'taskbar';
|
||||||
|
|
||||||
taskbar.tasklist = taskbar.taskbar.querySelector('ul');
|
taskbar.tasklist = taskbar.taskbar.querySelector('ul');
|
||||||
document.body.insertBefore(taskbar.taskbar, footerEl);
|
document.body.insertBefore(taskbar.taskbar, footerEl.nextSibling);
|
||||||
|
|
||||||
// Posts bar events
|
// Posts bar events
|
||||||
jTaskbar.on('click', 'li', function() {
|
jTaskbar.on('click', 'li', function() {
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
(function (module) {
|
(function (module) {
|
||||||
|
|
||||||
var config = {},
|
var config = {},
|
||||||
@@ -14,11 +12,11 @@
|
|||||||
fs = require('fs');
|
fs = require('fs');
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
templates.force_refresh = function(tpl) {
|
templates.force_refresh = function (tpl) {
|
||||||
return !!config.force_refresh[tpl];
|
return !!config.force_refresh[tpl];
|
||||||
}
|
}
|
||||||
|
|
||||||
templates.get_custom_map = function(tpl) {
|
templates.get_custom_map = function (tpl) {
|
||||||
if (config['custom_mapping'] && tpl) {
|
if (config['custom_mapping'] && tpl) {
|
||||||
for (var pattern in config['custom_mapping']) {
|
for (var pattern in config['custom_mapping']) {
|
||||||
if (tpl.match(pattern)) {
|
if (tpl.match(pattern)) {
|
||||||
@@ -30,11 +28,11 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
templates.is_available = function(tpl) {
|
templates.is_available = function (tpl) {
|
||||||
return jQuery.inArray(tpl, available_templates) !== -1;
|
return jQuery.inArray(tpl, available_templates) !== -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
templates.ready = function(callback) {
|
templates.ready = function (callback) {
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
if (this.ready_callback) {
|
if (this.ready_callback) {
|
||||||
this.ready_callback();
|
this.ready_callback();
|
||||||
@@ -50,7 +48,7 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
templates.prepare = function(raw_tpl, data) {
|
templates.prepare = function (raw_tpl, data) {
|
||||||
var template = {};
|
var template = {};
|
||||||
template.html = raw_tpl;
|
template.html = raw_tpl;
|
||||||
template.parse = parse;
|
template.parse = parse;
|
||||||
@@ -64,10 +62,10 @@
|
|||||||
var loaded = templatesToLoad.length;
|
var loaded = templatesToLoad.length;
|
||||||
|
|
||||||
for (var t in templatesToLoad) {
|
for (var t in templatesToLoad) {
|
||||||
(function(file) {
|
(function (file) {
|
||||||
fs.readFile(global.configuration.ROOT_DIRECTORY + '/public/templates/' + file + '.tpl', function(err, html) {
|
fs.readFile(__dirname + '/../templates/' + file + '.tpl', function (err, html) {
|
||||||
var template = function() {
|
var template = function () {
|
||||||
this.toString = function() {
|
this.toString = function () {
|
||||||
return this.html;
|
return this.html;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -86,12 +84,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadClient() {
|
function loadClient() {
|
||||||
jQuery.when(jQuery.getJSON(RELATIVE_PATH + '/templates/config.json'), jQuery.getJSON(RELATIVE_PATH + '/api/get_templates_listing')).done(function(config_data, templates_data) {
|
jQuery.when(jQuery.getJSON(RELATIVE_PATH + '/templates/config.json'), jQuery.getJSON(RELATIVE_PATH + '/api/get_templates_listing')).done(function (config_data, templates_data) {
|
||||||
config = config_data[0];
|
config = config_data[0];
|
||||||
available_templates = templates_data[0];
|
available_templates = templates_data[0];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
templates.ready();
|
templates.ready();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -101,14 +96,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
templates.init = function(templates_to_load) {
|
templates.init = function (templates_to_load) {
|
||||||
loadTemplates(templates_to_load || []);
|
loadTemplates(templates_to_load || []);
|
||||||
}
|
}
|
||||||
|
|
||||||
templates.getTemplateNameFromUrl = function(url) {
|
templates.getTemplateNameFromUrl = function (url) {
|
||||||
var parts = url.split('?')[0].split('/');
|
var parts = url.split('?')[0].split('/');
|
||||||
|
|
||||||
for(var i=0; i<parts.length; ++i) {
|
for (var i = 0; i < parts.length; ++i) {
|
||||||
if (templates.is_available(parts[i])) {
|
if (templates.is_available(parts[i])) {
|
||||||
return parts[i];
|
return parts[i];
|
||||||
}
|
}
|
||||||
@@ -117,30 +112,24 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
templates.load_template = function(callback, url, template) {
|
templates.load_template = function (callback, url, template) {
|
||||||
var location = document.location || window.location,
|
var location = document.location || window.location,
|
||||||
rootUrl = location.protocol + '//' + (location.hostname || location.host) + (location.port ? ':' + location.port : '');
|
api_url = (url === '' || url === '/') ? 'home' : url,
|
||||||
|
tpl_url = templates.get_custom_map(api_url.split('?')[0]),
|
||||||
|
trimmed = api_url;
|
||||||
|
|
||||||
var api_url = (url === '' || url === '/') ? 'home' : url;
|
if (!tpl_url) {
|
||||||
|
|
||||||
var tpl_url = templates.get_custom_map(api_url.split('?')[0]);
|
|
||||||
|
|
||||||
var trimmed = api_url;
|
|
||||||
|
|
||||||
if(!tpl_url) {
|
|
||||||
tpl_url = templates.getTemplateNameFromUrl(api_url);
|
tpl_url = templates.getTemplateNameFromUrl(api_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
var template_data = null;
|
var template_data = null;
|
||||||
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
var timestamp = new Date().getTime(); //debug
|
var timestamp = new Date().getTime(); //debug
|
||||||
|
|
||||||
if (!templates[tpl_url]) {
|
if (!templates[tpl_url]) {
|
||||||
jQuery.get(RELATIVE_PATH + '/templates/' + tpl_url + '.tpl?v=' + timestamp, function(html) {
|
jQuery.get(RELATIVE_PATH + '/templates/' + tpl_url + '.tpl?v=' + timestamp, function (html) {
|
||||||
var template = function() {
|
var template = function () {
|
||||||
this.toString = function() {
|
this.toString = function () {
|
||||||
return this.html;
|
return this.html;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -157,40 +146,34 @@
|
|||||||
parse_template();
|
parse_template();
|
||||||
}
|
}
|
||||||
|
|
||||||
}());
|
jQuery.get(RELATIVE_PATH + '/api/' + api_url, function (data) {
|
||||||
|
|
||||||
(function() {
|
if (!data) {
|
||||||
|
|
||||||
jQuery.get(API_URL + api_url, function(data) {
|
|
||||||
|
|
||||||
if(!data) {
|
|
||||||
ajaxify.go('404');
|
ajaxify.go('404');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
template_data = data;
|
template_data = data;
|
||||||
parse_template();
|
parse_template();
|
||||||
}).fail(function(data) {
|
}).fail(function (data) {
|
||||||
template_data = {};
|
app.alertError("Can't load template data!");
|
||||||
parse_template();
|
|
||||||
});
|
});
|
||||||
}());
|
|
||||||
|
|
||||||
|
|
||||||
function parse_template() {
|
function parse_template() {
|
||||||
if (!templates[tpl_url] || !template_data) return;
|
if (!templates[tpl_url] || !template_data) return;
|
||||||
|
|
||||||
if(typeof global !== "undefined")
|
if (typeof global !== "undefined")
|
||||||
template_data['relative_path'] = global.nconf.get('relative_path');
|
template_data['relative_path'] = nconf.get('relative_path');
|
||||||
else
|
else
|
||||||
template_data['relative_path'] = RELATIVE_PATH;
|
template_data['relative_path'] = RELATIVE_PATH;
|
||||||
|
|
||||||
document.getElementById('content').innerHTML = templates[tpl_url].parse(template_data);
|
translator.translate(templates[tpl_url].parse(template_data), function (translatedTemplate) {
|
||||||
|
document.getElementById('content').innerHTML = translatedTemplate;
|
||||||
|
|
||||||
jQuery('#content [template-variable]').each(function(index, element) {
|
jQuery('#content [template-variable]').each(function (index, element) {
|
||||||
var value = null;
|
var value = null;
|
||||||
|
|
||||||
switch(element.getAttribute('template-type')) {
|
switch (element.getAttribute('template-type')) {
|
||||||
case 'boolean':
|
case 'boolean':
|
||||||
value = (element.value === 'true' || element.value === '1') ? true : false;
|
value = (element.value === 'true' || element.value === '1') ? true : false;
|
||||||
break;
|
break;
|
||||||
@@ -209,24 +192,25 @@
|
|||||||
if (callback) {
|
if (callback) {
|
||||||
callback(true);
|
callback(true);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
templates.flush = function() {
|
templates.flush = function () {
|
||||||
parsed_variables = {};
|
parsed_variables = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
templates.get = function(key) {
|
templates.get = function (key) {
|
||||||
return parsed_variables[key];
|
return parsed_variables[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
templates.set = function(key, value) {
|
templates.set = function (key, value) {
|
||||||
parsed_variables[key] = value;
|
parsed_variables[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
//modified from https://github.com/psychobunny/dcp.templates
|
//modified from https://github.com/psychobunny/dcp.templates
|
||||||
var parse = function(data) {
|
var parse = function (data) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
function replace(key, value, template) {
|
function replace(key, value, template) {
|
||||||
@@ -235,7 +219,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function makeRegex(block) {
|
function makeRegex(block) {
|
||||||
return new RegExp("<!-- BEGIN " + block + " -->[^]*<!-- END " + block + " -->", 'g');
|
return new RegExp("<!-- BEGIN " + block + " -->[\\s\\S]*<!-- END " + block + " -->", 'g');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBlock(regex, block, template) {
|
function getBlock(regex, block, template) {
|
||||||
@@ -255,7 +239,8 @@
|
|||||||
return template.replace(regex, block);
|
return template.replace(regex, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
var template = this.html, regex, block;
|
var template = this.html,
|
||||||
|
regex, block;
|
||||||
|
|
||||||
return (function parse(data, namespace, template) {
|
return (function parse(data, namespace, template) {
|
||||||
if (!data || data.length == 0) {
|
if (!data || data.length == 0) {
|
||||||
@@ -270,14 +255,16 @@
|
|||||||
namespace += d + '.';
|
namespace += d + '.';
|
||||||
|
|
||||||
var regex = makeRegex(d),
|
var regex = makeRegex(d),
|
||||||
block = getBlock(regex, namespace.substring(0, namespace.length-1), template);
|
block = getBlock(regex, namespace.substring(0, namespace.length - 1), template);
|
||||||
|
|
||||||
if (block == null) {
|
if (block == null) {
|
||||||
namespace = namespace.replace(d + '.', '');
|
namespace = namespace.replace(d + '.', '');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var numblocks = data[d].length - 1, i = 0, result = "";
|
var numblocks = data[d].length - 1,
|
||||||
|
i = 0,
|
||||||
|
result = "";
|
||||||
|
|
||||||
do {
|
do {
|
||||||
result += parse(data[d][i], namespace, block);
|
result += parse(data[d][i], namespace, block);
|
||||||
@@ -301,7 +288,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
var regex = new RegExp("{" + namespace + "[^]*?}", 'g');
|
var regex = new RegExp("{" + namespace + "[\\s\\S]*?}", 'g');
|
||||||
template = template.replace(regex, '');
|
template = template.replace(regex, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,7 +302,8 @@
|
|||||||
templates.init();
|
templates.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
})('undefined' === typeof module ? {module:{exports:{}}} : module)
|
})('undefined' === typeof module ? {
|
||||||
|
module: {
|
||||||
|
exports: {}
|
||||||
|
}
|
||||||
|
} : module)
|
||||||
165
public/src/translator.js
Normal file
165
public/src/translator.js
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
(function (module) {
|
||||||
|
"use strict";
|
||||||
|
/*global RELATIVE_PATH*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO:
|
||||||
|
*
|
||||||
|
* 1. language en is hardcoded while system is developed. to switch language packs for now please edit DEFAULT_LANGUAGE
|
||||||
|
* b. need to write fallback system to default language if keys are missing (is this even necessary?)
|
||||||
|
* 2. recursion needed when parsing language keys (ex. topics:modal.delete.title), right now json is all one level deep
|
||||||
|
* 3. server side settings for default language
|
||||||
|
* 4. user side settings for preferred language
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
var DEFAULT_LANGUAGE = 'en';
|
||||||
|
|
||||||
|
var translator = {},
|
||||||
|
files = {
|
||||||
|
loaded: {},
|
||||||
|
loading: {},
|
||||||
|
callbacks: {} // could be combined with "loading" in future.
|
||||||
|
},
|
||||||
|
isServer = false;
|
||||||
|
|
||||||
|
module.exports = translator;
|
||||||
|
|
||||||
|
translator.get = function (key, callback) {
|
||||||
|
var parsedKey = key.split(':'),
|
||||||
|
languageFile = parsedKey[0];
|
||||||
|
|
||||||
|
parsedKey = parsedKey[1];
|
||||||
|
translator.load(languageFile, function (languageData) {
|
||||||
|
if (callback) {
|
||||||
|
callback(languageData[parsedKey]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return languageData[parsedKey];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Not fully converted to server side yet, ideally server should be able to parse whole templates on demand if necessary
|
||||||
|
* fix: translator.load should determine if server side and immediately return appropriate language file.
|
||||||
|
*/
|
||||||
|
translator.translate = function (data, callback) {
|
||||||
|
var keys = data.match(/\[\[.*?\]\]/g),
|
||||||
|
loading = 0;
|
||||||
|
|
||||||
|
function insertLanguage(text, key, value, variables) {
|
||||||
|
if (value) {
|
||||||
|
for (var i = 1, ii = variables.length; i < ii; i++) {
|
||||||
|
var variable = variables[i].replace(']]', '');
|
||||||
|
value = value.replace('%' + i, variable);
|
||||||
|
}
|
||||||
|
|
||||||
|
text = text.replace(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var key in keys) {
|
||||||
|
if (keys.hasOwnProperty(key)) {
|
||||||
|
var variables = keys[key].split(/[,][?\s+]/);
|
||||||
|
|
||||||
|
var parsedKey = keys[key].replace('[[', '').replace(']]', '').split(':'),
|
||||||
|
languageFile = parsedKey[0];
|
||||||
|
|
||||||
|
parsedKey = parsedKey[1].split(',')[0];
|
||||||
|
|
||||||
|
if (files.loaded[languageFile]) {
|
||||||
|
data = insertLanguage(data, keys[key], files.loaded[languageFile][parsedKey], variables);
|
||||||
|
} else {
|
||||||
|
loading++;
|
||||||
|
|
||||||
|
(function (languageKey, parsedKey) {
|
||||||
|
translator.load(languageFile, function (languageData) {
|
||||||
|
data = insertLanguage(data, languageKey, languageData[parsedKey], variables);
|
||||||
|
loading--;
|
||||||
|
checkComplete();
|
||||||
|
});
|
||||||
|
}(keys[key], parsedKey));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkComplete();
|
||||||
|
|
||||||
|
function checkComplete() {
|
||||||
|
if (loading === 0) {
|
||||||
|
callback(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
translator.load = function (filename, callback) {
|
||||||
|
if (isServer === true) {
|
||||||
|
if (callback) {
|
||||||
|
callback(files.loaded[filename]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return files.loaded[filename];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (files.loaded[filename] && !files.loading[filename]) {
|
||||||
|
if (callback) {
|
||||||
|
callback(files.loaded[filename]);
|
||||||
|
}
|
||||||
|
} else if (files.loading[filename]) {
|
||||||
|
if (callback) {
|
||||||
|
files.callbacks[filename] = files.callbacks[filename] || [];
|
||||||
|
files.callbacks[filename].push(callback);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var timestamp = new Date().getTime(); //debug
|
||||||
|
|
||||||
|
files.loading[filename] = true;
|
||||||
|
|
||||||
|
jQuery.getJSON(RELATIVE_PATH + '/language/' + DEFAULT_LANGUAGE + '/' + filename + '.json?v=' + timestamp, function (language) {
|
||||||
|
files.loaded[filename] = language;
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
callback(language);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (files.callbacks[filename] && files.callbacks[filename].length) {
|
||||||
|
files.callbacks[filename].pop()(language);
|
||||||
|
}
|
||||||
|
|
||||||
|
files.loading[filename] = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
translator.loadServer = function () {
|
||||||
|
isServer = true;
|
||||||
|
|
||||||
|
var utils = require('./utils.js'),
|
||||||
|
path = require('path'),
|
||||||
|
fs = require('fs');
|
||||||
|
|
||||||
|
utils.walk(path.join(__dirname, '../../', 'public/language/' + DEFAULT_LANGUAGE), function (err, data) {
|
||||||
|
var loaded = data.length;
|
||||||
|
|
||||||
|
for (var d in data) {
|
||||||
|
if (data.hasOwnProperty(d)) {
|
||||||
|
files.loaded[path.basename(data[d]).replace('.json', '')] = require(data[d]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if ('undefined' !== typeof window) {
|
||||||
|
window.translator = module.exports;
|
||||||
|
}
|
||||||
|
|
||||||
|
})('undefined' === typeof module ? {
|
||||||
|
module: {
|
||||||
|
exports: {}
|
||||||
|
}
|
||||||
|
} : module);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
(function (module) {
|
(function(module) {
|
||||||
|
|
||||||
var utils, fs;
|
var utils, fs;
|
||||||
|
|
||||||
@@ -10,15 +10,18 @@
|
|||||||
module.exports = utils = {
|
module.exports = utils = {
|
||||||
generateUUID: function() {
|
generateUUID: function() {
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||||
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
|
var r = Math.random() * 16 | 0,
|
||||||
|
v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||||
return v.toString(16);
|
return v.toString(16);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
//Adapted from http://stackoverflow.com/questions/5827612/node-js-fs-readdir-recursive-directory-search
|
//Adapted from http://stackoverflow.com/questions/5827612/node-js-fs-readdir-recursive-directory-search
|
||||||
walk: function(dir, done) {
|
walk: function(dir, done) {
|
||||||
var main_dir = global.configuration.ROOT_DIRECTORY + '/public/templates/';
|
var results = [],
|
||||||
var results = [];
|
path = require('path'),
|
||||||
|
main_dir = path.join(__dirname, '..', 'templates');
|
||||||
|
|
||||||
fs.readdir(dir, function(err, list) {
|
fs.readdir(dir, function(err, list) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
var pending = list.length;
|
var pending = list.length;
|
||||||
@@ -32,7 +35,7 @@
|
|||||||
if (!--pending) done(null, results);
|
if (!--pending) done(null, results);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
results.push(file.replace(main_dir, '').replace('.tpl', ''));
|
results.push(file.replace(main_dir + '/', '').replace('.tpl', ''));
|
||||||
if (!--pending) done(null, results);
|
if (!--pending) done(null, results);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -72,7 +75,7 @@
|
|||||||
// remove accents, swap ñ for n, etc
|
// remove accents, swap ñ for n, etc
|
||||||
var from = "àáäâèéëêìíïîıòóöôùúüûñçşğ·/_,:;";
|
var from = "àáäâèéëêìíïîıòóöôùúüûñçşğ·/_,:;";
|
||||||
var to = "aaaaeeeeiiiiioooouuuuncsg------";
|
var to = "aaaaeeeeiiiiioooouuuuncsg------";
|
||||||
for (var i=0, l=from.length ; i<l ; i++) {
|
for (var i = 0, l = from.length; i < l; i++) {
|
||||||
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
|
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,11 +94,11 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
isUserNameValid: function(name) {
|
isUserNameValid: function(name) {
|
||||||
return (name && name !== "" && (/^[a-zA-Z0-9 _-]{3,14}$/.test(name)));
|
return (name && name !== "" && (/^[a-zA-Z0-9 _-]+$/.test(name)));
|
||||||
},
|
},
|
||||||
|
|
||||||
isPasswordValid: function(password) {
|
isPasswordValid: function(password) {
|
||||||
return password && password.indexOf(' ') === -1 && password.length > 5;
|
return password && password.indexOf(' ') === -1;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Blatently stolen from: http://phpjs.org/functions/strip_tags/
|
// Blatently stolen from: http://phpjs.org/functions/strip_tags/
|
||||||
@@ -104,7 +107,7 @@
|
|||||||
var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
|
var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
|
||||||
commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
|
commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
|
||||||
|
|
||||||
return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) {
|
return input.replace(commentsAndPhpTags, '').replace(tags, function($0, $1) {
|
||||||
return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
|
return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -112,10 +115,10 @@
|
|||||||
buildMetaTags: function(tagsArr) {
|
buildMetaTags: function(tagsArr) {
|
||||||
var tags = '',
|
var tags = '',
|
||||||
tag;
|
tag;
|
||||||
for(var x=0,numTags=tagsArr.length;x<numTags;x++) {
|
for (var x = 0, numTags = tagsArr.length; x < numTags; x++) {
|
||||||
if (tags.length > 0) tags += "\n\t";
|
if (tags.length > 0) tags += "\n\t";
|
||||||
tag = '<meta';
|
tag = '<meta';
|
||||||
for(y in tagsArr[x]) {
|
for (y in tagsArr[x]) {
|
||||||
tag += ' ' + y + '="' + tagsArr[x][y] + '"';
|
tag += ' ' + y + '="' + tagsArr[x][y] + '"';
|
||||||
}
|
}
|
||||||
tag += ' />';
|
tag += ' />';
|
||||||
@@ -126,31 +129,65 @@
|
|||||||
return tags;
|
return tags;
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshTitle: function() {
|
refreshTitle: function(url) {
|
||||||
|
if (!url) {
|
||||||
var a = document.createElement('a');
|
var a = document.createElement('a');
|
||||||
|
|
||||||
a.href = document.location;
|
a.href = document.location;
|
||||||
socket.emit('api:meta.buildTitle', a.pathname.slice(1), function(title) {
|
url = a.pathname.slice(1);
|
||||||
document.title = title;
|
}
|
||||||
|
var notificationIcon;
|
||||||
|
|
||||||
|
socket.emit('api:meta.buildTitle', url, function(title, numNotifications) {
|
||||||
|
document.title = (numNotifications > 0 ? '(' + numNotifications + ') ' : '') + title;
|
||||||
|
notificationIcon = notificationIcon || document.querySelector('.notifications a i');
|
||||||
|
if (numNotifications > 0 && notificationIcon) notificationIcon.className = 'icon-circle active';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
jQuery.getJSON(RELATIVE_PATH + '/api/unread/total', function(data) {
|
||||||
|
var badge = jQuery('#numUnreadBadge');
|
||||||
|
badge.html(data.count > 20 ? '20+' : data.count);
|
||||||
|
|
||||||
|
if (data.count > 0) {
|
||||||
|
badge
|
||||||
|
.removeClass('badge-inverse')
|
||||||
|
.addClass('badge-important')
|
||||||
|
} else {
|
||||||
|
badge
|
||||||
|
.removeClass('badge-important')
|
||||||
|
.addClass('badge-inverse')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
isRelativeUrl: function(url) {
|
||||||
|
var firstChar = url.slice(0, 1);
|
||||||
|
return (firstChar === '.' || firstChar === '/');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!String.prototype.trim) {
|
if (!String.prototype.trim) {
|
||||||
String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g, '');};
|
String.prototype.trim = function() {
|
||||||
|
return this.replace(/^\s+|\s+$/g, '');
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!String.prototype.ltrim) {
|
if (!String.prototype.ltrim) {
|
||||||
String.prototype.ltrim=function(){return this.replace(/^\s+/,'');};
|
String.prototype.ltrim = function() {
|
||||||
|
return this.replace(/^\s+/, '');
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!String.prototype.rtrim) {
|
if (!String.prototype.rtrim) {
|
||||||
String.prototype.rtrim=function(){return this.replace(/\s+$/,'');};
|
String.prototype.rtrim = function() {
|
||||||
|
return this.replace(/\s+$/, '');
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!String.prototype.fulltrim) {
|
if (!String.prototype.fulltrim) {
|
||||||
String.prototype.fulltrim=function(){return this.replace(/(?:(?:^|\n)\s+|\s+(?:$|\n))/g,'').replace(/\s+/g,' ');};
|
String.prototype.fulltrim = function() {
|
||||||
|
return this.replace(/(?:(?:^|\n)\s+|\s+(?:$|\n))/g, '').replace(/\s+/g, ' ');
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -158,4 +195,8 @@
|
|||||||
window.utils = module.exports;
|
window.utils = module.exports;
|
||||||
}
|
}
|
||||||
|
|
||||||
})('undefined' === typeof module ? {module:{exports:{}}} : module)
|
})('undefined' === typeof module ? {
|
||||||
|
module: {
|
||||||
|
exports: {}
|
||||||
|
}
|
||||||
|
} : module)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="alert alert-error">
|
<div class="alert alert-danger">
|
||||||
<strong>Access Denied</strong>
|
<strong>[[global:403.title]]</strong>
|
||||||
<p>You seem to have stumbled upon a page that you do not have access to. Perhaps you should <a href="/login">try logging in?</a></p>
|
<p>[[global:403.message]]</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="alert alert-error">
|
<div class="alert alert-danger">
|
||||||
<strong>Not found</strong>
|
<strong>[[global:404.title]]</strong>
|
||||||
<p>You seem to have stumbled upon a page that does not exist. Return to the <a href="/">home page</a></p>
|
<p>[[global:404.message]]</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,37 +1,30 @@
|
|||||||
|
|
||||||
<div class="well">
|
<div class="well account">
|
||||||
|
|
||||||
|
<div class="account-username-box" data-userslug="{userslug}">
|
||||||
|
|
||||||
<div class="account-username-box">
|
|
||||||
<span class="account-username">
|
<span class="account-username">
|
||||||
<a href="/users/{userslug}">{username}</a>
|
<a href="/user/{userslug}">{username}</a>
|
||||||
</span>
|
</span>
|
||||||
<div class="account-sub-links inline-block pull-right">
|
|
||||||
<span id="settingsLink" class="pull-right"><a href="/users/{userslug}/settings">settings</a></span>
|
|
||||||
<span class="pull-right"><a href="/users/{userslug}/followers">followers</a></span>
|
|
||||||
<span class="pull-right"><a href="/users/{userslug}/following">following</a></span>
|
|
||||||
<span id="editLink" class="pull-right"><a href="/users/{userslug}/edit">edit</a></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
<div class="row-fluid">
|
<div class="col-md-2 account-block" style="text-align: center; margin-bottom:20px;">
|
||||||
<div class="span2" style="text-align: center; margin-bottom:20px;">
|
|
||||||
<div class="account-picture-block">
|
<div class="account-picture-block">
|
||||||
<img src="{picture}" class="user-profile-picture img-polaroid"/>
|
<img src="{picture}" class="user-profile-picture img-thumbnail"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="account-online-status">
|
<div class="account-online-status">
|
||||||
<span><i class="icon-circle-blank"></i> <span>offline</span></span>
|
<span><i class="icon-circle-blank"></i> <span>offline</span></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="{show_banned}">
|
||||||
|
<span class="label label-danger">banned</span>
|
||||||
|
</div>
|
||||||
<div id="user-actions">
|
<div id="user-actions">
|
||||||
<a id="follow-btn" href="#" class="btn hide">Follow</a>
|
<a id="follow-btn" href="#" class="btn btn-default">Follow</a>
|
||||||
<a id="unfollow-btn" href="#" class="btn hide">Unfollow</a>
|
<a id="unfollow-btn" href="#" class="btn btn-default">Unfollow</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="span4">
|
<div class="col-md-4">
|
||||||
<h4>profile</h4>
|
|
||||||
<div class="inline-block">
|
<div class="inline-block">
|
||||||
<div class="account-bio-block">
|
<div class="account-bio-block">
|
||||||
<span class="account-bio-label">email</span><i class="icon-eye-close {emailClass}" title="Email hidden"></i>
|
<span class="account-bio-label">email</span><i class="icon-eye-close {emailClass}" title="Email hidden"></i>
|
||||||
@@ -54,24 +47,28 @@
|
|||||||
<span>{age}</span>
|
<span>{age}</span>
|
||||||
<br/>
|
<br/>
|
||||||
<hr/>
|
<hr/>
|
||||||
<span class="account-bio-label">member for</span>
|
<span class="account-bio-label">joined</span>
|
||||||
<span>{joindate}</span>
|
<span class="timeago" title="{joindate}"></span>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<span class="account-bio-label">profile views</span>
|
||||||
|
<span class="formatted-number">{profileviews}</span>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<span class="account-bio-label">reputation</span>
|
<span class="account-bio-label">reputation</span>
|
||||||
<span id='reputation'>{reputation}</span>
|
<span class="formatted-number">{reputation}</span>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<span class="account-bio-label">posts</span>
|
<span class="account-bio-label">posts</span>
|
||||||
<span id='postcount'>{postcount}</span>
|
<span class="formatted-number">{postcount}</span>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<span class="account-bio-label">followers</span>
|
<span class="account-bio-label">followers</span>
|
||||||
<span>{followerCount}</span>
|
<span class="formatted-number">{followerCount}</span>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<span class="account-bio-label">following</span>
|
<span class="account-bio-label">following</span>
|
||||||
<span>{followingCount}</span>
|
<span class="formatted-number">{followingCount}</span>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
@@ -83,12 +80,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="span6 user-recent-posts">
|
<div class="col-md-6 user-recent-posts">
|
||||||
<h4>recent posts </h4>
|
|
||||||
<!-- BEGIN posts -->
|
<!-- BEGIN posts -->
|
||||||
<div class="topic-row img-polaroid clearfix" topic-url="topic/{posts.tid}/#{posts.pid}">
|
<div class="topic-row img-thumbnail clearfix" topic-url="topic/{posts.tid}/#{posts.pid}">
|
||||||
<span>{posts.content}</span>
|
<span>{posts.content}</span>
|
||||||
<span class="pull-right">{posts.relativeTime} ago</span>
|
<span class="pull-right timeago" title="{posts.relativeTime}"></span>
|
||||||
</div>
|
</div>
|
||||||
<!-- END posts -->
|
<!-- END posts -->
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,132 +1,132 @@
|
|||||||
|
|
||||||
<div class="well">
|
<div class="well">
|
||||||
|
|
||||||
|
<div id="change-picture-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="Change Picture" aria-hidden="true">
|
||||||
<!-- Change Picture Modal -->
|
<div class="modal-dialog">
|
||||||
<div id="change-picture-modal" class="modal hide" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
<h3 id="myModalLabel">Change Picture</h3>
|
<h3 id="myModalLabel">Change Picture</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
|
||||||
<div id="gravatar-box">
|
<div id="gravatar-box">
|
||||||
<img id="user-gravatar-picture" src="" class="img-polaroid user-profile-picture">
|
<img id="user-gravatar-picture" src="" class="img-thumbnail user-profile-picture">
|
||||||
<span class="user-picture-label">Gravatar</span>
|
<span class="user-picture-label">Gravatar</span>
|
||||||
<i class='icon-ok icon-2x'></i>
|
<i class='icon-ok icon-2x'></i>
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
<div id="uploaded-box">
|
<div id="uploaded-box">
|
||||||
<img id="user-uploaded-picture" src="" class="img-polaroid user-profile-picture">
|
<img id="user-uploaded-picture" src="" class="img-thumbnail user-profile-picture">
|
||||||
<span class="user-picture-label">Uploaded picture</span>
|
<span class="user-picture-label">Uploaded picture</span>
|
||||||
<i class='icon-ok icon-2x'></i>
|
<i class='icon-ok icon-2x'></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a id="uploadPictureBtn" href="#">Upload new picture</a>
|
<a id="uploadPictureBtn" href="#">Upload new picture</a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
|
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
|
||||||
<button id="savePictureChangesBtn" class="btn btn-primary">Save changes</button>
|
<button id="savePictureChangesBtn" class="btn btn-primary">Save changes</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div><!-- /.modal-content -->
|
||||||
|
</div><!-- /.modal-dialog -->
|
||||||
|
</div><!-- /.modal -->
|
||||||
|
|
||||||
<!-- Upload picture modal-->
|
<div id="upload-picture-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="Upload Picture" aria-hidden="true">
|
||||||
<div id="upload-picture-modal" class="modal hide" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
<h3 id="myModalLabel">Upload Picture</h3>
|
<h3 id="myModalLabel">Upload Picture</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
<form id="uploadForm" action="{relative_path}/user/uploadpicture" method="post" enctype="multipart/form-data">
|
||||||
<form id="uploadForm" action="{relative_path}/users/uploadpicture" method="post" enctype="multipart/form-data">
|
<div class="form-group">
|
||||||
<input id="userPhotoInput" type="file" name="userPhoto" />
|
<label for="userPhoto">Upload a picture</label>
|
||||||
|
<input type="file" id="userPhotoInput" name="userPhoto">
|
||||||
|
<p class="help-block">You may only upload PNG, JPG, or GIF files under 256kb.</p>
|
||||||
|
</div>
|
||||||
<input id="imageUploadCsrf" type="hidden" name="_csrf" value="" />
|
<input id="imageUploadCsrf" type="hidden" name="_csrf" value="" />
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div id="upload-progress-box" class="progress progress-striped active hide">
|
<div id="upload-progress-box" class="progress progress-striped">
|
||||||
<div id="upload-progress-bar" class="bar" style="width: 0%;"></div>
|
<div id="upload-progress-bar" class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="0" aria-valuemin="0">
|
||||||
|
<span class="sr-only"> success</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="alert-status" class="alert hide"></div>
|
<div id="alert-status" class="alert alert-info hide"></div>
|
||||||
<div id="alert-success" class="alert alert-success hide"></div>
|
<div id="alert-success" class="alert alert-success hide"></div>
|
||||||
<div id="alert-error" class="alert alert-error hide"></div>
|
<div id="alert-error" class="alert alert-danger hide"></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
|
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
|
||||||
<button id="pictureUploadSubmitBtn" class="btn btn-primary">Upload Picture</button>
|
<button id="pictureUploadSubmitBtn" class="btn btn-primary">Upload Picture</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div><!-- /.modal-content -->
|
||||||
|
</div><!-- /.modal-dialog -->
|
||||||
|
</div><!-- /.modal -->
|
||||||
|
|
||||||
<div class="account-username-box">
|
<div class="account-username-box" data-userslug="{userslug}">
|
||||||
<span class="account-username">
|
<span class="account-username">
|
||||||
<a href="/users/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
|
<a href="/user/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
|
||||||
<a href="/users/{userslug}/edit">edit</a>
|
<a href="/user/{userslug}/edit">edit</a>
|
||||||
</span>
|
</span>
|
||||||
<div class="account-sub-links inline-block pull-right">
|
|
||||||
<span id="settingsLink" class="pull-right"><a href="/users/{userslug}/settings">settings</a></span>
|
|
||||||
<span class="pull-right"><a href="/users/{userslug}/followers">followers</a></span>
|
|
||||||
<span class="pull-right"><a href="/users/{userslug}/following">following</a></span>
|
|
||||||
<span id="editLink" class="pull-right"><a href="/users/{userslug}/edit">edit</a></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row-fluid">
|
<div class="row">
|
||||||
<div class="span2" style="text-align: center; margin-bottom:20px;">
|
<div class="col-md-2" style="text-align: center; margin-bottom:20px;">
|
||||||
<div class="account-picture-block text-center">
|
<div class="account-picture-block text-center">
|
||||||
<img id="user-current-picture" class="user-profile-picture img-polaroid" src="{picture}" /><br/>
|
<img id="user-current-picture" class="user-profile-picture img-thumbnail" src="{picture}" /><br /><br />
|
||||||
<a id="changePictureBtn" href="#" class="btn btn-primary">change picture</a>
|
<a id="changePictureBtn" href="#" class="btn btn-primary">change picture</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="span10">
|
<div class="col-md-5">
|
||||||
<div class="inline-block">
|
<div>
|
||||||
<form class='form-horizontal'>
|
<form class='form-horizontal'>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="inputEmail">Email</label>
|
<label class="control-label" for="inputEmail">Email</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" id="inputEmail" placeholder="Email" value="{email}">
|
<input class="form-control" type="text" id="inputEmail" placeholder="Email" value="{email}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="inputFullname">Full Name</label>
|
<label class="control-label" for="inputFullname">Full Name</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" id="inputFullname" placeholder="Full Name" value="{fullname}">
|
<input class="form-control" type="text" id="inputFullname" placeholder="Full Name" value="{fullname}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="inputWebsite">Website</label>
|
<label class="control-label" for="inputWebsite">Website</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" id="inputWebsite" placeholder="http://website.com" value="{website}">
|
<input class="form-control" type="text" id="inputWebsite" placeholder="http://website.com" value="{website}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="inputLocation">Location</label>
|
<label class="control-label" for="inputLocation">Location</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" id="inputLocation" placeholder="Location" value="{location}">
|
<input class="form-control" type="text" id="inputLocation" placeholder="Location" value="{location}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="inputBirthday">Birthday</label>
|
<label class="control-label" for="inputBirthday">Birthday</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="date" id="inputBirthday" placeholder="mm/dd/yyyy" value="{birthday}">
|
<input class="form-control" type="date" id="inputBirthday" placeholder="mm/dd/yyyy" value="{birthday}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="inputSignature">Signature</label>
|
<label class="control-label" for="inputSignature">Signature</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<textarea id="inputSignature" placeholder="max 150 chars" rows="5">{signature}</textarea>
|
<textarea class="form-control" id="inputSignature" placeholder="max 150 chars" rows="5">{signature}</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="hidden" id="inputUID" value="{uid}">
|
<input type="hidden" id="inputUID" value="{uid}"><br />
|
||||||
|
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<a id="submitBtn" href="#" class="btn btn-primary">Save changes</a>
|
<a id="submitBtn" href="#" class="btn btn-primary">Save changes</a>
|
||||||
@@ -134,29 +134,36 @@
|
|||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="inline-block" style="vertical-align:top;">
|
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-5">
|
||||||
|
<div style="vertical-align:top;">
|
||||||
<form class='form-horizontal'>
|
<form class='form-horizontal'>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="inputCurrentPassword">Current Password</label>
|
<label class="control-label" for="inputCurrentPassword">Current Password</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="password" id="inputCurrentPassword" placeholder="Current Password" value="">
|
<input class="form-control" type="password" id="inputCurrentPassword" placeholder="Current Password" value="">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="inputNewPassword">Password</label>
|
<label class="control-label" for="inputNewPassword">Password</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="password" id="inputNewPassword" placeholder="New Password" value=""><br/><span id="password-notify" class="label label-important"></span>
|
<input class="form-control" type="password" id="inputNewPassword" placeholder="New Password" value="">
|
||||||
|
<div id="password-notify" class="alert alert-danger hide"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="inputNewPasswordAgain">Confirm Password</label>
|
<label class="control-label" for="inputNewPasswordAgain">Confirm Password</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="password" id="inputNewPasswordAgain" placeholder="Confirm Password" value=""><br/><span id="password-confirm-notify" class="label label-important"></span>
|
<input class="form-control" type="password" id="inputNewPasswordAgain" placeholder="Confirm Password" value="">
|
||||||
|
<div id="password-confirm-notify" class="alert alert-danger hide"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<br/>
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<a id="changePasswordBtn" href="#" class="btn btn-primary">Change Password</a>
|
<a id="changePasswordBtn" href="#" class="btn btn-primary">Change Password</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -171,4 +178,5 @@
|
|||||||
<input type="hidden" template-variable="gravatarpicture" value="{gravatarpicture}" />
|
<input type="hidden" template-variable="gravatarpicture" value="{gravatarpicture}" />
|
||||||
<input type="hidden" template-variable="uploadedpicture" value="{uploadedpicture}" />
|
<input type="hidden" template-variable="uploadedpicture" value="{uploadedpicture}" />
|
||||||
|
|
||||||
|
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>
|
||||||
<script type="text/javascript" src="{relative_path}/src/forum/accountedit.js"></script>
|
<script type="text/javascript" src="{relative_path}/src/forum/accountedit.js"></script>
|
||||||
|
|||||||
@@ -1,28 +1,24 @@
|
|||||||
|
|
||||||
<div class="well">
|
<div class="well">
|
||||||
|
|
||||||
<div class="account-username-box">
|
<div class="account-username-box" data-userslug="{userslug}">
|
||||||
<span class="account-username">
|
<span class="account-username">
|
||||||
<a href="/users/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
|
<a href="/user/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
|
||||||
<a href="/users/{userslug}/settings">settings</a>
|
<a href="/user/{userslug}/settings">settings</a>
|
||||||
</span>
|
</span>
|
||||||
<div class="account-sub-links inline-block pull-right">
|
|
||||||
<span id="settingsLink" class="pull-right"><a href="/users/{userslug}/settings">settings</a></span>
|
|
||||||
<span class="pull-right"><a href="/users/{userslug}/followers">followers</a></span>
|
|
||||||
<span class="pull-right"><a href="/users/{userslug}/following">following</a></span>
|
|
||||||
<span id="editLink" class="pull-right"><a href="/users/{userslug}/edit">edit</a></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row-fluid">
|
<div class="row">
|
||||||
<div class="span6">
|
<div class="col-md-6">
|
||||||
<h4>privacy</h4>
|
<h4>privacy</h4>
|
||||||
<label class="checkbox">
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
<input id="showemailCheckBox" type="checkbox" {showemail}> Show my email
|
<input id="showemailCheckBox" type="checkbox" {showemail}> Show my email
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="span6">
|
<div class="col-md-6">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -31,4 +27,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>
|
||||||
<script type="text/javascript" src="{relative_path}/src/forum/accountsettings.js"></script>
|
<script type="text/javascript" src="{relative_path}/src/forum/accountsettings.js"></script>
|
||||||
File diff suppressed because one or more lines are too long
@@ -2,20 +2,25 @@
|
|||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
<div class="alert alert-notify">
|
<div class="alert alert-warning">
|
||||||
<p>
|
<p>
|
||||||
Create a <strong>Facebook Application</strong> via the
|
Create a <strong>Facebook Application</strong> via the
|
||||||
<a href="https://developers.facebook.com/">Facebook Developers Page</a> and
|
<a href="https://developers.facebook.com/">Facebook Developers Page</a> and
|
||||||
then paste your application details here.
|
then paste your application details here.
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<input type="text" data-field="social:facebook:app_id" title="Application ID" class="input-medium" placeholder="App ID"><br />
|
<input type="text" data-field="social:facebook:app_id" title="Application ID" class="form-control input-lg" placeholder="App ID"><br />
|
||||||
<input type="text" data-field="social:facebook:secret" title="Application Secret" class="input-large" placeholder="App Secret"><br />
|
<input type="text" data-field="social:facebook:secret" title="Application Secret" class="form-control input-md" placeholder="App Secret"><br />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<button class="btn btn-large btn-primary" id="save">Save</button>
|
<button class="btn btn-lg btn-primary" id="save">Save</button>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
var loadDelay = setInterval(function() {
|
||||||
|
if (nodebb_admin) {
|
||||||
nodebb_admin.prepare();
|
nodebb_admin.prepare();
|
||||||
|
clearInterval(loadDelay);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
</script>
|
</script>
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="alert_window"></div>
|
||||||
|
|
||||||
<div id="footer" class="container" style="padding-top: 50px; display:none;">
|
<div id="footer" class="container" style="padding-top: 50px; display:none;">
|
||||||
<footer class="footer">Copyright © 2013 <a target="_blank" href="http://www.nodebb.com">NodeBB</a> by <a target="_blank" href="https://github.com/psychobunny">psychobunny</a>, <a href="https://github.com/julianlam" target="_blank">julianlam</a>, <a href="https://github.com/barisusakli" target="_blank">barisusakli</a> from <a target="_blank" href="http://www.designcreateplay.com">designcreateplay</a></footer>
|
<footer class="footer">Copyright © 2013 <a target="_blank" href="http://www.nodebb.com">NodeBB</a> by <a target="_blank" href="https://github.com/psychobunny">psychobunny</a>, <a href="https://github.com/julianlam" target="_blank">julianlam</a>, <a href="https://github.com/barisusakli" target="_blank">barisusakli</a> from <a target="_blank" href="http://www.designcreateplay.com">designcreateplay</a></footer>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,20 +2,25 @@
|
|||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
<div class="alert alert-notify">
|
<div class="alert alert-warning">
|
||||||
<p>
|
<p>
|
||||||
Create a <strong>Google Application</strong> via the
|
Create a <strong>Google Application</strong> via the
|
||||||
<a href="https://code.google.com/apis/console/">API Console</a> and then paste
|
<a href="https://code.google.com/apis/console/">API Console</a> and then paste
|
||||||
your application details here.
|
your application details here.
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<input type="text" data-field="social:google:id" title="Client ID" class="input-xxlarge" placeholder="Client ID"><br />
|
<input type="text" data-field="social:google:id" title="Client ID" class="form-control input-lg" placeholder="Client ID"><br />
|
||||||
<input type="text" data-field="social:google:secret" title="Client Secret" class="input-large" placeholder="Client Secret"><br />
|
<input type="text" data-field="social:google:secret" title="Client Secret" class="form-control" placeholder="Client Secret"><br />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<button class="btn btn-large btn-primary" id="save">Save</button>
|
<button class="btn btn-lg btn-primary" id="save">Save</button>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
var loadDelay = setInterval(function() {
|
||||||
|
if (nodebb_admin) {
|
||||||
nodebb_admin.prepare();
|
nodebb_admin.prepare();
|
||||||
|
clearInterval(loadDelay);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
</script>
|
</script>
|
||||||
100
public/templates/admin/groups.tpl
Normal file
100
public/templates/admin/groups.tpl
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
<h1>Groups</h1>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div class="groups">
|
||||||
|
<ul id="groups-list">
|
||||||
|
<!-- BEGIN groups -->
|
||||||
|
<li data-gid="{groups.gid}">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<h2>{groups.name}</h2>
|
||||||
|
<p>{groups.description}</p>
|
||||||
|
<div class="btn-group">
|
||||||
|
<button class="btn btn-default" data-action="members">Members</button>
|
||||||
|
<button class="btn btn-danger" data-action="delete">Delete Group</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<ul class="pull-right members">
|
||||||
|
<!-- BEGIN members -->
|
||||||
|
<li data-uid="{groups.members.uid}" title="{groups.members.username}"><img src="{groups.members.picture}" /></li>
|
||||||
|
<!-- END members -->
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<!-- END groups -->
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="text-center">
|
||||||
|
<button class="btn btn-primary" id="create">New Group</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="create-modal">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h4 class="modal-title">Create Group</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="alert alert-danger hide" id="create-modal-error"></div>
|
||||||
|
<form>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="group-name">Group Name</label>
|
||||||
|
<input type="text" class="form-control" id="create-group-name" placeholder="Group Name" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="group-name">Description</label>
|
||||||
|
<input type="text" class="form-control" id="create-group-desc" placeholder="A short description about your group" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||||
|
<button type="button" class="btn btn-primary" id="create-modal-go">Create</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="group-details-modal">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h4 class="modal-title">Manage Group</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="alert alert-danger hide" id="create-modal-error"></div>
|
||||||
|
<form>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="group-name">Group Name</label>
|
||||||
|
<input type="text" class="form-control" id="change-group-name" placeholder="Group Name" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="group-name">Description</label>
|
||||||
|
<input type="text" class="form-control" id="change-group-desc" placeholder="A short description about your group" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Members</label>
|
||||||
|
<p>Click on a user to remove them from the group</p>
|
||||||
|
<ul class="members current_members" id="group-details-members"></ul>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="add-member">Add User to Group</label>
|
||||||
|
<input type="text" class="form-control" id="group-details-search" placeholder="Search Users" />
|
||||||
|
<ul class="members" id="group-details-search-results"></ul>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="{relative_path}/src/forum/admin/groups.js"></script>
|
||||||
@@ -16,9 +16,12 @@
|
|||||||
<script type="text/javascript" src="{relative_path}/socket.io/socket.io.js"></script>
|
<script type="text/javascript" src="{relative_path}/socket.io/socket.io.js"></script>
|
||||||
<script type="text/javascript" src="{relative_path}/src/app.js"></script>
|
<script type="text/javascript" src="{relative_path}/src/app.js"></script>
|
||||||
<script type="text/javascript" src="{relative_path}/src/templates.js"></script>
|
<script type="text/javascript" src="{relative_path}/src/templates.js"></script>
|
||||||
|
<script type="text/javascript" src="{relative_path}/src/translator.js"></script>
|
||||||
<script type="text/javascript" src="{relative_path}/src/ajaxify.js"></script>
|
<script type="text/javascript" src="{relative_path}/src/ajaxify.js"></script>
|
||||||
|
<script src="{relative_path}/vendor/jquery/js/jquery.timeago.js"></script>
|
||||||
<script src="{relative_path}/vendor/requirejs/require.js"></script>
|
<script src="{relative_path}/vendor/requirejs/require.js"></script>
|
||||||
<script src="{relative_path}/vendor/bootbox/bootbox.min.js"></script>
|
<script src="{relative_path}/vendor/bootbox/bootbox.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
require.config({
|
require.config({
|
||||||
baseUrl: "{relative_path}/src/modules",
|
baseUrl: "{relative_path}/src/modules",
|
||||||
@@ -27,22 +30,25 @@
|
|||||||
</script>
|
</script>
|
||||||
<link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
|
<link rel="stylesheet" type="text/css" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
|
||||||
<script type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
|
<script type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="{relative_path}/css/style.css" />
|
<script src="{relative_path}/src/utils.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="{relative_path}/css/nodebb.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="{relative_path}/css/admin.css" />
|
<link rel="stylesheet" type="text/css" href="{relative_path}/css/admin.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="admin">
|
<body class="admin">
|
||||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||||
<div class="navbar-inner">
|
<div class="container">
|
||||||
<div class="container-fluid">
|
<div class="navbar-header">
|
||||||
<a class="brand" href="/admin/index">NodeBB ACP</a>
|
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||||
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="nav-collapse collapse">
|
<a class="navbar-brand" href="/admin/index">NodeBB ACP</a>
|
||||||
<ul class="nav">
|
</div>
|
||||||
|
<div class="collapse navbar-collapse">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
<li>
|
<li>
|
||||||
<a href="/" target="_blank"><i class="icon-book"></i> Forum</a>
|
<a href="/" target="_blank"><i class="icon-book"></i> Forum</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -52,6 +58,9 @@
|
|||||||
<li>
|
<li>
|
||||||
<a href="/admin/settings"><i class="icon-cogs"></i> Settings</a>
|
<a href="/admin/settings"><i class="icon-cogs"></i> Settings</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#" id="reconnect"></a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="nav pull-right" id="right-menu">
|
<ul class="nav pull-right" id="right-menu">
|
||||||
<li><a href="/users" id="user_label"></a></li>
|
<li><a href="/users" id="user_label"></a></li>
|
||||||
@@ -59,19 +68,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="alert_window"></div>
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
<div class="container-fluid">
|
<div class="col-md-3">
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="span3">
|
|
||||||
<div class="well sidebar-nav">
|
<div class="well sidebar-nav">
|
||||||
<ul class="nav nav-list">
|
<ul class="nav nav-list">
|
||||||
<li class="nav-header">NodeBB</li>
|
<li class="nav-header">NodeBB</li>
|
||||||
<li class='active'><a href='{relative_path}/admin/index'><i class='icon-home'></i> Home</a></li>
|
<li class='active'><a href='{relative_path}/admin/index'><i class='icon-home'></i> Home</a></li>
|
||||||
<li class=''><a href='{relative_path}/admin/categories/active'><i class='icon-folder-close-alt'></i> Categories</a></li>
|
<li class=''><a href='{relative_path}/admin/categories/active'><i class='icon-folder-close-alt'></i> Categories</a></li>
|
||||||
<li class=''><a href='{relative_path}/admin/users/latest'><i class='icon-user'></i> Users</a></li>
|
<li class=''><a href='{relative_path}/admin/users/latest'><i class='icon-user'></i> Users</a></li>
|
||||||
|
<li class=""><a href="{relative_path}/admin/groups"><i class="icon-group"></i> Groups</a></li>
|
||||||
<li class=''><a href='{relative_path}/admin/topics'><i class='icon-book'></i> Topics</a></li>
|
<li class=''><a href='{relative_path}/admin/topics'><i class='icon-book'></i> Topics</a></li>
|
||||||
<li class=''><a href='{relative_path}/admin/themes'><i class='icon-th'></i> Themes</a></li>
|
<li class=''><a href='{relative_path}/admin/themes'><i class='icon-th'></i> Themes</a></li>
|
||||||
<li class=''><a href='{relative_path}/admin/plugins'><i class='icon-code-fork'></i> Plugins</a></li>
|
<li class=''><a href='{relative_path}/admin/plugins'><i class='icon-code-fork'></i> Plugins</a></li>
|
||||||
@@ -100,4 +107,4 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div><!--/.well -->
|
</div><!--/.well -->
|
||||||
</div><!--/span-->
|
</div><!--/span-->
|
||||||
<div class="span9" id="content">
|
<div class="col-md-9" id="content">
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
|
|
||||||
<div class="hero-unit">
|
<div class="jumbotron">
|
||||||
<h1>Welcome to NodeBB</h1>
|
<h1>Welcome to NodeBB</h1>
|
||||||
<br />
|
<br />
|
||||||
<p>
|
<p>
|
||||||
<a target="_blank" href="http://www.nodebb.org" class="btn btn-large"><i class="icon-comment"></i> NodeBB Forum</a>
|
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="icon-comment"></i> NodeBB Forum</a>
|
||||||
<a target="_blank" href="http://www.nodebb.org" class="btn btn-large"><i class="icon-github-alt"></i> Get Plugins</a>
|
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="icon-github-alt"></i> Get Plugins</a>
|
||||||
<a target="_blank" href="http://www.nodebb.org" class="btn btn-large"><i class="icon-github-alt"></i> Get Themes</a>
|
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="icon-github-alt"></i> Get Themes</a>
|
||||||
<a target="_blank" href="http://www.nodebb.org" class="btn btn-large"><i class="icon-twitter"></i> dcplabs</a>
|
<a target="_blank" href="http://www.nodebb.org" class="btn btn-default btn-lg"><i class="icon-twitter"></i> dcplabs</a>
|
||||||
</p>
|
</p>
|
||||||
<p><small>You are running <strong>NodeBB v{version}</strong>. This is where we will check to make sure your <strong>NodeBB</strong> is latest, etc.</small></p>
|
<p><small>You are running <strong>NodeBB v{version}</strong>. Always make sure that your <strong>NodeBB</strong> is up to date for the latest security patches and bug fixes.</small></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
<h1>MOTD</h1>
|
<h1>MOTD</h1>
|
||||||
|
<hr />
|
||||||
<div class="alert motd">
|
<div class="alert alert-warning motd">
|
||||||
<p>
|
<p>
|
||||||
The <strong>Message of the Day</strong> (MOTD) is typically a message shown to users when they first log into a forum or chat room.
|
The <strong>Message of the Day</strong> (MOTD) is typically a message shown to users when they first log into a forum or chat room.
|
||||||
In NodeBB, the MOTD is present at the top of the forum homepage, and can be customized much like a header.
|
In NodeBB, the MOTD is present at the top of the forum homepage, and can be customized much like a header.
|
||||||
@@ -9,14 +9,25 @@
|
|||||||
<p>
|
<p>
|
||||||
You can enter either full HTML or Markdown text.
|
You can enter either full HTML or Markdown text.
|
||||||
</p>
|
</p>
|
||||||
<textarea placeholder="Welcome to NodeBB!" data-field="motd" rows="10"></textarea>
|
<br />
|
||||||
|
<textarea class="form-control" placeholder="Welcome to NodeBB!" data-field="motd" rows="10"></textarea>
|
||||||
|
<br />
|
||||||
<form class="form-inline">
|
<form class="form-inline">
|
||||||
<label class="checkbox" for="show_motd"><input type="checkbox" id="show_motd" data-field="show_motd" /> Show the Message of the Day</label>
|
<div class="checkbox">
|
||||||
|
<label for="show_motd">
|
||||||
|
<input type="checkbox" id="show_motd" data-field="show_motd" /> Show the Message of the Day
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="btn btn-large btn-primary" id="save" checked>Save</button>
|
<button class="btn btn-lg btn-primary" id="save" checked>Save</button>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
var loadDelay = setInterval(function() {
|
||||||
|
if (nodebb_admin) {
|
||||||
nodebb_admin.prepare();
|
nodebb_admin.prepare();
|
||||||
|
clearInterval(loadDelay);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
</script>
|
</script>
|
||||||
@@ -13,9 +13,9 @@
|
|||||||
<!-- END plugins -->
|
<!-- END plugins -->
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="alert">
|
<div class="alert alert-warning">
|
||||||
<p>
|
<p>
|
||||||
<strong>Interesed in writing plugins for NodeBB?</strong>
|
<strong>Interested in writing plugins for NodeBB?</strong>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Full documentation regarding plugin authoring can be found in the <a target="_blank" href="https://github.com/designcreateplay/NodeBB/wiki/Writing-Plugins-for-NodeBB">NodeBB Wiki</a>.
|
Full documentation regarding plugin authoring can be found in the <a target="_blank" href="https://github.com/designcreateplay/NodeBB/wiki/Writing-Plugins-for-NodeBB">NodeBB Wiki</a>.
|
||||||
|
|||||||
@@ -2,64 +2,85 @@
|
|||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<h3>General Settings</h3>
|
<h3>General Settings</h3>
|
||||||
<div class="alert">
|
<div class="alert alert-warning">
|
||||||
<form>
|
<form>
|
||||||
<label>Site Title</label>
|
<label>Site Title</label>
|
||||||
<input type="text" placeholder="Your Community Name" data-field="title" />
|
<input class="form-control" type="text" placeholder="Your Community Name" data-field="title" /><br />
|
||||||
<label>Site Description</label>
|
<label>Site Description</label>
|
||||||
<input type="text" class="input-xxlarge" placeholder="A short description about your community" data-field="description" />
|
<input type="text" class="form-control" placeholder="A short description about your community" data-field="description" /><br />
|
||||||
|
<label>Imgur Client ID</label>
|
||||||
|
<input type="text" class="form-control" placeholder="Imgur ClientID for image uploads" data-field="imgurClientID" /><br />
|
||||||
|
<label>Maximum User Image Size</label>
|
||||||
|
<input type="text" class="form-control" placeholder="Maximum size of uploaded user images in kilobytes" data-field="maximumProfileImageSize" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
<h3>Privilege Thresholds</h3>
|
<h3>Privilege Thresholds</h3>
|
||||||
<div class="alert alert-notify">
|
<div class="alert alert-warning">
|
||||||
<p>Use <strong>privilege thresholds</strong> to manage how much reputation a user must gain to receive moderator access.</p><br />
|
<p>Use <strong>privilege thresholds</strong> to manage how much reputation a user must gain to receive moderator access.</p><br />
|
||||||
<strong>Manage Thread</strong><br /> <input type="text" class="" value="1000"><br />
|
<strong>Manage Thread</strong><br /> <input type="text" class="form-control" value="1000"><br />
|
||||||
<strong>Moderate Users</strong><br /> <input type="text" class="" value="10000"><br />
|
<strong>Moderate Users</strong><br /> <input type="text" class="form-control" value="10000"><br />
|
||||||
<strong>Create Pinned Topics</strong><br /> <input type="text" class="" value="100000"><br />
|
<strong>Create Pinned Topics</strong><br /> <input type="text" class="form-control" value="100000"><br />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
<h3>Email Settings</h3>
|
<h3>Email Settings</h3>
|
||||||
<div class="alert alert-notify">
|
<div class="alert alert-warning">
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<strong>Email Address</strong><br />
|
<strong>Email Address</strong><br />
|
||||||
The following email address refers to the email that the recipient will see in the "From" and "Reply To" fields.
|
The following email address refers to the email that the recipient will see in the "From" and "Reply To" fields.
|
||||||
</p>
|
</p>
|
||||||
<input type="text" class="input-large" data-field="email:from" placeholder="info@example.org" />
|
<input type="text" class="form-control input-lg" data-field="email:from" placeholder="info@example.org" /><br />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<strong>SMTP Server Host</strong><br />
|
<strong>SMTP Server Host</strong><br />
|
||||||
(Default: <em>127.0.0.1</em>)
|
(Default: <em>127.0.0.1</em>)
|
||||||
</p>
|
</p>
|
||||||
<input type="text" class="input-medium" data-field="email:smtp:host" placeholder="127.0.0.1" />
|
<input type="text" class="form-control input-md" data-field="email:smtp:host" placeholder="127.0.0.1" /><br />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<strong>SMTP Server Port</strong>
|
<strong>SMTP Server Port</strong>
|
||||||
</p>
|
</p>
|
||||||
<input type="text" class="input-mini" data-field="email:smtp:port" placeholder="25" />
|
<input type="text" class="form-control input-md" data-field="email:smtp:port" placeholder="25" /><br />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<form>
|
||||||
|
<h3>User Settings</h3>
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
<strong>Minimum Username Length</strong><br />
|
||||||
|
<input type="text" class="form-control" value="2" data-field="minimumUsernameLength"><br />
|
||||||
|
<strong>Maximum Username Length</strong><br />
|
||||||
|
<input type="text" class="form-control" value="16" data-field="maximumUsernameLength"><br />
|
||||||
|
<strong>Minimum Password Length</strong><br />
|
||||||
|
<input type="text" class="form-control" value="6" data-field="minimumPasswordLength"><br />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
<h3>Post Settings</h3>
|
<h3>Post Settings</h3>
|
||||||
<div class="alert alert-notify">
|
<div class="alert alert-warning">
|
||||||
<strong>Post Delay</strong><br /> <input type="text" class="" value="10000" data-field="postDelay"><br />
|
<strong>Post Delay</strong><br /> <input type="text" class="form-control" value="10000" data-field="postDelay"><br />
|
||||||
<strong>Minimum Title Length</strong><br /> <input type="text" class="" value="3" data-field="minimumTitleLength"><br />
|
<strong>Minimum Title Length</strong><br /> <input type="text" class="form-control" value="3" data-field="minimumTitleLength"><br />
|
||||||
<strong>Minimum Post Length</strong><br /> <input type="text" class="" value="8" data-field="minimumPostLength"><br />
|
<strong>Minimum Post Length</strong><br /> <input type="text" class="form-control" value="8" data-field="minimumPostLength"><br />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<button class="btn btn-large btn-primary" id="save">Save</button>
|
<button class="btn btn-lg btn-primary" id="save">Save</button>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
var loadDelay = setInterval(function() {
|
||||||
|
if (nodebb_admin) {
|
||||||
nodebb_admin.prepare();
|
nodebb_admin.prepare();
|
||||||
|
clearInterval(loadDelay);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
</script>
|
</script>
|
||||||
@@ -10,7 +10,7 @@ jQuery(document).ready(function () {
|
|||||||
QUnit.init();
|
QUnit.init();
|
||||||
asyncTest( "Loading Categories", function() {
|
asyncTest( "Loading Categories", function() {
|
||||||
|
|
||||||
jQuery.get(config.api_url + 'home', function(data) {
|
jQuery.get(RELATIVE_PATH + '/api/home', function(data) {
|
||||||
ok( data.categories.length > 0, JSON.stringify(data.categories) );
|
ok( data.categories.length > 0, JSON.stringify(data.categories) );
|
||||||
|
|
||||||
start();
|
start();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<button id="topics_loadmore" class="btn btn-large">Load More Topics</button>
|
<button id="topics_loadmore" class="btn btn-primary btn-lg">Load More Topics</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript" src="{relative_path}/src/forum/admin/topics.js"></script>
|
<script type="text/javascript" src="{relative_path}/src/forum/admin/topics.js"></script>
|
||||||
@@ -2,20 +2,25 @@
|
|||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
<div class="alert alert-notify">
|
<div class="alert alert-warning">
|
||||||
<p>
|
<p>
|
||||||
Create a <strong>Twitter Application</strong> via the
|
Create a <strong>Twitter Application</strong> via the
|
||||||
<a href="https://dev.twitter.com/">Twitter Developers Page</a> and then
|
<a href="https://dev.twitter.com/">Twitter Developers Page</a> and then
|
||||||
paste your application details here.
|
paste your application details here.
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<input type="text" data-field="social:twitter:key" title="Consumer Key" class="input-large" placeholder="Consumer Key"><br />
|
<input type="text" data-field="social:twitter:key" title="Consumer Key" class="form-control input-lg" placeholder="Consumer Key"><br />
|
||||||
<input type="text" data-field="social:twitter:secret" title="Consumer Secret" class="input-xlarge" placeholder="Consumer Secret">
|
<input type="text" data-field="social:twitter:secret" title="Consumer Secret" class="form-control input-md" placeholder="Consumer Secret">
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<button class="btn btn-large btn-primary" id="save">Save</button>
|
<button class="btn btn-lg btn-primary" id="save">Save</button>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
var loadDelay = setInterval(function() {
|
||||||
|
if (nodebb_admin) {
|
||||||
nodebb_admin.prepare();
|
nodebb_admin.prepare();
|
||||||
|
clearInterval(loadDelay);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -7,21 +7,21 @@
|
|||||||
<li class=''><a href='/admin/users/search'>Search</a></li>
|
<li class=''><a href='/admin/users/search'>Search</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<br />
|
||||||
<div class="search {search_display} well">
|
<div class="search {search_display} well">
|
||||||
<input id="search-user" type="text" placeholder="Enter a username to search"/><br />
|
<input class="form-control" id="search-user" type="text" placeholder="Enter a username to search"/><br />
|
||||||
<i class="icon-spinner icon-spin none"></i>
|
<i class="icon-spinner icon-spin none"></i>
|
||||||
<span id="user-notfound-notify" class="label label-important hide">User not found!</span><br/>
|
<span id="user-notfound-notify" class="label label-danger hide">User not found!</span><br/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul id="users-container" class="users">
|
<ul id="users-container" class="users admin">
|
||||||
<!-- BEGIN users -->
|
<!-- BEGIN users -->
|
||||||
<div class="users-box" data-uid="{users.uid}" data-admin="{users.administrator}" data-username="{users.username}">
|
<div class="users-box" data-uid="{users.uid}" data-admin="{users.administrator}" data-username="{users.username}" data-banned="{users.banned}">
|
||||||
<a href="/users/{users.userslug}">
|
<a href="/user/{users.userslug}">
|
||||||
<img src="{users.picture}" class="img-polaroid"/>
|
<img src="{users.picture}" class="img-thumbnail"/>
|
||||||
</a>
|
</a>
|
||||||
<br/>
|
<br/>
|
||||||
<a href="/users/{users.userslug}">{users.username}</a>
|
<a href="/user/{users.userslug}">{users.username}</a>
|
||||||
<br/>
|
<br/>
|
||||||
<div title="reputation">
|
<div title="reputation">
|
||||||
<span id='reputation'>{users.reputation}</span>
|
<span id='reputation'>{users.reputation}</span>
|
||||||
@@ -32,17 +32,14 @@
|
|||||||
<i class='icon-pencil'></i>
|
<i class='icon-pencil'></i>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a href="#" class="btn admin-btn">Admin</a>
|
<a href="#" class="btn btn-default ban-btn">Ban</a>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<a href="#" class="btn delete-btn btn-danger">Delete</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- END users -->
|
<!-- END users -->
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="text-center {loadmore_display}">
|
<div class="text-center {loadmore_display}">
|
||||||
<button id="load-more-users-btn" class="btn">Load More</button>
|
<button id="load-more-users-btn" class="btn btn-primary">Load More</button>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" template-variable="yourid" value="{yourid}" />
|
<input type="hidden" template-variable="yourid" value="{yourid}" />
|
||||||
|
|
||||||
|
|||||||
@@ -1,95 +1,92 @@
|
|||||||
<div class="container">
|
<ol class="breadcrumb">
|
||||||
<ul class="breadcrumb">
|
|
||||||
<li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
<li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
<a href="/" itemprop="url"><span itemprop="title">Home</span></a>
|
<a href="/" itemprop="url"><span itemprop="title">[[global:home]]</span></a>
|
||||||
<span class="divider">/</span>
|
|
||||||
</li>
|
</li>
|
||||||
<li class="active" itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
<li class="active" itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
<span itemprop="title">{category_name}</span>
|
<span itemprop="title">{category_name} <a target="_blank" href="../{category_id}.rss"><i class="icon-rss-sign"></i></a></span>
|
||||||
</li>
|
</li>
|
||||||
<div id="category_active_users"></div>
|
<div id="category_active_users"></div>
|
||||||
</ul>
|
</ol>
|
||||||
</div>
|
|
||||||
<div class="alert alert-warning hide {no_topics_message}" id="category-no-topics">
|
|
||||||
<strong>There are no topics in this category.</strong><br />
|
|
||||||
Why don't you try posting one?
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
<button id="new_post" class="btn btn-primary btn-lg {show_topic_button}">[[category:new_topic_button]]</button>
|
||||||
<button id="new_post" class="btn btn-primary btn-large {show_topic_button}">New Topic</button>
|
|
||||||
|
|
||||||
<div class="inline-block pull-right">
|
<div class="inline-block pull-right">
|
||||||
<a target="_blank" href="../{category_id}.rss"><i class="icon-rss-sign icon-2x"></i></a>
|
|
||||||
<a href="#" id="facebook-share"><i class="icon-facebook-sign icon-2x"></i></a>
|
<a href="#" id="facebook-share"><i class="icon-facebook-sign icon-2x"></i></a>
|
||||||
<a href="#" id="twitter-intent"><i class="icon-twitter-sign icon-2x"></i></a>
|
<a href="#" id="twitter-intent"><i class="icon-twitter-sign icon-2x"></i></a>
|
||||||
<a href="#" id="google-share"><i class="icon-google-plus-sign icon-2x"></i></a>
|
<a href="#" id="google-share"><i class="icon-google-plus-sign icon-2x"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class="{show_sidebar}" />
|
<hr/>
|
||||||
|
|
||||||
|
<div class="alert alert-warning hide {no_topics_message}" id="category-no-topics">
|
||||||
|
[[category:no_topics]]
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="category row">
|
<div class="category row">
|
||||||
<div class="{topic_row_size}">
|
<div class="{topic_row_size}">
|
||||||
<ul id="topics-container">
|
<ul id="topics-container">
|
||||||
<!-- BEGIN topics -->
|
<!-- BEGIN topics -->
|
||||||
<a href="../../topic/{topics.slug}"><li class="category-item {topics.deleted-class}">
|
|
||||||
<div class="row-fluid">
|
<li class="category-item {topics.deleted-class}">
|
||||||
<!-- <div class="span1 thread-rating hidden-phone hidden-tablet">
|
<div class="row">
|
||||||
<span>
|
<div class="col-md-12 topic-row">
|
||||||
<i class="icon-star icon-3x"></i><br />
|
<div class="latest-post visible-lg visible-md">
|
||||||
38
|
<a href="../../topic/{topics.slug}#{topics.teaser_pid}">
|
||||||
</span>
|
|
||||||
</div> -->
|
|
||||||
<div class="span12 topic-row">
|
|
||||||
<div class="latest-post visible-desktop">
|
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<img style="width: 48px; height: 48px; /*temporary*/" src="{topics.teaser_userpicture}" />
|
<img class="img-rounded" style="width: 48px; height: 48px; /*temporary*/" src="{topics.teaser_userpicture}" />
|
||||||
<p><strong>{topics.teaser_username}</strong>: {topics.teaser_text}</p>
|
<p>{topics.teaser_text}</p>
|
||||||
<span>posted {topics.teaser_timestamp} ago</span>
|
<p class="meta">
|
||||||
|
<strong>{topics.teaser_username}</strong> posted <span class="timeago" title="{topics.teaser_timestamp}"></span>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
<a href="../../topic/{topics.slug}">
|
||||||
<div>
|
<div>
|
||||||
<h3><span class="topic-title"><span class="badge {topics.badgeclass}">{topics.postcount}</span>{topics.title}</span></h3>
|
<h3><span class="topic-title"><span class="badge {topics.badgeclass}">{topics.postcount}</span>{topics.title}</span></h3>
|
||||||
<small>
|
<small>
|
||||||
<strong><i class="{topics.pin-icon}"></i><i class="{topics.lock-icon}"></i></strong>
|
<strong><i class="{topics.pin-icon}"></i> <i class="{topics.lock-icon}"></i></strong>
|
||||||
Posted {topics.relativeTime} ago by
|
Posted <span class="timeago" title="{topics.relativeTime}"></span> by
|
||||||
<strong>{topics.username}</strong>.
|
<strong>{topics.username}</strong>.
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li></a>
|
</li>
|
||||||
|
|
||||||
<!-- END topics -->
|
<!-- END topics -->
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="span3 {show_sidebar} category-sidebar mobile-sidebar">
|
<div class="col-md-3 {show_sidebar} category-sidebar">
|
||||||
|
|
||||||
<div class="sidebar-block img-polaroid">
|
<div class="sidebar-block img-thumbnail">
|
||||||
<div class="block-header">
|
<div class="block-header">
|
||||||
Recent Replies
|
[[category:sidebar.recent_replies]]
|
||||||
</div>
|
</div>
|
||||||
<div class="block-content recent-replies">
|
<div class="block-content recent-replies">
|
||||||
<ul id="category_recent_replies"></ul>
|
<ul id="category_recent_replies"></ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebar-block img-polaroid">
|
<div class="sidebar-block img-thumbnail">
|
||||||
<div class="block-header">
|
<div class="block-header">
|
||||||
Active Participants
|
[[category:sidebar.active_participants]]
|
||||||
</div>
|
</div>
|
||||||
<div class="block-content">
|
<div class="block-content">
|
||||||
<!-- BEGIN active_users -->
|
<!-- BEGIN active_users -->
|
||||||
<a href="/users/{active_users.userslug}"><img title="{active_users.username}" src="{active_users.picture}" class="img-polaroid" /></a>
|
<a href="/user/{active_users.userslug}"><img title="{active_users.username}" src="{active_users.picture}" class="img-rounded" /></a>
|
||||||
<!-- END active_users -->
|
<!-- END active_users -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebar-block img-polaroid {moderator_block_class}">
|
<div class="sidebar-block img-thumbnail {moderator_block_class}">
|
||||||
<div class="block-header">
|
<div class="block-header">
|
||||||
Moderators
|
[[category:sidebar.moderators]]
|
||||||
</div>
|
</div>
|
||||||
<div class="block-content">
|
<div class="block-content">
|
||||||
<!-- BEGIN moderators -->
|
<!-- BEGIN moderators -->
|
||||||
<a href="/users/{moderators.userslug}"><img title="{moderators.username}" src="{moderators.picture}" class="img-polaroid" /></a>
|
<a href="/user/{moderators.userslug}"><img title="{moderators.username}" src="{moderators.picture}" class="img-rounded" /></a>
|
||||||
<!-- END moderators -->
|
<!-- END moderators -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,37 +1,42 @@
|
|||||||
{
|
{
|
||||||
"custom_mapping": {
|
"custom_mapping": {
|
||||||
"admin/testing/categories[^]*": "admin/testing/categories",
|
"admin/testing/categories.*": "admin/testing/categories",
|
||||||
"admin/topics[^]*": "admin/topics",
|
"admin/topics.*": "admin/topics",
|
||||||
"admin/categories[^]*": "admin/categories",
|
"admin/categories.*": "admin/categories",
|
||||||
"admin/users[^]*": "admin/users",
|
"admin/users.*": "admin/users",
|
||||||
"admin/redis[^]*": "admin/redis",
|
"admin/redis.*": "admin/redis",
|
||||||
"admin/index[^]*": "admin/index",
|
"admin/index.*": "admin/index",
|
||||||
"admin/themes[^]*": "admin/themes",
|
"admin/themes.*": "admin/themes",
|
||||||
"admin/plugins[^]*": "admin/plugins",
|
"admin/plugins.*": "admin/plugins",
|
||||||
"admin/settings[^]*": "admin/settings",
|
"^admin/settings.*": "admin/settings",
|
||||||
"admin/twitter[^]*": "admin/twitter",
|
"admin/twitter.*": "admin/twitter",
|
||||||
"admin/facebook[^]*": "admin/facebook",
|
"admin/facebook.*": "admin/facebook",
|
||||||
"admin/gplus[^]*": "admin/gplus",
|
"admin/gplus.*": "admin/gplus",
|
||||||
"admin/motd/?$": "admin/motd",
|
"admin/motd/?$": "admin/motd",
|
||||||
|
"admin/groups/?$": "admin/groups",
|
||||||
"install/?$": "install/mail",
|
"install/?$": "install/mail",
|
||||||
"install/mail/?": "install/mail",
|
"install/mail/?": "install/mail",
|
||||||
"install/social/?": "install/social",
|
"install/social/?": "install/social",
|
||||||
"install/privileges/?": "install/privileges",
|
"install/privileges/?": "install/privileges",
|
||||||
"users-sort-posts": "users",
|
"users/sort-posts": "users",
|
||||||
"users-latest": "users",
|
"users/latest": "users",
|
||||||
"users-sort-reputation": "users",
|
"users/sort-reputation": "users",
|
||||||
"users-search": "users",
|
"users/search": "users",
|
||||||
"users[^]*edit": "accountedit",
|
"user.*edit": "accountedit",
|
||||||
"users[^]*following": "following",
|
"user.*following": "following",
|
||||||
"users[^]*followers": "followers",
|
"user.*followers": "followers",
|
||||||
"users[^]*settings": "accountsettings",
|
"user.*settings": "accountsettings",
|
||||||
"users/[^]*": "account",
|
"user.*favourites": "favourites",
|
||||||
|
"user/.*": "account",
|
||||||
|
|
||||||
"recent": "recent",
|
"recent": "recent",
|
||||||
"unread": "unread",
|
"unread": "unread",
|
||||||
"popular": "category",
|
"popular": "category",
|
||||||
"active": "category",
|
"active": "category",
|
||||||
"search": "search"
|
"search": "search",
|
||||||
|
"reset/.*": "reset_code",
|
||||||
|
"reset": "reset"
|
||||||
|
|
||||||
},
|
},
|
||||||
"force_refresh": {
|
"force_refresh": {
|
||||||
"logout": true
|
"logout": true
|
||||||
|
|||||||
27
public/templates/favourites.tpl
Normal file
27
public/templates/favourites.tpl
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<div class="well favourites">
|
||||||
|
<div class="account-username-box" data-userslug="{userslug}">
|
||||||
|
<span class="account-username">
|
||||||
|
<a href="/user/{userslug}">{username}</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="no-favourites-notice" class="alert alert-warning {show_nofavourites}">You don't have any favourites, favourite some posts to see them here!</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12 user-favourite-posts">
|
||||||
|
<!-- BEGIN posts -->
|
||||||
|
<div class="topic-row img-thumbnail clearfix" topic-url="topic/{posts.tid}/#{posts.pid}">
|
||||||
|
<span><strong>{posts.username}</strong> : </span>
|
||||||
|
<span>{posts.content}</span>
|
||||||
|
<div>
|
||||||
|
<span class="pull-right timeago" title="{posts.relativeTime}"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
<!-- END posts -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="{relative_path}/src/forum/accountheader.js"></script>
|
||||||
|
<script type="text/javascript" src="{relative_path}/src/forum/favourites.js"></script>
|
||||||
@@ -1,38 +1,31 @@
|
|||||||
|
|
||||||
<div class="well">
|
<div class="well users">
|
||||||
|
|
||||||
<div class="account-username-box">
|
<div class="account-username-box" data-userslug="{userslug}">
|
||||||
<span class="account-username">
|
<span class="account-username">
|
||||||
<a href="/users/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
|
<a href="/user/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
|
||||||
<a href="/users/{userslug}/followers">followers</a>
|
<a href="/user/{userslug}/followers">followers</a>
|
||||||
</span>
|
</span>
|
||||||
<div class="account-sub-links inline-block pull-right">
|
|
||||||
<span id="settingsLink" class="pull-right"><a href="/users/{userslug}/settings">settings</a></span>
|
|
||||||
<span class="pull-right"><a href="/users/{userslug}/followers">followers</a></span>
|
|
||||||
<span class="pull-right"><a href="/users/{userslug}/following">following</a></span>
|
|
||||||
<span id="editLink" class="pull-right"><a href="/users/{userslug}/edit">edit</a></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<!-- BEGIN followers -->
|
<!-- BEGIN followers -->
|
||||||
<div class="users-box">
|
<div class="users-box">
|
||||||
<a href="/users/{followers.userslug}">
|
<a href="/user/{followers.userslug}">
|
||||||
<img src="{followers.picture}" class="img-polaroid"/>
|
<img src="{followers.picture}" class="img-thumbnail"/>
|
||||||
</a>
|
</a>
|
||||||
<br/>
|
<br/>
|
||||||
<a href="/users/{followers.userslug}">{followers.username}</a>
|
<a href="/user/{followers.userslug}">{followers.username}</a>
|
||||||
<br/>
|
<br/>
|
||||||
<div title="reputation">
|
<div title="reputation">
|
||||||
<span class='reputation'>{followers.reputation}</span>
|
<span class='formatted-number'>{followers.reputation}</span>
|
||||||
<i class='icon-star'></i>
|
<i class='icon-star'></i>
|
||||||
</div>
|
</div>
|
||||||
<div title="post count">
|
<div title="post count">
|
||||||
<span class='postcount'>{followers.postcount}</span>
|
<span class='formatted-number'>{followers.postcount}</span>
|
||||||
<i class='icon-pencil'></i>
|
<i class='icon-pencil'></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- END followers -->
|
<!-- END followers -->
|
||||||
</div>
|
</div>
|
||||||
<div id="no-followers-notice" class="alert alert-warning hide">This user doesn't have any followers :(</div>
|
<div id="no-followers-notice" class="alert alert-warning hide">This user doesn't have any followers :(</div>
|
||||||
|
|||||||
@@ -1,39 +1,31 @@
|
|||||||
|
|
||||||
<div class="well">
|
<div class="well users">
|
||||||
|
|
||||||
|
<div class="account-username-box" data-userslug="{userslug}">
|
||||||
|
|
||||||
<div class="account-username-box">
|
|
||||||
<span class="account-username">
|
<span class="account-username">
|
||||||
<a href="/users/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
|
<a href="/user/{userslug}">{username}</a> <i class="icon-chevron-right"></i>
|
||||||
<a href="/users/{userslug}/following">following</a>
|
<a href="/user/{userslug}/following">following</a>
|
||||||
</span>
|
</span>
|
||||||
<div class="account-sub-links inline-block pull-right">
|
|
||||||
<span id="settingsLink" class="pull-right"><a href="/users/{userslug}/settings">settings</a></span>
|
|
||||||
<span class="pull-right"><a href="/users/{userslug}/followers">followers</a></span>
|
|
||||||
<span class="pull-right"><a href="/users/{userslug}/following">following</a></span>
|
|
||||||
<span id="editLink" class="pull-right"><a href="/users/{userslug}/edit">edit</a></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<!-- BEGIN following -->
|
<!-- BEGIN following -->
|
||||||
<div class="users-box">
|
<div class="users-box">
|
||||||
<a href="/users/{following.userslug}">
|
<a href="/user/{following.userslug}">
|
||||||
<img src="{following.picture}" class="img-polaroid"/>
|
<img src="{following.picture}" class="img-thumbnail"/>
|
||||||
</a>
|
</a>
|
||||||
<br/>
|
<br/>
|
||||||
<a href="/users/{following.userslug}">{following.username}</a>
|
<a href="/user/{following.userslug}">{following.username}</a>
|
||||||
<br/>
|
<br/>
|
||||||
<div title="reputation">
|
<div title="reputation">
|
||||||
<span class='reputation'>{following.reputation}</span>
|
<span class='formatted-number'>{following.reputation}</span>
|
||||||
<i class='icon-star'></i>
|
<i class='icon-star'></i>
|
||||||
</div>
|
</div>
|
||||||
<div title="post count">
|
<div title="post count">
|
||||||
<span class='postcount'>{following.postcount}</span>
|
<span class='formatted-number'>{following.postcount}</span>
|
||||||
<i class='icon-pencil'></i>
|
<i class='icon-pencil'></i>
|
||||||
</div>
|
</div>
|
||||||
<a id="unfollow-btn" href="#" class="btn unfollow-btn" followingUid="{following.uid}" data-username="{following.username}">Unfollow</a>
|
<a id="unfollow-btn" href="#" class="btn btn-default unfollow-btn" followingUid="{following.uid}" data-username="{following.username}">Unfollow</a>
|
||||||
</div>
|
</div>
|
||||||
<!-- END following -->
|
<!-- END following -->
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,51 +2,56 @@
|
|||||||
|
|
||||||
</div><!--END container -->
|
</div><!--END container -->
|
||||||
|
|
||||||
<div id="disconnect-modal" class="modal hide" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
<div id="chat-modal" class="modal" tabindex="-1" role="dialog" aria-labelledby="Chat" aria-hidden="true">
|
||||||
<div class="modal-header">
|
<div class="modal-dialog">
|
||||||
<h3 id="myModalLabel">Socket Disconnect</h3>
|
<div class="modal-content">
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<span id="disconnect-text">Looks like you disconnected, try reloading the page.</span>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<a id="reload-button" href="/" class="btn btn-primary">Reload</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="chat-modal" class="modal hide" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
<h3 id="myModalLabel">Chat with <span id="chat-with-name"></span></h3>
|
<h3 id="myModalLabel">[[footer:chat.chatting_with]]</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<textarea id="chat-content" cols="40" rows="10" readonly></textarea><br/>
|
<textarea class="form-control" id="chat-content" cols="40" rows="10" readonly></textarea><br/>
|
||||||
<input id="chat-message-input" type="text" name="chat-message" placeholder="type chat message here press enter to send"/><br/>
|
<input id="chat-message-input" type="text" class="form-control" name="chat-message" placeholder="[[footer:chat.placeholder]]"/>
|
||||||
<button type="button" id="chat-message-send-btn" href="#" class="btn btn-primary">Send</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" id="chat-message-send-btn" href="#" class="btn btn-primary btn-lg btn-block
|
||||||
|
">[[footer:chat.send]]</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div><!-- /.modal-content -->
|
||||||
|
</div><!-- /.modal-dialog -->
|
||||||
|
</div><!-- /.modal -->
|
||||||
|
|
||||||
|
|
||||||
<div id="alert_window"></div>
|
<div id="alert_window"></div>
|
||||||
|
|
||||||
<div id="mobile-sidebar">
|
|
||||||
|
<footer id="footer" class="container footer">
|
||||||
|
<div class="row footer-stats">
|
||||||
|
<div class="col-md-3 col-xs-6">
|
||||||
|
<div class="stats-card well">
|
||||||
|
<h2><span id="stats_online"></span><br /><small>[[footer:stats.online]]</small></h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 col-xs-6">
|
||||||
|
<div class="stats-card well">
|
||||||
|
<h2><span id="stats_users"></span><br /><small>[[footer:stats.users]]</small></h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 col-xs-6">
|
||||||
|
<div class="stats-card well">
|
||||||
|
<h2><span id="stats_topics"></span><br /><small>[[footer:stats.topics]]</small></h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 col-xs-6">
|
||||||
|
<div class="stats-card well">
|
||||||
|
<h2><span id="stats_posts"></span><br /><small>[[footer:stats.posts]]</small></h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- START Forum Info -->
|
<div class="copyright">Copyright © 2013 <a target="_blank" href="http://www.nodebb.org">NodeBB</a> by <a target="_blank" href="https://github.com/psychobunny">psychobunny</a>, <a href="https://github.com/julianlam" target="_blank">julianlam</a>, <a href="https://github.com/barisusakli" target="_blank">barisusakli</a> from <a target="_blank" href="http://www.designcreateplay.com">designcreateplay</a></div>
|
||||||
<div id="footer" class="container hidden-phone" style="padding-top: 50px; display: none">
|
</footer>
|
||||||
<div class="alert alert-info">
|
|
||||||
<span id="active_users"></span>; <span id="active_record"></span><br />
|
|
||||||
<span id="number_of_users"></span> <span id="post_stats"></span><br />
|
|
||||||
<span id="latest_user"></span>
|
|
||||||
</div>
|
|
||||||
<footer class="footer">Copyright © 2013 <a target="_blank" href="http://www.nodebb.org">NodeBB</a> by <a target="_blank" href="https://github.com/psychobunny">psychobunny</a>, <a href="https://github.com/julianlam" target="_blank">julianlam</a>, <a href="https://github.com/barisusakli" target="_blank">barisusakli</a> from <a target="_blank" href="http://www.designcreateplay.com">designcreateplay</a></footer>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="mobile-menu">
|
|
||||||
<button id="mobile-menu-btn" type="button" class="btn btn-none"><i class="icon-th icon-2x"></i></button>
|
|
||||||
<button id="mobile-post-btn" type="button" class="btn btn-none"><i class="icon-plus icon-2x"></i></button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- END Forum Info -->
|
|
||||||
<script>
|
<script>
|
||||||
$.getScript(RELATIVE_PATH + '/src/forum/footer.js');
|
$.getScript(RELATIVE_PATH + '/src/forum/footer.js');
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -4,71 +4,109 @@
|
|||||||
<title>{browserTitle}</title>
|
<title>{browserTitle}</title>
|
||||||
{meta_tags}
|
{meta_tags}
|
||||||
<link href="{cssSrc}" rel="stylesheet" media="screen">
|
<link href="{cssSrc}" rel="stylesheet" media="screen">
|
||||||
<link href="{relative_path}/vendor/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet" media="screen">
|
|
||||||
<link rel="stylesheet" href="{relative_path}/vendor/fontawesome/css/font-awesome.min.css">
|
<link rel="stylesheet" href="{relative_path}/vendor/fontawesome/css/font-awesome.min.css">
|
||||||
<script>
|
<script>
|
||||||
var RELATIVE_PATH = "{relative_path}";
|
var RELATIVE_PATH = "{relative_path}";
|
||||||
</script>
|
</script>
|
||||||
<script src="http://code.jquery.com/jquery.js"></script>
|
|
||||||
<script src="{relative_path}/vendor/jquery/js/jquery-ui-1.10.3.custom.min.js"></script>
|
|
||||||
<script src="{relative_path}/vendor/bootstrap/js/bootstrap.min.js"></script>
|
|
||||||
<script src="{relative_path}/socket.io/socket.io.js"></script>
|
<script src="{relative_path}/socket.io/socket.io.js"></script>
|
||||||
<script src="{relative_path}/src/app.js"></script>
|
<!-- BEGIN clientScripts -->
|
||||||
<script src="{relative_path}/vendor/requirejs/require.js"></script>
|
<script src="{relative_path}/{clientScripts.script}"></script>
|
||||||
<script src="{relative_path}/vendor/bootbox/bootbox.min.js"></script>
|
<!-- END clientScripts -->
|
||||||
<script>
|
<script>
|
||||||
require.config({
|
require.config({
|
||||||
baseUrl: "{relative_path}/src/modules",
|
baseUrl: "{relative_path}/src/modules",
|
||||||
waitSeconds: 3
|
waitSeconds: 3
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<script src="{relative_path}/src/templates.js"></script>
|
|
||||||
<script src="{relative_path}/src/ajaxify.js"></script>
|
|
||||||
<script src="{relative_path}/src/jquery.form.js"></script>
|
|
||||||
<script src="{relative_path}/src/utils.js"></script>
|
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="{relative_path}/css/nodebb.css" />
|
<link rel="stylesheet" type="text/css" href="{relative_path}/css/nodebb.css" />
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="mobile-menu-overlay">
|
<div class="navbar navbar-inverse navbar-fixed-top header" role="navigation" id="header-menu">
|
||||||
</div>
|
|
||||||
<div class="navbar navbar-inverse navbar-fixed-top" id="header-menu">
|
|
||||||
<div class="navbar-inner">
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="brand" href="/">{title}</a>
|
<div class="navbar-header">
|
||||||
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="nav-collapse collapse">
|
<a href="/">
|
||||||
<ul id="main-nav" class="nav nodebb-inline-block">
|
<h1 class="navbar-brand forum-title">{title}</h1>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="navbar-collapse collapse navbar-ex1-collapse">
|
||||||
|
<ul id="main-nav" class="nav navbar-nav">
|
||||||
<li>
|
<li>
|
||||||
<a href="/recent">Recent</a>
|
<a href="/recent">[[global:header.recent]]</a>
|
||||||
|
</li>
|
||||||
|
<li class="nodebb-loggedin">
|
||||||
|
<a href="/unread"><span id="numUnreadBadge" class="badge badge-inverse">0</span> [[global:header.unread]]</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/unread">Unread</a>
|
<a href="/users">[[global:header.users]]</a>
|
||||||
|
</li>
|
||||||
|
<li class="visible-xs">
|
||||||
|
<a href="/search">[[global:header.search]]</a>
|
||||||
|
</li>
|
||||||
|
<li class="visible-xs">
|
||||||
|
<a href="/search">Search</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/users">Users</a>
|
<a href="/"></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul id="right-menu" class="nav pull-right nodebb-inline-block">
|
|
||||||
<li class="notifications dropdown text-center">
|
<form id="search-form" class="navbar-form navbar-right hidden-xs" role="search" method="GET" action="">
|
||||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="notif_dropdown"><i class="icon-circle-blank"></i></a>
|
<div class="hide" id="search-fields">
|
||||||
<ul id="notif-list" class="dropdown-menu" aria-labelledby="notif_dropdown">
|
<div class="form-group">
|
||||||
<li><a href="#"><i class="icon-refresh icon-spin"></i> Loading Notifications</a></li>
|
<input type="text" class="form-control" placeholder="Search" name="query" value="">
|
||||||
</ul>
|
</div>
|
||||||
</li>
|
<button type="submit" class="btn btn-default hide">[[global:search]]</button>
|
||||||
<form id="search-form"
|
</div>
|
||||||
class="form-search form-inline" action="" method="GET">
|
<button id="search-button" type="button" class="btn btn-link"><i class="icon-search"></i></button>
|
||||||
<input type="text" name="query" class="input-medium search-query">
|
|
||||||
<button type="submit" class="btn hide">Search</button>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<ul id="logged-in-menu" class="nav navbar-nav navbar-right hide">
|
||||||
|
<li>
|
||||||
|
<a href="#" id="reconnect"></a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li id="notifications-list" class="notifications dropdown text-center hidden-xs">
|
||||||
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="notif_dropdown"><i class="icon-circle-blank"></i></a>
|
||||||
|
<ul id="notif-list" class="dropdown-menu" aria-labelledby="notif_dropdown">
|
||||||
|
<li>
|
||||||
|
<a href="#"><i class="icon-refresh icon-spin"></i> [[global:notifications.loading]]</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a id="user_label" href="">
|
||||||
|
<img src=""/>
|
||||||
|
<span></span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li id="logout-link">
|
||||||
|
<a href="#">Log out</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<ul id="logged-out-menu" class="nav navbar-nav navbar-right">
|
||||||
|
<li id="register-link">
|
||||||
|
<a href="/register">Register</a>
|
||||||
|
</li>
|
||||||
|
<li id="login-link">
|
||||||
|
<a href="/login">Login</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="pagination-block">
|
||||||
|
<i class="icon-upload pointer"></i>
|
||||||
|
<span id="pagination"></span>
|
||||||
|
<i class="icon-upload pointer icon-rotate-180"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -76,6 +114,4 @@
|
|||||||
|
|
||||||
<input id="csrf_token" type="hidden" template-variable="csrf" value="{csrf}" />
|
<input id="csrf_token" type="hidden" template-variable="csrf" value="{csrf}" />
|
||||||
|
|
||||||
|
|
||||||
<div class="container" id="content">
|
<div class="container" id="content">
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<div class="hero-unit {motd_class}">
|
<div class="jumbotron {motd_class}">
|
||||||
{motd}
|
{motd}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row category-row">
|
<div class="row home">
|
||||||
<!-- BEGIN categories -->
|
<!-- BEGIN categories -->
|
||||||
<div class="span3">
|
<div class="col-md-3 col-xs-6">
|
||||||
<a href="category/{categories.slug}">
|
<a href="category/{categories.slug}">
|
||||||
<h4><span class="badge {categories.badgeclass}">{categories.topic_count} </span> {categories.name}</h4>
|
<h4><span class="badge {categories.badgeclass}">{categories.topic_count} </span> {categories.name}</h4>
|
||||||
<div class="category-icon {categories.blockclass}">
|
<div class="icon {categories.blockclass}">
|
||||||
<div id="category-{categories.cid}" class="category-slider-{categories.post_count}">
|
<div id="category-{categories.cid}" class="category-slider-{categories.post_count}">
|
||||||
<div class="category-box"><i class="{categories.icon} icon-4x"></i></div>
|
<div class="category-box"><i class="{categories.icon} icon-4x"></i></div>
|
||||||
<div class="category-box">{categories.description}</div>
|
<div class="category-box">{categories.description}</div>
|
||||||
|
|||||||
@@ -30,10 +30,10 @@
|
|||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<button data-path="mail" class="btn btn-primary btn-large">Next – <i class="icon-envelope"></i> Mail</button>
|
<button data-path="mail" class="btn btn-primary btn-lg">Next – <i class="icon-envelope"></i> Mail</button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button data-path="redis" class="btn btn-primary btn-large">Previous – <i class="icon-hdd"></i> Redis</button>
|
<button data-path="redis" class="btn btn-primary btn-lg">Previous – <i class="icon-hdd"></i> Redis</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
// ajaxify.go('install/redis');
|
// ajaxify.go('install/redis');
|
||||||
// app.alert({
|
// app.alert({
|
||||||
// alert_id: 'config-ready',
|
// alert_id: 'config-ready',
|
||||||
// type: 'error',
|
// type: 'danger',
|
||||||
// timeout: 10000,
|
// timeout: 10000,
|
||||||
// title: 'NodeBB Configuration Not Ready!',
|
// title: 'NodeBB Configuration Not Ready!',
|
||||||
// message: 'NodeBB cannot proceed with setup at this time as Redis database information ' +
|
// message: 'NodeBB cannot proceed with setup at this time as Redis database information ' +
|
||||||
@@ -110,7 +110,6 @@
|
|||||||
contentEl.addEventListener('click', function(e) {
|
contentEl.addEventListener('click', function(e) {
|
||||||
if (e.target.hasAttribute('data-path')) {
|
if (e.target.hasAttribute('data-path')) {
|
||||||
var href = 'install/' + e.target.getAttribute('data-path');
|
var href = 'install/' + e.target.getAttribute('data-path');
|
||||||
console.log(href);
|
|
||||||
if (!e.target.disabled) ajaxify.go(href);
|
if (!e.target.disabled) ajaxify.go(href);
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
@@ -135,7 +134,7 @@
|
|||||||
timeout: 2500,
|
timeout: 2500,
|
||||||
title: 'Configuration Not Saved',
|
title: 'Configuration Not Saved',
|
||||||
message: 'NodeBB encountered a problem saving your changes',
|
message: 'NodeBB encountered a problem saving your changes',
|
||||||
type: 'error'
|
type: 'danger'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
<div class="navbar-inner">
|
<div class="navbar-inner">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="brand" href="/install">NodeBB Installation</a>
|
<a class="brand" href="/install">NodeBB Installation</a>
|
||||||
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
<button type="button" class="btn navbar-btn" data-toggle="collapse" data-target=".nav-collapse">
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<button data-path="social" class="btn btn-primary btn-large">Next – <i class="icon-facebook"></i> Social</button>
|
<button data-path="social" class="btn btn-primary btn-lg">Next – <i class="icon-facebook"></i> Social</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -27,10 +27,10 @@
|
|||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<button id="start-nodebb" class="btn btn-success btn-large"><i class="icon-thumbs-up"></i> Start using NodeBB!</button>
|
<button id="start-nodebb" class="btn btn-success btn-lg"><i class="icon-thumbs-up"></i> Start using NodeBB!</button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button data-path="social" class="btn btn-primary btn-large">Previous – <i class="icon-facebook"></i> Social</button>
|
<button data-path="social" class="btn btn-primary btn-lg">Previous – <i class="icon-facebook"></i> Social</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<button data-path="basic" class="btn btn-primary btn-large" disabled>Next – <i class="icon-cog"></i> Basic</button>
|
<button data-path="basic" class="btn btn-primary btn-lg" disabled>Next – <i class="icon-cog"></i> Basic</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -34,10 +34,10 @@
|
|||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<button data-path="privileges" class="btn btn-primary btn-large">Next – <i class="icon-legal"></i> Privileges</button>
|
<button data-path="privileges" class="btn btn-primary btn-lg">Next – <i class="icon-legal"></i> Privileges</button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button data-path="mail" class="btn btn-primary btn-large">Previous – <i class="icon-envelope"></i> Mail</button>
|
<button data-path="mail" class="btn btn-primary btn-lg">Previous – <i class="icon-envelope"></i> Mail</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -1,30 +1,64 @@
|
|||||||
<h1>Login</h1>
|
<ol class="breadcrumb">
|
||||||
<div class="row-fluid">
|
<li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
<div class="well {login_window:spansize}">
|
<a href="/" itemprop="url"><span itemprop="title">[[global:home]]</span></a>
|
||||||
<h4>Login via Username & Password</h4>
|
</li>
|
||||||
<div class="alert alert-error" id="error" style="display:none">
|
<li class="active" itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
|
<span itemprop="title">[[login:login]]</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="{login_window:spansize}">
|
||||||
|
<div class="well well-lg">
|
||||||
|
<div class="alert alert-danger" id="login-error-notify" style="display:none">
|
||||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||||
<strong>Failed Login Attempt</strong> <p></p>
|
<strong>[[login:failed_login_attempt]]</strong> <p></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form>
|
<form class="form-horizontal" role="form">
|
||||||
<label>Username</label><input type="text" placeholder="Enter Username" name="username" id="username" /><br />
|
<div class="form-group">
|
||||||
<label>Password</label><input type="password" placeholder="Enter Password" name="password" id="password" /><br />
|
<label for="username" class="col-lg-2 control-label">[[login:username]]</label>
|
||||||
|
<div class="col-lg-10">
|
||||||
|
<input class="form-control" type="text" placeholder="Enter Username" name="username" id="username" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password" class="col-lg-2 control-label">[[login:password]]</label>
|
||||||
|
<div class="col-lg-10">
|
||||||
|
<input class="form-control" type="password" placeholder="Enter Password" name="password" id="password" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-lg-offset-2 col-lg-10">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox"> [[login:remember_me]]
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-lg-offset-2 col-lg-10">
|
||||||
|
<button class="btn btn-primary" id="login" type="submit">[[login:login]]</button> <a href="/reset">[[login:forgot_password]]</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<input type="hidden" name="_csrf" value="{token}" id="csrf-token" />
|
<input type="hidden" name="_csrf" value="{token}" id="csrf-token" />
|
||||||
<button class="btn btn-primary" id="login" type="submit">Login</button> <a href="/reset">Forgot Password?</a>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<span id="login-error-notify" class="label label-important hide">Invalid username/password</span><br/>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="well span6 {alternate_logins:display}">
|
<div class="col-md-6 {alternate_logins:display}">
|
||||||
<h4>Alternative Logins</h4>
|
<div class="well well-lg">
|
||||||
|
<h4>[[login:alternative_logins]]</h4>
|
||||||
<ul class="alt-logins">
|
<ul class="alt-logins">
|
||||||
<li data-url="/auth/twitter" class="twitter {twitter:display}"><i class="icon-twitter-sign icon-3x"></i></li>
|
<li data-url="/auth/twitter" class="twitter {twitter:display}"><i class="icon-twitter-sign icon-3x"></i></li>
|
||||||
<li data-url="/auth/google" class="google {google:display}"><i class="icon-google-plus-sign icon-3x"></i></li>
|
<li data-url="/auth/google" class="google {google:display}"><i class="icon-google-plus-sign icon-3x"></i></li>
|
||||||
<li data-url="/auth/facebook" class="facebook {facebook:display}"><i class="icon-facebook-sign icon-3x"></i></li>
|
<li data-url="/auth/facebook" class="facebook {facebook:display}"><i class="icon-facebook-sign icon-3x"></i></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript" src="{relative_path}/src/forum/login.js"></script>
|
<script type="text/javascript" src="{relative_path}/src/forum/login.js"></script>
|
||||||
@@ -1,7 +1,13 @@
|
|||||||
<div class="alert" id="message">
|
<ol class="breadcrumb">
|
||||||
<strong>Logout</strong>
|
<li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
<p>You have successfully logged out of NodeBB</p>
|
<a href="/" itemprop="url"><span itemprop="title">[[global:home]]</span></a>
|
||||||
<p>
|
</li>
|
||||||
<a href="/">NodeBB Home</a>
|
<li class="active" itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
</p>
|
<span itemprop="title">[[global:logout]]</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div class="alert alert-success" id="message">
|
||||||
|
<h4>[[global:logout.title]]</h4>
|
||||||
|
<p>[[global:logout.message]]</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
<ul class="breadcrumb">
|
<ol class="breadcrumb">
|
||||||
<li><a href="/">Home</a><span class="divider">/</span></li>
|
<li><a href="/">Home</a></li>
|
||||||
<li class="active">{category_name}</li>
|
<li class="active">{category_name}</li>
|
||||||
<div id="category_active_users"></div>
|
<div id="category_active_users"></div>
|
||||||
</ul>
|
</ol>
|
||||||
<ul class="topics">
|
<ul class="topics">
|
||||||
<!-- BEGIN topics -->
|
<!-- BEGIN topics -->
|
||||||
<li>
|
<li>
|
||||||
|
<span class="timestamp">{topics.teaser_timestamp}</span>
|
||||||
<a href="../../topic/{topics.slug}">{topics.title} ({topics.postcount})</a>
|
<a href="../../topic/{topics.slug}">{topics.title} ({topics.postcount})</a>
|
||||||
<div class="teaser">
|
<div class="teaser">
|
||||||
<img class="img-polaroid" src="../../graph/users/{topics.teaser_username}/picture" />
|
<img class="img-thumbnail" src="{topics.teaser_userpicture}" />
|
||||||
<p>
|
<p>
|
||||||
{topics.teaser_text} — {topics.teaser_timestamp} ago
|
{topics.teaser_text}
|
||||||
</p>
|
</p>
|
||||||
|
<div class="clear"></div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<!-- END topics -->
|
<!-- END topics -->
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<div class="alert alert-error">
|
<div class="alert alert-danger">
|
||||||
<p>
|
<p>
|
||||||
Your browser does not seem to support javascript. As a result, your viewing experience will be diminished.
|
Your browser does not seem to support javascript. As a result, your viewing experience will be diminished, and you have been placed in <strong>read-only mode</strong>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Please download a browser that supports javascript, or enable it, if it disabled (i.e. NoScript).
|
Please download a browser that supports javascript, or enable it, if it disabled (i.e. NoScript).
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
<ul class="posts">
|
<ul class="posts">
|
||||||
<!-- BEGIN main_posts -->
|
<!-- BEGIN main_posts -->
|
||||||
<li>
|
<li>
|
||||||
<div class="row-fluid">
|
<a name="{main_posts.pid}"></a>
|
||||||
<div class="span2">
|
<div class="row">
|
||||||
<img src="{main_posts.picture}" /><br />
|
<div class="col-lg-2 profile">
|
||||||
{main_posts.username}
|
<img class="img-thumbnail" src="{main_posts.picture}" /><br />
|
||||||
|
<span class="username">{main_posts.username}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="span10">
|
<div class="col-lg-10">
|
||||||
{main_posts.content}
|
{main_posts.content}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -14,12 +15,13 @@
|
|||||||
<!-- END main_posts -->
|
<!-- END main_posts -->
|
||||||
<!-- BEGIN posts -->
|
<!-- BEGIN posts -->
|
||||||
<li>
|
<li>
|
||||||
<div class="row-fluid">
|
<a name="{posts.pid}"></a>
|
||||||
<div class="span2">
|
<div class="row">
|
||||||
<img src="{posts.picture}" /><br />
|
<div class="col-lg-2 profile">
|
||||||
{posts.username}
|
<img class="img-thumbnail" src="{posts.picture}" /><br />
|
||||||
|
<span class="username">{posts.username}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="span10">
|
<div class="col-lg-10">
|
||||||
{posts.content}
|
{posts.content}
|
||||||
</div>
|
</div>
|
||||||
<div class="clear"></div>
|
<div class="clear"></div>
|
||||||
|
|||||||
@@ -1,11 +1,27 @@
|
|||||||
<div class="hero-unit">
|
<div class="outgoing">
|
||||||
<h2 class="form-signin-heading">Now Leaving NodeBB</h2>
|
<ol class="breadcrumb">
|
||||||
<p>
|
<li itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
|
<a href="/" itemprop="url"><span itemprop="title">Home</span></a>
|
||||||
|
</li>
|
||||||
|
<li class="active" itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
|
<span itemprop="title">Outgoing Link</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div class="well">
|
||||||
|
<h3>
|
||||||
You are now leaving NodeBB.
|
You are now leaving NodeBB.
|
||||||
</p>
|
</h3>
|
||||||
<br />
|
|
||||||
<p>
|
<p>
|
||||||
<a href="{url}" rel="nofollow" class="btn btn-large">Continue to {url}</a>
|
<a href="{url}" rel="nofollow" class="btn btn-primary btn-lg">Continue to {url}</a>
|
||||||
<a href="{home}" class="btn btn-large btn-inverse">Return to NodeBB</a>
|
<a id="return-btn" href="#" class="btn btn-lg btn-warning">Return to NodeBB</a>
|
||||||
</p>
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$('#return-btn').on('click', function() {
|
||||||
|
history.back();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
<div class="container">
|
<ol class="breadcrumb">
|
||||||
<ul class="breadcrumb">
|
<li><a href="/">Home</a></li>
|
||||||
<li><a href="/">Home</a><span class="divider">/</span></li>
|
|
||||||
<li class="active">{category_name}</li>
|
<li class="active">{category_name}</li>
|
||||||
<div id="category_active_users"></div>
|
<div id="category_active_users"></div>
|
||||||
</ul>
|
</ol>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<a href="/recent">
|
<a href="/recent">
|
||||||
<div class="alert hide" id="new-topics-alert"></div>
|
<div class="alert hide" id="new-topics-alert"></div>
|
||||||
@@ -21,23 +18,29 @@
|
|||||||
<!-- BEGIN topics -->
|
<!-- BEGIN topics -->
|
||||||
<a href="../../topic/{topics.slug}" id="tid-{topics.tid}">
|
<a href="../../topic/{topics.slug}" id="tid-{topics.tid}">
|
||||||
<li class="category-item {topics.deleted-class}">
|
<li class="category-item {topics.deleted-class}">
|
||||||
<div class="row-fluid">
|
<div class="row">
|
||||||
<div class="span12 topic-row img-polaroid">
|
<div class="col-md-12 col-xs-12 topic-row img-thumbnail">
|
||||||
<div class="latest-post visible-desktop">
|
<div class="latest-post visible-lg visible-md">
|
||||||
|
<a href="../../topic/{topics.slug}#{topics.teaser_pid}">
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<img style="width: 48px; height: 48px; /*temporary*/" src="{topics.teaser_userpicture}" />
|
<img class="img-rounded" style="width: 48px; height: 48px; /*temporary*/" src="{topics.teaser_userpicture}" />
|
||||||
<p><strong>{topics.teaser_username}</strong>: {topics.teaser_text}</p>
|
<p>{topics.teaser_text}</p>
|
||||||
<span>posted {topics.teaser_timestamp} ago</span>
|
<p class="meta">
|
||||||
|
<strong>{topics.teaser_username}</strong> posted <span class="timeago" title="{topics.teaser_timestamp}"></span>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
<a href="../../topic/{topics.slug}">
|
||||||
<div>
|
<div>
|
||||||
<h3><span class="topic-title"><span class="badge {topics.badgeclass}">{topics.postcount}</span>{topics.title}</span></h3>
|
<h3><span class="topic-title"><span class="badge {topics.badgeclass}">{topics.postcount}</span>{topics.title}</span></h3>
|
||||||
<small>
|
<small>
|
||||||
<strong><i class="{topics.pin-icon}"></i><i class="{topics.lock-icon}"></i></strong>
|
<strong><i class="{topics.pin-icon}"></i> <i class="{topics.lock-icon}"></i></strong>
|
||||||
Posted {topics.relativeTime} ago by
|
Posted <span class="timeago" title="{topics.relativeTime}"></span> by
|
||||||
<strong>{topics.username}</strong>.
|
<strong>{topics.username}</strong>.
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user