Compare commits

..

324 Commits

Author SHA1 Message Date
15badfeabe Update uwsgi to 4096 2025-05-17 01:10:21 +08:00
b6c561ef13 Removed lingering v2 recaptcha codes 2024-11-20 20:27:54 +08:00
b014148c31 Upgraded to Recaptcha v3 2024-11-15 08:23:32 +08:00
217c7efb88 Align notification center menu items 2024-11-14 23:12:32 +08:00
32884c3b7c Fixed preferred not working for SiteFile snippet 2024-11-14 15:25:28 +08:00
89e990c194 Forgot to pipe echo 2024-11-01 05:18:06 +08:00
cb6109876a Need linebreaks for multiple spec 2024-11-01 05:15:51 +08:00
a74f588640 Use configmap instead of secrets 2024-11-01 05:08:49 +08:00
3d05f82767 Dynamic contact button 2022-09-02 00:52:50 +08:00
ead452777e Remove Contact if recaptcha does not exist 2022-09-02 00:10:53 +08:00
3db2ae75e1 Removed now-useless container 2022-08-13 17:16:53 +08:00
bc7b440924 Display process time 2022-08-07 02:14:08 +09:00
e48346de0d Update README.md 2022-08-03 02:18:22 +09:00
880ec60407 Fixed rebuild hashbang 2022-08-03 01:52:09 +09:00
d5f76cd75b Removed duplicate headers 2022-08-03 01:35:32 +09:00
39b6d34376 Do not rebuild .c.* files if cache exists 2022-08-03 01:20:17 +09:00
a7c8c4dc84 Fixed all closure warnings 2022-08-03 00:54:40 +09:00
f0ab1a5d21 Attempt to reduce the amount of closure warnings 2022-08-03 00:34:37 +09:00
cc3ec05fb9 Fixed some css inheritence order 2022-08-03 00:17:51 +09:00
efb4eb0cde Fixed css crashing 2022-08-02 23:46:44 +09:00
27542b133c Bypass Celery for UNIT_TEST 2022-08-02 22:51:38 +09:00
70618b6b91 Better caching mechanics 2022-08-02 22:35:37 +09:00
00180c815d Dropped obsolete Build ns 2022-08-01 02:53:56 +09:00
15ed39bbee Fixed some snippet conf not set properly 2022-08-01 02:34:46 +09:00
c8210f2468 Revert "Revert prev commit, do not encodeURI on DataKey"
This reverts commit 04525d1e1a.
2022-08-01 02:23:34 +09:00
04525d1e1a Revert prev commit, do not encodeURI on DataKey 2022-07-31 22:06:39 +09:00
5cc5df4d3e decodeURI for album titles 2022-07-31 21:53:53 +09:00
ba9baacdd5 chmod setup/docker.start +x 2022-07-31 21:40:46 +09:00
87721da198 Use Concourse CI 2022-07-31 21:33:27 +09:00
856f1fae88 Fixed broken archive buttons 2022-04-19 19:12:02 +09:00
fc0ff969e9 Typo 2022-04-10 20:26:43 +09:00
6f3d85c7a8 Fixed broken avatar image style 2022-04-09 21:32:42 +08:00
b0ecbe42c3 Various bug fix due to CSP headers
SiteLibrary added name display on album view
Optimizations & removed some obsolete files
2022-04-09 20:47:11 +08:00
3b4ba29b6e Fixed compressed SyntaxHighlighter issue 2022-04-05 23:16:58 +09:00
5acc48289c Added RespH Snippet 2022-04-05 20:00:42 +09:00
16f112485a Reduced some image 301 round trips 2022-04-05 18:13:40 +09:00
ec55e174db Upgraded windows images to 20h2 2022-04-05 02:42:09 +09:00
2ede966b71 SiteFile can now have original size 2022-04-04 22:43:40 +09:00
962baf8d81 bind nginx conf from Secrets 2022-03-20 12:34:42 +09:00
3f02576dd8 Added nginx sidecar for direct access 2022-03-16 05:28:01 +09:00
9e1cb7f8a8 Fixed operation not permitted error 2022-03-16 03:16:36 +09:00
7fb7f01dc6 Split up k8s.yaml 2022-03-16 01:56:17 +09:00
9bd7f03301 Use initContainers to fix the permissions 2022-03-16 01:27:38 +09:00
923dfc5ba1 Using PVC instead, updated celery 2022-03-16 01:04:16 +09:00
a95c849f79 Use a smaller sized serif font 2021-09-10 15:30:44 +08:00
cc9c590581 Fixed ingress misconf for k8s 2021-09-06 00:29:08 +08:00
5cce3cf3e0 Merge branch 'core-master' into Astro 2021-09-05 23:30:07 +08:00
01dca50e2e Added docker windows container for dev 2021-09-05 23:26:51 +08:00
c631b194c4 Update image location for k8s changes 2021-09-05 22:02:29 +08:00
3fe92f03d6 Changed the compiler source 2020-09-24 00:10:46 +08:00
54ec35eb88 Proper name for igress res 2020-09-23 04:22:38 +08:00
2608ff4ed1 Use Alpine linux for smaller image 2020-09-23 02:57:50 +08:00
0640442953 Use a local redis instance 2020-09-23 02:03:35 +08:00
39ade9abe9 Added settings for k8s 2020-09-23 01:37:10 +08:00
c6c7d5dddc Use column-gap for album 2019-12-25 05:58:30 +08:00
3fcb6e22d7 Added AstXObject for dynamic class loading 2019-06-05 13:52:07 +08:00
9ac3479008 Moved SiteFiles.files to SFObjects 2019-04-02 00:52:14 +08:00
6f326d5b80 Use the swap font-display strategy 2019-04-01 21:52:50 +08:00
93bfc3d852 Darker background lines 2019-04-01 16:41:25 +08:00
b5cba02185 Fixed a naming conflict with grecaptcha 2019-04-01 15:40:44 +08:00
0c3381df99 Use compiled version in production 2019-03-10 15:37:54 +08:00
68bdcca991 Merge branch 'master' into Astro 2019-01-19 17:36:40 +08:00
7419c1c869 Rewrite service files for uwsgi & systemctl 2019-01-19 17:31:32 +08:00
9d4409c8e0 Better approach utilizing transform & animation frame 2019-01-19 17:20:30 +08:00
ed2cb2497e Merge remote-tracking branch 'origin/master' into Astro 2018-12-08 00:29:29 +08:00
a63e4751df Limit memory usage 2018-12-08 00:28:30 +08:00
89548ee569 Merge remote-tracking branch 'vim/master' into Astro 2018-11-20 18:06:37 +08:00
4462d7ba3d Added wq. Added custom wc which writes for copy to clipboard 2018-11-20 18:04:23 +08:00
5035d69b6b Merge remote-tracking branch 'vim/master' into Astro 2018-07-25 20:01:45 +08:00
17c4cc4d18 typo 2018-07-25 20:00:40 +08:00
7a29206edb Dispatch a "change" Event on quit to notify other handlers 2018-07-22 01:06:22 +08:00
f8722a3359 Removed unused js 2018-07-15 23:05:21 +08:00
f20d0b9773 Merge remote-tracking branch 'origin/master' into Astro 2018-05-15 17:57:14 +08:00
e6eb7ea34d Dropped Swd & ExtAPI 2018-05-15 17:55:56 +08:00
1cbc5a25a6 Removed parallax for Build, so laggy 2018-04-28 21:57:42 +08:00
c0f8ca7363 Merge remote-tracking branch 'vim/master' into Astro 2017-11-16 12:27:09 +08:00
9da78e2711 Improve the guessing of tabstop when file is in space 2017-11-16 12:25:50 +08:00
fcaab11145 Added dispatchEvent on Init 2017-11-08 11:05:50 +08:00
13b3288b74 Merge remote-tracking branch 'origin/master' into Astro 2017-10-26 16:22:38 +08:00
e2cec00454 Omitting http/s to follow current proto 2017-10-24 10:20:21 +08:00
a83b5c0680 Fixed vimeo https link 2017-10-24 10:14:05 +08:00
06700757ce Merge remote-tracking branch 'origin/master' into Astro 2017-09-26 13:09:21 +08:00
6c72ee9def Introducing new responsive classes 2017-09-26 13:01:10 +08:00
6945834de5 Merge remote-tracking branch 'vim/master' into Astro 2017-03-20 12:47:21 +08:00
4311ff3a6e Draft Actions MARK 2017-03-20 12:47:02 +08:00
282ecffce2 Added Support for S 2017-03-17 19:09:28 +08:00
3b21cce781 Merge remote-tracking branch 'vim/master' into Astro 2017-03-17 13:37:10 +08:00
1511c70957 Added :{number} support 2017-03-17 13:34:31 +08:00
68ee6dacc6 Fixed JOIN_LINES did not work properly 2017-03-15 15:12:42 +08:00
c9c5ff25af FIND does not work properly due to 5311dc0 2017-03-14 11:32:35 +08:00
7624d2b2fb Avoid using for..in 2017-03-07 18:45:38 +08:00
9aec0a1d82 Update README.md 2017-03-07 16:45:59 +08:00
87836ef9bb Update README.md 2017-03-07 16:44:58 +08:00
6070731899 Merge remote-tracking branch 'vim/master' into Astro 2017-03-07 15:56:52 +08:00
96b0a691c5 Advanced version number 2017-03-07 15:54:25 +08:00
08865e062e Fixed reverse FIND does not work properly 2017-03-07 15:01:40 +08:00
5311dc043d Fixed a cursor jumping issue for word-wrapped lines 2017-03-07 12:07:58 +08:00
a5e0be3221 Added Meta Snippet 2017-03-06 20:28:39 +08:00
28a15f031e Merge remote-tracking branch 'vim/master' into Astro 2017-03-02 18:28:09 +08:00
6c39f480bf can now q! 2017-03-02 18:26:14 +08:00
e81fe5cc37 Fix VA_REC broken by changes of DELETE 2017-01-31 11:54:53 +08:00
5f734a6030 Update Version Number 2017-01-30 21:00:49 +08:00
b9aefecb6f Merge remote-tracking branches 'origin/master' and 'vim/master' into Astro 2017-01-30 20:54:56 +08:00
0e84b4c260 Added c command 2017-01-30 20:51:12 +08:00
2fda27b7be c-d, c-u, HTML, gj, gk & bug fixes 2017-01-30 20:13:15 +08:00
06526f00a7 Added c-e, c-y 2017-01-30 14:55:57 +08:00
36a2dfac79 Fixed w motion, added e motion 2017-01-30 14:33:16 +08:00
b0f72f1281 b should not goes to the end of WORD 2017-01-30 13:41:05 +08:00
7000a67b4b Update Readme 2017-01-28 17:11:19 +08:00
9f7c0c4b7d Display session data in textarea instead of prompt 2017-01-28 14:37:58 +08:00
f85e65c23e Fixed last line cannot be dd-ed 2017-01-28 13:20:01 +08:00
a847510f49 VA_REC impl 2017-01-28 12:18:19 +08:00
d6a27ca87e First char INSERT issue due to prev commit 2017-01-25 15:42:05 +08:00
42bbc3b240 Fixed cursor mis-positioned on tab characters 2017-01-25 11:04:29 +08:00
7c6fa2bd18 Added Archived Ribbon 2017-01-10 18:06:55 +08:00
33bf67f587 Merge remote-tracking branch 'vim/master' into Astro 2017-01-09 10:49:14 +08:00
4b200697dc Fixed autoIndent by tab pos error 2017-01-09 10:48:00 +08:00
50686073d8 Replaced quirky tab char with virtual space chars 2017-01-09 10:18:21 +08:00
a6ccf7e4db Quote in between & PUT impl 2017-01-06 18:06:19 +08:00
39f4f086df Comment translate line breaks 2016-12-13 17:47:55 +08:00
61049939fb Fixed email address matching regex 2016-12-12 18:13:49 +08:00
5e48868fa8 HomeEntry Responsive style 2016-11-11 11:09:35 +08:00
0f2bf150a7 Merge remote-tracking branch 'origin/master' into Astro 2016-10-26 18:06:00 +08:00
1ab2e0a848 Mobile should have fewer slides 2016-10-26 18:02:34 +08:00
d4a8cba69c Merge remote-tracking branch 'origin/master' into Astro 2016-10-26 15:30:31 +08:00
8ef1df3c94 Gusets Comment Reply impl 2016-10-25 19:31:01 +08:00
fa50c2e90a Remove that freakin scrollbar! 2016-10-17 16:41:01 +08:00
a4762f734a Font weight should be bold for h4 2016-10-17 15:28:54 +08:00
9638054956 Style changes
Removed margin for code blocks
Reduce the resouces usage
Sync color across browsers
Using sans-serif font for chinese
Fixed the box-sizing for mbody
2016-10-14 13:13:06 +08:00
32804d23fb Sendmessage function 2016-09-10 02:00:17 +08:00
e674d339b0 Style changes 2016-07-10 03:34:41 +08:00
8f78202f75 Try not to trigger excessive style re-calc 2016-06-24 17:56:26 +08:00
18bcb8a81e Added dash line to show the document end 2016-06-08 23:46:02 +08:00
ce6e9eb43e Utilizing Starfall 2016-06-08 23:02:03 +08:00
e3914777c9 PublishSucces should also call save success 2016-06-08 13:04:57 +08:00
c739dfd76b Added transition decade 2016-06-04 13:21:36 +08:00
5b1955ced7 firefox does not support backgroundPositionY 2016-06-04 13:09:39 +08:00
bb9f8a87b3 background should cover the screen 2016-06-04 00:37:37 +08:00
1b48395017 Merge branch 'Astro' of AstroGit:BotanJS-Astro into Astro 2016-06-04 00:11:06 +08:00
3474ebd2fd Some minor adjustment, removed console log 2016-06-04 00:10:33 +08:00
581ac57d1b Changed the background 2016-06-04 00:09:28 +08:00
ceb74775ed Merge remote-tracking branch 'origin/master' into Astro 2016-06-01 00:36:53 +08:00
99bafa1483 Merge remote-tracking branch 'origin/master' into Astro 2016-06-01 00:24:16 +08:00
4cb79f9e85 Restructure 2016-05-31 23:32:39 +08:00
a2c96cec64 Removed testing templates for astrojs 2016-05-30 12:40:12 +08:00
5764257af7 Merge remote-tracking branch 'origin/master' into Astro 2016-05-30 12:33:09 +08:00
5a8b5225c0 Merge remote-tracking branch 'origin/master' into Astro 2016-05-28 01:49:27 +08:00
549eb95a90 Production config 2016-05-28 01:10:46 +08:00
5337d2d144 Fixed the redirection issue in AstroEdit 2016-05-28 00:25:53 +08:00
1829b333df Merge remote-tracking branch 'origin/master' into Astro 2016-05-28 00:25:22 +08:00
e7f169a7f8 Default ArticleContent set to inline-block 2016-05-25 13:03:36 +08:00
dd4f423919 Merge remote-tracking branch 'origin/master' into Astro 2016-05-25 12:16:56 +08:00
5d2029dd54 ArticleContent should display article title 2016-05-25 12:13:24 +08:00
1d17093c45 Merge remote-tracking branch 'origin/master' into Astro 2016-05-09 15:52:10 +08:00
a6c6de2407 Merge ArticleContent & ArticleReference together 2016-05-09 15:49:02 +08:00
047d82d3bb Doc fonts 2016-04-28 20:30:45 +08:00
664b0f2ec1 Update README.md 2016-04-28 12:38:38 +08:00
ebe6c67b31 Changed the link color 2016-04-28 10:49:55 +08:00
ebe1745429 New site for generating "tgckpg.github.io" 2016-04-27 23:44:49 +08:00
b816d0cd57 Fixed SyntaxHighlighter sometimes not initiating
Removed Penguin/Github
2016-04-27 23:44:06 +08:00
4ce1473d1c Merge remote-tracking branch 'vim/master' into Astro 2016-04-17 20:05:39 +08:00
5f42c711cf Bug fix UNDO / REDO error for indent chopping 2016-04-17 17:18:55 +08:00
3c2cb66c8f Bug fix for count movement 2016-04-16 22:33:02 +08:00
450a7d578c Polyfilling KeyboardEvent.key for Chrome < 51
Fixed mod commands overriding INSERT action
2016-04-16 21:50:16 +08:00
0413e943ae Enter act as j 2016-04-16 19:20:14 +08:00
5d91d516aa Bug fix for last line shifting 2016-04-16 19:07:13 +08:00
da21dd9a1e Merge remote-tracking branch 'vim/master' into Astro 2016-04-16 18:32:26 +08:00
d7b2754ba1 Update README.md 2016-04-16 04:05:47 +08:00
ce669c2cb6 Line shifting support 2016-04-16 04:00:15 +08:00
7229447ee1 UNDO / REDO for line shift 2016-04-16 00:51:21 +08:00
78cb3d3610 Partial indent command 2016-04-16 00:06:59 +08:00
a3fa2e82d7 PUT can now select registers 2016-04-07 23:56:09 +08:00
6f7a1cc92c Various bug fixes, rename InputEvent to ActionEvent 2016-04-07 23:11:23 +08:00
397239705c Indent based on last indent 2016-04-07 06:10:17 +08:00
2ea98446aa Added Snippet ArticleContent 2016-04-07 03:42:03 +08:00
2e56b29a1e Merge remote-tracking branch 'vim/master' into Astro 2016-04-07 03:03:40 +08:00
3db6a5d0b0 wrong col info 2016-04-07 03:01:21 +08:00
23fdc93a65 Update README.md 2016-04-05 07:52:25 +08:00
76243f2440 x also is removing last character... 2016-04-05 07:24:23 +08:00
20a8ced801 s-->e visual line AP at upper limit misplaced 2016-04-05 07:09:27 +08:00
de65c665a3 Merge remote-tracking branches 'vim/master' and 'origin/master' into Astro 2016-04-05 06:57:25 +08:00
6af0c542ab Missing commit 2016-04-05 06:56:02 +08:00
3ed8135791 minor bug fixes 2016-04-05 06:05:53 +08:00
11dbf01ddf Stator bug fix for UNDO / REDO 2016-04-05 04:36:29 +08:00
fcfe5d9b60 Added VISUAL LINE 2016-04-05 02:57:40 +08:00
2e175b33fd do not blur focus 2016-04-04 03:01:25 +08:00
6674931273 Vim Init 2016-04-04 02:08:18 +08:00
9e0af1531f Merge remote-tracking branches 'vim/master' and 'origin/master' into Astro 2016-04-04 02:08:06 +08:00
21221a6e4e Added ability to detect the screen size 2016-04-04 02:05:27 +08:00
cde4dd8c60 Prevent instance init collision 2016-04-04 00:35:59 +08:00
a72dcd8ca9 Guarding for infinite loop 2016-04-03 23:35:26 +08:00
fbb4bae316 Added b & w 2016-04-03 20:55:36 +08:00
3d2f3b889a Used the wrong movement function 2016-04-03 20:19:45 +08:00
4529f4b4a1 Added f, t movements 2016-04-03 19:46:35 +08:00
2b3eb9db31 JOIN_LINES for single action 2016-04-03 09:24:14 +08:00
593462f1e5 what?? 2016-04-03 08:01:48 +08:00
174ea40651 Merge remote-tracking branches 'vim/master' and 'origin/master' into Astro 2016-04-03 07:52:11 +08:00
be1fc29d39 Various basic editor commands 2016-04-03 07:50:19 +08:00
f4dc0e7d9c Some placeholder commands, working substitution 2016-04-03 05:23:26 +08:00
dd12efa607 Merge remote-tracking branch 'vim/master' into Astro 2016-04-02 20:09:19 +08:00
63575ce2e6 Update README.md 2016-04-02 20:08:04 +08:00
062e9d8bb9 FIND command 2016-04-02 20:00:23 +08:00
3ed7d2be84 History stacks 2016-04-02 18:35:12 +08:00
c7249c071c Search Ex Draft 2016-04-02 14:25:25 +08:00
ddc7058964 calculate document position 2016-04-01 05:22:02 +08:00
62d2de3800 fixed DEL the end resulting wrong pos 2016-04-01 04:52:41 +08:00
a927c90134 Rewrite moveX function 2016-04-01 04:05:43 +08:00
af2da6e023 Added YANK 2016-03-31 23:37:44 +08:00
cfa2e45e3d Put command 2016-03-31 20:25:43 +08:00
c24f74f70c Delete (Tested): dd diw d{bracket} dG dgg 2016-03-31 18:52:20 +08:00
8c5f50ec2c Bug fix for Ctrl + b/f 2016-03-31 04:34:08 +08:00
eb3669ebab Merge remote-tracking branch 'vim/master' into Astro 2016-03-31 03:19:31 +08:00
27ce6b3e50 Update README.md 2016-03-31 03:17:40 +08:00
79705e9b14 Reset analyzed content when needed 2016-03-31 03:12:18 +08:00
1bc1a90b31 Fixed a -> Enter -> BS -> Esc -> u inconsistency 2016-03-31 02:51:42 +08:00
553cab9776 Visual viw, viw{bracket}, Ctrl+f, Ctcl+b 2016-03-31 02:25:39 +08:00
030fb3226b Word range viw 2016-03-30 21:12:01 +08:00
2fbcce6a12 Lower the font-size of title, remove duplicate style 2016-03-30 20:17:59 +08:00
9faf2b4921 InputEvent carrying range 2016-03-30 20:11:48 +08:00
a7d2e80f4a Some boundary foundations 2016-03-30 08:39:13 +08:00
564aef86aa Previous approach had performance issue, fixing it 2016-03-30 06:17:37 +08:00
799a911e06 Partial % motion 2016-03-30 04:32:36 +08:00
c6e4bdc509 Merge remote-tracking branches 'origin/master' and 'vim/master' into Astro 2016-03-29 03:54:22 +08:00
3f687cb704 Some placeholders 2016-03-29 03:51:55 +08:00
78f8a20a5d DELETE command in VISUAL, generalized Stator Obj 2016-03-23 03:15:02 +08:00
5f5e0604fa Wrapping keyboardevent with InputEvent 2016-03-22 19:31:19 +08:00
75662e6d04 Some placeholder commands in VISUAL 2016-03-22 17:36:21 +08:00
605ac1e95a Update README.md 2016-03-22 02:55:29 +08:00
e52c312af5 added g8, v ( hightlight only )
Some structural changes on VimControls
2016-03-22 02:08:07 +08:00
8769e69f35 Insert mode line break bug fix 2016-03-20 07:52:44 +08:00
dc63a882e3 Aaiu, cursor position 2016-03-19 19:05:07 +08:00
b17ca21420 fixed G / gg issue on some cases 2016-03-18 08:34:36 +08:00
f227c7e16b G / gg commands 2016-03-18 05:55:04 +08:00
36897e6bbd Merge remote-tracking branches 'vim/master' and 'origin/master' into Astro 2016-03-18 05:39:13 +08:00
e0c50f1bff Rewrite the way to init VimControls 2016-03-18 05:32:51 +08:00
acb5d72d89 Added a beep sound 2016-03-18 03:35:45 +08:00
db922421be Handle the DELETE / BACKSPACE on INSERT 2016-03-17 19:59:07 +08:00
44fec5abfd Store the stacks indefinitely 2016-03-17 07:16:06 +08:00
865530709b Proper REDO / UNDO function ( without cursor pos ) 2016-03-17 06:08:38 +08:00
f1653727f2 Some sort of UNDO / REDO ( not functional yet ) 2016-03-17 04:57:43 +08:00
b1807ebc09 Merge remote-tracking branch 'origin/master' into Astro 2016-03-16 19:06:34 +08:00
ae6048ecb1 Merge remote-tracking branch 'vim/master' into Astro 2016-03-16 18:56:07 +08:00
bc3c511c6f Fix wrong position of lines with tab character 2016-03-16 18:55:18 +08:00
145445d6c1 Fix the link color in footnote 2016-03-16 18:53:59 +08:00
24dfd38eef The Github page 2016-03-16 00:14:40 +08:00
e2d9d83938 Merge remote-tracking branch 'vim/master' into Astro 2016-03-16 00:13:40 +08:00
5be04d850d Merge branch 'master' of github:tgckpg/BotanJS-vim 2016-03-16 00:12:00 +08:00
8bc4db7283 partial insert support 2016-03-16 00:11:39 +08:00
030a0f3c1a Create README.md 2016-03-15 06:12:31 +08:00
b7c693be07 externs 2016-03-15 05:22:37 +08:00
ee26a7dcc8 Remove useless imports 2016-03-15 03:38:05 +08:00
e883d154d2 Merge remote-tracking branch 'origin/master' into Astro 2016-03-15 03:08:46 +08:00
a6992e66a3 Merge remote-tracking branch 'vim/master' into Astro 2016-03-15 03:07:43 +08:00
52e4733fcc Some interfaces 2016-03-15 03:06:16 +08:00
cbec2c7475 wordwrap panning for k 2016-03-14 23:57:17 +08:00
97480cd0c6 wordwrap panning for j 2016-03-14 23:28:30 +08:00
9757dec7a0 Handle the tabwidth 2016-03-14 03:33:36 +08:00
bd35ed56b1 j for collapsed line ( partial ) 2016-03-14 02:15:24 +08:00
2548970f3a Partial nav of "jkhl$^" 2016-03-13 20:26:26 +08:00
751530b42d Some navigation, but not working:( 2016-03-13 08:35:29 +08:00
6ce714be1e Create LICENSE 2016-03-13 03:31:55 +08:00
d6bbf245c6 Some drafts 2016-03-13 03:30:33 +08:00
c83ca8e1a2 Login banned message 2016-03-11 22:17:02 +08:00
0e7234c325 Calendar style fix 2016-03-10 03:28:02 +08:00
cbd36260dc Escape strings 2016-03-09 23:42:55 +08:00
49d9bb0f4f Home entry image set to 100% 2016-03-09 19:58:35 +08:00
33b1d18836 Reset the candidate cycle when advancing levels 2016-03-09 14:54:46 +08:00
ab0add94d2 Merge remote-tracking branch 'origin/master' into Astro 2016-03-09 14:49:59 +08:00
9e310a6fe2 Match all 2016-03-09 14:48:58 +08:00
041617f0b4 Added footnote support 2016-03-06 23:25:13 +08:00
eda4250533 ArticleReference 2016-02-27 05:05:33 +08:00
a5cffc11e3 Destruct bug fix 2016-02-23 12:33:51 +08:00
ac5906de6e Merge remote-tracking branch 'origin/master' into Astro 2016-02-23 11:27:59 +08:00
fa8599d20d Heading snippet 2016-02-23 11:25:31 +08:00
33c515cd08 Early dynamic module loading for SmartInput 2016-02-22 09:45:59 +08:00
c7dc7430d8 Merge remote-tracking branch 'origin/master' into Astro 2016-02-22 07:56:20 +08:00
7be076461a Checkbox should wrapped with labels 2016-02-22 07:53:59 +08:00
e2cda7ca2c Choice Tabbing 2016-02-22 05:53:32 +08:00
1ab79e1d0d Merge remote-tracking branch 'origin/master' into Astro 2016-02-22 03:31:55 +08:00
5b04926596 Merge remote-tracking branch 'origin/master' into Astro 2016-02-22 03:10:20 +08:00
82ef981d0a SmartInput for back quoted text 2016-02-22 03:08:07 +08:00
82451a41b9 Responsive Ratio is now set to 1.2 2016-02-14 03:40:11 +08:00
f42ea7e190 CommentTaggle remove todo markings 2016-02-09 03:22:00 +08:00
4cc218b03a UserComment subscription 2016-02-09 02:24:20 +08:00
e37a9d8a72 Refine the notification panel 2016-02-07 09:13:22 +08:00
ebaceb86b9 Merge remote-tracking branch 'origin/master' into Astro 2016-02-07 05:44:15 +08:00
c0ab22eaee Minor adjustments 2016-02-07 05:20:41 +08:00
2b5ab65b20 Merge branch 'master' into Astro 2015-12-22 22:56:19 +08:00
33661021da Minor bug fixes for astroedit
sitefile snippet cancel not work
cannot delete Article
syntaxhighlighter disable quick-code
added rss button
2015-12-22 22:52:29 +08:00
73301ce88a Merge branch 'master' into Astro 2015-11-24 19:33:47 +08:00
bd966f2fac Https migrations 2015-11-24 19:23:30 +08:00
07ceb117da Various bug fixes & Preferred option for SiteFile 2015-10-27 07:50:11 +08:00
1b11a1dff0 wrong code 2015-10-21 02:33:42 +08:00
800b381f57 New Entry style - Tile 2015-10-21 02:23:10 +08:00
2778e12f38 minor bug fixes 2015-10-21 02:22:49 +08:00
8f05e37ee4 Check for grecaptcha availibility 2015-10-19 23:16:47 +08:00
dedb6bdae2 Merge branch 'master' into Astro 2015-10-01 00:45:16 +08:00
a35f33b1cf Minor bug fixes 2015-10-01 00:43:02 +08:00
3e8e6362b2 Early album draft 2015-09-30 00:46:54 +08:00
be4d5c6ce2 Merge branch 'master' into Astro 2015-09-28 07:41:19 +08:00
b741c687d8 Merge branch 'master' into Astro 2015-09-28 07:18:02 +08:00
ac7889e754 Chinese font fix 2015-09-28 03:26:22 +08:00
0f7896a925 Added Section, early plugin model 2015-09-23 02:23:16 +08:00
1d812de551 Generalize tags to flags 2015-09-22 19:31:53 +08:00
54464ce395 minor bugfixes 2015-09-21 02:04:53 +08:00
88ad9b8a53 Misc fixes 2015-09-08 20:25:50 +08:00
3294885db9 Contact form, brackground image and such 2015-09-02 19:04:14 +08:00
f98d2fd949 justify text 2015-09-02 11:56:00 +08:00
0cdd62d81f use bettor reading-font 2015-09-01 00:39:37 +08:00
22c0e5782e Bug fix for redirecting nulls 2015-08-31 15:07:55 +08:00
9042975e28 Allow indication for spoiler 2015-08-31 12:35:03 +08:00
4aaf3d445a Merge branch 'master' into Astro 2015-08-24 12:41:49 +08:00
4b4a430a5f Tag fix 2015-08-24 12:39:22 +08:00
2d858c48b8 deprecated the backup function 2015-08-21 12:38:13 +08:00
33808fd46d fix clicking the entire article for delete 2015-08-21 09:52:02 +08:00
a6618dc9ff Delete button 2015-08-18 16:03:07 +08:00
2d5b307fe3 Merge branch 'master' into Astro 2015-08-18 12:33:09 +08:00
1df7d4bb51 smooth backgroud wave 2015-08-18 12:28:51 +08:00
f1d20a82d4 Major bug fixes due to migration issue 2015-08-17 17:44:38 +08:00
f88643cead Pure Column 2015-08-15 01:13:54 +08:00
69b43d5b79 Added Library SyntaxHighlighter 2015-08-14 23:00:04 +08:00
c6a7cd79d3 Merge branch 'Astro' of AstroGit:BotanJS-Astro into Astro 2015-08-14 21:42:38 +08:00
0a25f87965 Astro Classes 2015-08-14 21:42:25 +08:00
fed72acd29 Astro Classes 2015-08-14 21:06:23 +08:00
360 changed files with 28649 additions and 543 deletions

17
.dockerignore Normal file
View File

@ -0,0 +1,17 @@
.dockerignore
.git
.gitignore
*~
*.swp
*.pyc
Dockerfile
k8s/
cache/
image/
concourse/
k8s/
windows/
__pycache__
cache/*
logs/*
env/*

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.DS_Store
*~ *~
*.swp *.swp
*.pyc *.pyc

24
Dockerfile Normal file
View File

@ -0,0 +1,24 @@
FROM alpine:3.15.3
WORKDIR /app
RUN mkdir -p /opt/utils
RUN apk add --update bash python3 uwsgi uwsgi-python openjdk11-jre-headless; python3 -m ensurepip
RUN echo "www-data:x:1001:1001:www-data:/var/www:/usr/sbin/nologin" >> /etc/passwd; echo "www-data:x:1001:" >> /etc/group
RUN pip3 install Flask redis compressinja Celery
ADD [ "https://github.com/tgckpg/BotanJS/releases/download/compressors/closure.jar" \
, "https://github.com/tgckpg/BotanJS/releases/download/compressors/yuicompressor.jar" \
, "/opt/utils/" ]
COPY . /app/
RUN chmod 644 /opt/utils/*.jar; \
chown www-data:www-data . -R
USER www-data
EXPOSE 5000
ENTRYPOINT ["setup/docker.start"]

View File

@ -1,8 +1,11 @@
# BotanJS # AstroJS for Blog
A working concept of Js/Css framework for web browsers [![Image](https://build.s.k8s.astropenguin.net/api/v1/teams/main/pipelines/astrojs/badge)](https://build.s.k8s.astropenguin.net/teams/main/pipelines/astrojs)
### Showcase The current backend Js/Css services for [my blog](https://blog.astropenguin.net)
- Pending
### Try it - Docker for windows (using windows container with nanoserver)
- docker -f windows/docker-compose.yml build
- docker -f windows/docker-compose.yml up
### Features ### Features
- Compressable by Closure Compiler (Advanced Compression) - Compressable by Closure Compiler (Advanced Compression)
@ -10,29 +13,13 @@ A working concept of Js/Css framework for web browsers
- Everything is merged into one file for that page - Everything is merged into one file for that page
- css class inheritance - css class inheritance
### Disclaimer
- This is a working concept. So it works on me. And may have a bunch of useless dependency. Use at your own risks!
### Documentation ### Documentation
- Will be added later - Will be added later
### Prerequisties ### Prerequisties
- python3 - python3
- virtualenv - virtualenv ( optional )
#### For Service.WebAPI
- pip install Flask - pip install Flask
- pip install Celery - pip install Celery
- pip install redis - pip install redis
- pip install compressinja - pip install compressinja
### Before start, run
```
virtualenv env
./botan-rebuild
```
#### To start just run ( in virtualenv )
```
./botan-start
```

View File

@ -1,4 +1,4 @@
#!env/bin/python #!/usr/bin/env python3
import os, sys import os, sys
sys.path.append( os.path.abspath( "." ) ) sys.path.append( os.path.abspath( "." ) )
@ -8,10 +8,10 @@ from botanjs.config import Config as config
SiteRoot = os.path.abspath( "." ) SiteRoot = os.path.abspath( "." )
# Setting the SiteRoot for config # Setting the SiteRoot for config
config["Paths"]["SiteRoot"] = SiteRoot; config["Paths"]["SiteRoot"] = SiteRoot
bmap = os.path.join( config["Paths"]["Cache"], "botanjs", "bmap.xml" ) bmap = os.path.join( config["Paths"]["Cache"], "botanjs", "bmap.xml" )
app.conf.update( BROKER_URL = config["BotanJS"]["CeleryBroker"] ) app.conf.update( broker_url = config["BotanJS"]["CeleryBroker"] )
JWork.buildClassMap.delay( config["BotanJS"]["SrcDir"], bmap ) JWork.buildClassMap.delay( config["BotanJS"]["SrcDir"], bmap )

View File

@ -1,57 +0,0 @@
#!env/bin/python
import os, sys
from botanjs.config import Config as config, DEBUG
from subprocess import Popen
from botanjs.service.webapi import WebAPI
SiteRoot = os.path.abspath( "." )
# Setting the SiteRoot for config
config["Paths"]["SiteRoot"] = SiteRoot;
# Create the lock folder for celery
lockDir = os.path.join( SiteRoot, "env", "var", "run", "celery" )
os.makedirs( lockDir, exist_ok=True )
sys.path.append( os.path.abspath( "." ) )
RUNTIME_ENV = os.path.abspath( os.path.join( "env", "bin" ) )
if RUNTIME_ENV not in os.environ[ "PATH" ]:
os.environ[ "PATH" ] = RUNTIME_ENV + os.pathsep + os.environ[ "PATH" ]
if __name__ == "__main__":
jwork = "botanjs.service.jwork"
nodeName = "botanNode1"
celOut = open( os.path.join( config["Paths"]["Log"], jwork + "-err.log" ), "a+" )
cel = Popen(
[
"celery", "multi", "restart", nodeName
, "-A", jwork, "worker"
, "--pidfile=" + os.path.join( lockDir, jwork + ".pid" )
, "--logfile=" + os.path.join( config["Paths"]["Log"], jwork + ".log" )
, "--workdir=" + config["Paths"]["Runtime"]
, "beat", "-l", "info"
]
, stdout = celOut
, stderr = celOut
)
celOut.close()
if not DEBUG and os.fork():
import logging
logging.basicConfig(
filename = os.path.join( config["Paths"]["Log"], "access.log" )
, level = logging.DEBUG
)
sys.exit()
WebAPI(
jsCache = config["Paths"]["Cache"]
, jsRoot = config["BotanJS"]["SrcDir"]
, brokerURL = config["BotanJS"]["CeleryBroker"]
)

View File

@ -1,12 +1,15 @@
#!/usr/bin/env python3 import os, re, sys
import os;
import re;
import sys;
from xml.dom import minidom from xml.dom import minidom
from collections import defaultdict from collections import defaultdict
from botanjs.config import DEBUG
if DEBUG:
from botanjs.utils import checksum_r as checksum
else:
from botanjs.utils import checksum
RegEx_N = re.compile( r""" RegEx_N = re.compile( r"""
.* .*
__namespace __namespace
@ -136,7 +139,7 @@ class ClassMap:
return True; return True;
def drawMap( self, ns, ci, ce, cf ): def drawMap( self, ns, ci, ce, cf, chksum ):
nsNode = self.getNode( ns ) nsNode = self.getNode( ns )
# Source every: # Source every:
@ -150,6 +153,8 @@ class ClassMap:
if not srcEvery: if not srcEvery:
nsNode.setAttribute( "src", cf ) nsNode.setAttribute( "src", cf )
nsNode.setAttribute( "js", chksum["js"] )
nsNode.setAttribute( "css", chksum["css"] )
for ex in ce: for ex in ce:
_t = eDef[ ex[0] ] _t = eDef[ ex[0] ]
@ -164,6 +169,8 @@ class ClassMap:
cNode.appendChild( impNode ) cNode.appendChild( impNode )
cNode.setAttribute( "src", cf ) cNode.setAttribute( "src", cf )
cNode.setAttribute( "js", chksum["js"] )
cNode.setAttribute( "css", chksum["css"] )
# the file dose not export classes # the file dose not export classes
# Hence it import for itself # Hence it import for itself
@ -187,7 +194,11 @@ class ClassMap:
continue continue
ns, ci, ce = classMeta( classFile ) ns, ci, ce = classMeta( classFile )
classFile = classFile.replace( self.R + os.path.sep, "" )
self.drawMap( ns, ci, ce, classFile )
return self.DOM.toxml()
chksum = {}
chksum[ "js" ] = checksum( classFile )
chksum[ "css" ] = checksum( classFile[:-2] + "css" )
classFile = classFile.replace( self.R + os.path.sep, "" )
self.drawMap( ns, ci, ce, classFile, chksum )
return self.DOM.toxml()

16
botanjs/compressor/closure.py Executable file → Normal file
View File

@ -1,13 +1,14 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
from sys import platform
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
from botanjs.config import Config as config from botanjs.config import Config as config
from botanjs.service.jwork import log
COMPILER = config[ "BotanJS" ][ "ClosureCompiler" ] COMPILER = config[ "BotanJS" ][ "ClosureCompiler" ]
if not os.path.isfile( COMPILER ): AVAILABLE = os.path.isfile( COMPILER )
raise Exception( "Compiler not found" )
COMPILER_OPTIONS = [ COMPILER_OPTIONS = [
@ -23,7 +24,7 @@ class Wrapper:
E = "" E = ""
def __init__( self ): def __init__( self ):
self.C = "java -jar "+ COMPILER + " " + " ".join( COMPILER_OPTIONS ) self.C = "java -jar -Xmx64M "+ COMPILER + " " + " ".join( COMPILER_OPTIONS )
def scanExterns( self, sdir ): def scanExterns( self, sdir ):
for root, dirs, files in os.walk( sdir ): for root, dirs, files in os.walk( sdir ):
@ -41,12 +42,15 @@ class Wrapper:
break break
def compress( self, loc ): def compress( self, loc ):
if not AVAILABLE:
log.error( "Compiler not found" )
return
content = "" content = ""
with open( loc, "rb" ) as f: with open( loc, "rb" ) as f:
content = f.read() content = f.read()
with NamedTemporaryFile() as f: with NamedTemporaryFile( delete = ( not platform == "win32" ) ) as f:
f.write( content[12:-5] ) f.write( content[12:-5] )
os.system( self.C + self.E + " --js " + f.name + " --js_output_file " + loc[:-3] + ".c.js" ) os.system( self.C + self.E + " --js " + f.name + " --js_output_file " + loc[:-3] + ".c.js" )

6
botanjs/compressor/yui.py Executable file → Normal file
View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
from sys import platform
from botanjs.config import Config as config from botanjs.config import Config as config
COMPILER = config[ "BotanJS" ][ "YuiCompressor" ] COMPILER = config[ "BotanJS" ][ "YuiCompressor" ]
@ -20,5 +21,8 @@ class Wrapper:
self.C = "java -jar " + COMPILER + " " + " ".join( COMPILER_OPTIONS ) self.C = "java -jar " + COMPILER + " " + " ".join( COMPILER_OPTIONS )
def compress( self, loc ): def compress( self, loc ):
os.system( self.C + " " + loc + " -o " + loc[:-4] + ".c.css" )
if platform == "win32":
loc = loc.replace( "C:", "" ).replace( "\\\\", "/" )
os.system( self.C + " " + loc + " -o " + loc[:-4] + ".c.css" )

12
botanjs/config.py Executable file → Normal file
View File

@ -1,7 +1,15 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import configparser import configparser, os
Config = configparser.ConfigParser( interpolation = configparser.ExtendedInterpolation() ) Config = configparser.ConfigParser( interpolation = configparser.ExtendedInterpolation() )
Config.read( "settings.ini" ) Config.read( "settings.ini" )
DEBUG = Config[ "Env" ][ "Debug" ] DEBUG = os.getenv( "DEBUG" )
if DEBUG is None:
DEBUG = Config.getboolean( "Env", "Debug" )
else:
Config[ "Env" ][ "Debug" ] = str( DEBUG == "1" )
REDIS_CONN = os.getenv( "REDIS_CONN" )
if not REDIS_CONN is None:
Config[ "Redis" ][ "ConnStr" ] = REDIS_CONN

View File

@ -1,7 +1,13 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
class log: class log:
def info( self, *args ):
@staticmethod
def info( *args ):
print( *args )
@staticmethod
def error( *args ):
print( *args ) print( *args )
class dummyTask( object ): class dummyTask( object ):
@ -18,7 +24,7 @@ class dummyTask( object ):
pass pass
class dummyConf: class dummyConf:
def update( self, BROKER_URL = None ): def update( self, broker_url = None ):
pass pass
class app: class app:

View File

@ -16,8 +16,11 @@ class Resolver:
EX_FUNC = "method" EX_FUNC = "method"
EX_CLASS = "class" EX_CLASS = "class"
_rLookup = None
def __init__( self, classMap ): def __init__( self, classMap ):
self.classMap = classMap self.classMap = classMap
self._rLookup = {}
self._reload() self._reload()
def _reload( self ): def _reload( self ):
@ -30,13 +33,23 @@ class Resolver:
def resource( self, elem ): def resource( self, elem ):
if "src" in elem.attrib: if "src" in elem.attrib:
return elem.attrib[ "src" ] key = elem.attrib[ "src" ]
if not key in self._rLookup:
self._rLookup[ key ] = {
"src": elem.attrib[ "src" ]
, "js": elem.attrib[ "js" ]
, "css": elem.attrib[ "css" ]
}
return self._rLookup[ key ]
parent = self.parentMap[ elem ] parent = self.parentMap[ elem ]
if parent != None: if parent is not None:
return self.resource( parent ) return self.resource( parent )
def locate( self, key ):
return self._rLookup.get( key )
def resolve( self, c, classList ): def resolve( self, c, classList ):
self.resolved = [] self.resolved = []
self.__resolve( c, classList ) self.__resolve( c, classList )
@ -99,7 +112,9 @@ class BotanClassResolver:
classMap = "" classMap = ""
flagCompress = True flagCompress = True
oModeIfSizelt = 50 * 1024
returnHash = False returnHash = False
returnDynamic = False
resv = None resv = None
def __init__( self, jwork, BotanRoot, classMap, cacheRoot ): def __init__( self, jwork, BotanRoot, classMap, cacheRoot ):
@ -122,12 +137,17 @@ class BotanClassResolver:
return content return content
def BotanCache( self, t ): def BotanCache( self, srcFile, fileHash, hashContentDynamic ):
content = ""
with open( t, "r" ) as f:
content = f.read()
return content for _ in [0]:
if hashContentDynamic and os.path.getsize( srcFile ) < self.oModeIfSizelt:
break
if self.returnHash:
return fileHash
with open( srcFile, "r" ) as f:
return f.read()
def cleanList( self, lista ): def cleanList( self, lista ):
olist = [] olist = []
@ -146,37 +166,35 @@ class BotanClassResolver:
if src not in classFiles: if src not in classFiles:
classFiles.append( src ) classFiles.append( src )
def cssLookup( self, jsList, cssList ): def cssLookup( self, classList, cssList ):
for f in jsList: for cdef in classList:
possibleList = [] f = cdef[ "src" ]
cssFile = os.path.splitext( f )[0] + ".css" cssFile = os.path.splitext( f )[0] + ".css"
if cssFile not in possibleList: cssGroup = []
possibleList.append( cssFile ) if not cdef[ "css" ] == "1":
cssGroup.append( cdef )
f = f.split( PY_SEP ) f = f.split( PY_SEP )
l = len( f ) l = len( f )
for i in range( 1, l ): for i in range( 1, l ):
cssFile = PY_SEP.join( x for x in f[:-i] ) + PY_SEP + "@_this.css" key = PY_SEP.join( x for x in f[:-i] ) + PY_SEP + "_this.js"
if cssFile not in possibleList: _def = self.resv.locate( key )
possibleList.append( cssFile )
possibleList.sort() if _def and not _def[ "css" ] == "1":
cssGroup.append( _def )
for f in possibleList:
f = f.replace( "@_this.css", "_this.css" )
if os.path.exists( os.path.join( self.R, f ) ):
cssList.append( f )
cssGroup.sort( key = lambda x : x[ "src" ] )
cssList.extend( cssGroup )
def getCache( self, fileList, cName, mode ): def getCache( self, fileList, cName, mode ):
if self.CR == None: if self.CR == None:
return None return None
md5 = hashlib.md5( bytearray( "".join( fileList ), "utf-8" ) ).hexdigest() md5 = hashlib.md5( bytearray( "|".join( x[mode] for x in fileList ), "utf-8" ) ).hexdigest()
cName[0] = oFHash = md5 + "." + mode cName[0] = oFHash = md5 + "." + mode
cFHash = md5 + ".c." + mode cFHash = md5 + ".c." + mode
@ -186,19 +204,14 @@ class BotanClassResolver:
# Compressed file # Compressed file
cFile = os.path.join( self.CR, cFHash ) cFile = os.path.join( self.CR, cFHash )
dates = list( cCached = self.useCache( cFile )
os.path.getmtime( os.path.join( self.R, x ) )
if os.path.exists( os.path.join( self.R, x ) ) else -1
for x in fileList
)
# Root file date if self.flagCompress and cCached:
dates.append( os.path.getmtime( os.path.join( self.R, "_this.js" ) ) ); return self.BotanCache( cFile, cFHash, self.returnDynamic )
if self.flagCompress and self.useCache( cFile, dates ): if self.useCache( oFile ):
return cFHash if self.returnHash else self.BotanCache( cFile )
elif self.useCache( oFile, dates ): if not cCached:
self.JWork.saveCache( self.JWork.saveCache(
oFile oFile
# Content is None to initiate a compression # Content is None to initiate a compression
@ -207,19 +220,12 @@ class BotanClassResolver:
, os.path.join( self.R, "externs" ) , os.path.join( self.R, "externs" )
) )
return oFHash if self.returnHash else self.BotanCache( oFile ) return self.BotanCache( oFile, oFHash, False )
def useCache( self, f, dList ): return None
if not os.path.exists( f ):
return False
t = os.path.getmtime( f ) def useCache( self, f ):
return os.path.exists( f )
for i in dList:
if t < i:
return False
return True
def compileJs( self, cList, xList ): def compileJs( self, cList, xList ):
md5 = [ None ] md5 = [ None ]
@ -229,14 +235,14 @@ class BotanClassResolver:
cacheFile = self.getCache( cList, md5, "js" ) cacheFile = self.getCache( cList, md5, "js" )
if cacheFile != None: if cacheFile is not None:
return cacheFile; return cacheFile;
# The root file # The root file
outputJs = self.BotanFile( "_this.js" ) outputJs = self.BotanFile( "_this.js" )
for f in cList: for f in cList:
f = f[ "src" ]
path = ( path = (
os.path.splitext( f )[0] os.path.splitext( f )[0]
.replace( PY_SEP, "." ) .replace( PY_SEP, "." )
@ -248,7 +254,7 @@ class BotanClassResolver:
outputJs = wrapScope( outputJs ) outputJs = wrapScope( outputJs )
[ self.JWork.saveCache if self.returnHash else self.JWork.saveCache ][0] ( self.JWork.saveCache(
os.path.join( self.CR, md5[0] ) os.path.join( self.CR, md5[0] )
, outputJs , outputJs
, "js" , "js"
@ -275,17 +281,16 @@ class BotanClassResolver:
md5 = [ None ] md5 = [ None ]
cacheFile = self.getCache( cList, md5, "css" ) cacheFile = self.getCache( cList, md5, "css" )
if cacheFile != None: if cacheFile is not None:
return cacheFile; return cacheFile;
outputCss = "" struct = "/* @ */"
outputCss = struct + self.BotanFile( "_this.css" )
for f in self.cleanList( cList ): for f in self.cleanList( cList ):
outputCss += self.BotanFile( f ) outputCss += self.BotanFile( f["src"][:-2] + "css" )
[ self.JWork.saveCache if self.returnHash else self.JWork.saveCache ][0] ( self.JWork.saveCache( os.path.join( self.CR, md5[0] ), outputCss, "css" )
os.path.join( self.CR, md5[0] ), outputCss, "css"
)
if self.returnHash: if self.returnHash:
return md5[0] return md5[0]
@ -299,13 +304,26 @@ class BotanClassResolver:
flag = mode[0] flag = mode[0]
requestAPIs = code requestAPIs = code
# Return compressed contents if possible
# otherwise return raw contents
if flag == "o": if flag == "o":
mode = mode[1:] mode = mode[1:]
# Return raw contents only
elif flag == "r": elif flag == "r":
mode = mode[1:] mode = mode[1:]
self.flagCompress = False self.flagCompress = False
# Return hashed filenames only
elif flag == "h":
mode = mode[1:]
self.returnHash = True
# Return hashed filenames if content is larger than self.oModeIfSizelt bytes
# otherwise act as "o" mode
else: else:
self.returnHash = True self.returnHash = True
self.returnDynamic = True
try: try:
requestAPIs = ( requestAPIs = (
@ -329,7 +347,8 @@ class BotanClassResolver:
for apis in requestAPIs: for apis in requestAPIs:
if apis == None: continue if not apis:
continue
classList = [] classList = []
lookupList = imports lookupList = imports

View File

@ -1,10 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
from botanjs.compressor.closure import Wrapper as ClosureWrapper
from botanjs.compressor.yui import Wrapper as YUIWrapper
from botanjs.classmap import ClassMap from botanjs.classmap import ClassMap
if os.getenv( "UNIT_TEST" ) == "1":
CeleryExists = False
else:
CeleryExists = True CeleryExists = True
try: try:
from celery import Celery from celery import Celery
except ImportError: except ImportError:
@ -17,7 +19,7 @@ if CeleryExists:
if os.path.exists( "settings.ini" ): if os.path.exists( "settings.ini" ):
from botanjs.config import Config from botanjs.config import Config
app.conf.update( BROKER_URL = Config["BotanJS"]["CeleryBroker"] ) app.conf.update( broker_url = Config["BotanJS"]["CeleryBroker"] )
else: else:
from botanjs.dummy import app from botanjs.dummy import app
@ -34,10 +36,11 @@ class JWork:
if mode == "js": if mode == "js":
JWork.compressJs.delay( location, externs ) JWork.compressJs.delay( location, externs )
elif mode == "css": elif mode == "css":
JWork.compressCss.delay( location ) JWork.compressCss( location )
@app.task() @app.task()
def compressJs( md5, externs ): def compressJs( md5, externs ):
from botanjs.compressor.closure import Wrapper as ClosureWrapper
log.info( "Compress js: " + md5 ) log.info( "Compress js: " + md5 )
w = ClosureWrapper() w = ClosureWrapper()
w.scanExterns( externs ) w.scanExterns( externs )
@ -45,6 +48,7 @@ class JWork:
@app.task() @app.task()
def compressCss( md5 ): def compressCss( md5 ):
from botanjs.compressor.yui import Wrapper as YUIWrapper
log.info( "Compress css: " + md5 ) log.info( "Compress css: " + md5 )
w = YUIWrapper() w = YUIWrapper()
w.compress( md5 ) w.compress( md5 )
@ -54,5 +58,6 @@ class JWork:
log.info( "Building Class Map" ) log.info( "Building Class Map" )
c = ClassMap( src ) c = ClassMap( src )
os.makedirs( os.path.dirname( location ), exist_ok = True )
with open( location, "w" ) as f: with open( location, "w" ) as f:
f.write( c.build() ) f.write( c.build() )

20
botanjs/service/webapi.py Executable file → Normal file
View File

@ -1,11 +1,10 @@
#!/usr/bin/env python3
from flask import Flask from flask import Flask
from flask import Response from flask import Response
from flask import render_template from flask import render_template
from flask import request from flask import request
from botanjs.service.jclassresv import BotanClassResolver as JCResv from botanjs.service.jclassresv import BotanClassResolver as JCResv
from botanjs.service.jwork import app as CeleryApp, JWork from botanjs.service.jwork import app as CeleryApp, JWork
from botanjs.config import Config, DEBUG from botanjs.config import Config
import os import os
@ -24,25 +23,28 @@ class WebAPI:
self.BMap = os.path.join( self.BCache, "bmap.xml" ) self.BMap = os.path.join( self.BCache, "bmap.xml" )
if brokerURL != None: if brokerURL != None:
CeleryApp.conf.update( BROKER_URL = brokerURL ) CeleryApp.conf.update( broker_url = brokerURL )
self.app = Flask( __name__, static_url_path = self.BCache, static_folder = self.BCache ) self.app = Flask( __name__, static_url_path = "/cache/botanjs", static_folder = self.BCache )
self.app.jinja_env.add_extension( "compressinja.html.HtmlCompressor" ) self.app.jinja_env.add_extension( "compressinja.html.HtmlCompressor" )
self.app.add_url_rule( "/" , view_func = self.index ) self.app.add_url_rule( "/" , view_func = self.index )
self.app.add_url_rule( "/<mode>/" , view_func = lambda mode: self.api_request( mode, "zpayload" ) ) self.app.add_url_rule( "/<mode>/" , view_func = lambda mode: self.api_request( mode, "zpayload" ) )
self.app.add_url_rule( "/<mode>/<path:code>" , view_func = self.api_request ) self.app.add_url_rule( "/<mode>/<path:code>" , view_func = self.api_request )
self.app.run( def run( self, *args, **kwargs ):
host = Config[ "Service" ][ "BindAddress" ] JWork.buildClassMap( self.BRoot, self.BMap )
, port = int( Config[ "Service" ][ "Port" ] ) return self.app.run( *args, **kwargs )
, debug = DEBUG )
def index( self ): def index( self ):
return "Hello, this is the BotanJS Service API.", 200 return "Hello, this is the BotanJS Service API.", 200
def api_request( self, mode, code ): def api_request( self, mode, code ):
if mode == "rebuild":
JWork.buildClassMap.delay( self.BRoot, self.BMap )
return "OK", 200
if code == "zpayload": if code == "zpayload":
code = request.args.get( "p" ) code = request.args.get( "p" )
@ -56,6 +58,8 @@ class WebAPI:
srvHandler = JCResv( JWork, self.BRoot, self.BMap, self.BCache ) srvHandler = JCResv( JWork, self.BRoot, self.BMap, self.BCache )
return Response( srvHandler.getAPI( code, mode = mode ), mimetype = t ) return Response( srvHandler.getAPI( code, mode = mode ), mimetype = t )
except Exception as e: except Exception as e:
if self.app.config[ "DEBUG" ]:
raise
return str(e), 404 return str(e), 404

View File

@ -0,0 +1,554 @@
(function(){
var ns = __namespace( "Astro.Blog.AstroEdit" );
/** @type {System.Cycle} */
var Cycle = __import( "System.Cycle" );
/** @type {System.utils} */
var utils = __import( "System.utils" );
/** @type {System.utils.EventKey} */
var EventKey = __import( "System.utils.EventKey" );
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMObject} */
var IDOMObject = __import( "Dandelion.IDOMObject" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Astro.Blog.Config} */
var Config = __import( "Astro.Blog.Config" );
/** @type {Astro.Blog.Components.Bubble} */
var Bubble = __import( "Astro.Blog.Components.Bubble" );
var opostData = __import( "System.Net.postData" );
var prettyDate = __import( "Astro.utils.Date.pretty" );
var Visualizer = ns[ NS_INVOKE ]( "Visualizer" );
var Flag = ns[ NS_INVOKE ]( "Flag" );
// Editor Override
var postData = function( processor, data, success, failed )
{
data[ "editor" ] = 1;
opostData( processor, data, success, failed );
};
// Wrappers for every plugins
var PluginBundles = function( article, plugins )
{
this.plugins = plugins;
for( var i in this.plugins )
{
/* @type {Astro.Blog.AstroEdit.IPlugins} */
var g = this.plugins[i];
g.bindArticle = article;
}
};
PluginBundles.prototype.setForView = function( pluginId, data )
{
for( var i in this.plugins )
{
var p = this.plugins[i];
if( p.id == pluginId )
{
p.setForView( data );
}
}
};
PluginBundles.prototype.getData = function( pluginId, data )
{
for( var i in this.plugins )
{
var p = this.plugins[i];
if( p.id == pluginId )
{
return p.getData( data );
}
}
};
var Article = function( processorSet, plugins )
{
var pBubble = new Bubble();
var Draft = ns[ NS_INVOKE ]( "Draft" );
var _title = "";
var _content = "";
//// Classes & obj
var _visualizer = null;
var timestamp = new Date();
/** @type {_AstJson_.AJaxGetArticle.entry} */
var ArticleModel = {
title: ""
, slug: ""
, content: ""
, date_modified: timestamp
, date_published: timestamp
, date_created: timestamp
, archived: false
, tags: null
, section: null
, draft: true
, article_id: false
};
var ae_content = Dand.id( "ae_content" );
var ae_title = Dand.id( "ae_title" );
// Article info
var ae_cdate = Dand.id( "ae_cdate" );
var ae_mdate = Dand.id( "ae_mdate" );
var ae_pdate = Dand.id( "ae_pdate" );
var ae_status = Dand.id( "ae_status" );
var ae_backup = Dand.id( "ae_backup_btn" );
var ae_publish = Dand.id( "ae_publish_btn" );
var ae_preview = Dand.id( "ae_preview" );
/** @type {_AstConf_.AstroEdit} */
var a_conf = Config.get( "AstroEdit" );
var base_path = utils.siteProto( Config.get( "BasePath" ) );
/*{{{ preview fields */
var ae_p_fields = {
mtime: set_field_name( Dand.wrap( "input" ), "date_modified" )
, ptime: set_field_name( Dand.wrap( "input" ), "date_published" )
, title: set_field_name( Dand.wrap( "input" ), "title" )
, content: set_field_name( Dand.wrap( "input" ), "content" )
, tags: set_field_name( Dand.wrap( "input" ), "tags" )
, section: set_field_name( Dand.wrap( "input" ), "section" )
};
// Initialize id
var __article_id = false;
var canSave = false;
var temp;
for ( var i in ae_p_fields ) ae_preview.appendChild( ae_p_fields[i] );
/* End preview fields }}}*/
/*{{{ Button sections */
var ae_stitles = Dand.glass( "ae_stitle", true );
var ae_panel_section = Dand.glass( "ae_panel_section", true );
var l = ae_stitles.length;
for( var i = 0; i < l; i ++ )
{
var t = ae_stitles[i];
var p = ae_panel_section[i];
// If they are snippets or sections
if( i == 2 || i == 3 )
{
p.style.height = "auto";
continue;
}
t.addEventListener( "Click", function( e )
{
var p = this.p;
if( this.t.expanded = !this.t.expanded )
{
p.style.height = "auto";
Cycle.next(
function(){
p.style.height = this.h + "px";
}.bind({ h: p.element.clientHeight })
);
p.style.height = 0;
}
else
{
p.style.height = 0;
}
}.bind({ t: t, p: p }) );
}
ae_stitles[0].element.click();
/* End Button sections }}}*/
// Install plugins
plugins = new PluginBundles( this, plugins );
var enableSaveFunction = function ()
{
ae_backup.className = "ae_iValue ae_dodgerblue flsf";
canSave = true;
}
, disableSaveFunction = function ()
{
ae_backup.className = "ae_iValue ae_disabled flsf";
canSave = false;
}
, contentUpdate = function ()
{
if( !canSave ) enableSaveFunction();
// (_visualizer.saveRaw() != _content) ? enableSaveFunction() : disableSaveFunction();
}
//// private methods
////// Handlers ///////
, saveSuccess = function ( obj )
{
disableSaveFunction();
ae_mdate.innerHTML = prettyDate( new Date( obj.date_modified ) );
// Replace state of the content and title
ArticleModel.title = _title;
ArticleModel.content = _content;
ArticleModel.date_modified = obj.date_modified;
// If this is a published article
// we need to set the ref_id for ArticleModel
// then set current id to draft's id
if( ArticleModel.article_id != obj.article_id )
{
ArticleModel.draft = true;
ArticleModel.ref_id = __article_id;
ArticleModel.article_id = obj.article_id;
}
// Set article id if this is a new document
if ( obj.article_id )
ArticleModel.article_id = __article_id = obj.article_id;
window.history.replaceState( ArticleModel, "", base_path + "astroedit/" + __article_id + "/" );
}
, publishSuccess = function ( obj )
{
saveSuccess( obj );
ae_publish.innerHTML = "Done edit";
ae_backup.innerHTML = "Backup(Ctrl + s)";
ArticleModel.date_published = obj.date_published;
ae_pdate.innerHTML = prettyDate( new Date( obj.date_published ) );
this.contentUpdate && saveSuccess( obj );
new MessageBox(
"AstroEdit"
, "You have successfully published your article!"
, "Stay here", "Exit and goto article"
, publishAction
).show();
}
, publishAction = function ( stay )
{
if ( !stay )
{
var op = window.open( base_path + "article/id-view/" + ArticleModel.article_id + "/" );
Cycle.next( function() {
if( op ) window.close();
});
}
}
, restoreArticle = function( obj )
{
debug.Info("[Document] Looking for stored data");
if ( obj )
{
debug.Info("[Document] .. data found");
// Set stored article id
__article_id = obj.article_id;
setArticle( obj );
}
else
{
if (!( ArticleModel && 0 < ArticleModel.article_id ))
{
debug.Info("[Document] .. data not found");
// This is a state of new article
var d = Math.floor(new Date().getTime()/1000);
__article_id = false;
setArticle({
title:""
, content:""
, date_modified: d
, date_published: 0
, date_created: d
, archived: false
, tags: null
, draft: true
, article_id: false
});
window.history.replaceState( ArticleModel, "", base_path + "astroedit/new/" );
}
}
}
/** @param {_AstJson_.AJaxGetArticle} */
, showArticle = function( obj )
{
if ( obj && obj.entry )
{
debug.Info( "[Document] Article Loaded" );
if ( obj.entry.ref_id )
{
// This is a backup item
__article_id = obj.article_id;
pBubble.setColor( "royalblue" );
pBubble.pop( "Using backup entry" );
Cycle.delay( function () { pBubble.blurp() }, 3000 );
}
setArticle( obj.entry );
__statePusher( obj.entry, __article_id );
}
else
{
debug.Info( "[Document] Article: " + String( __article_id ) + " not found on server." );
__article_id = false;
}
}
, setArticle = function ( entry )
{
ArticleModel = entry;
ae_title.value = _title = ArticleModel.title;
_visualizer.visualizeData( _content = ArticleModel.content );
ae_mdate.innerHTML = prettyDate( new Date( ArticleModel.date_modified ) );
ae_cdate.innerHTML = prettyDate( new Date( ArticleModel.date_created ) );
ae_pdate.innerHTML = ArticleModel.date_published
? prettyDate( new Date( ArticleModel.date_published ) )
: "Not published."
;
ae_status.innerHTML =
( ArticleModel.archived ? "Archived. " : "" )
+ ( ArticleModel.draft ? "In draft" : "Published" )
;
ae_publish.innerHTML = ArticleModel.draft ? "Publish" : "Done edit";
ae_backup.innerHTML = ( ArticleModel.draft ? "Save" : "Backup" ) + "(Ctrl + s)";
plugins.setForView( "tags", ArticleModel.tags );
plugins.setForView( "section", ArticleModel.section );
}
, deleteDraft = function ( confirmed )
{
if ( confirmed )
{
var _data = {
"draft": ArticleModel.draft ? 1 : 0
, "article_id": __article_id
, "del": 1
};
postData( processorSet, _data, deleteSuccess, serverFailed );
}
}
, deleteSuccess = function ( obj )
{
var loc = window.location;
loc.replace(
loc.href.replace(
"/" + ArticleModel.article_id
, ArticleModel.ref_id ? ( "/" + ArticleModel.ref_id ) : ""
)
);
}
, serverFailed = function ( obj )
{
pBubble.setColor( "red" );
pBubble.pop( obj ? obj["mesg"] : "Server Error" );
Cycle.delay( function () { pBubble.blurp() }, 3000 );
}
, contentEmpty = function ()
{
return !Boolean( ae_content.hasChildNodes() );
}
;
// Bind properties
this.saveOrBackup = function ()
{
if ( canSave )
{
// Store current content and title
_title = ae_title.value.trim();
_content = _visualizer.saveRaw();
/** @type {_AstJson_.AJaxGetArticle.entry} */
var _data =
{
article_id: __article_id ? __article_id : ""
, title: _title
, content: _content
, draft: 1
, tags: plugins.getData( "tags" )
, section: plugins.getData( "section" )
};
postData( processorSet, _data, saveSuccess, serverFailed );
}
};
this.load = function ( aid, statePusher )
{
if( aid && __article_id != aid )
{
debug.Info( "[Document] Loading article: " + aid );
__statePusher = statePusher;
postData(
a_conf.paths.get_article
, { article_id: __article_id = aid }
, showArticle
, serverFailed
);
}
};
this.getArticleId = function () { return __article_id; }
this.preview = function ()
{
ae_p_fields.title.value = ae_title.value;
ae_p_fields.content.value = _visualizer.saveRaw();
ae_p_fields.mtime.value = ArticleModel.date_modified;
ae_p_fields.ptime.value = Number( ArticleModel.date_published )
? ArticleModel.date_published
: Math.floor( 0.001*( new Date().getTime() ) )
;
ae_p_fields.tags.value = plugins.getData( "tags" );
ae_p_fields.section.value = plugins.getData( "section" );
ae_preview.submit();
};
this.invoke = function (_class)
{
if ( _class instanceof Draft ) _ae_draft = _class;
if ( _class instanceof Visualizer )
{
_visualizer = _class;
_visualizer.setContentDiv( ae_content );
}
};
this.saveAndPublish = function ()
{
if ( contentEmpty() ) return;
/** @type {_AstJson_.AJaxGetArticle.entry} */
var _data = {
article_id: __article_id ? __article_id : ""
, draft: 0
};
if ( !ArticleModel.draft )
{
// This is a published article
canSave = true;
}
if ( canSave )
{
// Store current content and title
_title = ae_title.value.trim();
_content = _visualizer.saveRaw();
_data.title = _title;
_data.content = _content;
_data.tags = plugins.getData( "tags" );
_data.section = plugins.getData( "section" );
postData( processorSet, _data, publishSuccess.bind({ contentUpdate: true }), serverFailed );
}
else
{
// Do not submit uneccessary data!
postData( processorSet, _data, publishSuccess, serverFailed );
}
};
this.drop = function ()
{
if( ArticleModel.draft )
{
new MessageBox(
"Delete draft"
, "Are you sure you want to delete this draft? (Published article will only remove backup draft.)"
, "Delete", "No"
, deleteDraft
).show();
}
else
{
new MessageBox(
"Delete Draft"
, "There is no draft to delete"
).show();
}
};
this.updateContent = contentUpdate;
// Setting Ctrl+s functions
new IDOMObject(document).addEventListener(
new EventKey("KeyDown", function(e)
{
// key Ctrl(17)
if(e.ctrlKey == true && e.which == 83)
{
// key s (83)
this.saveOrBackup();
e.preventDefault();
}
}.bind(this))
);
IDOMElement( ae_backup ).addEventListener( "Click", this.saveOrBackup );
window.addEventListener(
"popstate"
, function( event )
{
debug.Info( "[Document] Pop State fired" );
restoreArticle( event.state );
}
);
ae_title.oninput = function ()
{
( ae_title.value != _title ) ? enableSaveFunction() : disableSaveFunction();
}
temp = IDOMElement(ae_content);
temp.addEventListener( "Input", function() { enableSaveFunction(); } );
document.body.appendChild( pBubble.init() );
return this;
};
var set_field_name = function ( elem, value )
{
elem.name = value;
elem.type = "hidden";
return elem;
};
ns[ NS_EXPORT ]( EX_CLASS, "Article", Article );
})();

View File

@ -0,0 +1,158 @@
(function(){
var ns = __namespace( "Astro.Blog.AstroEdit" );
/** @type {System.Cycle} */
var Cycle = __import( "System.Cycle" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
var postData = __import( "System.Net.postData" );
/** @param {Astro.Blog.AstroEdit.Article} article */
var Draft = function ( article, draftsUri )
{
/** @type {Astro.Blog.AstroEdit.Article} */
var Article = ns[ NS_INVOKE ]( "Article" );
if ( !( article instanceof Article ) ) return;
// Drafts Container
var ae_expand = Dand.id("ae_expand")
, ae_drafts = Dand.id("ae_user_drafts")
, ae_drafts_h = null
////// Draft Section
, showDrafts = function ()
{
showDrafts = function() { };
// One-time trigger only.
getDraftList({offset: 0});
}
, getDraftList = function ( p )
{
postData( draftsUri, p, listDraft.bind(p), draftFailed );
}
/** @param {_AstJson_.AJaxGetDrafts} obj */
, listDraft = function ( obj )
{
var entries = obj.entries, entry;
for ( var i in entries )
{
/** @param {_AstJson_.AJaxGetDrafts.entry} */
entry = entries[i];
// Insert entries
ae_drafts.appendChild(
entry = Dand.wrapc(
"ae_dEntry"
, [
Dand.wrapc(
"ae_dEntry_title fls"
, entry.active
?
[
Dand.textNode( entry.title )
, Dand.wrap( "span", null, "ae_dActive_bubble", "\u25CF" )
]
: entry.title
)
, Dand.wrapc( "ae_dEntry_content flsf", entry.content )
, Dand.wrapc( "ae_dEntry_date fsf", entry.date )
]
, entry.active
? [ new IKey ( "value", entry._id ), new IKey( "active" ) ]
: new IKey( "value", entry._id ) )
);
// Register on click function
entry.addEventListener( "click", function() {
article.load( this.getAttribute( "value" ), __pushState );
}.bind( entry ) );
}
ae_drafts_h = ae_drafts.clientHeight;
ae_drafts.style.height = 0;
Cycle.next(function(){
// This doesn't make sense
// but we need to actually access the clientHeight
// to get the height animation working
ae_drafts.clientHeight;
ae_drafts.style.height = String( ae_drafts_h ) + "px";
});
}
, draftFailed = function (obj)
{
}
// Handlers
, setupExpand = function ()
{
ae_expand.className = "ae_expand_btn";
var panel = Dand.id("ae_minor_panel");
panel.onmouseover = function()
{
ae_expand.style.height = "20px";
}
panel.onmouseout = function()
{
ae_expand.style.height = "";
}
panel.onclick = function()
{
ae_expand.style.height = "";
ae_drafts.style.height = String(ae_drafts_h) + "px";
Cycle.delay(setupCollapse , 250);
// Disable mouse events
panel.onmouseover = panel.onmouseout = panel.onclick = null;
showDrafts();
}
}
, setupCollapse = function ()
{
ae_expand.className = "ae_callapse_btn";
Cycle.delay(function()
{
ae_expand.onclick = function()
{
ae_expand.style.backgroundColor = "";
ae_drafts.style.height = "0";
Cycle.delay(setupExpand, 250);
// Disable mouse events
ae_expand.onmouseover = ae_expand.onmouseout = ae_expand.onclick = null;
}
ae_expand.onmouseover = function()
{
ae_expand.style.backgroundColor = "rgba(255, 255, 255, 0.2)";
}
ae_expand.onmouseout = function()
{
ae_expand.style.backgroundColor = "";
}
}, 250);
}
// End Handlers
, __pushState = function ( obj, article_id )
{
window.history.pushState( obj, "", "/astroedit/" + article_id + "/" );
}
setupExpand();
article.invoke( this );
};
ns[ NS_EXPORT ]( EX_CLASS, "Draft", Draft );
})();

View File

@ -0,0 +1,27 @@
.flag_active {
color: white;
opacity: 1 !important;
}
.ae_flag_delete {
color: white;
padding: 0 0.5em 0 0;
}
.ae_flag_delete:hover {
color: red;
}
.ae_flag_add {
color: white;
cursor: default;
font-weight: 200;
}
.ae_flag_add:hover {
color: dodgerblue;
}
.ae_flags > span {
float: left;
}

View File

@ -0,0 +1,190 @@
(function(){
var ns = __namespace( "Astro.Blog.AstroEdit" );
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Astro.Blog.Config} */
var Config = __import( "Astro.Blog.Config" );
var postData = __import( "System.Net.postData" );
/* @type {AstroEdit.IPlugins} */
var Flag = function ( id, target, flagConf )
{
this.id = id;
var stage = Dand.id( target );
var ae_addFlag = Dand.glass( "ae_flag_add" , true, stage )[0];
var ae_flags = Dand.glass( "ae_flags" , false, stage )[0];
// Store flags for future use
var flags = {};
////// Handlers
ae_addFlag.addEventListener(
"Click", function ( e )
{
e.stopPropagation();
// Input fields
var ae_flagInput;
// Popup MessageBox
new MessageBox(
"Add new flag(s)"
, Dand.wrape([
Dand.wrapc(
"v_instruction flsf"
, "Flags are separated by \\n. (existing flags will be ignored.)"
)
, ae_flagInput = Dand.wrap( "textarea", null, "v_snippet_input" )
])
, "OK", "Cancel"
, parseFlags.bind( ae_flagInput )
).show();
}
);
var deleteFlag = function (e)
{
e.stopPropagation();
var p = { stage: this.parentNode };
p[ id ] = this.nodeValue;
p[ "id" ] = id;
postData( flagConf.URICount, p, confirmDelete.bind( p ), serverFailed );
};
var confirmDelete = function (obj)
{
new MessageBox(
"Delete Flag"
, [
Dand.wrapc("ae_blockswitch",
[
Dand.textNode( "Are you sure you want to delete " )
, Dand.wrap( "span", null, "flag_active", Dand.textNode( this[ id ] ) )
, Dand.textNode( " ?." )
]
)
, obj.count > 0
? Dand.wrape([
Dand.textNode( "This will affect " )
, Dand.wrap(
"span", null, "ae_affected_count", Dand.textNode( obj.count )
)
, Dand.textNode(" article(s).")
])
: null
]
, "Delete", "No"
, doDelete.bind( this )
).show();
};
var doDelete = function( confirmed )
{
if ( confirmed )
{
this[ "del" ] = 1;
postData(
flagConf.URISet
, this
, deleteSuccess.bind( this )
, serverFailed
);
}
};
var deleteSuccess = function(obj)
{
// Remove element
this.stage.parentNode.removeChild( this.stage );
// Delete reference
delete flags[ this[ id ] ];
};
var parseFlags = function ()
{
// Filter invalid flags
var nflags = this.value.trim().match(/[^\n]+/g), d, e;
for (var i in nflags)
{
if(!flags[(i = nflags[i]).toLowerCase()])
{
flags[i] = Dand.wrap("span", null, "flag_active",
[d = Dand.wrap("span", null, "ae_flag_delete", "\u00D7"), e = Dand.textNode(i)]
);
// Seperator
ae_flags.appendChild(Dand.textNode(" "));
ae_flags.appendChild(flags[i]);
flags[i].onclick = function() { toggleFlag(this) }.bind(flags[i]);
d.onclick = deleteFlag.bind(e);
}
else
{
debug.Info("Flag exist: " + i);
// Hightlight these flags
flags[i.toLowerCase()].className = "flag_active";
}
}
};
var toggleFlag = function (flag)
{
var isEnabled = flag.className == "flag_active" ? true : false;
flag.className = isEnabled ? "ae_disabled" : "flag_active";
};
var serverFailed = function (obj) { };
var cflag, ae_children = ae_flags.childNodes;
for (var i in ae_children)
{
if((cflag = ae_children[i]).nodeType == 1)
{
flags[cflag.lastChild.nodeValue.toLowerCase()] = cflag;
IDOMElement( cflag ).addEventListener( "Click", function() { toggleFlag( this ); }.bind( cflag ) );
// Bind the last child (x button) to firstChild (textNode: flagname)
IDOMElement( cflag.firstChild ).addEventListener( "Click", deleteFlag.bind( cflag.lastChild ) );
}
}
this.getData = function ()
{
// Compile flag list
var tlist = [];
// Return names
for (var i in flags)
{
if(flags[i].className == "flag_active")
tlist[tlist.length] = flags[i].lastChild.nodeValue;
}
return tlist.join("\n");
}
this.setForView = function ( flagList )
{
// Disable all flags first
for ( var i in flags ) flags[i].className = "ae_disabled";
// Set flags from flagList
for ( i in flagList )
if ( flagList[i] ) flags[flagList[i].toLowerCase()].className = "flag_active";
}
}
Flag.prototype.getSetData = function () { };
Flag.prototype.setForView = function ( flagList ) { };
ns[ NS_EXPORT ]( EX_CLASS, "Flag", Flag );
})();

View File

@ -0,0 +1,415 @@
#siteLibrary {
position: fixed;
width: 100%;
height: 100%;
top: calc(-100% - 5px);
}
#siteLibrary:hover {
top: calc(-100% + 1.5em);
}
#asl_viewer {
width: calc(100% - 300px);
height: 100%;
overflow-x: hidden;
overflow-y: scroll;
float: left;
position: relative;
}
.asl_colls.canvasGeneral {
color: #BBB;
}
.canvasGeneral.asl_colls > div > span.c75 { width: 75%; }
.canvasGeneral.asl_colls > div > span.c25 { width: 25%; }
.asl_header {
width: 100%;
height: 20px;
top: 100%;
margin-top: -20px;
position: absolute;
z-index: 1;
}
#asl_viewer > #canvasView {
position: absolute;
min-height: 100%;
width: 100%;
}
.asl_viewer {
width: 100%;
height: 100%;
background: #EEE;
-moz-box-shadow: 0 7px 5px black;
-webkit-box-shadow: 0 7px 5px black;
box-shadow: 0 7px 5px black;
}
.asl_contentMenu {
bottom: 0;
position: absolute;
padding: 1em;
}
.asl_contentMenu > span {
margin: 0 0.2em;
padding: 0.5em 0.5em;
cursor: default;
color: white;
background-color: rgba(0, 0, 0, 0.6);
font-family: custom-serif;
}
.asl_contentMenu > span:hover {
background-color: rgba(0, 0, 0, 0.8);
}
.asl_contentMenu > span[current] {
background-color: rgba(0, 0, 0, 0.8);
}
.asl_smask {
height: 10px;
background-color: royalblue;
position: absolute;
bottom: -5px;
width: 100%;
}
.asl_smask:before {content: '';
width: 100%;
height: 20px;
top: -10px;
position: absolute;
z-index: -1;
background-color: transparent;
}
.asl_smask[expand] {
background-image: url(/assets/blog/layout-images/collapse.png);
background-position: center 2.5px;
background-repeat: no-repeat;
}
.asl_smask[expand]:hover {
height: 20px;
}
#siteLibrary .asl_title, .asl_intitle {
font-size: 1.5em;
font-family: custom-sans;
overflow: hidden;
background-color: royalblue;
color: white;
}
#siteLibrary .asl_title {
padding: 0.3em 0.5em;
}
.asl_contentPanel {
overflow: hidden;
position: absolute;
height: calc(100% - 2.5em);
width: 100%;
}
#siteLibrary .asl_title {
cursor: default;
display: inline-block;
position: absolute;;
right: 350px;
bottom: -1.7em;
-moz-box-shadow: 2px 2px 5px black;
-webkit-box-shadow: 2px 2px 5px black;
box-shadow: 2px 2px 5px black;
}
/*** ASL Canvases ***/
.canvasImage > span {
width: 100px;
height: 100px;
margin: 0.2em;
background-repeat: no-repeat;
background-position: center;
border: 1px solid transparent;
display: inline-block;
vertical-align: middle;
position: relative;
overflow: hidden;
}
.canvasImage > span:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
}
.canvasImage > span img {
vertical-align: middle;
display: inline-block;
}
.canvasImage > span:after {
content: attr(data-title);
background-color: rgba(0,0,0,0.6);
color: white;
position: absolute;
left: 0;
bottom: -2em;
font-size: 0.8em;
width: 100%;
padding-left: 0.5em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
-webkit-transition: all .25s ease-out;
-moz-transition: all .25s ease-out;
-o-transition: all .25s ease-out;
transition: all .25s ease-out;
}
.canvasImage > span:hover:after {
bottom: 0%;
}
.canvasImage > span[selected] {
background-color: lightblue;
border-color: royalblue;
}
.canvasImage > span > span {
width: 100%;
height: 100%;
display: block;
}
.canvasImage > span > span:hover {
background-color: rgba(0, 0, 0, 0.2) !important;
border-color: #444 !important;
}
.ci_album {
-moz-box-shadow: 2px 3px 0 0 black;
-webkit-box-shadow: 2px 3px 0 0 black;
box-shadow: 2px 3px 0 0 #666;
border: 1px solid #666 !important;
}
.canvasGeneral {
padding: 0.2em;
cursor: default;
color: #444;
}
.canvasGeneral > div {
padding: 0.2em;
}
.canvasGeneral > div:hover {
background-color: rgba(0, 0 ,0, 0.2);
}
.canvasGeneral > div > span {
display: inline-block;
width: 30%;
padding: 0.2em 0;
overflow: hidden;
text-overflow: ellipsis;
}
.canvasGeneral > div > span:last-child {
width: 10%;
}
.canvasGeneral > div[selected] {
background-color: orangered;
color: white;
}
/*** End ASL Canvases ***/
/*** Uploader ***/
#asl_uploader {
width: 300px;
height: 100%;
float: right;
font-family: custom-sans;
}
#asl_u_head {
position: absolute;
background: #EEE;
z-index: 1;
}
.upldr_title {
font-size: 1.5em;
}
.asl_fwrapper {
overflow-y: scroll;
position: absolute;
top: 0;
width: 100%;
height: 100%;
/*
-moz-box-shadow: inset 0 0 20px black;
-webkit-box-shadow: inset 0 0 20px black;
box-shadow: inset 0 0 20px black;
*/
}
.asl_fileList {
font-family: sans-serif;
color: #444;;
cursor: default;
}
.asl_fileList > div {
/* 0.5em for fwrapper padding */
margin-right: 50%;
padding: 0.5em;
overflow: hidden;
text-overflow: ellipsis;
}
.asl_uItem:hover {
background-color: rgba(0, 0, 0, 0.2);
}
.asl_uItemStat {
padding: 0 0.5em 0 0;
color: orange;
}
.asl_split {
position: relative;
height: 80px;
overflow: hidden;
}
.asl_split > div {
height: 100%;
padding: 0.5em;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.asl_left {
float: left;
width: 135px;
}
.asl_right {
float: right;
width: calc(100% - 135px);
}
.asl_fileName {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.asl_preview {
padding: 0.2em;
background-color: white;
height: 100%;
}
/* Progress indicator */
.asl_progress {
padding: 0.5em 0;
}
.asl_ptext {
font-size: 0.8em;
}
.asl_pbar {
background-color: white;
position: relative;
height: 1em;
margin-top: 0.2em;
}
.asl_pbar_fill {
background: greenyellow;
position: absolute;
width: 0%;
height: 100%;
}
.asl_go_up {
width: 0;
height: 0;
border-top: 0 solid transparent;
border-bottom: 0.5em solid transparent;
border-left: 0.5em solid #FFF;
position: absolute;
left: 0;
}
.asl_btn {
padding: 0.3em;
text-align: center;
cursor: default;
}
.asl_btn:hover {
background-color: rgba( 0, 0, 0, 0.2);
}
.asl_instruction {
width: 100%;
height: 100%;
font-size: 0.8em;
}

View File

@ -0,0 +1,768 @@
(function(){
var ns = __namespace( "Astro.Blog.AstroEdit" );
/** @type {System.Cycle} */
var Cycle = __import( "System.Cycle" );
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
/** @type {System.utils.Perf} */
var Perf = __import( "System.utils.Perf" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {System.utils.EventKey} */
var EventKey = __import( "System.utils.EventKey" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
/** @type {Components.Mouse.ContextMenu} */
var ContextMenu = __import( "Components.Mouse.ContextMenu" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMObject} */
var IDOMObject = __import( "Dandelion.IDOMObject" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Astro.Blog.Config} */
var Conf = __import( "Astro.Blog.Config" );
var postData = __import( "System.Net.postData" );
var prettyDate = __import( "Astro.utils.Date.pretty" );
var SiteLibrary = function ( basePath, processorGet, processorSet )
{
var view_index = []
, currentView
, inCollection = 0
, indexingItem
, itemSelected = false
, holdingCtrl = false
, holdingShift = false
/** @type {_AstConf_.SiteFile} */
, config = Conf.get( "SiteFile" )
, contentPanel = Dand.id("asl_viewer")
, canvasView
, contextMenu
, stage = Dand.id( "siteLibrary", true )
, asl_smask = Dand.id( "asl_smask", true )
, getItemKeys = function (data)
{
return [
new DataKey("id", data.id)
, new IKey("data-title", data.name)
, new IKey("data-author", data.author)
, new DataKey("hash", data.hash)
];
}
, bindData = function(target, source, data)
{
IDOMElement(source).addEventListener(new EventKey("MouseDown", function (e)
{
// pass neccessary informations for contextMenu to read
target.idata = this;
if(e.which == 1 || (e.which == 3 && !this.stage.hasAttribute("selected")))
{
// Mousedown event will bubble up to parent node, set itemselected to true
itemSelected = true;
if( !holdingCtrl ) deselectAllItem.bind( target )();
if(holdingShift) rangedSelect();
else indexingItem = this.stage;
selectItem.bind(target)();
}
}.bind(
{
stage: source
, id: data.id
, href: data.src_location
, hash: data.hash
, author: data.author
, name: data.name
, date: data.date_created
, isCollection: 0 < data.cCount
}
)));
}
////// Canvas builders
, resetCanvas = function (name)
{
if(canvasView)
{
contentPanel.removeChild(canvasView);
contentPanel.appendChild(canvasView = Dand.wrap(null, "canvasView", name || canvasView.getAttribute("class"), null, new DataKey("name", currentView)));
}
else
{
contentPanel.appendChild(canvasView = Dand.wrap(null, "canvasView", name, null, new DataKey("name", currentView)));
}
IDOMElement(canvasView).addEventListener(
new EventKey("Click", function (e)
{
if(e.which == 1)
{
if(!itemSelected)
{
deselectAllItem.bind(canvasView)();
canvasView.idata = null;
}
itemSelected = false;
}
}
)
);
}
, buildAudioCanvas = function (e)
{
// TODO
resetCanvas("canvasAudio");
}
/** @param {_AstJson_.AJaxGetFiles} */
, buildImageCanvas = function ( e )
{
var f = e.files;
resetCanvas( "canvasImage" );
for( var i in f )
{
/** @param {_AstJson_.AJaxGetFiles.file} */
var file = f[i];
// id: i, name: file.name, hash: file.hash, sorce: file.src_location, date: file.date_created
var img = Number( file.cCount )
////// Album item
? Dand.wrap(
"span", "img_" + Perf.uuid, "ci_album"
, Dand.wrapna( "img", new IKey( "src", basePath + "image/s100/" + file.hash + ".jpg" ) )
, [
new IKey("title"
, "Album: " + file.name
+ "\n" + file.cCount + " file(s)"
+ "\nDate: " + prettyDate( new Date( file.date_created ), true )
+ "\nCreated by: " + file.author
)
, new IKey("collection", 1)
].concat( getItemKeys( file ) )
)
//////// Normal filele
: Dand.wrap(
"span", "img_" + Perf.uuid, null
, Dand.wrapna( "img", new IKey( "src", basePath + "image/s100/" + file.hash + ".jpg" ) )
, [
new IKey("title"
, "File: " + file.name
+ "\nDate: " + prettyDate( new Date( file.date_created ), true )
+ "\nCreated by: " + file.author
)
].concat( getItemKeys( file ) )
);
canvasView.appendChild( img );
bindData( canvasView, img, file );
}
contextMenu = new ContextMenu(canvasView, [
new EventKey("Open", openAction)
, {
name: "Copy"
, items: [
new EventKey("Copy source link", copyItemLink)
, new EventKey("Copy hash", copyHash)
]
}
, {
name: "Selection"
, items: [
{
name: "Select"
, items: [
new EventKey("all", selectAllItem)
, new EventKey("none", deselectAllItem)
, new EventKey("Invert selection", reverseSelection)
]
}
,{
name: "By type"
, items:
[
new EventKey("Only albums", selectAllCollections)
, new EventKey("Only files", selectAllFiles)
]
}
]
}
, {
name: "Action"
, items: [
new EventKey("Group selected file(s)", setCollection)
, new EventKey("Add file(s) to collection", insertCollection)
// TODO: in-group file action changes
, new EventKey("Move file(s) to collection", function(){})
, new EventKey("Remove files(s) from collection", excludeCollection)
]
}
,new EventKey("Refresh", refreshCanvas)
, new EventKey("Rename", popupRename)
, new EventKey("Delete", confirmDelete)
], "RMB");
}
// General file, list view
/** @param {_AstJson_.AJaxGetFiles} */
, buildGeneralCanvas = function ( e )
{
if( !e ) return;
var f = e.files, dateStamp;
resetCanvas( "canvasGeneral" );
for(var i in f)
{
/** @param {_AstJson_.AJaxGetFiles.file} */
var file = f[i];
dateStamp = Dand.wrap( "span" );
dateStamp.innerHTML = prettyDate( new Date( file.date_created ) ) ;
var li = Dand.wrap(
null, "g_item" + Perf.uuid, null
, [
Dand.wrapne( "span", file.name )
, dateStamp
, Dand.wrapne( "span", file.author )
]
, getItemKeys( file )
);
canvasView.appendChild( li );
bindData( canvasView, li, file );
}
contextMenu = new ContextMenu(canvasView, [
{
name: "Copy"
, items: [
new EventKey("Copy source link", copyItemLink)
, new EventKey("Copy hash", copyHash)
]
}
, new EventKey("Delete file", confirmDelete)
], "RMB");
}
, selHasCollection = false
// Return the selected files
, selections = function(return_id) {
var s = [];
selHasCollection = false;
IDOMElement(canvasView).foreach(1, function(elem) {
// Save the hashes
if(elem.hasAttribute("selected"))
{
s[s.length] = return_id ? IDOMElement(elem).getDAttribute("id") : elem;
if(elem.hasAttribute("collection")) selHasCollection = true;
}
});
return s;
}
/// Menu item handlers
, confirmDelete = function ()
{
new MessageBox("Confirm delete"
, [
Dand.wrape("Are you sure you want to delete the selected item(s)?")
, Dand.wrape("Warning: This action cannot be undone! Make sure you have de-referenced them from your articles.", new IKey("style", "color: yellow;"))
]
, "Delete it", "No"
, requestDelete.bind({files: selections()})).show();
}
, popupRename = function ()
{
var name_field = Dand.wrap("input", null, "v_snippet_input_single", null, new IKey("type", "text"));
new MessageBox("Rename \"" + canvasView.idata.name + "\"", name_field, "OK", "Cancel", requestRename.bind(
{
name: name_field
, stage: canvasView.idata.stage
, isCollection: canvasView.idata.isCollection
}
)).show();
}
, copyItemLink = function () { return config.f_host + canvasView.idata.href; }
, copyHash = function ()
{
var data = canvasView.idata;
return data.isCollection ? data.id : data.hash;
}
, openAction = function ()
{
if(canvasView.idata.isCollection) openCollection(IDOMElement(canvasView.idata.stage).getDAttribute("id"));
else window.open( config.f_host + canvasView.idata.href);
}
//// ContextMenu Handlers: Selections
, selectItem = function()
{
canvasView.idata.stage.hasAttribute("selected") ? canvasView.idata.stage.removeAttribute("selected") : canvasView.idata.stage.setAttribute("selected", 1);
}
, selectAllItem = function ()
{
IDOMElement(canvasView).foreach(1, function(target)
{
target.setAttribute("selected", 1);
});
}
, selectAllCollections = function ()
{
IDOMElement(canvasView).foreach(1, function(target)
{
target.hasAttribute("collection") ? target.setAttribute("selected", 1) : target.removeAttribute("selected");
});
}
, selectAllFiles = function ()
{
IDOMElement(canvasView).foreach(1, function(target)
{
target.hasAttribute("collection") ? target.removeAttribute("selected") : target.setAttribute("selected", 1);
});
}
, rangedSelect = function ()
{
var items = canvasView.childNodes;
var k = indexingItem;
if(Array.prototype.indexOf.call(items, k) < Array.prototype.indexOf.call(items, canvasView.idata.stage))
{
while(k != canvasView.idata.stage)
{
k.setAttribute("selected", 1);
k = k.nextSibling;
}
}
else
{
while(k != canvasView.idata.stage)
{
k.setAttribute("selected", 1);
k = k.previousSibling;
}
}
}
, deselectAllItem = function ()
{
IDOMElement(canvasView).foreach(1, function(target)
{
target.removeAttribute("selected");
});
}
, reverseSelection = function ()
{
IDOMElement(canvasView).foreach(1, function(target)
{
target.hasAttribute("selected") ? target.removeAttribute("selected") : target.setAttribute("selected", 1);
});
}
//// ContextMenu Handlers: Collections
, setCollection = function ()
{
var s = selections( true )
var name_field = Dand.wrap(
"input", null
, "v_snippet_input_single", null
, new IKey( "type", "text" )
);
new MessageBox(
"Collection name"
, name_field
, "OK", "Cancel"
, requestCollection.bind({ name: name_field, files: s.join(",") })
).show();
}
, openCollection = function ( id ) {
refreshCanvas( id, true );
}
, excludeCollection = function() {
}
, insertCollection = function() {
var collections = []
, ul = Dand.wrapc( "canvasGeneral asl_colls" )
;
// Get current albums to list
IDOMElement(canvasView).foreach(1, function(target)
{
if(target.hasAttribute("collection"))
{
var t = IDOMElement(target)
// item structure
, li = Dand.wrap(
null, "g_item" + Perf.uuid, null
, [
Dand.wrap("span", null, "c75", t.getDAttribute("title") )
, Dand.wrap("span", null, "c25", t.getDAttribute("author") )
]
, new DataKey("id", t.getDAttribute("id"))
);
// Set selection behaviour
IDOMElement(li).addEventListener("Click", function(e) {
IDOMElement(ul).foreach(1, function(elem) { elem.hasAttribute("selected") && elem.removeAttribute("selected"); });
this.setAttribute("selected", 1);
}.bind(li));
ul.appendChild(li);
}
});
new MessageBox("Select a collection", ul, "OK", "Cancel", requestInsert.bind({ albumList: ul, collection: selections(true) })).show();
}
//// ContextMenu Handlers: General actions
, requestRename = function( confirmed )
{
if( confirmed )
{
var pData = {
"name": this.name.value
, "id": IDOMElement( this.stage ).getDAttribute( "id" )
};
if(this.isCollection) pData.group = "rename";
else pData.file = "rename";
postData( processorSet, pData, refreshCanvas, loadFailed );
}
}
, requestDelete = function (confirmed)
{
if(confirmed || this.reConfirmed)
{
if(this.files.length < 2)
{
var file = this.files[0];
if(selHasCollection)
{
new MessageBox("Also delete files?"
, "Do you also want to delete the files within the collections?"
, "Delete all files", "Only delete collection"
, delCollection.bind(file)).show();
}
else
{
postData(
processorSet
, { "file": "remove", "hash": IDOMElement(file).getDAttribute("hash") }
, fileDeleted.bind(file), loadFailed
);
}
}
else
{
if(!this.reConfirmed && selHasCollection)
{
// Set the reconfirmation attr
this.reConfirmed = true;
new MessageBox("Also delete files?"
, "You have also selected collection(s), do you want to also delete files inside?"
, "Delete all files", "Only delete collection"
, requestDelete.bind(this)).show();
return;
}
var files = this.files;
for(var i in files)
{
if(files[i].hasAttribute("collection"))
{
// redirect confirmation to delCollection handler
// delete all things when true
delCollection.bind(files[i])(confirmed);
}
else
{
// redirect to self
requestDelete.bind({files: [files[i]]})(true);
}
}
}
}
}
, requestInsert = function(confirmed)
{
if( confirmed )
{
var selectedAlbum = IDOMElement(
IDOMElement( this.albumList ).first( 1, function(elem) {
return elem.hasAttribute("selected");
} ) ).getDAttribute( "id" );
postData(
processorSet
, { "group": "insert", "id": selectedAlbum , "files": this.collection.join(",") }
, refreshCanvas, loadFailed
);
}
}
, delCollection = function (confirmed)
{
var album_id = IDOMElement(this).getDAttribute("id");
if( confirmed )
{
postData( processorGet, { group: "get", aid: album_id }, getFilestoDelete.bind( this ), loadFailed );
}
else
{
postData( processorSet, { group: "remove", id: album_id }, refreshCanvas, loadFailed );
}
}
, getFilestoDelete = function ( e )
{
var l = Object.keys(e.files).length
, fc = 0
, _self = this
, echoDeleted = function()
{
debug.Info("[ASL] File deleted: " + this.name);
fc ++;
if(l == fc) delCollection.bind(_self)(false);
}
, deleteFailed = function ()
{
debug.Error( new Error( "[ASL] Failed to delete: " + this.name ) );
fc ++;
if(l == fc) delCollection.bind(_self)(false);
}
;
for(var i in e.files)
{
postData(
processorSet
, { "file": "remove", "hash": e.files[i]}, echoDeleted.bind({ "name": i })
, deleteFailed.bind({ "name": i })
);
}
}
, fileDeleted = function () { this.parentNode.removeChild(this); }
, requestCollection = function ()
{
if(this.name.value)
{
postData(
processorSet
, { "group": "create", "name": this.name.value, "files": this.files }
, refreshCanvas, loadFailed
);
}
}
////// End canvas builders
, refreshCanvas = function ( view, openCollection )
{
if( typeof view != "string" && !openCollection ) view = null;
// prepare postData
/** @type {_AstJson_.AJaxGetFiles.Request} */
var pdata = {};
if( openCollection )
{
// Set and remove to prevent invalid content set to currentView
inCollection = view;
view = false;
}
currentView = view || ( currentView || "application" );
//// postData parameters
// if we are in collection
if( inCollection )
{
pdata.group = "list";
pdata.aid = inCollection;
}
// else we are in root
else pdata.listFiles = currentView;
switch( currentView )
{
case "image":
postData( processorGet, pdata, buildImageCanvas, loadFailed );
break;
case "audio":
postData( processorGet, pdata, buildAudioCanvas, loadFailed );
break;
default:
postData( processorGet, pdata, buildGeneralCanvas, loadFailed );
break;
}
}
/** @param {_AstJson_.AJaxGetFiles} e */
, panelSwitch = function ( e )
{
if( view_index.length < 1 )
{
var menuBar = Dand.id( "asl_contentMenu" )
, f = e.files, first;
// button mime/type ( counts )
for( var i in f )
{
var elem = Dand.wrap(
"span", null, "asl_menuItem"
, i + "(" + f[i] + ")"
, new DataKey( "name", i ) );
view_index[view_index.length] = [i, elem];
menuBar.appendChild(elem);
IDOMElement(elem).addEventListener(new EventKey("Click", switchView.bind(IDOMElement(elem))));
if( !first ) first = [ i, elem ];
}
if( !first )
{
debug.Info( "No files" );
return;
}
// begin load index
refreshCanvas( first[0] );
// Set style
first[1].setAttribute("current", 1);
}
else
{
// Should update the menu buttons
debug.Info( "Should update the menu buttons" );
}
}
, switchView = function ()
{
// Do nothing if current
if(this.getDAttribute("name") == currentView) return;
for(var i in view_index)
{
if(view_index[i][0] == currentView)
{
view_index[i][1].removeAttribute("current");
}
}
// switching view, reset collection
inCollection = 0;
this.setAttribute("current", 1);
refreshCanvas(this.getDAttribute("name"));
}
, showLibrary = new EventKey("Click"
, function ()
{
stage.style.top = "0";
asl_smask.setAttribute( "expand", 1 );
// Switch behaviour
stage.removeEventListener( showLibrary );
Cycle.delay(function () {
Dand.id( "ae_body" ).style.display = Dand.id( "ae_panel" ).style.display = "none";
asl_smask.addEventListener( hideLibrary );
// load library statistics
loadLibStats( panelSwitch, loadFailed );
}, 500);
}
)
, hideLibrary = new EventKey(
"Click"
, function ()
{
stage.style.top = "";
asl_smask.removeAttribute( "expand" );
// Switch behaviour
asl_smask.removeEventListener( hideLibrary );
Dand.id("ae_body").style.display = Dand.id( "ae_panel" ).style.display = "";
Cycle.delay(function () {
stage.addEventListener( showLibrary );
}, 500);
}
)
, loadFailed = function (e)
{
// TODO: make some notifications here
}
, loadLibStats = function ( handler, failedHandler )
{
postData( processorGet, { "countTypes": 1 }, handler, failedHandler );
}
, keyHold = function(e) { holdingCtrl = e.ctrlKey; holdingShift = e.shiftKey; }
, dKeyUp = new EventKey( "KeyUp", keyHold )
, dKeyDown = new EventKey( "KeyDown", keyHold )
;
Dand.id( "asl_homeBtn", true ).addEventListener( "click", function( e ) { refreshCanvas( 0, true ); } );
Dand.id( "asl_refresh", true ).addEventListener( "click", function( e ) { refreshCanvas( 0 ); } );
new IDOMObject( document ).addEventListeners([ dKeyUp, dKeyDown ]);
stage.addEventListener(showLibrary);
};
ns[ NS_EXPORT ]( EX_CLASS, "SiteLibrary", SiteLibrary );
})();

View File

@ -0,0 +1,71 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.SmartInput.CandidateAction" );
/** @type {Astro.Blog.Config} */
var Config = __import( "Astro.Blog.Config" );
var getData = __import( "System.Net.getData" );
var prettyDate = __import( "Astro.utils.Date.pretty" );
/** @type {_AstConf_.AstroEdit} */
var Conf = Config.get( "AstroEdit" );
/** @type {Astro.Blog.AstroEdit.SmartInput.ICandidateAction} */
var ArticleRefs = function ( visualizer, key )
{
this.visualizer = visualizer;
this.key = key;
this.__cands = {};
};
ArticleRefs.prototype.GetCandidates = function( handler )
{
var _self = this;
getData( Conf.paths.list_articles, function( e ) {
e = JSON.parse( e );
for( var i in e.entries )
{
var ent = e.entries[i];
_self.__cands[ ent.title ] = { "desc": ent.content, id: ent.id };
}
handler( _self.__cands );
} );
};
ArticleRefs.prototype.Process = function( key )
{
var cand = this.__cands[ key ];
if( !cand ) return false;
this.visualizer.insertSnippet( "articlelink", { value: cand.id } );
return true;
};
ArticleRefs.prototype.Retreat = function( sender, e )
{
return sender.value == "" && e.keyCode == 8; // Backspace
};
/** @type {Astro.Blog.AstroEdit.SmartInput.ICandidateAction} */
var ArticleContent = function ( visualizer, key )
{
ArticleRefs.call( this, visualizer, key );
};
__extends( ArticleContent, ArticleRefs );
ArticleContent.prototype.Process = function( key )
{
var cand = this.__cands[ key ];
if( !cand ) return false;
this.visualizer.insertSnippet( "articlecontent", { value: cand.id } );
return true;
};
ns[ NS_EXPORT ]( EX_CLASS, "ArticleContent", ArticleContent );
ns[ NS_EXPORT ]( EX_CLASS, "ArticleReference", ArticleRefs );
})();

View File

@ -0,0 +1,37 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.SmartInput.CandidateAction" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Astro.Blog.AstroEdit.SmartInput.ICandidateAction} */
var Footnote = function ( visualizer, key )
{
this.visualizer = visualizer;
this.key = key;
};
Footnote.prototype.GetCandidates = function( handler )
{
handler( false );
};
Footnote.prototype.Process = function( content )
{
this.visualizer.insertSnippet( "footnote", { "value": content } );
};
Footnote.prototype.Retreat = function( sender, e )
{
return sender.value == "" && e.keyCode == 8; // Backspace
};
ns[ NS_EXPORT ]( EX_CLASS, "Footnote", Footnote );
})();

View File

@ -0,0 +1,28 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.SmartInput.CandidateAction" );
/** @type {Astro.Blog.AstroEdit.SmartInput.ICandidateAction} */
var Heading = function ( visualizer, key )
{
this.visualizer = visualizer;
this.key = key;
};
Heading.prototype.GetCandidates = function( handler )
{
handler( false );
};
Heading.prototype.Process = function( content )
{
this.visualizer.insertSnippet( "heading", { "size": this.key, "value": content } );
};
Heading.prototype.Retreat = function( sender, e )
{
return sender.value == "" && e.keyCode == 8; // Backspace
};
ns[ NS_EXPORT ]( EX_CLASS, "Heading", Heading );
})();

View File

@ -0,0 +1,21 @@
.smartbar-candidates {
padding: 0.5em;
background-color: rgba( 0, 0, 0, 0.2 );
}
.smartbar-candidates .cn {
padding: 0.2em 0.5em;
}
.smartbar-candidates .cn:hover {
background-color: rgba( 0, 0, 0, 0.2 );
}
.smartbar-candidates .cn[data-selected="1"] {
background-color: orangered;
}
.cn .desc {
margin-left: 0.5em;
opacity: 0.65;
}

View File

@ -0,0 +1,521 @@
(function(){
var ns = __namespace( "Astro.Blog.AstroEdit" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion.IDOMObject} */
var IDOMObject = __import( "Dandelion.IDOMObject" );
/** @type {System.Cycle} */
var Cycle = __import( "System.Cycle" );
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
/** @type {System.Net.ClassLoader} */
var Loader = __import( "System.Net.ClassLoader" );
/** @type {System.utils} */
var utils = __import( "System.utils" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
/** @type {Astro.Blog.Config} */
var Config = __import( "Astro.Blog.Config" );
var moduleNs = "Astro.Blog.AstroEdit.SmartInput.CandidateAction.";
var service_uri = Config.get( "ServiceUri" );
var Destructor = function( target )
{
this.target = target;
this.target.Disposed = false;
this.destructSequence = [];
};
Destructor.prototype.Register = function( destruct )
{
this.destructSequence.push( destruct );
};
Destructor.prototype.Destruct = function()
{
for( var i in this.destructSequence )
{
this.destructSequence[i]();
}
this.target.Disposed = true;
this.destructSequence = null;
};
var KeyHandler = function( sender, handler )
{
return function( e )
{
e = e || window.event;
if ( e.keyCode ) code = e.keyCode;
else if ( e.which ) code = e.which;
handler( sender, e );
};
};
// {{{ Candidates Class
var Candidates = function( title, desc, defs )
{
this.title = title;
this.desc = desc;
this.__cands = [];
this.__defs = defs || {};
this.Empty = !defs;
};
Candidates.prototype.Get = function()
{
if( this.__cands.length ) return this.__cands;
for( var i in this.__defs )
{
/** @param {Astro.Blog.AstroEdit.SmartInput.Definition} */
var c = this.__defs[i];
this.__cands.push( Dand.wrapc( "cn", [ i, Dand.wrapc( "desc", c.desc ) ], new DataKey( "key", i ) ) );
}
return this.__cands;
};
Candidates.prototype.Reset = function()
{
var Cands = this.Get();
for( var i in Cands )
{
var c = IDOMElement( Cands[i] );
c.setAttribute( new DataKey( "selected", 0 ) );
}
};
Candidates.prototype.Filtered = function()
{
var Cands = this.Get();
var selected = [];
for( var i in Cands )
{
var c = IDOMElement( Cands[i] );
c.setAttribute( new DataKey( "selected", 0 ) );
if( c.style.display != "none" )
{
selected.push( c );
}
}
return selected;
};
Candidates.prototype.Selected = function()
{
var Cands = this.Get();
for( var i in Cands )
{
var c = IDOMElement( Cands[i] );
if( c.getDAttribute( "selected" ) == "1" )
{
return c;
}
}
return null;
};
// }}}
/** @param {Astro.Blog.AstroEdit.Visualizer} */
var SmartInput = function( visualizer )
{
this.Present = false;
var destructor = new Destructor( this );
var _self = this;
var insert = function() { return Dand.textNode( "" ); };
var ModLevels = [];
var BindingBox = null;
ModLevels.Cands = function() { return ModLevels[0][0]; };
ModLevels.Action = function() { return ModLevels[0][1]; };
ModLevels.Retreat = function() { return ModLevels[0][2]; };
var __title = null;
var title = function( reload )
{
if( !reload && __title ) return __title;
var l = ModLevels.length - 1;
var t = ModLevels[ l ][0].title;
for( var i = 0; i < l; i ++ )
{
var Mod = ModLevels[i];
t = t + " > " + Mod[0].title;
}
if( __title )
{
__title.textContent = t;
}
else
{
__title = Dand.wrape( t );
}
return __title;
};
var __stage = null;
var stage = function( incoming )
{
if( __stage )
{
if( incoming )
{
IDOMElement( __stage[1] ).clear();
var ThisCands = ModLevels.Cands().Get();
if( ThisCands.length )
{
IDOMElement( __stage[1] ).loot( Dand.wrape( ThisCands ) );
}
}
return __stage;
}
var Cands = ModLevels.Cands();
var Command = Dand.wrap(
"input", null, "v_snippet_input_single"
, null, IKey.quickDef( "type", "text", "placeholder", Cands.desc, "value", "`" )
);
var CandList = Dand.wrap( "div", null, "compx smartbar-candidates", Cands.Get() );
Command.selectionStart = Command.selectionEnd = 1;
return __stage = [ Command, CandList ];
};
var CandidateCycle = -1;
var KeywordTyped = 0;
var shiftTabbed = false;
var HandleInput = function( sender, e )
{
// Don't handle if holding shift or ctrl key
if( e.shiftKey || e.ctrlKey )
{
// Except the Shift + Tab, we need to cycle this
shiftTabbed = e.shiftKey && e.keyCode == 9;
if( !shiftTabbed ) return;
}
switch( e.keyCode )
{
case 192: // `
// If we are not are the first level, do nothing
if( 1 < ModLevels.length ) break;
// Closing the quote, that means this is a block-quoted text
e.preventDefault();
insert = undefined;
// Hitting ` twice escapes the ` character itself
var v = sender.value.substr( 1 );
if( v == "" )
{
insert = function() { return Dand.textNode( "`" ); };
BindingBox.close( true );
break;
}
BindingBox.close();
// Insert the code snippet with inline flag
visualizer.insertSnippet( "code", { "inline": "on", "lang": "plain", "value": v } );
break;
case 13: // Enter
// Not closing the quote, either a direct text or the first matched action
e.preventDefault();
// No candidates, directly pass the input text to the processor
if( ModLevels.Cands().Empty && 1 < ModLevels.length )
{
ModLevels.Action()( sender.value.substr( 1 ) );
BindingBox.close();
break;
}
var selected = ModLevels.Cands().Selected();
// Check if matched an action first
if( selected )
{
insert = undefined;
var close = ModLevels.Action()( selected.getDAttribute( "key" ) );
if( close ) BindingBox.close();
}
else
{
// Insert this text directly
var v = Dand.textNode( sender.value.substr( 1 ) );
insert = function() { return v; };
BindingBox.close( true );
}
break;
case 27: // Esc
BindingBox.close();
break;
case 9: // Tab
// Hitting tab will cycle around the candidates
e.preventDefault();
var c = ModLevels.Cands().Filtered();
var l = c.length;
if( !l ) break;
CandidateCycle += e.shiftKey ? -1 : 1;
if( CandidateCycle == l )
{
CandidateCycle = 0;
}
else if( CandidateCycle == -1 )
{
CandidateCycle = c.length - 1;
}
var ThisCandidate = c[ CandidateCycle ];
ThisCandidate.setAttribute( new DataKey( "selected", 1 ) );
var CyclingKeyword = ThisCandidate.getDAttribute( "key" );
sender.value = "`" + CyclingKeyword;
// Check if only 1 matched
if( c.length == 1 && KeywordTyped == sender.value.length )
{
insert = undefined;
ModLevels.Action()( ThisCandidate.getDAttribute( "key" ) );
break;
}
sender.setSelectionRange( KeywordTyped, sender.value.length );
break;
default:
ModLevels.Cands().Filtered();
CandidateCycle = -1;
}
};
var TestEmpty = function( sender, e )
{
if( ModLevels.Retreat()( sender, e ) )
{
_self.RetreatLevel( sender );
if( !ModLevels.length ) return;
}
// Search exact matched Candidates
switch( e.keyCode )
{
case 9: // Tab, do nothing
break;
case 16: // Shift, check if shiftTabbed
if( shiftTabbed )
{
shiftTabbed = false;
break;
}
default:
if( CandidateCycle == -1 )
{
KeywordTyped = sender.value.length;
}
var c = ModLevels.Cands().Get();
var keyword = sender.value.substr( 1 );
for( var i in c )
{
var Cand = IDOMElement( c[i] );
var t = Cand.getDAttribute( "key" );
Cand.style.display = t.match( new RegExp( keyword, "i" ) ) ? "" : "none";
// Highlight the exact match
if( t.match( new RegExp( "^" + keyword + "$", "i" ) ) )
{
Cand.setAttribute( new DataKey( "selected", 1 ) );
}
}
}
};
var ClosePanel = function( confirmed )
{
visualizer.restoreSelection();
if( confirmed && insert != undefined )
visualizer.insertAtCaret( insert() );
// Posponing this prevents the BackQuoteBinding firing
Cycle.next( function() {
_self.Present = false;
destructor.Destruct();
} );
};
// Advance the input level by CandidateAction
this.advanceLevel = function( Candidates, Action, Retreat )
{
if( ModLevels.length )
{
ModLevels[0].selected = ModLevels.Cands().Selected().getDAttribute( "key" );
}
ModLevels.unshift([ Candidates, Action, Retreat ]);
if( 1 < ModLevels.length )
{
CandidateCycle = -1;
stage( Candidates );
title( true );
stage()[0].value = "`";
stage()[0].setAttribute( "placeholder", ModLevels.Cands().desc );
BindingBox.show();
}
};
this.RetreatLevel = function( sender )
{
if( ModLevels.length == 1 )
{
BindingBox.close();
destructor.Destruct();
}
ModLevels.shift();
if( ModLevels.length )
{
var Cands = ModLevels.Cands();
var input = stage( Cands )[0];
title( true );
input.value
= "`" + Cands.Selected().getDAttribute( "key" );
input.setAttribute( "placeholder", Cands.desc );
input.selectionStart = 1;
input.selectionEnd = input.value.length;
BindingBox.show();
}
};
this.Show = function()
{
if( _self.Present ) return;
visualizer.saveSelection();
_self.Present = true;
var MsgBox = new MessageBox(
title()
, Dand.wrape( stage() )
, "Back", false
, ClosePanel
);
MsgBox.show();
var Command = stage()[0];
BindingBox = MsgBox;
Command.focus();
var DCommand = IDOMElement( Command );
var KDown = KeyHandler( Command, HandleInput );
var KUp = KeyHandler( Command, TestEmpty );
DCommand.addEventListener( "KeyDown", KDown );
DCommand.addEventListener( "KeyUp", KUp );
destructor.Register( function() {
DCommand.removeEventListener( "KeyDown", KDown );
DCommand.removeEventListener( "KeyUp", KUp );
} );
};
};
var MasterInput = function( visualizer )
{
var Cands = {
"Article Reference": { module: "ArticleReference", desc: "Links to other article" }
, "Article Content": { module: "ArticleContent", desc: "Put contents of an article" }
, "facts": { module: "Facts", desc: "Facts, a fact bubble popup when mouseover" }
, "footnote": { module: "Footnote", desc: "Footnote, a footnote displayed at the end of article" }
, "h1": { module: "Heading", options: 1, desc: "Heading, size 1" }
, "h2": { module: "Heading", options: 2, desc: "Heading, size 2" }
, "h3": { module: "Heading", options: 3, desc: "Heading, size 3" }
, "h4": { module: "Heading", options: 4, desc: "Heading, size 4" }
, "h5": { module: "Heading", options: 5, desc: "Heading, size 5" }
};
var LoadModule = function( mod )
{
var ldr = new Loader( service_uri, "o" );
var ModItem = Cands[ mod ];
ldr.load( moduleNs + ModItem.module, function( e ) { ModuleLoaded( mod, e ); } );
};
var InputBox = null;
var ModuleLoaded = function( sender, e )
{
/** @type {Astro.Blog.AstroEdit.SmartInput.ICandidateAction} */
var module = new ( __import( e ) )( visualizer, sender );
var ModItem = Cands[ sender ];
module.GetCandidates( function( x ) {
InputBox.advanceLevel(
new Candidates( ModItem.module, ModItem.desc, x )
, module.Process.bind( module )
, module.Retreat.bind( module )
);
} );
};
var BackQuoteBinding = function ( sender, e )
{
if( !InputBox || InputBox.Disposed )
{
InputBox = new SmartInput( visualizer );
InputBox.advanceLevel(
// First level Candidates
new Candidates( "Quick Access", "Keyword", Cands )
, LoadModule
, function( sender, e ) { return sender.value == ""; }
);
}
if( !InputBox.Present && code == 192 )
{
e.preventDefault();
InputBox.Show();
}
};
IDOMObject( document ).addEventListener( "KeyDown", KeyHandler( document, BackQuoteBinding ), false );
};
ns[ NS_EXPORT ]( EX_CLASS, "SmartInput", MasterInput );
})();

View File

@ -0,0 +1,241 @@
(function( ){
var ns = __namespace( "Astro.Blog.AstroEdit" );
/** @type {System.Cycle} */
var Cycle = __import( "System.Cycle" );
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
/** @type {System.utils.EventKey} */
var EventKey = __import( "System.utils.EventKey" );
/** @type {Components.Mouse.ContextMenu} */
var ContextMenu = __import( "Components.Mouse.ContextMenu" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMObject} */
var IDOMObject = __import( "Dandelion.IDOMObject" );
/** @type {Astro.Blog.Config} */
var Conf = __import( "Astro.Blog.Config" );
/** @type {System.utils.Perf} */
var Perf = __import( "System.utils.Perf" );
var postFile = __import( "System.Net.postFile" );
var Uploader = function ( set_file_uri )
{
/** @type {_AstConf_.SiteFile} */
var config = Conf.get( "SiteFile" );
// linkage
var busy = false
, placedFiles = []
, currentFile
// Prepare structure for dockpanel
, ptext = Dand.id( "asl_ptext" )
, pbar = Dand.id( "asl_pbar_fill" )
, ppreview = Dand.id( "asl_preview" )
, pfileName = Dand.id( "asl_fileName" )
, instruction = Dand.id( "asl_instruction" )
, p_status = Dand.id( "asl_u_head" )
, fileList = Dand.id( "asl_fileList" )
, stage = Dand.id( "asl_uploader" )
, uploadProgress = function(e)
{
var done = e.position || e.loaded
, total = e.totalSize || e.total
, percentage = String( Math.floor( done / total * 1000 )/10 ) + "%";
// Set progress
ptext.innetText
= ptext.textContent
= pbar.style.width
= percentage;
}
, uploadComplete = function ( response )
{
try
{
var obj = JSON.parse( response );
if(obj.status)
{
currentFile.setStatus( "ok", config.f_host + obj.destination );
}
else
{
currentFile.setStatus( "error", obj.message );
}
new ContextMenu( currentFile.stage, currentFile.menuKeys, "LMB", stage );
}
catch ( ex )
{
currentFile.setStatus( "error", ex.message );
debug.Error( ex );
}
beginUpload();
}
, beginUpload = function()
{
busy = true;
if( placedFiles.length )
{
currentFile = placedFiles.pop();
if( currentFile )
{
var file = currentFile.file;
pfileName.textContent = pfileName.innetText = file.name;
var fd = new FormData();
fd.append( "uploadFile", file );
postFile( set_file_uri, fd, { progress: uploadProgress, complete: uploadComplete } );
currentFile.setStatus("active");
instruction.style.marginTop = "-80px";
}
else
{
// deleted file, skip it
beginUpload();
}
}
else
{
busy = false;
instruction.style.marginTop = "";
}
}
, clearFileList = function ()
{
while( fileList.hasChildNodes() )
{
fileList.removeChild( fileList.firstChild );
}
}
, retryUpload = function ()
{
this.setStatus("pending");
placedFiles[placedFiles.length] = this;
new ContextMenu( this.stage, this.menuKeys, "RMB", stage );
if( !busy ) beginUpload();
}
, removeItem = function ()
{
this.stage.style.marginTop = "-2em";
this.stage.style.opacity = "0";
if( placedFiles.indexOf(this) != -1 )
{
delete placedFiles[placedFiles.indexOf(this)];
}
Cycle.delay(function () {
fileList.removeChild(this);
}.bind(this.stage), 250);
}
;
fileList.style.paddingTop = String(p_status.clientHeight) + "px";
var docDom = IDOMObject( document );
// Drag/drop handlers
docDom.addEventListener( "DragOver", function ( e )
{
e.preventDefault();
this.className = "dragged_over";
} );
docDom.addEventListener( "DragEnd", function () { this.className = ""; } );
docDom.addEventListener( "Drop", function ( e )
{
e.preventDefault();
this.className = "";
// Push files
var list = e.dataTransfer.files;
for(var i in list)
{
if(list[i].type != undefined)
{
var fileItem = new ASLFileItem(list[i], {clear: clearFileList, remove: removeItem, retry: retryUpload});
placedFiles[placedFiles.length] = fileItem;
fileList.appendChild(fileItem.stage);
new ContextMenu(fileItem.stage, fileItem.menuKeys, "LMB", stage);
}
}
if(!busy) beginUpload();
return false;
} );
};
var ASLFileItem = function (file, callbacks)
{
var statusblob = Dand.wrap("span", null, "asl_uItemStat", "\u25CF")
, msg
, _items = [
new EventKey("Remove this item", callbacks.remove.bind(this)) // Reserved for remove item
, null // Reserved for retry/ Open link
, null // Reserved for get Error message
, new EventKey("Clear all", callbacks.clear)
]
, popMessage = function ()
{
new MessageBox("Upload error", msg).show();
}
, getFileLink = function ()
{
return msg;
}
;
this.stage = Dand.wrap( null, "asl_item" + Perf.uuid, "asl_uItem", [ statusblob, Dand.textNode(file.name) ] );
this.file = file;
this.menuKeys = _items;
this.setStatus = function (st, message)
{
msg = message;
switch(st)
{
case "active":
statusblob.style.color = "cornflowerblue";
break;
case "error":
statusblob.style.color = "red";
_items[1] = new EventKey( "Retry", callbacks.retry.bind(this) );
_items[2] = new EventKey( "Whats wrong ?", popMessage );
break;
case "ok":
statusblob.style.color = "greenyellow";
_items[1] = new EventKey( "Copy file link", getFileLink );
break;
default:// pending
delete _items[1];
delete _items[2];
statusblob.style.color = "";
}
}
};
ns[ NS_EXPORT ]( EX_CLASS, "Uploader", Uploader );
})();

View File

@ -0,0 +1,5 @@
.v_boundary[data-type="AcquireLib"] > span {
background-color: #444;
color: white;
padding: 0.2em 0.5em;
}

View File

@ -0,0 +1,100 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
var acquirelib = function(insertSnippet, snippetWrap, createContext, override)
{
var temp, i, j
, handler = function ()
{
// Input fields
var input_text = Dand.wrap('input', null, "v_snippet_input_single", null, new IKey("type", "text"));
if (this._stage)
{
input_text.value = this._text;
}
// Popup MessageBox
new MessageBox(
"Acquire library" + ( this._stage ? " (Edit)" : "" )
, Dand.wrape([ Dand.wrapc( "v_instruction flsf", "Module" ) , input_text ])
, "OK", "Cancel"
, visualizer.bind({ text:input_text, stage: this._stage })
).show();
}
, visualizer = function (submitted, override)
{
var src = override ? override.value : this.text.value
, stage = this.stage;
if (submitted && src)
{
// Shared clause
if (!stage)
{
if (!src) return;
// Visualize component
temp = Dand.wrap(
'span', null, "flsf"
, "AcquireLib: " + src
, [ new DataKey( "value", src ) ]
);
insertSnippet(j = snippetWrap("AcquireLib", temp, false, 'span'), Boolean(override));
}
else
{
IDOMElement(stage).setAttribute( new DataKey("value", src) );
stage.removeChild(stage.firstChild);
stage.appendChild(Dand.textNode("AcquireLib: " + src));
// set temp back to stage
temp = stage;
}
i = {_text: src, _stage: temp};
// Set context menu
createContext(i, j, handler);
}
};
if (override)
{
visualizer(true, override);
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function (stage)
{
var element = IDOMElement(stage);
return "[acquirelib]" + element.getDAttribute("value") + "[/acquirelib]";
};
__static_method( acquirelib, "compile", compile );
ns[ NS_EXPORT ]( EX_CLASS, "AcquireLib", acquirelib );
})();

View File

@ -0,0 +1,7 @@
.v_boundary[data-type="ArticleContent"] {
color: #999;
}
.v_boundary[data-type="ArticleContent"] span.info {
color: #f15a24;
}

View File

@ -0,0 +1,160 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
/** @type {Astro.Blog.Config} */
var Config = __import( "Astro.Blog.Config" );
/** @type {System.utils.Perf} */
var Perf = __import( "System.utils.Perf" );
/** @type {Astro.utils.Date} */
var XDate = __import( "Astro.utils.Date" );
var escapeStr = ns[ NS_INVOKE ]( "escapeStr" );
var unescapeStr = ns[ NS_INVOKE ]( "unescapeStr" );
var compileProp = ns[ NS_INVOKE ]( "compileProp" );
var postData = __import( "System.Net.postData" );
/** @type {_AstConf_.AstroEdit} */
var config = null;
var ArticleContent = function ( insertSnippet, snippetWrap, createContext, override )
{
config = Config.get( "AstroEdit" );
if( !config ) throw new Error( "config is not defined" );
var temp, i, j
, handler = function ()
{
// Input fields
var v_snippetInput = Dand.wrap( "input", null, "v_snippet_input_single", null, new IKey( "type", "text" ) );
if ( this._stage )
{
v_snippetInput.value = this._id;
}
// Popup MessageBox
new MessageBox(
"ArticleContent"
, Dand.wrape([
Dand.wrapc( "v_instruction", "ArticleContent id:" )
, v_snippetInput
])
, "OK", "Cancel"
, visualizer.bind({
id: v_snippetInput
, stage: this._stage
})
).show();
}
, visualizer = function ( submitted, override )
{
var id, stage = this.stage;
if( override )
{
id = unescapeStr( override.value );
}
else
{
id = this.id.value;
}
var ACInfo = [ "ArticleContent[ ", Dand.wrap( "span", null, "info", id ), " ]" ];
if ( submitted && id )
{
// Visualize component
if (!stage)
{
temp = Dand.wrapne( "span"
, ACInfo
, new DataKey( "value", id )
);
insertSnippet(
j = snippetWrap(
"ArticleContent"
, temp
, false, "span"
)
, !!override
);
}
else
{
var stg = IDOMElement( stage );
stg.clear();
stg.loot( Dand.wrape( ACInfo ) );
stg.setAttribute( new DataKey( "value", id ) );
}
i = {
_id: id
, _stage: temp
};
// Get title of this article
postData(
config.paths.get_article
, { article_id: id }
/** @param {_AstJson_.AJaxGetArticle} */
, function( e )
{
ACInfo[1].firstChild.textContent = e.entry.title;
}
, function()
{
ACInfo[1].firstChild.textContent = "ERROR";
} );
// Set context menu
createContext( i, j, handler );
}
};
if ( override )
{
visualizer( true, override );
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function ( stage )
{
stage = IDOMElement( stage );
var options = "";
var opt;
return "[articlecontent]"
+ escapeStr( stage.getDAttribute( "value" ) )
+ "[/articlecontent]";
};
__static_method( ArticleContent, "compile", compile );
ns[ NS_EXPORT ]( EX_CLASS, "ArticleContent", ArticleContent );
})();

View File

@ -0,0 +1,9 @@
.v_boundary[data-type="ArticleLink"]:before {
content: "[";
}
.v_boundary[data-type="ArticleLink"] {
color: #f15a24;
}
.v_boundary[data-type="ArticleLink"]:after {
content: "]";
}

View File

@ -0,0 +1,176 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
/** @type {Astro.Blog.Config} */
var Config = __import( "Astro.Blog.Config" );
/** @type {System.utils.Perf} */
var Perf = __import( "System.utils.Perf" );
/** @type {Astro.utils.Date} */
var XDate = __import( "Astro.utils.Date" );
var escapeStr = ns[ NS_INVOKE ]( "escapeStr" );
var unescapeStr = ns[ NS_INVOKE ]( "unescapeStr" );
var compileProp = ns[ NS_INVOKE ]( "compileProp" );
var postData = __import( "System.Net.postData" );
/** @type {_AstConf_.AstroEdit} */
var config = null;
var ArticleLink = function ( insertSnippet, snippetWrap, createContext, override )
{
config = Config.get( "AstroEdit" );
if( !config ) throw new Error( "config is not defined" );
var temp, i, j
, handler = function ()
{
// Input fields
var v_snippetInput = Dand.wrap( "input", null, "v_snippet_input_single", null, new IKey( "type", "text" ) )
, input_title = Dand.wrap( "input", null, "v_snippet_input_single", null, new IKey( "type", "text" ) )
;
if ( this._stage )
{
v_snippetInput.value = this._id;
input_title.value = this._title;
}
// Popup MessageBox
new MessageBox(
"Link to article"
, Dand.wrape([
Dand.wrapc( "v_instruction", "Article id:" )
, v_snippetInput
, Dand.wrapc( "v_instruction", "Title override:" )
, input_title
])
, "OK", "Cancel"
, visualizer.bind({
id: v_snippetInput
, title: input_title
, stage: this._stage
})
).show();
}
, visualizer = function ( submitted, override )
{
var id, stage = this.stage;
if( override )
{
id = unescapeStr( override.value );
title = unescapeStr( override.title ) || "";
}
else
{
id = this.id.value;
title = this.title.value;
}
if ( submitted && id )
{
// Visualize component
if (!stage)
{
temp = Dand.wrapne( "span"
, title || "ArticleLink[" + id + "]"
, [
new DataKey( "value", id )
, new DataKey( "title", title )
]
);
insertSnippet(
j = snippetWrap( "ArticleLink", temp, false, "span" )
, !!override
);
}
else
{
stage.firstChild.textContent = title || "ArticleLink[" + id + "]";
IDOMElement( stage ).setAttribute([
new DataKey( "value", id )
, new DataKey( "title", title )
]);
}
// Get the default title if not defined
if( !title )
{
postData(
config.paths.get_article
, { article_id: id }
/** @param {_AstJson_.AJaxGetArticle} */
, function( e )
{
j.firstChild.textContent = e.entry.title;
}
, function()
{
j.firstChild.textContent = "ArticleLink[ ERROR ]";
} );
}
i = {
_id: id
, _title: title
, _stage: temp
};
// Set context menu
createContext( i, j, handler );
}
};
if ( override )
{
visualizer( true, override );
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function ( stage )
{
stage = IDOMElement( stage );
var options = "";
var opt;
if( opt = stage.getDAttribute( "title" ) )
{
options += " title=\"" + escapeStr( opt ) + "\"";
}
return "[articlelink" + options + "]"
+ escapeStr( stage.getDAttribute( "value" ) )
+ "[/articlelink]";
};
__static_method( ArticleLink, "compile", compile );
ns[ NS_EXPORT ]( EX_CLASS, "ArticleLink", ArticleLink );
})();

View File

@ -0,0 +1,12 @@
.v_boundary[data-inline="on"][data-type="Code"] {
display: inline-block;
background-color: #EEE;
}
.v_box[data-inline="on"] .v_description {
display: none;
}
.v_box[data-inline="on"] {
min-height: 0;
}

View File

@ -0,0 +1,214 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
var escapeStr = ns[ NS_INVOKE ]( "escapeStr" );
var unescapeStr = ns[ NS_INVOKE ]( "unescapeStr" );
var compileProp = ns[ NS_INVOKE ]( "compileProp" );
var code = function ( insertSnippet, snippetWrap, createContext, override )
{
var temp, i, j
, codeLangs = IKey.quickDef(
"Plain text" , "plain"
, "AS3" , "as3"
, "bash" , "bash"
, "C#" , "csharp"
, "C/C++" , "cpp"
, "CSS" , "css"
, "php" , "php"
, "Python" , "python"
, "Perl" , "perl"
, "Ruby" , "ruby"
, "Html/Xml" , "xml"
, "Java" , "java"
, "JavaScript" , "js"
, "SQL" , "sql"
)
// Private methods
, compileListItems = function ()
{
var arr = [];
for ( i in codeLangs )
{
arr[ arr.length ] = Dand.wrapne(
"option"
, codeLangs[i].keyName
, new IKey( "value", codeLangs[i].keyValue )
);
}
return arr;
}
// Snippet Class structure: handler & visualizer
, handler = function ()
{
// Input fields
var v_snippetInput = Dand.wrap( "textarea", null, "v_snippet_input" )
, v_codelang = Dand.wrap( "select", null, "v_select flsf", compileListItems() )
, input_inline = Dand.wrapna( "input", new IKey( "type", "checkbox" ) );
if ( this._stage )
{
if ( this._lang )
{
for ( i = 0; i < codeLangs.length; i ++ )
{
if ( codeLangs[i].keyValue == this._lang )
{
v_codelang.selectedIndex = i;
}
}
}
v_snippetInput.value = this._content || "";
input_inline.checked = ( this._inline == "on" );
}
else
{
// Remember the last choice
if ( typeof( this.pSnippeCodeChoice ) == "number" )
v_codelang.selectedIndex = this.pSnippeCodeChoice;
}
// Popup MessageBox
new MessageBox(
( this._stage ? "Edit" : "Insert" ) + " code snippet"
, Dand.wrapc(
"v_trimmer"
, [
Dand.wrapc( "v_instruction", v_codelang )
, v_snippetInput
, Dand.wrape( Dand.wrapne( "label", [ input_inline, "Inline" ] ) )
]
)
, "OK", "Cancel"
// Switcher
, visualizer.bind({ code:v_snippetInput, inline: input_inline, lang: v_codelang, stage: this._stage })
).show();
}
/* @type override {_AstXObject_.AstroEdit.Visualizer.Snippet.Code.Override} */
, visualizer = function( submitted, override )
{
var lang, code, inline
, stage = this.stage;
if( override )
{
lang = unescapeStr( override.lang );
code = unescapeStr( override.value );
inline = override.inline;
}
else
{
lang = this.lang[this.pSnippeCodeChoice = this.lang.selectedIndex].value;
code = this.code.value;
inline = this.inline.checked ? "on" : "";
}
var langName;
for( var i in codeLangs )
{
if( codeLangs[i].keyValue == lang )
{
langName = codeLangs[i].keyName;
break;
}
}
if ( submitted && code )
{
if ( !stage )
{
// Visualize component
temp = Dand.wrapc(
"v_box"
, [
Dand.wrapne( "pre", code )
, Dand.wrapc( "v_description", "Script language: " + langName )
]
, [
new DataKey( "value", code )
, new DataKey( "lang", lang )
, new DataKey( "inline", inline )
]
);
insertSnippet( j = snippetWrap( "Code", temp ), Boolean( override ) );
}
else
{
IDOMElement( stage ).setAttribute(
[
new DataKey( "value", code )
, new DataKey( "lang", lang )
, new DataKey( "inline", inline )
]
);
temp = stage.firstChild;
temp.removeChild( temp.firstChild );
stage.firstChild.appendChild( Dand.textNode( code ) );
temp = stage.lastChild;
temp.removeChild( temp.firstChild );
temp.appendChild( Dand.textNode( "Script language: " + langName ) );
temp = stage;
}
i = { _inline: inline, _lang: lang, _content: code, _stage: temp };
// Set the inline style
IDOMElement( j ).setAttribute( new DataKey( "inline", inline ) );
// Set context menu
createContext( i, j, handler );
}
}
;
if ( override )
{
visualizer( true, override );
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function ( stage )
{
// [code lang=\"" + lang + "\"]" + code + "[/code]"
var element = IDOMElement( stage )
, props= [ "lang", "inline" ];
return "[code"
+ compileProp( element, props )
+ "]"
+ escapeStr( element.getDAttribute( "value" ) )
+ "[/code]"
;
};
__static_method( code, "compile", compile );
ns[ NS_EXPORT ]( EX_CLASS, "Code", code );
})();

View File

@ -0,0 +1,3 @@
.v_boundary[data-type="Footnote"] {
color: #f15a24;
}

View File

@ -0,0 +1,98 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
var unescapeStr = ns[ NS_INVOKE ]( "unescapeStr" );
var escapeStr = ns[ NS_INVOKE ]( "escapeStr" );
var footnote = function( insertSnippet, snippetWrap, createContext, override )
{
var temp, i, j
, handler = function ()
{
// Input fields
var v_snippetInput = Dand.wrap( "textarea", null, "v_snippet_input" );
if ( this._stage )
{
v_snippetInput.value = this._mText;
}
// Popup MessageBox
new MessageBox(
"Insert Footnote"
, v_snippetInput
, "OK", "Cancel"
, visualizer.bind({ mText: v_snippetInput, stage: this._stage })
).show();
}
, visualizer = function( submitted, override )
{
var mText, stage = this.stage;
mText = override ? unescapeStr( override.value ) : this.mText.value;
if (submitted && mText)
{
if (!stage)
{
// Visualize component
temp = Dand.wrapne( "span", "^", [
new DataKey( "value", mText )
]);
insertSnippet(
j = snippetWrap( "Footnote", temp, false, "span" )
, Boolean( override )
);
}
else
{
IDOMElement( stage ).setAttribute(new DataKey( "value", mText ));
temp = stage;
}
i = { _mText: mText, _stage: temp };
// Set context menu
createContext( i, j, handler );
}
};
if ( override )
{
visualizer( true, override );
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function (stage)
{
// [footnote][/footnote]
return "[footnote]" + escapeStr( IDOMElement(stage).getDAttribute("value") ) + "[/footnote]";
};
__static_method( footnote, "compile", compile );
ns[ NS_EXPORT ]( EX_CLASS, "Footnote", footnote );
})();

View File

@ -0,0 +1,178 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
var unescapeStr = ns[ NS_INVOKE ]( "unescapeStr" );
var escapeStr = ns[ NS_INVOKE ]( "escapeStr" );
var compileProp = ns[ NS_INVOKE ]( "compileProp" );
var heading = function ( insertSnippet, snippetWrap, createContext, override )
{
var temp, i, j
, Sizes = IKey.quickDef(
"h1", "h1"
, "h2", "h2"
, "h3", "h3"
, "h4", "h4"
, "h5", "h5"
)
// Private methods
, compileListItems = function ()
{
var arr = [];
for ( i in Sizes )
{
arr[ arr.length ] = Dand.wrapne(
"option"
, Sizes[i].keyName
, new IKey( "value", Sizes[i].keyValue )
);
}
return arr;
}
// Snippet Class structure: handler & visualizer
, handler = function ()
{
// Input fields
var v_snippetInput = Dand.wrap('input', null, "v_snippet_input_single", null, new IKey("type", "text") )
, v_headingsize = Dand.wrap( "select", null, "v_select flsf", compileListItems() );
if ( this._stage )
{
if ( this._size )
{
for ( i = 0; i < Sizes.length; i ++ )
{
if ( Sizes[i].keyValue == this._size )
{
v_headingsize.selectedIndex = i;
}
}
}
v_snippetInput.value = this._content || "";
}
else
{
// Remember the last choice
if ( typeof( this.pSnippeHeadingChoice ) == "number" )
v_headingsize.selectedIndex = this.pSnippeHeadingChoice;
}
// Popup MessageBox
new MessageBox(
( this._stage ? "Edit" : "Insert" ) + " heading text"
, Dand.wrapc(
"v_trimmer"
, [
v_snippetInput
, Dand.wrapc( "v_instruction", v_headingsize )
]
)
, "OK", "Cancel"
// Switcher
, visualizer.bind({ heading:v_snippetInput, size: v_headingsize, stage: this._stage })
).show();
}
, visualizer = function ( submitted, override )
{
var size, heading
, stage = this.stage;
if ( override )
{
size = unescapeStr( override.size );
heading = unescapeStr( override.value );
}
else
{
size = this.size[this.pSnippeHeadingChoice = this.size.selectedIndex].value;
heading = this.heading.value;
}
var size;
for( var i in Sizes )
{
if( Sizes[i].keyValue == size )
{
size = Sizes[i].keyName;
break;
}
}
if ( submitted && heading )
{
if ( !stage )
{
// Visualize component
temp = Dand.wrapne( "span", Dand.wrapne( size, heading ), [
new DataKey( "value", heading )
, new DataKey( "size", size )
]);
insertSnippet( j = snippetWrap( "Heading", temp ), Boolean( override ) );
}
else
{
IDOMElement( stage ).setAttribute([
new DataKey( "value", heading )
, new DataKey( "size", size )
]);
stage.removeChild( stage.firstChild );
stage.appendChild( Dand.wrapne( size, heading ) );
temp = stage;
}
i = { _size: size, _content: heading, _stage: temp };
// Set context menu
createContext( i, j, handler );
}
}
;
if ( override )
{
visualizer( true, override );
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function ( stage )
{
var element = IDOMElement( stage )
, props = [ "size" ];
return "[heading"
+ compileProp( element, props )
+ "]"
+ escapeStr( element.getDAttribute( "value" ) )
+ "[/heading]"
;
};
__static_method( heading, "compile", compile );
ns[ NS_EXPORT ]( EX_CLASS, "Heading", heading );
})();

View File

@ -0,0 +1,107 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
var escapeStr = ns[ NS_INVOKE ]( "escapeStr" );
var unescapeStr = ns[ NS_INVOKE ]( "unescapeStr" );
var html = function( insertSnippet, snippetWrap, createContext, override )
{
var temp, i, j
, handler = function ()
{
// Input fields
var v_snippetInput = Dand.wrap( "textarea", null, "v_snippet_input" );
if ( this._stage )
{
v_snippetInput.value = this._code;
}
// Popup MessageBox
new MessageBox(
"Insert Html snippet"
, v_snippetInput
, "OK", "Cancel"
, visualizer.bind({ code: v_snippetInput, stage: this._stage })
).show();
}
, visualizer = function( submitted, override )
{
var code, stage = this.stage;
code = override ? unescapeStr( override.value ) : this.code.value;
if (submitted && code)
{
if (!stage)
{
// Visualize component
temp = Dand.wrapc(
"v_box"
, [
Dand.wrapne( "pre", code )
, Dand.wrapc( "v_description", "Raw Html Codes" )
]
, [
new DataKey( "value", code )
, new IKey( "style", "max-height: 150px;" )
]
);
insertSnippet(j = snippetWrap("Html", temp), Boolean(override));
}
else
{
IDOMElement( stage ).setAttribute(new DataKey( "value", code ));
temp = stage.firstChild;
temp.removeChild(temp.firstChild);
stage.firstChild.appendChild(Dand.textNode( code ));
temp = stage;
}
i = { _code: code, _stage: temp };
// Set context menu
createContext( i, j, handler );
}
};
if ( override )
{
visualizer( true, override );
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function (stage)
{
// [html][/html]
return "[html]" + escapeStr( IDOMElement(stage).getDAttribute("value") ) + "[/html]";
};
__static_method( html, "compile", compile );
ns[ NS_EXPORT ]( EX_CLASS, "Html", html );
})();

View File

@ -0,0 +1,173 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
var escapeStr = ns[ NS_INVOKE ]( "escapeStr" );
var unescapeStr = ns[ NS_INVOKE ]( "unescapeStr" );
var compileProp = ns[ NS_INVOKE ]( "compileProp" );
var image = function( insertSnippet, snippetWrap, createContext, override )
{
var temp, i, j
, handler = function ()
{
// Input fields
var input_url = Dand.wrap(
"input", null, "v_snippet_input_single", null, new IKey( "type", "text" )
)
, input_a = Dand.wrap(
"input", null, "v_snippet_input_single", null, new IKey( "type", "text" )
)
, input_preferred = Dand.wrapna( "input", new IKey( "type", "checkbox" ) )
;
if ( this._stage )
{
input_url.value = this._url;
input_a.value = this._href;
input_preferred.checked = ( this._preferred == "on" );
}
// Popup MessageBox
new MessageBox(
( this._stage ? "Edit" : "Insert" ) + " image snippet",
Dand.wrape([
Dand.wrapc( "v_instruction flsf", "Link to the image:" )
, input_url
, Dand.wrapc( "v_instruction flsf", "Ancohr link(optional):" )
, input_a
, Dand.wrape( Dand.wrapne( "label", [ input_preferred, "Preferred" ] ) )
]
)
, "OK", "Cancel"
, visualizer.bind({ url:input_url, href:input_a, stage: this._stage, preferred: input_preferred })
).show();
}
, visualizer = function ( submitted, override )
{
var src, href, preferred
, stage = this.stage;
if ( override )
{
src = unescapeStr( override.value );
href = unescapeStr( override.href );
preferred = override.preferred ? "on" : "";
}
else
{
src = this.url.value;
href = this.href.value;
preferred = this.preferred.checked ? "on" : "";
}
if ( submitted && src )
{
// Shared clause
i = Dand.textNode(href ? ("link to: " + href): "No link");
if ( !stage )
{
if ( !src ) return;
// Visualize component
temp = Dand.wrapc(
"v_box"
, [
Dand.wrapna(
"img"
, [
new IKey( "src", src )
, new IKey( "style", "max-width: 100%" )
]
)
// caption
, Dand.wrapc( "v_description", i )
]
, [
new DataKey( "value", src )
, new DataKey( "href", href )
, new DataKey( "preferred", preferred )
]
);
insertSnippet( j = snippetWrap( "Image", temp ), Boolean( override ) );
}
else
{
IDOMElement( stage ).setAttribute
([
new DataKey( "value", src )
, new DataKey( "href", href )
, new DataKey( "preferred", preferred )
]);
stage.firstChild.setAttribute("src", src);
temp = stage.lastChild;
temp.removeChild(temp.firstChild);
temp.appendChild(i);
// set temp back to stage
temp = stage;
}
i = {
_url: src
, _href: href
, _preferred: preferred || "off"
, _stage: temp
};
// Set context menu
createContext( i, j, handler );
}
}
;
if ( override )
{
visualizer( true, override );
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function ( stage )
{
// [img href=\"" + this.href.value + "\"]" + this.url.value + "[/img]
var element = IDOMElement( stage )
, props = [ "href", "preferred" ]
return "[img" + compileProp( element, props ) + "]"
+ escapeStr( element.getDAttribute( "value" ) )
+ "[/img]"
;
};
// Alias
var alias = "img";
__static_method( image, "compile", compile );
__const( image, "alias", alias );
ns[ NS_EXPORT ]( EX_CLASS, "Image", image );
})();

View File

@ -0,0 +1,3 @@
.v_boundary[data-type="Link"] {
color: #f15a24;
}

View File

@ -0,0 +1,132 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
var escapeStr = ns[ NS_INVOKE ]( "escapeStr" );
var unescapeStr = ns[ NS_INVOKE ]( "unescapeStr" );
var link = function(insertSnippet, snippetWrap, createContext, override)
{
var temp, i, j
, handler = function ()
{
// Input fields
var input_text = Dand.wrap("input", null, "v_snippet_input_single", null, new IKey("type", "text"))
, input_a = Dand.wrap("input", null, "v_snippet_input_single", null, new IKey("type", "text"));
if (this._stage)
{
input_text.value = this._text;
input_a.value = this._href;
}
// Popup MessageBox
new MessageBox(
(this._stage ? "Edit" : "Insert") + " link",
Dand.wrape([
Dand.wrapc("v_instruction flsf", "Text")
, input_text
, Dand.wrapc("v_instruction flsf", "Link to:")
, input_a
])
, "OK", "Cancel", visualizer.bind({text:input_text, href:input_a, stage: this._stage})).show();
}
, visualizer = function (submitted, override)
{
var src, href
, stage = this.stage;
if( override )
{
src = unescapeStr( override.value );
href = unescapeStr( override.href );
}
else
{
src = this.text.value;
href = this.href.value;
}
if (submitted && src && href)
{
// Shared clause
if (!stage)
{
if (!src) return;
// Visualize component
temp =
Dand.wrapne("span", src
, [
new DataKey("value", src)
, new DataKey("href", href)
]
);
insertSnippet(j = snippetWrap("Link", temp, false, "span"), Boolean(override));
}
else
{
IDOMElement(stage).setAttribute
(
[
new DataKey("value", src)
, new DataKey("href", href)
]
);
stage.removeChild(stage.firstChild);
stage.appendChild(Dand.textNode(src));
// set temp back to stage
temp = stage;
}
i = {_text: src, _href: href, _stage: temp};
// Set context menu
createContext(i, j, handler);
}
};
if (override)
{
visualizer(true, override);
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function (stage)
{
// [link href=\"" + this.href.value + "\"]" + text + "[/link]
var element = IDOMElement(stage)
, href = escapeStr( element.getDAttribute("href") )
, val = escapeStr( element.getDAttribute("value") ) ;
return "[link" + (href ? (" href=\"" + href + "\"") : "") + "]" + val + "[/link]";
};
__static_method( link, "compile", compile );
ns[ NS_EXPORT ]( EX_CLASS, "Link", link );
})();

View File

@ -0,0 +1,5 @@
.v_boundary[data-type="Meta"] > span {
background-color: #444;
color: white;
padding: 0.2em 0.5em;
}

View File

@ -0,0 +1,94 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
var escapeStr = ns[ NS_INVOKE ]( "escapeStr" );
var unescapeStr = ns[ NS_INVOKE ]( "unescapeStr" );
var meta = function( insertSnippet, snippetWrap, createContext, override )
{
var temp, i, j
, handler = function ()
{
// Input fields
var v_snippetInput = Dand.wrap( "textarea", null, "v_snippet_input" );
if ( this._stage )
{
v_snippetInput.value = this._code;
}
// Popup MessageBox
new MessageBox(
"Insert Meta Tags"
, v_snippetInput
, "OK", "Cancel"
, visualizer.bind({ code: v_snippetInput, stage: this._stage })
).show();
}
, visualizer = function( submitted, override )
{
var code, stage = this.stage;
code = override ? unescapeStr( override.value ) : this.code.value;
if (submitted && code)
{
if (!stage)
{
// Visualize component
temp = Dand.wrap(
'span', null, "flsf"
, "Meta Tags"
, [ new DataKey( "value", code ) ]
);
insertSnippet(j = snippetWrap( "Meta", temp, false, "span" ), Boolean(override));
}
else
{
IDOMElement( stage ).setAttribute(new DataKey( "value", code ));
temp = stage;
}
i = { _code: code, _stage: temp };
// Set context menu
createContext( i, j, handler );
}
};
if ( override )
{
visualizer( true, override );
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function (stage)
{
return "[meta]" + escapeStr( IDOMElement(stage).getDAttribute("value") ) + "[/meta]";
};
__static_method( meta, "compile", compile );
ns[ NS_EXPORT ]( EX_CLASS, "Meta", meta );
})();

View File

@ -0,0 +1,5 @@
.v_boundary[data-type="RespH"] > span {
background-color: #444;
color: white;
padding: 0.2em 0.5em;
}

View File

@ -0,0 +1,99 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
var escapeStr = ns[ NS_INVOKE ]( "escapeStr" );
var unescapeStr = ns[ NS_INVOKE ]( "unescapeStr" );
var resph = function( insertSnippet, snippetWrap, createContext, override )
{
var temp, i, j
, handler = function ()
{
// Input fields
var v_snippetInput = Dand.wrap( "textarea", null, "v_snippet_input" );
if ( this._stage )
{
v_snippetInput.value = this._code;
}
// Popup MessageBox
new MessageBox(
"Insert Response Headers"
, v_snippetInput
, "OK", "Cancel"
, visualizer.bind({ code: v_snippetInput, stage: this._stage })
).show();
}
, visualizer = function( submitted, override )
{
var code, stage = this.stage;
code = override ? unescapeStr( override.value ) : this.code.value;
if (submitted && code)
{
if (!stage)
{
// Visualize component
temp = Dand.wrap(
'span', null, "flsf"
, "Response Headers"
, [
new DataKey( "value", code )
, new IKey(
"style", "background-color: #444; color: white; padding: 0.2em 0.5em;"
)
]
);
insertSnippet(j = snippetWrap( "RespH", temp, false, "span" ), Boolean(override));
}
else
{
IDOMElement( stage ).setAttribute(new DataKey( "value", code ));
temp = stage;
}
i = { _code: code, _stage: temp };
// Set context menu
createContext( i, j, handler );
}
};
if ( override )
{
visualizer( true, override );
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function (stage)
{
return "[resph]" + escapeStr( IDOMElement(stage).getDAttribute("value") ) + "[/resph]";
};
__static_method( resph, "compile", compile );
ns[ NS_EXPORT ]( EX_CLASS, "RespH", resph );
})();

View File

@ -0,0 +1,3 @@
.v_box.sf-view {
max-height: 150px;
}

View File

@ -0,0 +1,289 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
/** @type {Astro.Blog.Config} */
var Config = __import( "Astro.Blog.Config" );
/** @type {System.utils.Perf} */
var Perf = __import( "System.utils.Perf" );
/** @type {System.Cycle.Trigger} */
var Trigger = __import( "System.Cycle.Trigger" );
/** @type {Astro.utils.Date} */
var XDate = __import( "Astro.utils.Date" );
var escapeStr = ns[ NS_INVOKE ]( "escapeStr" );
var compileProp = ns[ NS_INVOKE ]( "compileProp" );
var getData = __import( "System.Net.getData" );
/** @type {_AstConf_.SiteFile} */
var config = null;
var sitefile = function ( insertSnippet, snippetWrap, createContext, override )
{
config = Config.get( "SiteFile" );
if( !config ) throw new Error( "config is not defined" );
var temp, i, j
, handler = function ()
{
// Input fields
var v_snippetInput = Dand.wrap("input", null, "v_snippet_input_single", null, new IKey("type", "text"))
, input_preferred = Dand.wrapna( "input", new IKey( "type", "checkbox" ) )
;
if ( this._stage )
{
v_snippetInput.value = this._content;
input_preferred.checked = ( this._preferred == "on" );
}
// Popup MessageBox
new MessageBox(
"Insert site file"
, Dand.wrape([
v_snippetInput
, Dand.wrape( Dand.wrapne( "label", [ input_preferred, "Preferred" ] ) )
])
, "OK", "Cancel"
, visualizer.bind({
code: v_snippetInput
, input_preferred: input_preferred
, stage: this._stage
})
).show();
}
, __applyData = function (e)
{
if( typeof( e ) == "string" )
e = JSON.parse(e);
var _stage = IDOMElement( this.stage );
var isAlbum = false;
// Check if this is an album
if( isAlbum = ( "files" in e ) )
{
e.file = e.files[0];
_stage.setAttribute( new DataKey( "collection", 1 ) );
}
var s, m, l, o;
var finfo = e.file;
var content = this.stage.firstChild;
var desc = this.stage.lastChild;
var _hash = finfo.hash;
switch ( finfo.type )
{
case "image":
this.stage.removeChild(content);
// Default size is large
var _image = Dand.wrapna( "img", new IKey("src", config.path.image.large + _hash + ".jpg") );
var keys = [ new IKey( "type", "radio" ), new IKey( "name", "size_grp" + Perf.uuid ) ];
var sid;
var detectImageChange = function() { return _image.complete; };
var setImageSizeProp = function()
{
_stage.setAttribute( new DataKey( "dimensions", _image.naturalWidth + "x" + _image.naturalHeight ) );
};
var selectionChanged = function ()
{
_stage.setAttribute( new DataKey( "size", this.size ) );
//// Handles the size selection
switch(this.size)
{
case "small":
_image.setAttribute( "src", config.path.image.small + _hash + ".jpg" );
break;
case "medium":
_image.setAttribute( "src", config.path.image.medium + _hash + ".jpg" );
break;
case "large":
_image.setAttribute( "src", config.path.image.large + _hash + ".jpg" );
break;
case "original":
_image.setAttribute( "src", config.path.image.original + _hash + ".jpg" );
break;
}
Trigger.register( detectImageChange, setImageSizeProp, 100 );
};
Trigger.register( detectImageChange, setImageSizeProp, 100 );
this.stage.insertBefore( _image, desc );
desc.removeChild( desc.firstChild );
desc.appendChild(
Dand.wrape([
Dand.textNode( ( isAlbum ? "[Album] " : "" ) + "Size: ")
, s = Dand.wrapna("input", keys.concat( new IKey("id", sid = "size_" + Perf.uuid) ))
, Dand.wrapne("label", "small", new IKey("for", sid))
, m = Dand.wrapna("input", keys.concat( new IKey("id", sid = "size_" + Perf.uuid) ))
, Dand.wrapne("label", "medium", new IKey("for", sid))
, l = Dand.wrapna("input", keys.concat( new IKey("checked", "1"), new IKey("id", sid = "size_" + Perf.uuid) ))
, Dand.wrapne("label", "large (default)", new IKey("for", sid))
, o = Dand.wrapna("input", keys.concat( new IKey("id", sid = "size_" + Perf.uuid) ))
, Dand.wrapne("label", "original", new IKey("for", sid))
])
);
// ad handlers to handles size change event
IDOMElement(s).addEventListener("Change", selectionChanged.bind({size: "small"}));
IDOMElement(m).addEventListener("Change", selectionChanged.bind({size: "medium"}));
IDOMElement(l).addEventListener("Change", selectionChanged.bind({size: "large"}));
IDOMElement(o).addEventListener("Change", selectionChanged.bind({size: "original"}));
var hasValue = _stage.getDAttribute( "size" );
if( hasValue )
{
switch( hasValue )
{
case "small": s.checked = 1; break;
case "medium": m.checked = 1; break;
case "large": l.checked = 1; break;
case "original": o.checked = 1; break;
}
selectionChanged.bind({ size: hasValue })();
}
break;
case "audio":
// TODO
break;
default:
content.firstChild.nodeValue = "Regular file: " + finfo.name;
content.style.paddingBottom = "2em";
content.appendChild( Dand.wrap( "br" ) );
content.appendChild( Dand.textNode( "Date: " + XDate.pretty( new Date( finfo.date_created ), true ) ) );
}
}
, loadFailed = function (e) { }
, visualizer = function ( submitted, override )
{
var hash, _obj, stage = this.stage;
if( override )
{
hash = override.value;
preferred = override[ "preferred" ] ? "on" : "";
}
else
{
hash = this.code.value;
preferred = this.input_preferred.checked ? "on" : "";
}
_obj = { file: hash };
if ( submitted && hash )
{
// Visualize component
if (!stage)
{
temp = Dand.wrapc("v_box sf-view"
, [
Dand.wrape("Getting information from Server ...")
, Dand.wrapc("v_description", "Site file (hash): " + hash)
]
, [
new DataKey( "value", hash )
, new DataKey( "size", ( override && override.size ) || "large" )
, new DataKey( "preferred", preferred )
]
);
// Get data from site library
getData( config.path.info + hash, __applyData.bind({stage: temp, hash: hash}), loadFailed );
insertSnippet(
j = snippetWrap( "SiteFile", temp )
, !!override
);
}
else
{
IDOMElement( stage ).setAttribute([
new DataKey( "value", hash )
, new DataKey( "preferred", preferred )
]);
getData( config.path.info + hash, __applyData.bind({stage: temp, hash: hash}), loadFailed );
}
i = {
_content: hash
, _preferred: preferred || "off"
, _stage: temp
};
// Set context menu
createContext( i, j, handler );
}
};
if (override)
{
visualizer(true, override);
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function ( stage )
{
stage = IDOMElement( stage );
var options = "";
var opt;
if( opt = stage.getDAttribute( "collection" ) )
{
options += " collection=\"1\"";
}
if( opt = stage.getDAttribute( "size" ) )
{
options += " size=\"" + opt + "\"";
}
if( opt = stage.getDAttribute( "dimensions" ) )
{
options += " dimensions=\"" + opt + "\"";
}
if( opt = stage.getDAttribute( "preferred" ) )
{
options += " preferred=\"" + opt + "\"";
}
return "[sitefile" + options + "]"
+ escapeStr( stage.getDAttribute( "value" ) )
+ "[/sitefile]";
};
__static_method( sitefile, "compile", compile );
ns[ NS_EXPORT ]( EX_CLASS, "SiteFile", sitefile );
})();

View File

@ -0,0 +1,146 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
var compileProp = ns[ NS_INVOKE ]( "compileProp" );
var sound = function (insertSnippet, snippetWrap, createContext, override)
{
var temp, i, j
, defaultArt = "/assets/blog/layout-images/disc_s.png"
, handler = function ()
{
// Input fields
var input_url = Dand.wrap('input', null, "v_snippet_input_single", null, new IKey("type", "text"))
, input_albumArt = Dand.wrap('input', null, "v_snippet_input_single", null, new IKey("type", "text"))
, input_lrc = Dand.wrap('input', null, "v_snippet_input_single", null, new IKey("type", "text"))
;
if (this._stage)
{
input_url.value = this._url;
input_albumArt.value = this._albumArt;
input_lrc.value = this._lrc;
}
new MessageBox(
(this._stage ? "Edit" : "Insert") + " sound snippet"
, Dand.wrape([
Dand.wrapc("v_instruction flsf", "Link to sound:")
, input_url
, Dand.wrapc("v_instruction flsf", "Link to album art(optional):")
, input_albumArt
, Dand.wrapc("v_instruction flsf", "Link to lrc(optional):")
, input_lrc
]
)
, "OK", "Cancel", visualizer.bind({url:input_url, albumArt:input_albumArt, lrc:input_lrc, stage: this._stage})).show();
}
, visualizer = function (submitted)
{
var src, albumArt , lrc
, stage = this.stage;
if (override)
{
src = override.url;
albumArt = override.albumArt;
lrc = override.lrc;
}
else
{
src = this.url.value;
albumArt = this.albumArt.value;
lrc = this.lrc.value;
}
if (submitted && src)
{
if (!stage)
{
// Visualize component
temp = Dand.wrapc('v_box'
, [
Dand.wrape(null, new IKey
(
"style", "height: 75px; background-size: auto 75px; background-repeat: no-repeat;"
+ "background-image: url(" + (albumArt ? albumArt : defaultArt) + ")"
)
)
, Dand.wrapc('v_description', "Sound snippet")
]
, [
new DataKey("value", "")
, new DataKey("url", src)
, new DataKey("albumArt", albumArt)
, new DataKey("lrc", lrc)
]
);
insertSnippet(j = snippetWrap("Sound", temp), Boolean(override));
}
else
{
// Edit properties
stage.firstChild.style.backgroundImage = "url(" + (albumArt ? albumArt : defaultArt) + ")" ;
IDOMElement(stage).setAttribute
(
[
new DataKey("url", src)
, new DataKey("albumArt", albumArt)
, new DataKey("lrc", lrc)
]
);
}
i = {_url: src, _albumArt: albumArt, _lrc: lrc, _stage: temp};
// Set context menu
createContext(i, j, handler);
}
}
;
if (override)
{
visualizer(true, override);
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function (stage)
{
// [sound url="" albumArt="" lrc="" ][/sound]");
var element = IDOMElement(stage)
, props = ["url", "albumArt", "lrc"];
return "[sound" + compileProp( element, props ) + "][/sound]";
};
__static_method( sound, "compile", compile );
ns[ NS_EXPORT ]( EX_CLASS, "Sound", sound );
})();

View File

@ -0,0 +1,155 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
var compileProp = ns[ NS_INVOKE ]( "compileProp" );
var escapeStr = ns[ NS_INVOKE ]( "escapeStr" );
var unescapeStr = ns[ NS_INVOKE ]( "unescapeStr" );
var spoiler = function(insertSnippet, snippetWrap, createContext, override)
{
var temp, i, j
, handler = function ()
{
// Input fields
var v_snippetInput = Dand.wrap("textarea", null, "v_snippet_input")
, input_title = Dand.wrap("input", null, "v_snippet_input_single", null, new IKey("type", "text"))
, input_expanded = Dand.wrapna("input", new IKey("type", "checkbox"))
if (this._stage)
{
v_snippetInput.value = this._content;
input_title.value = this._title;
input_expanded.checked = (this._expanded == "on");
}
// Popup MessageBox
new MessageBox("Insert spoiler content"
, Dand.wrape([
Dand.wrapc("v_instruction flsf", "Title")
, input_title
, Dand.wrapc("v_instruction flsf", "Content")
, v_snippetInput
, Dand.wrape( Dand.wrapne( "label", [ input_expanded, "Expanded" ] ) )
]
)
, "OK", "Cancel", visualizer.bind({title: input_title, content:v_snippetInput, expanded: input_expanded, stage: this._stage})).show();
}
/* @type override {_AstXObject_.AstroEdit.Visualizer.Snippet.Spoiler.Override} */
, visualizer = function( submitted, override )
{
var content, title, expanded
, stage = this.stage;
if( override )
{
content = unescapeStr( override.value );
title = unescapeStr( override.title );
expanded = override.expanded ? "on" : "";
}
else
{
content = this.content.value;
title = this.title.value;
expanded = this.expanded.checked ? "on" : "";
}
if (submitted && content)
{
// Shared Clause
i = Dand.textNode(title || "Spoiler");
if (!stage)
{
if (!content) return;
// Visualize component
temp = Dand.wrapc("v_box",
[
// caption
Dand.wrapc("v_caption", i)
, Dand.textNode(content)
],
[
new DataKey("value", content)
, new DataKey("title", title)
, new DataKey("expanded", expanded)
]
);
insertSnippet(j = snippetWrap("Spoiler", temp), Boolean(override));
}
else
{
IDOMElement(stage).setAttribute
([
new DataKey("value", content)
, new DataKey("title", title)
, new DataKey("expanded", expanded)
]);
temp = stage.firstChild;
temp.removeChild(temp.firstChild);
temp.appendChild(i);
stage.removeChild(stage.lastChild);
stage.appendChild(Dand.textNode(content));
// set temp back to stage
temp = stage;
}
i = {
_title: title
, _content: content
, _expanded: expanded || "off"
, _stage: temp
};
// Set context menu
createContext(i, j, handler);
}
}
;
if (override)
{
visualizer(true, override);
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function ( stage )
{
var element = IDOMElement( stage )
, props = ["title", "expanded"];
return "[spoiler"
+ compileProp( element, props )
+ "]"
+ escapeStr( element.getDAttribute( "value" ) )
+ "[/spoiler]";
};
__static_method( spoiler, "compile", compile );
ns[ NS_EXPORT ]( EX_CLASS, "Spoiler", spoiler );
})();

View File

@ -0,0 +1,18 @@
.v_boundary[data-type="Video"] {
width: 640px; height: 390px;
background-color: black;
padding: 0;
}
.v_boundary[data-type="Video"] .v_box {
width: 640px; height: 390px;
position: relative;
display: table-cell;
text-align: center;
vertical-align: middle;
}
.v_boundary[data-type="Video"] .v_description {
text-align: left;
padding-left: 0.5em;
}

View File

@ -0,0 +1,141 @@
(function ()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
var getData = __import( "System.Net.getData" );
var BLANK_IMG = __import( "Dandelion.StaticRes.BLANK_IMG" );
var video = function (insertSnippet, snippetWrap, createContext, override)
{
var temp, i, j, imgSrc
, getVimeoThumbnail = function( v )
{
getData(
"//vimeo.com/api/oembed.json?url=https%3A//vimeo.com/" + v
, setThumbnail
, noThumb
);
}
, setImgSrc = function( url )
{
if( imgSrc ) imgSrc.src = url;
}
, noThumb = function () { }
, setThumbnail = function (str)
{
setImgSrc( JSON.parse(str)["thumbnail_url"] );
}
, handler = function ()
{
// Input fields
var input_url = Dand.wrap('input', null, "v_snippet_input_single", null, new IKey("type", "text"));
// Popup MessageBox
new MessageBox("Insert video snippet"
, Dand.wrape([ Dand.wrapc("v_instruction flsf", "Paste a vimeo/Youtube link below:"), input_url ])
, "OK", "Cancel", visualizer.bind(input_url)
).show();
}
, visualizer = function (submitted, override)
{
var t, v;
if (override)
{
v = override.value;
i = override.type;
}
else
{
t = this.value;
// Match youtube links
v = t.match(/\/\/(www\.)?youtube\.com\/watch\?.*?v=([^\&\?\/\#]+)/) || t.match(/\/\/(www\.)?youtube\.com\/embed\/([^\&\?\/]+)/)
|| t.match(/\/\/(www\.)?youtube\.com\/v\/([^\&\?\/]+)/) || t.match(/\/\/(www\.)?youtu\.be\/([^\&\?\/]+)/);
if (v)
{
i = "youtube";
v = v[2];
}
else
{
// match vimeo links
v = t.match(/\/\/(www\.)?vimeo.com\/(\d+)($|\/)/);
if (v)
{
i = "vimeo";
v = v[2];
}
else
{
// None matched, do nothing
return;
}
}
}
if (submitted)
{
// Visualize component
temp = Dand.wrapc('v_box'
, [
Dand.wrapc( 'v_description', i[0].toUpperCase() + i.substr(1) + ": " + v )
, imgSrc = Dand.wrapna( "img", [ new IKey( "src", BLANK_IMG ) ] )
]
, [ new DataKey("value", v), new DataKey("type", i) ]
);
if( i[0] == "v" )
{
getVimeoThumbnail( v );
}
else
{
setImgSrc( "//img.youtube.com/vi/" + v + "/hqdefault.jpg" );
}
insertSnippet(j = snippetWrap("Video", temp), Boolean(override));
// Set context menu
createContext(null, j);
}
}
if (override)
{
visualizer(true, override);
override = false;
}
else
{
return handler;
}
return true;
};
var compile = function (stage)
{
// [video type=\"youtube\"]" + v[2] + "[/video]
var element = IDOMElement(stage)
, type = element.getDAttribute("type");
return "[video type=\"" + type + "\"]" + element.getDAttribute("value") + "[/video]";
};
__static_method( video, "compile", compile );
ns[ NS_EXPORT ]( EX_CLASS, "Video", video );
})();

View File

@ -0,0 +1,41 @@
(function()
{
var ns = __namespace( "Astro.Blog.AstroEdit.Visualizer.Snippet" );
var escapeStr = function ( str )
{
if( !str ) return str;
return str
.replace( /\[/g, "&#x5B;" )
.replace( /\]/g, "&#x5D;" )
.replace( /"/g, "&quot;" )
;
};
var unescapeStr = function( str )
{
if( !str ) return str;
return str
.replace( /&#x5B;/g, "[" )
.replace( /&#x5D;/g, "]" )
.replace( /&quot;/g, "\"" )
;
};
var compileProp = function ( _iDOM, keys )
{
var i, j = "", k;
for (i in keys)
{
if( ( k = _iDOM.getDAttribute(keys[i]) ) )
{
j += " " + keys[i] + "=\"" + escapeStr( k ) + "\"";
}
}
return j;
};
ns[ NS_EXPORT ]( EX_FUNC, "escapeStr", escapeStr );
ns[ NS_EXPORT ]( EX_FUNC, "unescapeStr", unescapeStr );
ns[ NS_EXPORT ]( EX_FUNC, "compileProp", compileProp );
})();

View File

@ -0,0 +1,122 @@
.v_snippet_input {
width: 600px;
height: 350px;
}
.v_boundary {
cursor: default;
padding: 0.2em;
}
.v_box {
min-height: 3em;
overflow: hidden;
position: relative;
}
.v_caption, .v_description {
background: rgba(0, 0, 0, 0.8);
padding: 0.2em;
color: white;
width: 100%;
font-family: sans-serif;
font-size: 1em;
}
.v_caption {
position: relative;
}
.v_description {
position: absolute;
left: 0;
bottom: 0;
}
.v_caption_desc {
font-size: 60%;
}
.v_boundary:hover {
background-color: rgba(0, 0, 0, 0.2);
}
.v_snippet_input_single {
width: 600px;
margin-bottom: 0.5em;
}
textarea.v_snippet_input {
font-family: site-mono;
font-size: 1em;
}
.v_instruction {
padding: 0.2em 0;
}
.v_trimmer {
overflow: hidden;
}
.v_select {
width: 100%;
background-color: #222;
font-size: 1em;
color: white;
background-image: none;
border: none;
box-shadow: none;
-webkit-appearance: none;
}
div[data-type="token"] {
background-color: #111;
color: #EEE;
padding: 0.25em 0.5em;
margin-right: 100%;
min-width: 8em;
display: inline-block;
position: relative;
}
div[data-type="token"]:hover {
background-color: #444;
}
div[data-type="token"]:after {
content: "Loading";
position: absolute;
color: rgba( 255, 255, 255, 0.2 );
right: 0;
bottom: 0;
}
div[data-type="token"]:hover:after {
color: rgba( 255, 255, 255, 0.5 );
}
#ae_visual_snippets > span[data-name="code"] { background: white; color: cornflowerblue; }
#ae_visual_snippets > span[data-name="image"] { background: #ff0084; }
#ae_visual_snippets > span[data-name="sound"] { background: YellowGreen; }
#ae_visual_snippets > span[data-name="video"] { background: Crimson; }
#ae_visual_snippets > span[data-name="spoiler"] { background: cornflowerblue; }
#ae_visual_snippets > span[data-name="link"] { background: blue; }
#ae_visual_snippets > span[data-name="acquirelib"] { background: black; }
#ae_visual_snippets > span[data-name="html"] { background: coral; }
#ae_visual_snippets > span[data-name="sitefile"] { background: royalblue; }
#ae_visual_snippets > span[data-name="heading"] { }
#ae_visual_snippets > span[data-name="footnote"] { }
#ae_visual_snippets > span[data-name="resph"] { }
#ae_visual_snippets > span[data-name="meta"] { }
#ae_visual_snippets > span[data-name="articlelink"] { }
#ae_visual_snippets > span[data-name="articlecontent"] { }

View File

@ -0,0 +1,503 @@
(function(){
var ns = __namespace( "Astro.Blog.AstroEdit" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
/** @type {System.utils} */
var utils = __import( "System.utils" );
/** @type {System.utils.Perf} */
var Perf = __import( "System.utils.Perf" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {System.utils.EventKey} */
var EventKey = __import( "System.utils.EventKey" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.Net.ClassLoader} */
var Loader = __import( "System.Net.ClassLoader" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
/** @type {Components.Mouse.ContextMenu} */
var ContextMenu = __import( "Components.Mouse.ContextMenu" );
/** @type {Astro.Blog.Config} */
var Config = __import( "Astro.Blog.Config" );
var snippetList = [
"Code"
, "Image"
, "Sound"
, "Video"
, "Spoiler"
, "Link"
, "AcquireLib"
, "Html"
, "SiteFile"
, "Heading"
, "Footnote"
, "RespH"
, "Meta"
, "ArticleLink"
, "ArticleContent"
];
var snippetNs = "Astro.Blog.AstroEdit.Visualizer.Snippet.";
//// Document Visualizer visualize snippets, used in AstroEdit and comments
var Visualizer = function ( e_document, snippetControls, service_uri )
{
var Article = ns[ NS_INVOKE ]( "Article" );
var loadedModule = {};
//// Constants
var article;
// "[^]" does not work in IE
var stackMatch = /\[([a-z][0-9a-z]*?)([\s\S]*?)\]([\s\S]*?)\[\/\1\]/ig;
var typeMatch = /([a-z][0-9a-z]*)\=\"([^"]+)\"/ig;
var snippetTokenQueue = {};
if ( e_document instanceof Article )
{
article = e_document;
// Allow Html snippet
}
else if ( e_document instanceof CeDocument )
{
article = e_document;
}
else return;
////// Variables
var contentDiv = Dand.wrap()
var selRange;
var snippetExists = false;
var lastOffset = 0;
var raw;
///// private methods
var snippetWrap = function( snippetType, element, editable, _with )
{
var snippet = Dand.wrap(
_with || "div"
, Perf.uuid
, "comp v_boundary"
, element
, [
new IKey( "contentEditable", editable ? "true" : "false" )
, new DataKey( "type", snippetType )
]
);
return snippet;
};
var appendLinebreak = function ()
{
this.parentNode.insertBefore(Dand.wrap("br"), this.nextSibling);
}
var insertLinebreak = function ()
{
this.parentNode.insertBefore(Dand.wrap("br"), this);
};
var snippetDelete = function ()
{
this.parentNode.removeChild(this);
};
var snippetBBCode = function()
{
var snippet = IDOMElement( this );
var type = snippet.getDAttribute( "type" ).toLowerCase();
/** @type {Astro.Blog.AstroEdit.Visualizer.Snippet.Model} */
var module = loadedModule[ type ];
var title = "An error occurred";
var message = "No such module";
if( module )
{
title = "BBCode for Snippet: " + type;
message = module.compile( this.firstChild );
}
new MessageBox( title, Dand.wrapne( "pre", message ) ).show();
};
var createSnippetMenu = function ( snippetProp, snippet, editHandler, snippetActions )
{
var contextItems = [
editHandler && new EventKey( "Edit", editHandler.bind( snippetProp ) )
, new EventKey( "Insert a linebreak", insertLinebreak.bind( snippet ) )
, new EventKey( "Append a linebreak", appendLinebreak.bind( snippet ) )
, new EventKey( "Delete", snippetDelete.bind( snippet ) )
, new EventKey( "View BBCode", snippetBBCode.bind( snippet ) )
];
e_document.updateContent();
if ( snippetActions instanceof Array )
{
contextItems = snippetActions.concat( contextItems );
}
return new ContextMenu( snippet, contextItems, "RMB" );
};
var _savSelection = function ()
{
contentDiv.focus();
if ( window.getSelection )
{
var sel = window.getSelection();
if ( sel.getRangeAt && sel.rangeCount )
{
selRange = sel.getRangeAt(0);
}
}
else if ( document.selection && document.selection.createRange )
{
selRange = document.selection.createRange();
}
else
{
selRange = null;
}
};
var _resSelection = function ()
{
contentDiv.focus();
if ( selRange )
{
if ( window.getSelection )
{
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange( selRange );
}
else if ( document.selection && selRange.select )
{
selRange.select();
}
}
};
var lastLine = Dand.wrap( "br", "v_linebreak" );
var ensureLastLinebreak = function ()
{
if( !Dand.id( "v_linebreak" ) )
{
insertElement( lastLine, true );
}
else
{
insertElement( contentDiv.removeChild( lastLine ), true );
}
};
var insertAtCaret = function( element, newLine )
{
var sel, range;
if( newLine == undefined ) newLine = true;
sel = window.getSelection();
if ( sel.getRangeAt && sel.rangeCount )
{
range = sel.getRangeAt(0);
range.deleteContents();
range.insertNode( element );
range.setStartAfter( element );
range.setEndAfter( element );
range.collapse( false );
sel.removeAllRanges();
sel.addRange( range );
}
e_document.updateContent();
if( newLine ) ensureLastLinebreak();
};
var insertElement = function( element, override )
{
if ( override )
{
contentDiv.appendChild( element );
return;
}
_resSelection();
insertAtCaret( element );
};
var replaceToken = function( element )
{
contentDiv.insertBefore( element, this.token );
contentDiv.removeChild( this.token );
};
var parseKeys = function ( match, name, value )
{
this[ name ] = value;
};
var snippetQueue = function( type, alias )
{
var q = snippetTokenQueue[ type ] || [];
if( alias )
{
if( !( alias instanceof Array ) ) alias = [ alias ];
for( var i in alias )
{
q = snippetTokenQueue[ alias[i] ] || [];
if( q.length ) return q;
}
}
return ( snippetTokenQueue[ type ] = q );
};
var parseSnippet = function( match, type, properties, _value, offset )
{
var temp, i, j;
// Texts goes first
if ( lastOffset != offset )
{
// innerText does not work in firefox:(
temp = Dand.wrape( raw.substr( lastOffset, offset - lastOffset ) );
// innerHTML will escape html entities, now replace linebreaks to br
temp.innerHTML = temp.innerHTML.replace( /[\r\n]/g, "<br>" );
IDOMElement( contentDiv ).loot( temp );
}
lastOffset = offset + match.length;
// Snippet Args
temp = { value: _value };
// to ekeys
properties.replace( typeMatch, parseKeys.bind( temp ) );
// Now deal with snippet
/** @type {Astro.Blog.AstroEdit.Visualizer.Snippet.Model} */
var _module = loadedModule[ type ];
if ( _module )
{
// Visualize snippet
new ( _module )( insertElement, snippetWrap, createSnippetMenu, temp );
}
else
{
// no such module, or module is not loaded yet
debug.Info( "[Visualizer] Queueing: " + type );
var token = snippetWrap( "token", type, false );
token.setAttribute( "class", token.getAttribute( "class" ) + " flsf" );
snippetQueue( type ).push([ token, temp ]);
insertElement( token, true );
}
};
var linebreakNodes = ["P", "DIV"];
var linebreakNode = function( name )
{
if( -1 < linebreakNodes.indexOf( name.toUpperCase() ) ) return "\n";
return "";
};
var ensureGoodness = function ()
{
_savSelection();
ensureLastLinebreak();
};
var stepContent = function ( element, level )
{
var j , snippetType
, elements = element.childNodes
, output = "";
for (var i = 0, l = elements.length; i < l; i ++)
{
j = elements[i];
// do nothing on lastline
if (j == lastLine) continue;
if (j.nodeType == 1)
{
snippetType = IDOMElement( j ).getDAttribute( "type" );
if( snippetType && loadedModule[ snippetType = snippetType.toLowerCase() ] )
{
output += loadedModule[ snippetType ].compile( j.firstChild );
}
else if ( j.firstChild )
{
// Text
output += linebreakNode( j.nodeName ) + stepContent(j, ++level);
}
else
{
// Handle special <div><br></div> => one line break
if(l == 1 && j.nodeName.toUpperCase() == "BR") continue;
// Line breaks
output += "\n";
}
}
// Text
else if (j.nodeType == 3)
{
output += j.nodeValue;
}
}
return output;
};
///// Initializations
var snippetReady = function ( e )
{
// Initialize modules
var mod_name = e.substr( e.lastIndexOf(".") + 1, e.length ).toLowerCase()
/** @type {Astro.Blog.AstroEdit.Visualizer.Snippet.Model} */
var _module = __import( e );
var alias = _module.alias;
// Implement module if valid and available
if ( _module && _module.compile )
{
loadedModule[ mod_name ] = _module;
debug.Info( "[Visualizer] Module loaded: " + mod_name );
// Set alias
if ( alias )
{
alias = ( alias instanceof Array ) ? alias : [ alias ];
for ( var k in alias )
{
loadedModule[ alias[k] ] = _module;
debug.Info( "[Visualizer] Alias: " + mod_name + " => " + alias );
}
}
// Append module"s control
temp = Dand.wrapne( "span", mod_name, new IKey( "data-name", mod_name ) );
snippetControls.appendChild( temp );
snippetControls.appendChild( Dand.textNode( "\t" ) );
temp.onclick = new ( _module )( insertElement, snippetWrap, createSnippetMenu );
var queue = snippetQueue( mod_name, _module.alias );
for( var i in queue )
{
var token = queue[i];
new ( _module )( replaceToken.bind({ token: token[0] }), snippetWrap, createSnippetMenu, token[1] );
delete queue[i];
}
}
else
{
if ( _module )
{
delete loadedModule[ mod_name ];
debug.Info( "[Visualizer] Module discarded: invalid module \"" + mod_name + "\"" );
}
else
{
debug.Info( "[Visualizer] Module \"" + mod_name + "\" does not exists" );
}
}
};
this.setContentDiv = function( element )
{
contentDiv = element;
// listeners that return values cannot use addEventListener
contentDiv.onkeypress = function(e)
{
if (e.which == 13)
{
insertAtCaret( Dand.wrap( "br" ) );
_savSelection();
return false;
}
return true;
};
temp = IDOMElement( contentDiv );
temp.addEventListener( "Input", ensureGoodness );
temp.addEventListener( "KeyUp", ensureGoodness );
temp.addEventListener( "Click", ensureGoodness );
contentDiv.focus();
ensureGoodness();
try {
document.execCommand( "insertBrOnReturn", false, "true" );
} catch(e) {
debug.Info( "Not firefox" );
}
};
this.saveRaw = function ()
{
return stepContent( contentDiv, 0 );
};
this.visualizeData = function ( data )
{
if ( !data ) return;
lastOffset = 0;
// clear content
contentDiv.innerHTML = "";
( raw = data ).replace( stackMatch, parseSnippet );
if ( lastOffset != raw.length )
{
// innerText does not work in firefox:(
temp = Dand.wrape( raw.substr( lastOffset, raw.length - lastOffset ) );
// innerHTML will escape html entities, now replace linebreaks to br
temp.innerHTML = temp.innerHTML.replace( /[\r\n]/g, "<br>" );
IDOMElement( contentDiv ).loot( temp );
}
temp = null;
raw = null;
};
this.saveSelection = _savSelection;
this.restoreSelection = _resSelection;
this.insertAtCaret = insertAtCaret;
this.insertSnippet = function( type, options )
{
var _module = loadedModule[ type ];
new ( _module )(
// Disables the override
function( e ) { insertElement( e ); }
, snippetWrap, createSnippetMenu, options
);
};
article.invoke(this);
var modules = [];
for( var i = 0; i < snippetList.length; i ++ )
{
modules[ modules.length ] = snippetNs + snippetList[i];
}
var ldr = new Loader( service_uri, "o" );
ldr.load( modules, snippetReady );
};
ns[ NS_EXPORT ]( EX_CLASS, "Visualizer", Visualizer );
})();

View File

@ -0,0 +1,256 @@
.ae_panel_section {
padding: 0 1em;
color: white;
height: 0;
overflow: hidden;;
}
.ae_section_prop {
margin: 0.5em 0;
text-align: right;
}
.ae_prop_name {
opacity: 0.8;
}
.ae_prop_value {
font-size: 1.2em;
text-align: right;
}
/* Interactive value */
.ae_iValue {
text-align: center;
padding: 0.5em;
cursor: default;
}
.ae_background {
background-color: #fff;
background-image:
linear-gradient(90deg, transparent 1em, #666 1em, #666 1.2em, transparent 1.2em),
linear-gradient(#EEE .1em, transparent .1em);
background-size: 100% 1.5em;
}
/* Buttons */
.ae_purple { background: purple; }
.ae_purple:hover { background: darkmagenta; }
.ae_coral { background: orangered; }
.ae_coral:hover { background: darkorange; }
.ae_dodgerblue { background: dodgerblue; }
.ae_caution { color: red; }
.ae_caution:hover { background: #333; }
.ae_dodgerblue:hover { background: cornflowerblue; }
/* End buttons */
.ae_disabled {
color: grey;
background: none;
}
.ae_blockswitch {
line-height: 2em;
}
.ae_blockswitch > span {
white-space: nowrap;
/* text-transform:uppercase; */
font-family: custom-sans;
padding: 0.2em 0.5em;
cursor: default;
opacity: 0.5;
}
.ae_blockswitch > span:hover {
background-color: black;
opacity: 1;
}
.ae_body {
max-height: 100%;
overflow-y: scroll;
position: fixed;
}
.ae_content {
width: auto;
background: SkyBlue;
}
.ae_panel {
width: 300px;
height: auto;
min-height: 100%;
background: #222;
color: white;
position: absolute;
top: 0;
right: 0;
/* will handel mouse scroll later*/
overflow: hidden;
-moz-box-shadow: -2px 0 5px black;
-webkit-box-shadow: -2px 0 5px black;
box-shadow: -2px 0 5px black;
}
.ae_topbar {
width: 100%;
color: #222;
padding: 0.35em 0;
overflow: hidden;
border-bottom: 7px solid #222;
}
.ae_title, .ae_stitle {
padding: 0.35em;
}
.ae_title {
position: relative;
top: 0.25em;
font-size: 2em;
}
.ae_stitle:hover {
background-color: rgba( 0, 0, 0, 0.2 );
}
.ae_stitle {
font-size: 1.5em;
}
#ae_title {
font-size: 2.5em;
color: #444;
}
#ae_content {
font-size: 100%;
margin-bottom: 100%;
border-bottom: 1px black dashed;
}
#ae_title, #ae_content {
background: none;
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
#ae_title:focus {
background: rgba(255, 255, 255, 0);
}
#ae_content:focus {
background: rgba(255, 255, 255, 0);
}
#ae_bgdimmer {
background: rgba(255, 255, 255, 0);
}
#ae_content, #ae_bgdimmer {
color: #555;
padding: 1em 1em 0.01em 1em;
}
.ae_preview {
display: block;
color: white;
text-decoration: none;
padding: 0.4em;
font-size: 100%;
width: 100%;
}
.ae_user_info {
background: #111;
overflow: hidden;
position: relative;
}
.ae_draft_section {
padding: 0.5em;
}
.ae_draft_logo {
font-size: 3em;
position: absolute;
opacity: 0.2;
cursor: default;
}
.ae_name {
text-align: right;
padding: 0.2em;
}
.ae_user_content {
padding: 0.2em
}
#ae_user_drafts {
overflow: hidden;
}
.ae_dEntry {
cursor: default;
padding: 0.2em;
background: rgba(255, 255, 255, 0);
}
.ae_dEntry:hover {
background: rgba(255, 255, 255, 0.2);
}
.ae_dEntry_date {
text-align: right;
}
.ae_expand_btn, .ae_callapse_btn {
background: url(/assets/blog/layout-images/collapse.png) center 2.5px no-repeat;
width: 100%;
height: 10px;
}
.ae_expand_btn {
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
transform: rotate(180deg);
}
.ae_callapse_btn {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
transform: rotate(0deg);
}
.ae_affected_count {
color: red;
}
/*Active draft notation*/
.ae_dActive_bubble {
float: right;
color: yellowgreen;
text-shadow: 0 0 5px yellowgreen;
font-size: 80%;
}
body {
margin: 0 auto;
min-width: 1200px;
}

View File

@ -0,0 +1,143 @@
(function(){
var ns = __namespace( "Astro.Blog.AstroEdit" );
/** @type {System.utils} */
var utils = __import( "System.utils" );
/** @type {System.Cycle} */
var Cycle = __import( "System.Cycle" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Astro.Bootstrap} */
var Bootstrap = __import( "Astro.Bootstrap" );
/** @type {Astro.Blog.Config} */
var Config = __import( "Astro.Blog.Config" );
/** @type {Astro.Blog.AstroEdit.Article} */
var Article = __import( "Astro.Blog.AstroEdit.Article" );
/** @type {Astro.Blog.AstroEdit.Draft} */
var Draft = __import( "Astro.Blog.AstroEdit.Draft" );
/** @type {Astro.Blog.AstroEdit.Flag} */
var Flag = __import( "Astro.Blog.AstroEdit.Flag" );
/** @type {Astro.Blog.AstroEdit.Visualizer} */
var Visualizer = __import( "Astro.Blog.AstroEdit.Visualizer" );
/** @type {Astro.Blog.AstroEdit.Uploader} */
var Uploader = __import( "Astro.Blog.AstroEdit.Uploader" );
/** @type {Astro.Blog.AstroEdit.SiteLibrary} */
var SiteLibrary = __import( "Astro.Blog.AstroEdit.SiteLibrary" );
/** @type {Components.Vim.VimArea} */
var VimArea = __import( "Components.Vim.VimArea" );
// calls the smart bar
var SmartInput = __import( "Astro.Blog.AstroEdit.SmartInput" );
// __import( "Astro.Blog.SharedStyle" ); CSS_RESERVATION
var wh, ww, cw, html, article;
var init = function ()
{
//// Component initializations
/** @type {_AstConf_.AstroEdit} */
var a_conf = Config.get( "AstroEdit" );
var base_path = utils.siteProto( Config.get( "BasePath" ) );
Cycle.next(
function()
{
article.load(
a_conf.article_id
, function( obj, id )
{
window.history.replaceState( obj, "", base_path + "astroedit/" + id + "/" );
}
);
}
);
article = new Article(
a_conf.paths.set_article
, [
new Flag( "tags", "ae_tags", a_conf.paths.tags )
, new Flag( "section", "ae_secs", a_conf.paths.sections )
]
);
// Article modules
new Draft( article, a_conf.paths.get_drafts );
var Vis = new Visualizer(
article
, Dand.id( "ae_visual_snippets" )
, Config.get( "ServiceUri" )
);
new SmartInput( Vis );
// Independent modules
new Uploader( a_conf.paths.set_file );
new SiteLibrary(
base_path
, a_conf.paths.get_files
, a_conf.paths.set_file
);
var title = Dand.id("ae_title");
var content = Dand.id("ae_content");
// content height
content.style.minHeight = String(screen.availHeight) + "px";
html = document.body.parentNode;
window.onresize = adjustLayout;
// Setting event handlers
title.onblur = content.onblur = function () { Dand.id("ae_bgdimmer").style.background = ""; };
content.onfocus = content.onfocus = function ()
{
Dand.id("ae_bgdimmer").style.background = "rgba(255, 255, 255, 0.2)";
};
Dand.id( "ae_publish_btn" ).onclick = function () { article.saveAndPublish(); };
Dand.id( "ae_preview_btn" ).onclick = function () { article.preview(); };
Dand.id( "ae_drop_btn" ).onclick = function () { article.drop(); };;
adjustLayout();
VimTrigger();
};
var VimTrigger = function()
{
var f10Binding = function ( e )
{
e = e || window.event;
if ( e.keyCode ) code = e.keyCode;
else if ( e.which ) code = e.which;
if ( code == 121 )
{
e.preventDefault();
var node = document.activeElement;
if( node.nodeName == "TEXTAREA" )
{
new VimArea( node, true );
}
}
};
//Attach the var with the event = function
if(document.addEventListener) document.addEventListener('keydown', f10Binding, false);
else if(document.attachEvent) document.attachEvent('onkeydown', f10Binding);
else document.onkeydown = f10Binding;
};
var adjustLayout = function ()
{
ww = html.clientWidth;
wh = html.clientHeight;
cw = ww - 300;
Dand.id("ae_body").style.width = String(cw) + "px";
};
Bootstrap.regInit( init );
})();

View File

@ -0,0 +1,14 @@
.site-file[data-type="album"] {
column-width: 225px;
column-gap: 0.75em;
}
.site-file[data-type="album"] > div {
display: inline-block;
margin-bottom: 0.5em;
width: 100%;
}
.site-file[data-type="album"] > div img {
width: 100%;
}

View File

@ -0,0 +1,96 @@
(function(){
var ns = __namespace( "Astro.Blog.Components" );
/** @type {System.Cycle} */
var Cycle = __import( "System.Cycle" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Astro.Bootstrap} */
var Bootstrap = __import( "Astro.Bootstrap" );
/** @type {System.utils.Perf} **/
var Perf = __import( "System.utils.Perf" );
/** @type {Astro.Blog.Config} */
var Conf = __import( "Astro.Blog.Config" );
/** @type {_AstConf_.SiteFile} */
var config = null;
var SiteFile = ns[ NS_INVOKE ]( "SiteFile" );
var BLANK_IMG = __import( "Dandelion.StaticRes.BLANK_IMG" );
var Album = function ( id, hash )
{
if( !config ) throw new Error( "config is not defined" );
var stage = Dand.id( id, true );
var sf = new SiteFile( id, hash );
if( sf.type != "album" ) return;
var ostage = stage.element;
var applyStructure = function( obj )
{
/** @type {_AstJson_.SiteFile} */
var finfo = JSON.parse( obj );
var files = finfo.files;
var l = files.length;
// XXX: Not traditional!
// Maximum of 4 for listing
if( ostage.parentNode.className == "h_img" && 4 < l )
{
l = 4;
}
for( var i = 0; i < l; i ++ )
{
/** @type {_AstJson_.SiteFile} */
var file = files[i];
var uuid = Perf.uuid;
ostage.appendChild( Dand.wrapne(
"div"
, Dand.wrapna( "img", [ new IKey( "src", BLANK_IMG ) ] )
, [ new IKey( "id", uuid ), new DataKey( "size", "medium" ) ]
) );
Cycle.next( function()
{
new SiteFile( this.id, this.info.hash, this.info );
}.bind({ id: uuid, info: file }) );
}
};
var loadFailed = function( obj )
{
console.log( obj );
};
sf.loadInfo( applyStructure, loadFailed );
};
var init = function()
{
config = Conf.get( "SiteFile" );
if( config )
{
var SFOs = Conf.get( "SFObjects" );
for( var i in SFOs )
{
var f = SFOs[i];
new Album( f[0], f[1] );
}
}
};
Bootstrap.regInit( init );
ns[ NS_EXPORT ]( EX_CLASS, "Album", Album );
})();

View File

@ -0,0 +1 @@
.ref-content { display: inline-block; }

View File

@ -0,0 +1 @@
// __namespace( "Astro.Blog.Components.ArticleContent" );

View File

@ -0,0 +1,35 @@
.bubble {
position: fixed;
background: white;
border-radius: 300px;
-moz-box-shadow: 7px 7px 10px;
-webkit-box-shadow: 7px 7px 10px;
box-shadow: 7px 7px 10px;
z-index: 98;
}
.innerBubble {
border-radius: 300px;
position: relative;
overflow: hidden;
}
.innerBubble:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
}
.bInner{
display: inline-block;
width: 100%;
vertical-align: middle;
text-align: center;
font-size: 1.35em;
color: white;
}

View File

@ -0,0 +1,133 @@
(function(){
var ns = __namespace( "Astro.Blog.Components" );
/** @type {System.Cycle} */
var Cycle = __import( "System.Cycle" );
/** @type {System.utils.EventKey} */
var EventKey = __import( "System.utils.EventKey" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
var Bubble = function () {
this.stage = null;
this.bubble = null;
//// default is somewhat purple
this.bgColor = "#662D91";
this.blowInner = function ()
{
var b_style = this.bubble.style
, s_style = this.stage.style;
b_style.margin = "10px 10px";
b_style.width = "150px";
b_style.height = "150px";
s_style.width = "170px";
s_style.height = "170px";
s_style.bottom = "20px";
s_style.right = "20px";
};
this.blowOuter = function ()
{
var b_style = this.bubble.style
, s_style = this.stage.style;
b_style.margin = "100px 100px";
s_style.width = "200px";
s_style.height = "200px";
s_style.bottom = "10px";
s_style.right = "10px";
Cycle.delay( this.blowInner.bind(this), 250 );
};
this.Void = function ()
{
this.stage.style.display = "none";
};
// Set Bindings
this.init = this.init.bind(this);
this.blurp = this.blurp.bind(this);
this.pop = this.pop.bind(this);
this.setColor = this.setColor.bind(this);
};
var wrapc = function( aClass, elem )
{
return Dand.wrapc( "comp " + aClass, elem );
};
Bubble.prototype.init = function ()
{
this.stage = wrapc( "bubble" );
this.bubble = wrapc( "innerBubble" );
var b_style = this.bubble.style
, s_style = this.stage.style;
b_style.margin = "85px 85px";
b_style.width = "0px";
b_style.height = "0px";
b_style.background = this.bgColor;
b_style.overflow = "hidden";
this.bubble.appendChild(
this.message = wrapc( "bInner flsf" )
);
this.stage.appendChild(this.bubble);
s_style.display = "none";
s_style.width = "10px";
s_style.height = "10px";
s_style.bottom = "85px";
s_style.right = "85px";
// onClick handle to prevent persistent bubble
IDOMElement( this.stage ).addEventListener( new EventKey( "Click", this.blurp ) );
return this.stage;
};
Bubble.prototype.setColor = function (color)
{
this.bubble.style.background = color;
};
Bubble.prototype.blurp = function ()
{
var b_style = this.bubble.style
, s_style = this.stage.style;
b_style.margin = "0 0";
b_style.width = "0px";
b_style.height = "0px";
b_style.overflow = "hidden";
s_style.position = "fixed";
s_style.width = "10px";
s_style.height = "10px";
s_style.bottom = "85px";
s_style.right = "85px";
Cycle.delay( this.Void.bind(this), 250 );
};
Bubble.prototype.pop = function (message)
{
this.message.innerHTML = message;
this.stage.style.display = "block";
Cycle.delay( this.blowOuter.bind(this), 100 );
};
ns[ NS_EXPORT ]( EX_CLASS, "Bubble", Bubble );
})();

View File

@ -0,0 +1,67 @@
.calendar, #timeline {
cursor: default;
}
.calendar{
position: absolute;
display: none;
background: white;
margin: 20px auto;
font-size: 17px;
padding: 3px;
width: 241px;
box-shadow: 3px 3px 4px black;
border: 10px solid dodgerblue;
border-collapse: collapse;
font-family: custom-sans;
}
/*Inline_Blocks*/
.calDate, #calDays > div > span {
display:-moz-inline-block;
display:-moz-inline-box;
display:inline-block;
}
/*End_Inline_Blocks*/
#calDays > div > span {
background: white;
border: 0px solid;
margin: 1.71428%;
padding: 3px 0px 3px 0px;
#:100/7 - (0.24% margin);
width: 10.857%;
text-align: center;
font-size: 0.8em;
}
#calDays>div {
height: 27px;
white-space: nowrap;
}
.calDate {
width: 155px;
text-align: center;
}
.navbtn {
opacity: .5;
width: 17px;
height: 20px;
}
.navbtn:hover {
opacity: 1;
}
.onhover {
border: 3px solid !important;
margin-left: -2px !important;
margin-top: -4px !important;
vertical-align: top;
padding: 0px 1px 2px 0px;
box-shadow: 3px 3px 3px black;
}
.toNorm {
}
#norec{color: #FF7BAC;}
#notfin{color: #3FA9F5;}
#notyet{color: #BDCCD4;}
#today{color: #7AC943;}

View File

@ -0,0 +1,244 @@
(function(){
var ns = __namespace( "Astro.Blog.Components" );
/** @type {System.Cycle} */
var Cycle = __import( "System.Cycle" );
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Astro.utils.Date} */
var XDate = __import( "Astro.utils.Date" );
var Calendar = function ()
{
this.stage = null;
this.calDate = null;
this.show = false;
this.caption = null;
this.calDays = false;
this.currentHandler = function( v ) {
debug.Info( "[Astro.Blog.Components.Calendar] " + v );
};
};
var bodyClick = function ( e )
{
var s = e.target.getAttribute("calObj")
if(s)
{
this.stage.style.display = "none";
this.stage.style.position = "";
this.show = false;
}
if( this.show && !this.istg.contains( e.target ) )
{
this.stage.style.display = "none";
this.stage.style.position = "";
this.show = false;
}
};
var addZero = function ( num )
{
return num < 10
? "0" + String(num)
: String(num)
;
};
Calendar.prototype.init = function()
{
this.stage = Dand.wrapc( "compx calendar" );
this.istg = IDOMElement( this.stage );
this.calDate = new Date;
IDOMElement( document.body ).addEventListener( "Click", bodyClick.bind( this ) );
var tr = Dand.wrap(null, "navbar")
, td = Dand.wrap("span")
, btn = Dand.wrap("a", null, "navbtn")
;
tr.setAttribute("style", "position: relative");
btn.onclick = function (e) { this.nextMon(); }.bind(this);
td.style.textAlign = "right";
td.style.width = "100%";
td.style.position = "absolute";
td.style.left = "0";
btn.appendChild(Dand.textNode("\u25ba"));
td.appendChild(btn);
tr.appendChild(td);
td = Dand.wrap("span");
btn = Dand.wrap("a", null, "navbtn");
btn.appendChild(Dand.textNode("\u25c4"));
btn.onclick = function (e) { this.prevMon(); }.bind(this);
td.style["float"] = "left";
td.style.position = "absolute";
td.appendChild(btn);
tr.appendChild(td);
caption = Dand.wrap("span", null, "calDate");
caption.style.width = "100%";
caption.appendChild(
Dand.textNode(
XDate.MONTH[this.calDate.getMonth()] + ", " + this.calDate.getFullYear()
)
);
tr.appendChild(caption);
this.stage.appendChild(tr);
this.stage.onselectstart = function() { return false;};
return this.stage;
};
Calendar.prototype.pop = function ( dateObj, handler )
{
if( typeof( dateObj ) == "string" )
{
var p = dateObj.split(",");
if ( p.length == 3 )
dateObj = new Date( p[2], p[1] - 1, p[0] );
}
this.draw( dateObj, handler );
this.show = false;
this.stage.style.display = "block";
Cycle.next( function (){ this.show = true; }.bind(this) );
};
Calendar.prototype.draw = function (dateObj, handler)
{
if(!dateObj)
dateObj = new Date;
this.calDate = dateObj;
var mon = dateObj.getMonth()
, yr = dateObj.getFullYear()
, j = dateObj.getDay()
, dt = dateObj.getDate()
, thisDate = new Date
, thisYear = thisDate.getFullYear()
, thisMonth = thisDate.getMonth()
, thisDate = thisDate.getDate()
, thisDate = Number(String(thisYear) + addZero(thisMonth) + addZero(thisDate))
, currHead = String(yr) + addZero(mon)
, currDate;
( typeof handler == "function" ) && ( this.currentHandler = handler );
caption.innerHTML = XDate.MONTH[this.calDate.getMonth()] + ", " + this.calDate.getFullYear();
if(this.calDays)
this.calDays.parentElement.removeChild(this.calDays);
this.calDays = Dand.wrap(null, "calDays");
var days = (mon == 1) ? (yr % 4 == 0 ? 29: 28) : XDate.CAP_MONTHS[mon] ? 30 : 31;
for (var i = 0; i < days; i ++)
{
if(j < 0)
j = 6;
if(dt - i == 1)
break;
j --;
}
var tr = Dand.wrap(), td;
for(i = 0; i < 7; i ++)
{
td = Dand.wrap("span");
td.appendChild( Dand.textNode( XDate.DAY_ABBR[i] ) );
tr.appendChild(td);
}
this.calDays.appendChild(tr);
tr = Dand.wrap();
for(i = 0; i < j; i ++)
{
td = Dand.wrap("span");
td.style.background = "none";
tr.appendChild(td);
}
i = 0;
while( i ++ < days )
{
currDate = Number(currHead + addZero(i));
if(j > 6)
{
j = 0;
this.calDays.appendChild(tr);
tr = Dand.wrap();
}
td = Dand.wrap( "span" );
td.setAttribute( "value", i + "," + (mon + 1) + "," + yr );
td.setAttribute( "onmouseover", "className=\"onhover\";" );
td.setAttribute( "onmouseout", "className=\"toNorm\";" );
// Unique identifier for body click
// to test whether choice is chosen
td.setAttribute("calObj", "1");
td.onclick = function ( e )
{
this.currentHandler( e.target.getAttribute("value") );
}.bind(this);
if(thisDate < currDate)
{
td.setAttribute("id", "notyet");
}
else if(thisDate > currDate)
{
td.setAttribute("id", "norec");
/*
if(!( book[yr] && book[yr][mon + 1] && book[yr][mon + 1][i] )) {
td.setAttribute("id", "norec");
} else if(book[yr][mon + 1][i][1]) {
td.setAttribute("id", "notfin");
}
*/
}
else if(currDate == thisDate)
{
td.setAttribute("id", "today");
currlabel = td;
}
td.appendChild(Dand.textNode(i));
tr.appendChild(td);
j ++;
}
if(j) this.calDays.appendChild(tr);
this.stage.appendChild(this.calDays);
};
Calendar.prototype.prevMon = function () {
this.draw( this.calDate = new Date( this.calDate.getFullYear(), this.calDate.getMonth() - 1 ) );
};
Calendar.prototype.nextMon = function () {
this.draw( this.calDate = new Date( this.calDate.getFullYear(), this.calDate.getMonth() + 1 ) );
};
ns[ NS_EXPORT ]( EX_CLASS, "Calendar", Calendar );
})();

View File

@ -0,0 +1,288 @@
.comment-stage {
width: 80%;
float: right;
padding-bottom: 1em;
position: relative;
}
.c_body {
position: relative;
padding-left: 10px;
}
.c_title {
padding: 1em 0.5em;
}
.c_bsign {
margin-left: -0.47em;
padding: 0.1em 0.5em 0.1em 1em;
font-size: 2em;
color: white;
background: cornflowerblue;
}
.uc_ntoggle {
font-family: custom-sans;
vertical-align: top;
padding: 0.2em 0em;
}
.uc_ntoggle:before { content: '..'; }
.uc_ntoggle:after { content: '!'; }
.cr_ntoggle {
font-family: custom-sans;
padding: 0;
margin: 0;
position: absolute;
width: 1.5em;
height: 1.5em;
bottom: 0;
right: -3em;
border-radius: 2em 2em 2em 0em;
border: 0.5em solid white;
line-height: 1.5em !important;
background-color: white;
/* box-shadow: 2px 2px 10px -5px black; */
}
.cr_ntoggle:before, .cr_ntoggle:after {
padding: 0;
border-radius: 2em;
}
.cr_ntoggle:before {
content: '..';
background-color: slategrey;
}
.cr_ntoggle:after { content: '!'; }
.c_comm {
position: relative;
left: 1.6em;
padding-right: 1.6em;
}
.c_comm > .c_cont:after {
content: "";
width: 0;
height: 0;
border-top: 1em solid transparent;
border-bottom: 1em solid transparent;
border-right: 1em solid white;
position: absolute;
top: 1em;
left: -0.9em;
}
.c_comm > .c_cont:before {
content: "";
top: 0;
left: -2.15em;
position: absolute;
background: cornflowerblue;
width: 8px;
height: 100%;
}
.c_cont {
position: relative;
background-color: white;
padding: 1em;
margin-top: 1em;
border: 1px solid #D7D4C9
}
.c_text {
padding-bottom: 0.5em;
word-wrap: break-word;
}
.c_info > div:first-child, .c_info > div > a {
text-align: right;
color: #D4145A;
}
.c_info > div:last-child {
text-align: right;
color: #AAA;
}
.cu_stack {
/* padding 0.5 - 0.2 border width */
margin: 0 0 -0.3em 0.3em;
position: relative;
text-align: right;
width: 100%;
}
.cu_stack > div {
display: inline-block;
}
.cu_avatar {
/* Equal to the border width */
margin: 0 0 -0.2em 0.5em;
}
.cu_avatar > img {
border: 0.2em white solid;
box-shadow: 0px 0px 5px 0 black;
width: 64px;
height: 64px;
float: right;
}
.reply {
margin-left: 20%;
width: 80%;
}
.reply > .c_cont:after, .r_indicator {
content: "";
width: 0;
height: 0;
border-left: 1em solid transparent;
border-right: 1em solid transparent;
border-bottom: 1em solid white;
position: absolute;
top: 0;
right: 1em;
}
#ri_switch[data-pointy="1"] { top: -1em; }
.c_relative_wrap {
position: relative;
padding: 1em;
background: radial-gradient(circle, rgba(0, 0, 0, 0) 10px, #EEE 10px) 0px 10px, #FFF;
background-size: 20px 20px;
}
.commentblock {
margin-top: 1em;
width: 100%;
position: relative;
#background: white;
}
#c_submit {
background: cornflowerblue;
}
#c_submit:hover {
background: cadetblue;
}
.c_reply {
background: Coral;
}
.c_reply:hover {
background: LightCoral;
}
.c_tag {
cursor: pointer;
position: absolute;
overflow: hidden;
height: 100%;
width: 0;
right: 0;
top: 0;
}
.c_tag > span {
-moz-transform: rotate(90deg);
-moz-transform-origin: 50% 50%;
-webkit-transform: rotate(90deg);
-webkit-transform-origin: 50% 50%;
transform: rotate(90deg);
transform-origin: 50% 50%;
font-size: 1.5em;
display: block;
color: white;
}
.commentInput {
width: 100%;
height: 80px;
font-size: 1.2em;
font-family: custom-sans;
}
.c_caption {
font-size: 1.2em;
font-family: custom-sans;
}
.c_false_input {
font-size: 0.8em;
font-size: custom-serif;
font-style: italic;
color: red;
text-align: right;
height: 0;
overflow: hidden;
}
.nocomment {
font-size: 1.2em;
padding: 1em;
background: white;
font-family: custom-serif !important;
margin: 1em;
}
.info_field > div{
margin: 0.2em 0;
text-align: right;
}
.info_field .website span { width: 20%; }
.info_field .website input { width: 80%; }
iframe[src="about:blank"] {
/* recaptcha about:blank page */
display: none;
}
.commentblock, #capcha_wrapper, #c_input_panel, .c_comm {
-webkit-transition: all 500ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
-moz-transition: all 500ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
-ms-transition: all 500ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
-o-transition: all 500ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
transition: all 500ms cubic-bezier(0.770, 0.000, 0.175, 1.000); /* easeInOutQuart */
-webkit-transition-timing-function: cubic-bezier(0.770, 0.000, 0.175, 1.000);
-moz-transition-timing-function: cubic-bezier(0.770, 0.000, 0.175, 1.000);
-ms-transition-timing-function: cubic-bezier(0.770, 0.000, 0.175, 1.000);
-o-transition-timing-function: cubic-bezier(0.770, 0.000, 0.175, 1.000);
transition-timing-function: cubic-bezier(0.770, 0.000, 0.175, 1.000); /* easeInOutQuart */
}
#c_input_panel.reply {
max-width: 80%;
}
.c_so_sorry {
padding: 0.2em;
font-size: 0.8em;
color: orangered;
display: none;
}

View File

@ -0,0 +1,625 @@
(function(){
var ns = __namespace( "Astro.Blog.Components.Comment" );
/** @type {System.Cycle} */
var Cycle = __import( "System.Cycle" );
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
/** @type {System.Cycle.Trigger} */
var Trigger = __import( "System.Cycle.Trigger" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.EventKey} */
var EventKey = __import( "System.utils.EventKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {System.utils.Perf} */
var Perf = __import( "System.utils.Perf" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Astro.Bootstrap} */
var Bootstrap = __import( "Astro.Bootstrap" );
/** @type {Astro.Blog.Config} */
var Conf = __import( "Astro.Blog.Config" );
/** @type {Astro.Blog.Components.Bubble} */
var Bubble = __import( "Astro.Blog.Components.Bubble" );
var postData = __import( "System.Net.postData" );
/** @type {_3rdParty_.Recaptcha} */
var Recaptcha;
var RECAPTCHA_SITE_KEY = null;
/** @type {_AstConf_.UserInfo} */
var currentUser = Conf.get( "UserInfo" );
/** @type {_AstConf_.Comment} */
var Config = Conf.get( "Comment" );
/** @type {_AstConf_.Article} */
var article = Conf.get( "Article" );
/*{{{ Validation Methods */
var v_match = function( str, regEx )
{
// Optional string is empty
if( !str ) return true;
// Not empty, validate
if( str.match( regEx ) != null ) return str;
return false;
};
var validateMail = function ( str )
{
return v_match( str, /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i );
};
var validateURL = function ( str )
{
return v_match( str, /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/ );
};
/* End Validation Methods}}}*/
var wrapc = Dand.wrapc;
var init = function ()
{
// TODO: should add controls to be able to remove comments
var contentHaveText = false
, nameHaveText = false
, fieldReady = false
, releaseReplyLock
, submit_button
, cBubble
, button
, cHeight = 0
, elmH = "1.2em"
, cp = Dand.id( "c_input_panel" )
, contentField = Dand.id( "content_field" )
, nameField = Dand.id( "name_field" )
, c_body = Dand.id( "comment_body" )
// If nameField exists, we assume logged in
, loggedIn = !nameField
, contentHadHaveText = false
, commentInput = function ()
{
// trim whitespaces
contentHaveText = contentField.value.trim();
if( contentHaveText != contentHadHaveText ) {
fieldReadyTrigger();
contentHadHaveText = contentHaveText;
}
}
, nameHadHaveText = false
, nameInput = function ()
{
if( !nameField )
return;
// trim whitespaces
nameHaveText = nameField.value.trim();
if( nameHadHaveText != nameHaveText ) {
fieldReadyTrigger();
nameHadHaveText = nameHaveText;
}
}
, doReply = function ()
{
var c_reply = this;
// This will ensure capcha_wrapper is set
fieldReadyTrigger();
// Set comment id
submit_button.setAttribute( new DataKey( "cid", c_reply.getAttribute( "value" ) ) );
// close the triangle in the top rigth corner
Dand.id( "ri_switch", true ).removeAttribute( "data-pointy" );
// If this button is not that button
button && ( c_reply != button ) && releaseReplyButton();
// Lock reply button
c_reply.setAttribute("locked", "1");
c_reply.onclick = null;
c_reply.style.cursor = "default";
c_reply.style.background = "Crimson";
c_reply.style.width = "1.2em";
c_reply.style.right = "-1.2em";
// Configure release lock
button = c_reply;
hideSubmit();
Cycle.delay( function() {
closeInputPanel( function() {
cp.classList.add( "reply" );
reviveInputpanel.bind( c_reply.parentNode.parentNode )();
} );
}, 500);
}
, releaseReplyButton = function ()
{
button.removeAttribute("locked");
button.onclick = doReply.bind(button);
button.style.cursor
= button.style.background
= button.style.width
= button.style.right
= "";
}
, fieldReadyTrigger = loggedIn
? /* Overload */ function ()
{
submit_button || ( submit_button = Dand.id( "c_submit", true ) );
if(contentHaveText)
{
// show submit button
showSubmit();
fieldReady = true;
}
else
{
// hide submit button
hideSubmit();
fieldReady = false;
}
}
: /* Overload */ function ()
{
submit_button || ( submit_button = Dand.id( "c_submit", true ) );
if(!fieldReady && contentHaveText && nameHaveText)
{
// show submit button
showSubmit();
fieldReady = true;
}
else if(!(contentHaveText || nameHaveText))
{
// hide submit button
hideSubmit();
fieldReady = false;
}
}
, submitComment = loggedIn
? /* Overload */ function ()
{
// Postdata
var p = {
"article_id": article.id
, "name": currentUser.name
, "website": currentUser.website
, "avatar": currentUser.avatar
}
// pass-through obj
, comment_id = submit_button.getDAttribute( "cid" );
p.article_id = article.id;
// Set comment id if available
comment_id && ( p["comment_id"] = comment_id );
hideSubmit();
if( getFieldsValidated(p) )
{
popBubble();
// Post the data, bind obj to Handler
postData( Config.processor, p, commentSuccess.bind(p), commentFailed );
}
else
{
Cycle.delay( showSubmit, 1500 );
}
}
: /* Overload */ function ()
{
var p = { "article_id": article.id }
, comment_id = submit_button.getDAttribute( "cid" );
// Set comment id if available
comment_id && ( p["comment_id"] = comment_id );
hideSubmit();
if( getFieldsValidated( p ) )
{
popBubble();
Recaptcha.execute( RECAPTCHA_SITE_KEY, { "action": "submit" } )
.then(function( token )
{
p[ "token" ] = token;
// Post the data, bind obj to Handler
postData( Config.processor, p, commentSuccess.bind(p), commentFailed );
});
}
else
{
Cycle.delay( showSubmit, 1500 );
}
}
, commentSuccess = function ( obj )
{
// Pass Color = Green
cBubble.setColor("YellowGreen");
// Popup Success message
cBubble.pop("Success");
// blurp after 1 sec
Cycle.delay( function (){ cBubble.blurp(); }, 1500 );
generateCommentStack( this, obj );
}
// Input panel control
, closeInputPanel = function (handler) {
cHeight = cp.clientHeight;
cp.style.transition = "all 0s";
cp.style.height = cHeight + "px";
cp.style.overflow = "hidden";
// Delay for 10 millisec for establishing transition properties
Cycle.next(function() {
this.style.transition = "";
}.bind(cp));
Trigger.transition(cp.style, "", function()
{
cp.style.padding = "0";
cp.style.height = "0";
});
// After transition finished, remove input panel
Cycle.delay(function()
{
cp.parentNode.removeChild(cp);
// Pass panel to handler
if(handler) handler();
}, 500);
}
, openInputPanel = function ()
{
cp.style.padding = "";
cp.style.height = cHeight + "px";
// Delay for 500 millisec waiting for transition finished
Cycle.delay(function()
{
cp.style.transition = "all 0s";
cp.style.height = "";
cp.style.overflow = "";
// Pop back up the pointy triangle
Dand.id( "ri_switch", true ).setAttribute( new DataKey( "pointy", "1" ) );
fieldReady = false;
fieldReadyTrigger();
}, 500);
}
, reviveInputpanel = function ()
{
this.appendChild(cp);
Cycle.next(openInputPanel);
}
// Comments submission and handling
, commentFailed = function (obj)
{
// Handle error here to prevent accidental catch by caller
try
{
if(obj != null)
{
if(obj.reload)
{
Cycle.delay(showSubmit, 1500);
Cycle.delay( function()
{
this.innerHTML = "Recaptcha failure";
this.style.height = "1.2em";
}.bind(f), 500 );
Cycle.delay(function (){cBubble.blurp();}, 500);
}
else
{
// Reload not needed, serious error had occurred
Cycle.delay(function (){cBubble.blurp();}, 500);
Cycle.delay(function ()
{
cBubble.setColor("red");
cBubble.pop("Server error");
}, 1000);
}
}
else
{
Cycle.delay(showSubmit, 1500);
Cycle.delay(function (){cBubble.blurp();}, 500);
Cycle.delay(function ()
{
cBubble.setColor("red");
cBubble.pop("Cannot connect");
}, 1000);
}
}
catch(e)
{
debug.Error(e);
}
}
, submitKey = new EventKey("Click", submitComment)
, showSubmit = function ()
{
// prevent multiple prop assign
if( !submit_button.hasListener( submitKey ) )
{
submit_button.style.width = "1.2em";
submit_button.style.right = "-1.2em";
submit_button.style.cursor = "pointer";
}
submit_button.addEventListener( submitKey );
}
, hideSubmit = function ()
{
// prevent multiple prop assign
if( submit_button.hasListener( submitKey ) )
{
submit_button.style.cursor = "default";
submit_button.style.width = "";
submit_button.style.right = "";
}
submit_button.removeEventListener( submitKey );
}
, __createContentText = function( text )
{
var e = wrapc( "c_text", text );
e.innerHTML = e.innerHTML.replace( /\n/g, "<br />" );
return e;
}
, generateCommentStack = function ( rObj, obj )
{
var
// Hold for transitions
c_ind, c_cont, cpole
// The info stack
, _c_info = wrapc("c_info",
[
wrapc("fls", rObj.website ? Dand.wrapne( "a", rObj.name, IKey.quickDef( "target", "_blank", "href", rObj.website ) ) : rObj.name )
, wrapc( "flsf", obj.time )
])
// loggedIn Overload
, c_info = loggedIn
? wrapc("cu_stack", [ _c_info
, Dand.textNode(" ")
, wrapc("cu_avatar"
, Dand.wrapna( "img", IKey.quickDef( "src", rObj.avatar, "alt", "avatar" ) )
)]
)
: _c_info
// Generate comment stack
, c_stack = rObj["comment_id"]
// Reply Structure
? wrapc("reply", wrapc("c_cont", [ c_ind = wrapc("r_indicator") , __createContentText( rObj.content ) , c_info ]))
: wrapc("c_comm",
[
c_ind = wrapc("c_indicator")
, c_cont = wrapc("c_cont", [ cpole = wrapc("cpole") , __createContentText( rObj.content ) , c_info ])
]
)
;
// Remove transition properties
c_stack.style.transition = "all 0s";
// Close Input panel
closeInputPanel( null );
// Remove false_fields
for(var i in fields) {
i = Dand.id("false_" + fields[i]);
i.parentNode.removeChild(i);
}
c_stack.style.opacity = 0;
cp.parentNode.insertBefore( c_stack, cp );
c_stack.style.marginTop = ( -c_stack.clientHeight ) + "px";
// if nocomment notice exist, remove it
if( i = Dand.id("nocomment") )
{
i.style.transition = "all 0s";
i.style.width = "658px";
i.style.height = "22px";
i.style.overflow = "hidden";
// transition
Cycle.next(function()
{
this.style.transition = "";
this.style.margin = "0";
this.style.width = "0";
this.style.padding = "0";
this.style.height = "0";
}.bind(i));
// Pending remove
Trigger.height(i, 0, function(){ this.parentNode.removeChild(this); }.bind(i));
}
// Delay for 10 millisec for establishing transition properties
Cycle.next( function() { this.style.transition = ""; }.bind( c_stack ) );
Cycle.delay(function()
{
this.style.marginTop = "";
this.style.opacity = 1;
}.bind(c_stack), 600);
}
// Validation
, fields = loggedIn ? ["content"] : [ "content", "name", "email", "website", "email_notify" ]
, getFieldsValidated = function (obj)
{
var name, field, falsefield, f;
for(var i in fields)
{
name = fields[i];
field = name + "_field";
falsefield = "false_" + name;
f = Dand.id( falsefield );
if( f ) f.style.height = 0;
switch(name)
{
case "name":
if(!( obj[name] = Dand.id(field).value.trim() ))
Cycle.delay( function() { this.style.height = elmH; }.bind(f), 500 );
break;
case "content":
if(!( obj[name] = Dand.id(field).value.trim() ))
Cycle.delay( function() { this.style.height = elmH; }.bind(f), 500 );
break;
case "website":
if(!( obj[name] = validateURL( Dand.id(field).value.trim() )))
{
obj[name] = false;
Cycle.delay( function() { this.style.height = elmH; }.bind(f), 500 );
}
else
{
if(obj[name] == true)
delete obj[ name ];
}
break;
case "email":
if(!( obj[name] = validateMail( Dand.id(field).value.trim() ) ))
{
obj[name] = false;
Cycle.delay( function() { this.style.height = elmH; }.bind(f), 500 );
}
else
{
if( obj[ name ] == true )
delete obj[ name ];
}
break;
case "email_notify":
if( obj[ name ] = Dand.id( field ).checked )
{
if( obj[ "email" ] == undefined )
{
obj[ name ] = false;
Cycle.delay( function() { this.style.height = elmH; }.bind(f), 500 );
}
}
else
{
delete obj[ name ];
}
break;
}
}
for( var i in obj )
if( !obj[i] ) return false;
return true;
}
, showReplyButton = function ()
{
this.style.width = "1.2em";
this.style.right = "-1.2em";
}
, hideReplyButton = function ()
{
if(!this.getAttribute("locked"))
this.style.width = this.style.right = "";
}
, popBubble = function ()
{
if(cBubble == null)
{
// create a new bubble
cBubble = new Bubble();
document.body.appendChild( cBubble.init() );
// pop message
cBubble.setColor( "cornflowerblue" );
Cycle.next( function () { cBubble.pop("Submitting"); } );
}
}
;
if( !loggedIn )
{
IDOMElement( nameField ).addEventListener( "Input", nameInput );
}
IDOMElement( contentField ).addEventListener( "Input", commentInput );
var l = c_body.childNodes, c_id;
for( var i in l )
{
if( l[i].nodeType == 1
&& ( c_id = IDOMElement( l[i] ).getDAttribute("value") )
)
{
var reply_button = Dand.id("c_reply_" + c_id);
reply_button.onclick = doReply.bind(reply_button);
l[i].onmouseover = showReplyButton.bind(reply_button);
l[i].onmouseout = hideReplyButton.bind(reply_button);
}
}
if( !loggedIn )
{
var limit = 5;
var i = 0;
var reUUID = Perf.uuid;
RECAPTCHA_SITE_KEY = Dand.id( "recaptcha-js" ).src.split( "?render=" )[1];
Cycle.perma(
reUUID, function()
{
if( limit < i ++ )
{
var mesg = Dand.glass( "c_so_sorry" );
if( mesg.length ) mesg[0].style.display = "block";
}
if(( Recaptcha = window["grecaptcha"] ))
{
Cycle.permaRemove( reUUID );
debug.Info( "Recaptcha instance is up" );
}
} , 500
);
}
Cycle.next( nameInput );
Cycle.next( commentInput );
};
Bootstrap.regInit( init );
})();

View File

@ -0,0 +1,50 @@
.control_panel {
height: 100%;
margin-top: 0.2em;
}
.control_panel > a {
display: inline-block;
position: relative;
overflow: hidden;
width: 80px;
height: 80px;
}
.control_panel > a:after {
content: attr(data-desc);
font-family: custom-sans;
background-color: rgba(0, 0, 0, 0.6);
color: white;
position: absolute;
width: 100%;
padding: 0 0.2em;
left: 0;
bottom: 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.control_panel > a > span {
padding: 0.2em 0.5em;
background-color: orange;
color: white;
}
.control_panel > div {
font-size: 0.8em;
font-family: custom-sans;
}
.control_panel > div > a {
color: #222;
}

View File

@ -0,0 +1 @@
// __namespace( "Astro.Blog.Components.ControlPanel" );

View File

@ -0,0 +1,6 @@
.tags > a {
color: saddlebrown;
font-family: custom-sans;
padding: 0.2em;
float: left;
}

View File

@ -0,0 +1 @@
// __namespace( "Astro.Blog.Components.CrowdTag" );

View File

@ -0,0 +1,123 @@
.b_entry img {
max-width: 100%;
height: auto;
}
.inline-code {
font-family: site-mono;
font-size: 1.12em;
color: black;
background-color: #EEE;
padding: 0.2em 0.5em;
}
.b_entry {
background-color: #FAFAFA;
/* box-shadow: 0 0 8px -2px black; */
border: 1px solid #D7D4C9;
word-wrap: break-word;
position: relative;
margin-top: 0;
padding: 1em;
}
.b_entry.archived::after {
display: block;
content: "Archived";
text-align: center;
background:
linear-gradient(-45deg, transparent 36%, black 36%, black 82%, transparent 82%)
, linear-gradient(45deg, transparent 36%, black 36%, black 82%, transparent 82%);
color: white;
position: absolute;
width: 4.4em;
right: -2.25em;
top: 1.45em;
font-size: 1.5em;
padding: 0.15em 2.25em;
transform: rotate(45deg);
opacity: 0.5;
}
.b_title {
font-family: custom-serif;
font-size: 2.5em;
margin-bottom: 0.25em;
color: #444;
}
.b_avartar {
margin: 0 0 0.5em 0.5em;
line-height: 0;
float: right;
-moz-box-shadow: 2px 2px 5px 0 black;
-webkit-box-shadow: 2px 2px 5px 0 black;
box-shadow: 2px 2px 5px 0 black;
border: 0.4em solid white;
background-color: white;
background-position: center;
background-repeat: no-repeat;
}
.b_bodyWrapper {
color: #555;
text-align: justify;
min-height: 155px;
margin-bottom: 3em;
}
.b_bodyWrapper a { color: #f15a24; }
.b_edit {
background-color: yellowgreen;
}
.b_preview {
background-color: orangered;
}
.b_author {
color: purple;
text-align: right;
}
.b_entry .top-date {
float: right;
opacity: 0.35;
}
.b_entry .top-date:hover {
opacity: 0.6;
}
.b_date, .b_mdate {
text-align: right;
}
.b_date {
font-family: custom-serif;
}
.b_mdate {
font-style: italic;
font-family: custom-sans;
font-size: 0.8em;
opacity: 0.5;
}
.b_tags > a {
font-size: 1em;
color: #76400C;
}

View File

@ -0,0 +1,28 @@
(function(){
var ns = __namespace( "Astro.Blog.Components.Entry.Blog" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Astro.Bootstrap} */
var Bootstrap = __import( "Astro.Bootstrap" );
/** @type {Astro.utils.Date} */
var XDate = __import( "Astro.utils.Date" );
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
var init = function()
{
var entry = Dand.id( "b_entry", true );
var time = new Date( entry.getDAttribute( "time" ) );
entry.element.insertBefore(
Dand.wrapc(
"top-date"
, Dand.textNode( XDate.chinese( time ) )
)
, entry.first( 1 )
);
};
Bootstrap.regInit( init );
})();

View File

@ -0,0 +1,124 @@
.home_entry {
position: relative;
margin: 1em 0;
}
.h_info {
position: absolute;
height: 100%;
width: 7em;
text-align: right;
}
.h_body {
margin-left: 7em;
margin-right: 0.5em;
}
.h_bodyWrapper {
border: 1px solid #D4D7C9;
background-color: #FAFAFA;
color: #777;
padding: 1em 1em 2em 1em;
min-height: 155px;
/* Same as image size */
max-width: 600px;
}
.h_datetime {
right: 0;
bottom: 0.95em;
}
.h_auth_com {
padding-top: 0.5em;
font-family: Calibri;
color: #D4145A;
}
.h_avatarWrapper {
display: block;
width: 80px;
height: 80px;
}
.h_avatar, .a_avatarWrapper {
width: 80px;
height: 80px;
margin: 0 auto;
}
.h_avatar {
border-radius: 80px;
background-color: #FAFAFA;
background-size: 50px 50px;
background-repeat: no-repeat;
background-position: center;
-moz-box-shadow: 2px 2px 5px 0 black;
-webkit-box-shadow: 2px 2px 5px 0 black;
box-shadow: 2px 2px 5px 0 black;
}
.h_avatar:hover {
width: 70px;
height: 70px;
border-radius: 70px;
margin-top: 5px;
background-size: 60px 60px;
}
.h_infoWrapper {
padding: 0.5em;
}
.h_cCount {
font-family: sans-serif;
color: cornflowerblue;
font-size: 80%;
}
.h_title {
font-size: 2em;
color: #444;
}
.h_title, .h_desc {
overflow: hidden;
text-overflow: ellipsis;
}
.h_read_full {
position: absolute;
bottom: 0.5em;
right: 1.5em;
font-size: 0.8em;
text-align: right;
padding: 0.5em 0 0.5em 0;
color: #F15A24;
}
.h_read_full_a {
color: #F15A24;
}
.h_img {
width: 100%;
max-height: 350px;
overflow: hidden;
}
.h_img img {
max-width: 100%;
height: auto;
}

View File

@ -0,0 +1 @@
// __namespace( "Astro.Blog.Components.Entry.Home" );

View File

@ -0,0 +1,67 @@
.list_entry {
position: relative;
margin: 1em 0;
padding: 0.5em;
background-color: #FAFAFA;
border: 1px solid #D4D7C9;
}
.caption {
font-size: 2.5em;
color: #444;
}
.title {
font-size: 1.5em;
color: #555;
}
.content {
color: #777;
}
.tags {
padding: 0.5em 0;
}
.flag {
font-family: custom-sans;
font-size: 0.8em;
padding: 0 0.5em;
margin: 0 0 0 0.2em;
float: right;
cursor: default;
}
.flag.archived { color: white; background: #888; }
.flag.archived:hover { background: #666; }
.flag.featured { color: white; background: coral; }
.flag.featured:hover { background: orangered; }
.tag {
color: #76400C;
padding: 0.2em 0.5em;
font-family: custom-sans;
}
.mdate, .author {
text-align: right;
}
.author {
color: crimson;
}
.mdate {
color: #AAA;
font-size: 0.8em;
font-family: custom-sans;
}

View File

@ -0,0 +1 @@
// __namespace( "Astro.Blog.Components.Entry.List" );

View File

@ -0,0 +1,68 @@
.t_title {
font-size: 2.5em;
color: #444;
}
.ts_title {
font-size: 1.5em;
color: #555;
}
ul.n-archive > li {
position: relative;
padding: 0.5em 0.5em 0.1em;
margin: 0.5em;
border-right: 1px solid transparent;
}
ul.n-archive > li:hover {
border-right: 1px solid #555;
}
ul.n-archive h4 {
color: black;
}
ul.n-archive a {
color: #666;
width: 100%;
display: inline-block;
}
ul.n-archive a:before {
content: attr(data-value);
margin-right: 0.5em;
padding: 0.5em;
float: left;
width: 1.4em;
text-align: center;
color: white;
font-family: custom-sans;
}
ul.n-archive a:hover:before {
text-decoration: underline;
}
ul.n-archive a:hover {
text-decoration: none;
}
ul.n-archive a.Sun:before { color: rgba(255, 29, 37, 1); }
ul.n-archive a.Mon:before { color: rgba(102, 45, 145, 1); }
ul.n-archive a.Tue:before { color: rgba(63, 169, 245, 1); }
ul.n-archive a.Wed:before { color: rgba(122, 201, 67, 1); }
ul.n-archive a.Thu:before { color: rgba(255, 123, 172, 1); }
ul.n-archive a.Fri:before { color: rgba(96, 56, 19, 1); }
ul.n-archive a.Sat:before { color: rgba(255, 147, 30, 1); }
ul.n-archive a.Sun:hover:before { color: white; background: rgba(255, 29, 37, 1); }
ul.n-archive a.Mon:hover:before { color: white; background: rgba(102, 45, 145, 1); }
ul.n-archive a.Tue:hover:before { color: white; background: rgba(63, 169, 245, 1); }
ul.n-archive a.Wed:hover:before { color: white; background: rgba(122, 201, 67, 1); }
ul.n-archive a.Thu:hover:before { color: white; background: rgba(255, 123, 172, 1); }
ul.n-archive a.Fri:hover:before { color: white; background: rgba(96, 56, 19, 1); }
ul.n-archive a.Sat:hover:before { color: white; background: rgba(255, 147, 30, 1); }

View File

@ -0,0 +1 @@
// __namespace( "Astro.Blog.Components.Entry.Tag" );

View File

@ -0,0 +1,90 @@
.tile-block {
float: left;
width: 150px;
height: 150px;
position: relative;
overflow: hidden;
display: inline-block;
background-image: linear-gradient(
135deg, transparent 40%, rgba(0,0,0,.2) 40%, rgba(0,0,0,.2) 60%, transparent 60%
)
, linear-gradient(
225deg, transparent 40%, rgba(0,0,0,.2) 40%, rgba(0,0,0,.2) 60%, transparent 60%
)
, linear-gradient( 45deg, rgba(0,0,0,.2) 0%, rgba(0,0,0,.2) 10%, transparent 10% )
, linear-gradient( 135deg, rgba(0,0,0,.2) 0%, rgba(0,0,0,.2) 10%, transparent 10% )
, linear-gradient( 225deg, rgba(0,0,0,.2) 0%, rgba(0,0,0,.2) 10%, transparent 10% )
, linear-gradient( 315deg, rgba(0,0,0,.2) 0%, rgba(0,0,0,.2) 10%, transparent 10% )
;
background-size: 100px 100px;
background-color: white;
border: 1px solid #d4d7c9;
}
.tile-block .banner {
background-repeat: no-repeat;
background-position: center center;
opacity: 0.9;
background-color:white;
}
.tile-block .banner, .tile-block .link {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.tile-block .link {
background-color: black;
color: white;
opacity: 0;
text-align: center;
text-decoration: none;
padding-top: 55%;
background-image: linear-gradient(
135deg, transparent 40%, rgba(255,255,255,.1) 40%, rgba(255,255,255,.1) 60%, transparent 60%
)
, linear-gradient(
225deg, transparent 40%, rgba(255,255,255,.1) 40%, rgba(255,255,255,.1) 60%, transparent 60%
)
, linear-gradient( 45deg, rgba(255,255,255,.1) 0%, rgba(255,255,255,.1) 10%, transparent 10% )
, linear-gradient( 135deg, rgba(255,255,255,.1) 0%, rgba(255,255,255,.1) 10%, transparent 10% )
, linear-gradient( 225deg, rgba(255,255,255,.1) 0%, rgba(255,255,255,.1) 10%, transparent 10% )
, linear-gradient( 315deg, rgba(255,255,255,.1) 0%, rgba(255,255,255,.1) 10%, transparent 10% )
;
background-size: 100px 100px;
background-position: 100% 0;
-webkit-transition: all 200ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
-moz-transition: all 200ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
-ms-transition: all 200ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
-o-transition: all 200ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
transition: all 200ms cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
-webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
-moz-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
-ms-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
-o-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
}
.tile-block .link:hover {
padding-top: 50%;
opacity: 1;
}
.tile-block .title {
margin-top: -0.5em;
}

View File

@ -0,0 +1 @@
// __namespace( "Astro.Blog.Components.Entry.Tile" );

View File

@ -0,0 +1,35 @@
.footnote {
padding-top: 0.25em;
position: relative;
margin-bottom: 2em;
}
.footnote a {
color: #f15a24;
}
.footnote {
color: #555;
list-style-type: decimal;
list-style-position: inside;
}
.footnote > li {
padding-left: 0.5em;
}
.footnote > li[focused] {
background-color: #EE5;
}
.footnote:before {
content: "";
position: absolute;
top: 0;
width: 40%;
border-top: 1px black solid;
}

View File

@ -0,0 +1,46 @@
(function(){
var ns = __namespace( "Astro.Blog.Components.Footnote" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Astro.Bootstrap} */
var Bootstrap = __import( "Astro.Bootstrap" );
/** @type {Astro.Blog.Config} */
var Config = __import( "Astro.Blog.Config" );
/** @type {Astro.utils.Date} */
var XDate = __import( "Astro.utils.Date" );
/** @param {Dandelion.IDOMElement} elem */
var Footnote = function( elem )
{
var jumpers = Dand.glass( "ft", true );
if( !jumpers.length ) return;
var notes = Dand.glass( "footnote", true )[0];
jumpers.forEach( function( e ) {
var a = e.first( 1 );
IDOMElement( a ).addEventListener( "Click", function()
{
var clicked = a.hash.substr( 1 );
notes.foreach( 1, function( e ) {
if( e.id == clicked )
{
e.setAttribute( "focused", 1 );
}
else
{
e.removeAttribute( "focused" );
}
});
});
} );
};
Bootstrap.regInit(function() {
new Footnote();
});
})();

View File

@ -0,0 +1,172 @@
.notifications {
float: right;
cursor: default;
position: relative;
}
.nt_body {
position: absolute;
top: 0;
left: -300px;
max-width: 300px;
text-align: left;
display: none;
z-index: 1;
}
.nt_body > div { float: right; }
.nt_button {
float: left;
text-align: left;
display: block;
padding: 0 0.5em 0 0;
color: white;
background-color: #444;
}
.nt_button:before {
content: attr(data-count);
display: inline-block;
padding: 0 0.5em;
margin-right: 0.5em;
line-height: 2em;
background-color: royalblue;
}
.nt_button:before, .nt_switch:before, .nt_icon_settings {
-webkit-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
-moz-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
-ms-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
-o-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
-webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
-moz-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
-ms-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
-o-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
}
.nt_button:hover:before {
background: dodgerblue;
}
.nt_arrow {
margin-top: 0.2em;
border-top: 0.8em solid transparent;
border-left: 1em solid #444;
border-bottom: 0.8em solid transparent;
}
.nt_container {
min-width: 300px;
padding: 0.5em;
background: #444;
margin-right: 0.5em;
margin-top: -2em;
overflow: hidden;
}
.nt_date {
text-align: right;
}
.nt_container > ul {
max-height: 400px;
width: 120%;
white-space: nowrap;
text-overflow: ellipsis;
overflow-y: scroll;
color: white;
}
.nt_container > ul > li {
width: 80%;
padding: 0.25em 0.5em;
color: white;
text-decoration: none;
}
.nt_container > ul > li:hover {
background-color: orangered;
}
.nt_icon_settings {
float: right;
padding: 0em 0.2em;
width: 2em; height: 2em;
background: #333 url(/assets/blog/layout-images/settings.png) no-repeat center center;
background-size: 1.5em 1.5em;
}
.nt_icon_settings:hover {
background-color: #555;
}
ul.nt_smenu {
font-family: custom-sans;
cursor: default;
}
ul.nt_smenu > li {
padding: 0.2em 0.5em;
}
ul.nt_smenu > li:hover {
background-color: black;
}
ul.nt_smenu > li[active] > span.nt_switch:before {
margin-top: -1.2em;
}
ul.nt_smenu > li > span {
display: inline-block;
vertical-align: top;
}
.nt_switch {
width: 2.5em;
height: 1.2em;
text-align: center;
overflow: hidden;
}
.nt_switch:before {
float: left;
color: red;
content: 'OFF';
}
.nt_switch:after {
float: left;
color: yellowgreen;
content: 'ON';
}
.nt_tname {
padding-left: 0.5em;
}
.nt_tcount {
float: right;
}

View File

@ -0,0 +1,240 @@
(function(){
var ns = __namespace( "Astro.Blog.Components.Notification" );
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
/** @type {System.Cycle} */
var Cycle = __import( "System.Cycle" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
/** @type {System.utils.EventKey} */
var EventKey = __import( "System.utils.EventKey" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
/** @type {Components.Mouse.ContextMenu} */
var ContextMenu = __import( "Components.Mouse.ContextMenu" );
/** @type {Astro.Bootstrap} */
var Bootstrap = __import( "Astro.Bootstrap" );
/** @type {Astro.Blog.Config} */
var Config = __import( "Astro.Blog.Config" );
/** @type {Astro.utils.Date} */
var XDate = __import( "Astro.utils.Date" );
var postData = __import( "System.Net.postData" );
var smstamp = __import( "Astro.utils.Date.smstamp" );
var init = function ()
{
var stage = Dand.id( "notifications" );
var bodyStyle = Dand.id( "nt_body" ).style;
/** @type {_AstConf_.Notification} */
var conf = Config.get( "Notification" );
var processor = conf.processor;
var contextMenu;
var itemsMenu;
var nError = function( e ) {
// TODO: Do something on error
debug.Info( e );
};
var followLink = function(e)
{
window.location = this.link;
};
var toggleFollow = function(e)
{
var _action = "enable";
if( this.item.getAttribute( "active" ) )
{
_action = "disable";
if(
0 < IDOMElement( this.count ).getDAttribute( "count" )
&& !confirm( "All followed notifications of this type will be unfollowed. Continue?" )
) return;
}
postData(
processor
, {
"action": _action
, "tid": IDOMElement( this.item ).getDAttribute( "tid" )
, "cid": 0
}
, toggleSuccess.bind(this)
, nError
);
};
var toggleSuccess = function(e)
{
if( this.item.getAttribute( "active" ) )
{
this.item.removeAttribute( "active" );
this.count.innerHTML = "N/A";
}
else
{
this.item.setAttribute( "active", 1 );
this.count.innerHTML = "0";
}
};
var showSettings = function( e )
{
// Create list <ul> <li> ... </ul>
var ul = Dand.wrap("ul", "nt_imenu", "nt_smenu");
for( var i in e.data )
{
var data = e.data[i];
var li
, li_s = [
// On/off toggle
Dand.wrap( "span", null, "nt_switch" )
, Dand.wrap( "span", null, "nt_tname", data.name )
]
, keys = [ new DataKey( "tid", data.type ) ]
;
if( data.hasOwnProperty("count") )
{
// type count
li_s[2] = Dand.wrap(
"span"
, null
, "nt_tcount"
, e.data[i].count + ""
, new DataKey( "count", data.count )
);
// Active
keys[ keys.length ] = new IKey( "active", 1 );
}
else
{
li_s[2] = Dand.wrap( "span", null, "nt_tcount", "N/A" );
}
// Create li element
li = Dand.wrapne( "li", li_s, keys );
ul.appendChild( li );
IDOMElement( li ).addEventListener(
"Click"
, toggleFollow.bind({ item: li, count: li_s[2] })
);
}
var msgBox = new MessageBox( "Notification Settings", ul, "Close" ).show();
};
var popupSettings = function()
{
postData( processor, { action: "getSettings" }, showSettings, nError );
};
var readNotification = function(e)
{
postData( processor, { action: "read", id: this.id }, followLink.bind( this ), nError );
};
// functions
var createContextMenu = function(e)
{
var items = [], menuShow = false;
var hasNotis = 0 < e.data.length;
for( var n in e.data )
{
/** @type {_AstJson_.AJaxGetNotis} */
var data = e.data[n];
// Create items
items[ items.length ] = new IKey(
data.mesg
, new EventKey(
"m_" + data.id
, readNotification.bind( data )
)
);
}
Dand.glass( "nt_icon_settings", true )[0].addEventListener( "Click", popupSettings );
contextMenu = new ContextMenu(
Dand.id( "nt_open_menu" )
, items
, "LMB"
, nt_body
// showMenu/hideMenu overrides style settings
, {
"class": "nt_container"
, "showMenu": function( stage, event )
{
if( stage.className == "nt_date" ) return;
if( !hasNotis || menuShow ) return;
bodyStyle.marginLeft = "1em";
bodyStyle.marginRight = "-1em";
bodyStyle.opacity = 0;
bodyStyle.display = "block";
Cycle.next(function()
{
bodyStyle.marginLeft
= bodyStyle.marginRight = 0;
bodyStyle.opacity = 1;
menuShow = true;
});
}
, "hideMenu": function( stage )
{
if( stage.className == "nt_date" ) return;
if( !menuShow ) return;
bodyStyle.marginLeft = "1em";
bodyStyle.marginRight = "-1em";
bodyStyle.opacity = 0;
Cycle.delay(function()
{
bodyStyle.display = "none";
// cubic 200, we set delay to 200
menuShow = false;
}, 200);
}
// Prevent default subnode chaining
, "chainHide": function( stage ) { }
, "chainShow": function( stage ) { }
}
);
for( n in e.data )
{
/** @type {_AstJson_.AJaxGetNotis} */
var data = e.data[n];
var li = contextMenu.getItemByKey( "m_" + data.id ).stage;
li.appendChild(
Dand.wrapc(
"nt_date"
, smstamp( new Date( data.date ) )
)
);
}
};
postData( processor, { "action": "get" }, createContextMenu );
};
Bootstrap.regInit( init );
})();

View File

@ -0,0 +1,58 @@
.section-buttons > a {
display: inline-block;
position: relative;
color: white;
background-color: darkslategray;
margin: 0.5em 0.2em;
padding: 0.75em 0;
opacity: 0.5;
}
.section-buttons > a:hover, .section-buttons > a[data-active="1"]:hover {
opacity: 0.8;
text-decoration: none;
}
.section-buttons > a[data-name="blog"] {
background-color: purple;
}
.section-buttons > a[data-name="works"] {
background-color: royalblue;
}
.section-buttons > a[data-name="album"] {
background-color: crimson;
background-image:
repeating-linear-gradient(
45deg, transparent
, transparent 2px, rgba(0,0,0,.2) 2px
, rgba(0,0,0,.2) 3px, transparent 3px
, transparent 5px, rgba(0,0,0,.2) 5px
);
}
.section-buttons > a[data-name="lifestyle"] {
text-shadow: 1px 1px 1px black;
background-image:
repeating-linear-gradient(
-15deg
, orangered 0%, orangered 16.6%
, lawngreen 16.6%, lawngreen 33.2%
, turquoise 33.2%, turquoise 49.8%
, darkorchid 49.8%, darkorchid 66.6%
, violetred 66.6%, violetred 83.3%
, royalblue 83.3%, royalblue
);
}
.section-buttons > a > span {
padding: 0.75em 0.5em;
}
.section-buttons > a[data-active="1"] {
opacity: 1;
}
.section-buttons > a > .count {
background-color: rgba( 0, 0, 0, 0.3 );
}

View File

@ -0,0 +1 @@
// __namespace( "Astro.Blog.Components.Section" );

View File

@ -0,0 +1,17 @@
.site-file {
max-width: 100%;
height: auto;
}
.sf_regular sup { vertical-align: baseline; }
.sf_regular {
padding: 1em;
background-color: #F0F0F0;
display: inline-block;
}
.sf_failed {
color: orangered;
opacity: 0.5;
}
.sf_failed:hover { opacity: 1; }

View File

@ -0,0 +1,174 @@
(function(){
var ns = __namespace( "Astro.Blog.Components" );
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Astro.Bootstrap} */
var Bootstrap = __import( "Astro.Bootstrap" );
/** @type {Astro.Blog.Config} */
var Conf = __import( "Astro.Blog.Config" );
var getData = __import( "System.Net.getData" );
var getSMStamp = __import( "Astro.utils.Date.smstamp" );
/** @type {_AstConf_.SiteFile} */
var config = null;
var SiteFile = function ( id, hash, nObj )
{
if( !config ) throw new Error( "config is not defined" );
// TODO: Make a trigger for downloading from server
var stage = Dand.id( id );
if( !stage )
{
debug.Info( "[SiteFile] id not found: " + id );
return;
}
this.id = id;
this.hash = hash;
this.type = IDOMElement( stage ).getDAttribute( "type" );
if(!( this.type == "default" || this.type == null )) return this;
if( stage.getAttribute( "noauto" ) != null ) return this;
var applyStructure = function( obj )
{
return _applyStructure( JSON.parse( obj ).file );
};
var _applyStructure = function( obj )
{
/** @type {_AstJson_.SiteFile} */
var finfo = obj;
switch( finfo.type )
{
case "image":
var node = Dand.tag( "img", false, stage )[0];
switch( IDOMElement(stage).getDAttribute('size') )
{
case "small":
node.src = finfo.thumbs.small || ( config.path.image.small + hash + '.jpg' );
break;
case "medium":
node.src = finfo.thumbs.medium || ( config.path.image.medium + hash + '.jpg' );
break;
case "original":
node.src = config.path.image.original + hash + '.jpg';
break;
default: // large
node.src = finfo.thumbs.large || ( config.path.image.large + hash + '.jpg' );
}
stage.appendChild(Dand.wrapne(
'a', node
, [
new IKey( 'href', config.f_host + finfo.src_location )
, new IKey( 'title', finfo.name )
, new IKey( 'target', '_blank' )
]
));
break;
case "audio":
// TODO
break;
default:
// create a form to post hash string to php
var hash_field = Dand.wrapna(
'input', [ new IKey( 'type', 'hidden' ), new IKey( 'name', 'hash' ) ]
)
, name_field = Dand.wrapna(
'input', [ new IKey( 'type', 'hidden' ), new IKey( 'name', 'name' ) ]
)
, link = Dand.wrapne(
'a', 'download', new IKey( 'href', config.path.download + finfo.name )
)
, form = Dand.wrap(
'form', null, 'sf_regular'
, [ name_field, hash_field ]
, [
new IKey('target', '_blank')
, new IKey('action', config.path.download + finfo.name)
, new IKey('method', 'POST')
]
)
;
hash_field.value = hash;
name_field.value = finfo.name;
IDOMElement(link).addEventListener(
'Click'
, function(e) {
form.submit();
e.preventDefault();
return false;
}
);
// file name
form.appendChild( Dand.wrapne( 'span', 'File: ' + finfo.name) );
// download, submit button
form.appendChild( Dand.wrapne( 'sup', [ Dand.textNode(" ["), link, Dand.textNode("]") ] ) );
// hash
form.appendChild( Dand.wrapne( 'sup', Dand.wrape( 'MD5: ' + hash ) ) );
// date
form.appendChild( Dand.wrapne( 'sup', Dand.wrape( 'Date: ' + getSMStamp( new Date( finfo.date_created ) ) ) ) );
stage.appendChild(form);
}
};
var loadFailed = function( obj )
{
while( stage.hasChildNodes() ) stage.removeChild( stage.firstChild );
stage.appendChild( Dand.wrapc( "sf_failed", Dand.textNode( "Error: Failed to get resources info" ) ) );
};
if( nObj )
{
_applyStructure( nObj );
}
else
{
this.loadInfo( applyStructure, loadFailed );
}
};
SiteFile.prototype.loadInfo = function( success, failed )
{
getData( config.path.info + this.hash, success, failed );
};
var init = function()
{
config = Conf.get( "SiteFile" );
if( config )
{
var SFOs = Conf.get( "SFObjects" );
for( var i in SFOs )
{
var f = SFOs[i];
new SiteFile( f[0], f[1] );
}
}
};
Bootstrap.regInit( init );
ns[ NS_EXPORT ]( EX_CLASS, "SiteFile", SiteFile );
})();

View File

@ -0,0 +1,8 @@
.social_panel {
margin: 0.5em 0;
text-align: right;
}
.social_panel > div {
vertical-align: top;
}

View File

@ -0,0 +1,40 @@
(function(){
var ns = __namespace( "Astro.Blog.Components.SocialButtons" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {System.utils.IKey} */
var IKey = __import( "System.utils.IKey" );
/** @type {Astro.Bootstrap} */
var Bootstrap = __import( "Astro.Bootstrap" );
var init = function( id )
{
var s = Dand.tag( "script" )[0];
// Facebook
var fb = Dand.wrapna(
"script"
, IKey.quickDef(
"type" , 'text/javascript'
, "id" , 'facebook-jssdk'
, "src" , "//connect.facebook.net/en_US/all.js#xfbml=1"
)
);
// Google+
var gplus = Dand.wrapna(
"script"
, IKey.quickDef(
"type" , 'text/javascript'
, "async" , true
, "src" , "https://apis.google.com/js/plusone.js"
)
);
s.parentNode.insertBefore( fb, s );
s.parentNode.insertBefore( gplus, s );
};
Bootstrap.regInit( init );
})();

View File

@ -0,0 +1,35 @@
.spoiler {
}
.spoiler .title {
background: cornflowerblue;
color: white;
padding: 0.2em 0.5em;
cursor: default;
}
.spoiler .title:hover {
background: royalblue;
}
.spoiler .title[clicked] {
opacity: 0.8;
}
.spoiler .title:before {
padding-right: 0.5em;
content: "\25BC";
font-size: 0.75em;
}
.spoiler .title[clicked]:before {
content: "\25B2";
}
.spoiler .content {
padding: 0.5em;
font-size: 0.9em;
line-height: 1.2em;
background-color: rgba( 0, 0, 0, 0.02 );
display: none;
}

View File

@ -0,0 +1,49 @@
(function(){
var ns = __namespace( "Astro.Blog.Components.Spoiler" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Astro.Bootstrap} */
var Bootstrap = __import( "Astro.Bootstrap" );
/** @type {Astro.Blog.Config} */
var Config = __import( "Astro.Blog.Config" );
var Spoiler = function( id )
{
var sp_stage = Dand.id( "spoiler_" + id );
var sp_display = ( sp_stage.nodeName == "span" ) ? "inline-block" : "block";
var ostage = IDOMElement( sp_stage );
var sp_title = ostage.first( "DIV" );
var sp_content = ostage.last( "DIV" );
sp_title.onclick = function ()
{
var s_style = sp_content.style;
if( s_style.display == sp_display )
{
s_style.display = "none";
sp_title.removeAttribute( "clicked" );
}
else
{
s_style.display = sp_display;
sp_title.setAttribute( "clicked", "" );
}
};
sp_stage.hasAttribute( "expanded" ) && sp_title.onclick();
};
var sps = Config.get( "Spoiler" );
Bootstrap.regInit(function() {
for( var i in sps )
{
new Spoiler( sps[i] );
}
});
})();

View File

@ -0,0 +1,24 @@
.tag-ctrl .title {
font-size: 1.5em;
color: #444;
clear: both;
}
.tag-ctrl {
white-space-collapse: discard;
}
.tag-ctrl > div > div {
padding: 0.2em 0;
float: left;
}
.tag-ctrl > div > div > a {
padding: 0 0.2em;
}
.tag-ctrl > div > div > a:first-child:hover {
color: white;
background: purple;
text-decoration: none;
}

View File

@ -0,0 +1 @@
// __namespace( "Astro.Blog.Components.TagControl" );

View File

@ -0,0 +1,46 @@
.b_notify { background-color: #222 !important; }
.b_notify:before { content: 'Mute'; }
.b_notify:after { content: 'Notify'; }
.uc_ntoggle {
font-family: custom-sans;
vertical-align: top;
padding: 0.2em 0em;
}
.uc_ntoggle:before { content: '..'; }
.uc_ntoggle:after { content: '!'; }
.cr_ntoggle {
font-family: custom-sans;
padding: 0;
margin: 0;
position: absolute;
width: 1.5em;
height: 1.5em;
bottom: 0;
right: -3em;
border-radius: 2em 2em 2em 0em;
border: 0.5em solid white;
line-height: 1.5em !important;
background-color: white;
/* box-shadow: 2px 2px 10px -5px black; */
}
.cr_ntoggle:before, .cr_ntoggle:after {
padding: 0;
border-radius: 2em;
}
.cr_ntoggle:before {
content: '..';
background-color: orange;
}
.cr_ntoggle:after { content: '!'; }

View File

@ -0,0 +1,35 @@
(function(){
var ns = __namespace( "Astro.Blog.Components.ToggleButton.CommentToggle" );
var ToggleButton = __import( "Astro.Blog.Components.ToggleButton" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Astro.Bootstrap} */
var Bootstrap = __import( "Astro.Bootstrap" );
/** @type {Astro.Blog.Config} */
var Conf = __import( "Astro.Blog.Config" );
/** @type {_AstConf_.CommentToggle} */
var settings = Conf.get( "CommentToggle" );
var CommentToggle = function( id, processor, object )
{
ToggleButton.call( this, id, processor, object );
};
__extends( CommentToggle, ToggleButton );
var init = function()
{
for( var i in settings )
{
var button = settings[i];
new CommentToggle( button[0], button[1], button[2] );
}
}
Bootstrap.regInit( init );
})();

View File

@ -0,0 +1,42 @@
.b_button {
position: relative;
font-family: custom-sans;
font-size: 1em;
padding: 0.2em 0.5em;
margin: 0.5em 0.2em;
background-color: grey;
color: white;
cursor: default;
float: right;
}
.b_delete {
color: crimson;
background-color: crimson;
position: relative;
}
.b_delete:after {
content: "\2715";
color: white;
position: absolute;
width: 100%;
height: 100%;
text-align: center;
padding-top: 0.15em;
top: 0;
right: 0;
}
.b_delete:hover:after {
text-decoration: underline;
}
.b_scope { background-color: slategrey; }
.b_scope:before { content: 'Private'; background-color: purple; }
.b_scope:after { content: 'Public'; background-color: orangered; }

View File

@ -0,0 +1,50 @@
(function(){
var ns = __namespace( "Astro.Blog.Components.ToggleButton.DeleteArticle" );
/** @type {Components.MessageBox} */
var MessageBox = __import( "Components.MessageBox" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Astro.Bootstrap} */
var Bootstrap = __import( "Astro.Bootstrap" );
var postData = __import( "System.Net.postData" );
var init = function()
{
var aid = Dand.id( "b_entry", true ).getDAttribute( "aid" );
var stage = Dand.glass( "b_delete", true, Dand.id( "b_entry" ) );
if( !stage.length ) return;
stage = stage[0];
var doDelete = function( confirmed )
{
var a_deleteSuccess = function( args ) { window.location.reload( true ); };
var a_deleteFailed = function( args ) { };
if( confirmed ) postData(
"/ajax/del-article"
, { "article_id": aid }
, a_deleteSuccess
, a_deleteFailed
);
};
stage.addEventListener(
'Click'
, function (e) {
new MessageBox(
"Confirm"
, "Are you sure you want to delete this article?. Comments will also be deleted!"
, "Yes", "No"
, doDelete
).show();
}
);
};
Bootstrap.regInit( init );
})();

View File

@ -0,0 +1,85 @@
.btn_toggle {
position: relative;
font-family: serif;
font-size: 1em;
padding: 0.2em 0.5em;
margin: 0.5em 0.2em;
background-color: #222;
color: white;
cursor: default;
overflow: hidden;
display: inline-block;
opacity: 0.8;
}
.btn_toggle > .btn_space {
visibility: hidden;
padding: 0 0.5em;
}
.btn_toggle:hover {
opacity: 1;
text-decoration: none;
}
.btn_toggle:hover:before, .btn_toggle:hover:after {
text-decoration: underline;
}
.btn_toggle:before, .btn_toggle:after {
text-align: center;
position: absolute;
padding-top: 0.15em;
width: 100%;
height: 100%;
top: 0;
left: 0;
-webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
-moz-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
-ms-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
-o-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
}
.btn_toggle:before {
content: '';
top: 0%;
-webkit-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
-moz-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
-ms-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
-o-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
}
.btn_toggle:after {
content: '';
background-color: #4169E1;
top: 100%;
-webkit-transition: all 750ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
-moz-transition: all 750ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
-ms-transition: all 750ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
-o-transition: all 750ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
}
.btn_toggle[data-active="1"]:after {
top: 0%;
}
.btn_toggle[data-active="1"]:before {
top: -100%;
}

View File

@ -0,0 +1,65 @@
(function(){
var ns = __namespace( "Astro.Blog.Components" );
/** @type {Dandelion} */
var Dand = __import( "Dandelion" );
/** @type {Dandelion.IDOMElement} */
var IDOMElement = __import( "Dandelion.IDOMElement" );
/** @type {Astro.Bootstrap} */
var Bootstrap = __import( "Astro.Bootstrap" );
/** @type {Astro.Blog} */
var config = __import( "Astro.Blog.Config" );
/** @type {System.utils.DataKey} */
var DataKey = __import( "System.utils.DataKey" );
var postData = __import( "System.Net.postData" );
var ToggleButton = function ( elem, processor, obj )
{
var stage = Dand.id( elem, true );
if( !stage ) return;
var n_toggle = function (args)
{
if( stage.getDAttribute("active") == 1 )
{
stage.setAttribute( new DataKey( "active", 0 ) );
}
else
{
stage.setAttribute( new DataKey( "active", 1 ) );
}
};
var nError = function (args)
{
};
stage.addEventListener(
"Click"
, function (e) {
var _action = stage.getDAttribute( "active" ) == 1
? obj[ "disable" ]
: obj[ "enable" ]
;
postData( processor, _action, n_toggle, nError );
}
);
};
var init = function()
{
var toggles = config.get( "ToggleButtons" );
for( var i in toggles )
{
new ToggleButton( toggles[ i ][0], toggles[ i ][1], toggles[ i ][2] );
}
};
Bootstrap.regInit( init );
ns[ NS_EXPORT ]( EX_CLASS, "ToggleButton", ToggleButton );
})();

Some files were not shown because too many files have changed in this diff Show More