git ssb

0+

k4ml / belajar-js



Commit 0e4c66532895ce03fe710648bbd4aee0648ed182

New MyDev website content based on Jekyll

Ikhwan Hayat committed on 1/18/2015, 1:31:14 AM
Parent: e2c09fc58509d520fc6c34e591c0faf0b890b38c

Files changed

README.mdchanged
index.htmlchanged
.gitignoreadded
images/bg_hr.pngdeleted
images/blacktocat.pngdeleted
images/icon_download.pngdeleted
images/sprite_download.pngdeleted
404.htmladded
CNAMEadded
javascripts/main.jsdeleted
Gemfileadded
params.jsondeleted
Gemfile.lockadded
stylesheets/pygment_trac.cssdeleted
stylesheets/stylesheet.cssdeleted
LICENSE.mdadded
_config.ymladded
_includes/head.htmladded
_includes/sidebar.htmladded
_includes/toc.htmladded
_layouts/default.htmladded
_layouts/page.htmladded
_layouts/post.htmladded
_posts/2012-12-15-automated-testing.mdadded
_posts/2012-12-22-buku-pilihan.mdadded
_posts/2012-12-28-jargon-pengaturcaraan.mdadded
_posts/2013-03-22-memahami-dependency-injection.mdadded
_posts/2014-09-13-memahami-session.mdadded
_posts/2014-09-15-belajar-javascript-part-1.mdadded
_posts/2014-11-04-belajar-javascript-part-2.mdadded
_posts/2014-11-09-belajar-javascript-part-3.mdadded
about.mdadded
archive.htmladded
atom.xmladded
authors.htmladded
public/apple-touch-icon-144-precomposed.pngadded
public/css/custom.cssadded
public/css/hyde.cssadded
public/css/poole.cssadded
public/css/syntax.cssadded
public/favicon.icoadded
public/js/toc.jsadded
README.mdView
@@ -1,4 +1,14 @@
1-mydevcommunity.github.io
2-========================
1+Kod sumber untuk laman kolaboratif [www.mydev.my][1].
32
4-Stub site
3+[![Build Status](https://travis-ci.org/mydevcommunity/mydev.png)](https://travis-ci.org/mydevcommunity/mydev)
4+
5+## Maklumat Ringkas
6+
7+* [Latar belakang permulaan projek ini][2]
8+* [Bagaimana hendak menyumbang][3]
9+* [Integrasi dengan Travis-CI][4]
10+
11+[1]:http://www.mydev.my/
12+[2]:https://plus.google.com/115371258798208681274/posts/AriuBixckCX
13+[3]:https://plus.google.com/105721265741813048018/posts/TwdRGBimcvP
14+[4]:https://plus.google.com/115371258798208681274/posts/aa4RJRHXDNo
index.htmlView
@@ -1,74 +1,47 @@
1-<!DOCTYPE html>
2-<html>
1+---
2+layout: default
3+title: Home
4+---
35
4- <head>
5- <meta charset='utf-8'>
6- <meta http-equiv="X-UA-Compatible" content="chrome=1">
7- <meta name="description" content="Mydevcommunity.github.io : Stub site">
6+<div class="posts">
7+ {% for post in paginator.posts %}
8+ <div class="post">
9+ <h1 class="post-title">
10+ <a href="{{ site.baseurl}}{{ post.url }}">
11+ {{ post.title }}
12+ </a>
13+ </h1>
814
9- <link rel="stylesheet" type="text/css" media="screen" href="stylesheets/stylesheet.css">
15+ <span class="post-date">
16+ Ditulis pada {{ post.date | date_to_string }}
1017
11- <title>Mydevcommunity.github.io</title>
12- </head>
18+ {% assign author = site.authors[post.author] %}
19+ {% if author %}
20+ <span> oleh {{ author.name }}</span>
21+ {% endif %}
22+ </span>
1323
14- <body>
24+ <p>
25+ {{ post.excerpt : | remove: '<p>' | remove: '</p>' }}<span>&#8230; <a href="{{ site.baseurl}}{{ post.url }}">(artikel penuh)</a></span>
26+ </p>
1527
16- <!-- HEADER -->
17- <div id="header_wrap" class="outer">
18- <header class="inner">
19- <a id="forkme_banner" href="https://github.com/mydevcommunity">View on GitHub</a>
28+ </div>
29+ {% endfor %}
30+</div>
2031
21- <h1 id="project_title">Mydevcommunity.github.io</h1>
22- <h2 id="project_tagline">Stub site</h2>
23-
24- </header>
25- </div>
26-
27- <!-- MAIN CONTENT -->
28- <div id="main_content_wrap" class="outer">
29- <section id="main_content" class="inner">
30- <h3>
31-<a name="welcome-to-github-pages" class="anchor" href="#welcome-to-github-pages"><span class="octicon octicon-link"></span></a>Welcome to GitHub Pages.</h3>
32-
33-<p>This automatic page generator is the easiest way to create beautiful pages for all of your projects. Author your page content here using GitHub Flavored Markdown, select a template crafted by a designer, and publish. After your page is generated, you can check out the new branch:</p>
34-
35-<pre><code>$ cd your_repo_root/repo_name
36-$ git fetch origin
37-$ git checkout gh-pages
38-</code></pre>
39-
40-<p>If you're using the GitHub for Mac, simply sync your repository and you'll see the new branch.</p>
41-
42-<h3>
43-<a name="designer-templates" class="anchor" href="#designer-templates"><span class="octicon octicon-link"></span></a>Designer Templates</h3>
44-
45-<p>We've crafted some handsome templates for you to use. Go ahead and continue to layouts to browse through them. You can easily go back to edit your page before publishing. After publishing your page, you can revisit the page generator and switch to another theme. Your Page content will be preserved if it remained markdown format.</p>
46-
47-<h3>
48-<a name="rather-drive-stick" class="anchor" href="#rather-drive-stick"><span class="octicon octicon-link"></span></a>Rather Drive Stick?</h3>
49-
50-<p>If you prefer to not use the automatic generator, push a branch named <code>gh-pages</code> to your repository to create a page manually. In addition to supporting regular HTML content, GitHub Pages support Jekyll, a simple, blog aware static site generator written by our own Tom Preston-Werner. Jekyll makes it easy to create site-wide headers and footers without having to copy them across every page. It also offers intelligent blog support and other advanced templating features.</p>
51-
52-<h3>
53-<a name="authors-and-contributors" class="anchor" href="#authors-and-contributors"><span class="octicon octicon-link"></span></a>Authors and Contributors</h3>
54-
55-<p>You can <a href="https://github.com/blog/821" class="user-mention">@mention</a> a GitHub username to generate a link to their profile. The resulting <code>&lt;a&gt;</code> element will link to the contributor's GitHub Profile. For example: In 2007, Chris Wanstrath (<a href="https://github.com/defunkt" class="user-mention">@defunkt</a>), PJ Hyett (<a href="https://github.com/pjhyett" class="user-mention">@pjhyett</a>), and Tom Preston-Werner (<a href="https://github.com/mojombo" class="user-mention">@mojombo</a>) founded GitHub.</p>
56-
57-<h3>
58-<a name="support-or-contact" class="anchor" href="#support-or-contact"><span class="octicon octicon-link"></span></a>Support or Contact</h3>
59-
60-<p>Having trouble with Pages? Check out the documentation at <a href="http://help.github.com/pages">http://help.github.com/pages</a> or contact <a href="mailto:support@github.com">support@github.com</a> and we’ll help you sort it out.</p>
61- </section>
62- </div>
63-
64- <!-- FOOTER -->
65- <div id="footer_wrap" class="outer">
66- <footer class="inner">
67- <p>Published with <a href="http://pages.github.com">GitHub Pages</a></p>
68- </footer>
69- </div>
70-
71-
72-
73- </body>
74-</html>
32+<div class="pagination">
33+ {% if paginator.next_page %}
34+ <a class="pagination-item older" href="{{ site.baseurl }}/page{{paginator.next_page}}">&laquo;</a>
35+ {% else %}
36+ <span class="pagination-item older">&laquo;</span>
37+ {% endif %}
38+ {% if paginator.previous_page %}
39+ {% if paginator.page == 2 %}
40+ <a class="pagination-item newer" href="{{ site.baseurl }}/">&raquo;</a>
41+ {% else %}
42+ <a class="pagination-item newer" href="{{ site.baseurl }}/page{{paginator.previous_page}}">&raquo;</a>
43+ {% endif %}
44+ {% else %}
45+ <span class="pagination-item newer">&raquo;</span>
46+ {% endif %}
47+</div>
.gitignoreView
@@ -1,0 +1,41 @@
1+# Ignore docs files
2+_gh_pages
3+_site
4+.ruby-version
5+
6+# Numerous always-ignore extensions
7+*.diff
8+*.err
9+*.orig
10+*.log
11+*.rej
12+*.swo
13+*.swp
14+*.zip
15+*.vi
16+*~
17+
18+# OS or Editor folders
19+.DS_Store
20+._*
21+Thumbs.db
22+.cache
23+.project
24+.settings
25+.tmproj
26+*.esproj
27+nbproject
28+*.sublime-project
29+*.sublime-workspace
30+.idea
31+
32+# Komodo
33+*.komodoproject
34+.komodotools
35+
36+# grunt-html-validation
37+validation-status.json
38+validation-report.json
39+
40+# Folders to ignore
41+node_modules
images/bg_hr.png
images/bg_hr.png
images/blacktocat.png
images/blacktocat.png
images/icon_download.png
images/icon_download.png
images/sprite_download.png
images/sprite_download.png
404.htmlView
@@ -1,0 +1,10 @@
1+---
2+layout: default
3+title: "404: Page not found"
4+permalink: 404.html
5+---
6+
7+<div class="page">
8+ <h1 class="page-title">404: Page not found</h1>
9+ <p class="lead">Sorry, we've misplaced that URL or it's pointing to something that doesn't exist. <a href="{{ site.baseurl }}">Head back home</a> to try finding it again.</p>
10+</div>
CNAMEView
@@ -1,0 +1,1 @@
1+www.mydev.my
javascripts/main.jsView
@@ -1,1 +1,0 @@
1-console.log('This would be the main JS file.');
GemfileView
@@ -1,0 +1,3 @@
1+source 'https://rubygems.org'
2+gem 'github-pages'
3+gem 'wdm', '~> 0.1.0' if Gem.win_platform?
params.jsonView
@@ -1,1 +1,0 @@
1-{"name":"Mydevcommunity.github.io","tagline":"Stub site","body":"### Welcome to GitHub Pages.\r\nThis automatic page generator is the easiest way to create beautiful pages for all of your projects. Author your page content here using GitHub Flavored Markdown, select a template crafted by a designer, and publish. After your page is generated, you can check out the new branch:\r\n\r\n```\r\n$ cd your_repo_root/repo_name\r\n$ git fetch origin\r\n$ git checkout gh-pages\r\n```\r\n\r\nIf you're using the GitHub for Mac, simply sync your repository and you'll see the new branch.\r\n\r\n### Designer Templates\r\nWe've crafted some handsome templates for you to use. Go ahead and continue to layouts to browse through them. You can easily go back to edit your page before publishing. After publishing your page, you can revisit the page generator and switch to another theme. Your Page content will be preserved if it remained markdown format.\r\n\r\n### Rather Drive Stick?\r\nIf you prefer to not use the automatic generator, push a branch named `gh-pages` to your repository to create a page manually. In addition to supporting regular HTML content, GitHub Pages support Jekyll, a simple, blog aware static site generator written by our own Tom Preston-Werner. Jekyll makes it easy to create site-wide headers and footers without having to copy them across every page. It also offers intelligent blog support and other advanced templating features.\r\n\r\n### Authors and Contributors\r\nYou can @mention a GitHub username to generate a link to their profile. The resulting `<a>` element will link to the contributor's GitHub Profile. For example: In 2007, Chris Wanstrath (@defunkt), PJ Hyett (@pjhyett), and Tom Preston-Werner (@mojombo) founded GitHub.\r\n\r\n### Support or Contact\r\nHaving trouble with Pages? Check out the documentation at http://help.github.com/pages or contact support@github.com and we’ll help you sort it out.\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."}
Gemfile.lockView
@@ -1,0 +1,128 @@
1+GEM
2+ remote: https://rubygems.org/
3+ specs:
4+ RedCloth (4.2.9)
5+ activesupport (4.2.0)
6+ i18n (~> 0.7)
7+ json (~> 1.7, >= 1.7.7)
8+ minitest (~> 5.1)
9+ thread_safe (~> 0.3, >= 0.3.4)
10+ tzinfo (~> 1.1)
11+ blankslate (2.1.2.4)
12+ celluloid (0.16.0)
13+ timers (~> 4.0.0)
14+ classifier-reborn (2.0.3)
15+ fast-stemmer (~> 1.0)
16+ coffee-script (2.3.0)
17+ coffee-script-source
18+ execjs
19+ coffee-script-source (1.8.0)
20+ colorator (0.1)
21+ execjs (2.2.2)
22+ fast-stemmer (1.0.2)
23+ ffi (1.9.6-x64-mingw32)
24+ gemoji (2.1.0)
25+ github-pages (31)
26+ RedCloth (= 4.2.9)
27+ github-pages-health-check (~> 0.2)
28+ jekyll (= 2.4.0)
29+ jekyll-coffeescript (= 1.0.1)
30+ jekyll-mentions (= 0.2.1)
31+ jekyll-redirect-from (= 0.6.2)
32+ jekyll-sass-converter (= 1.2.0)
33+ jekyll-sitemap (= 0.6.3)
34+ jemoji (= 0.4.0)
35+ kramdown (= 1.3.1)
36+ liquid (= 2.6.1)
37+ maruku (= 0.7.0)
38+ mercenary (~> 0.3)
39+ pygments.rb (= 0.6.0)
40+ rdiscount (= 2.1.7)
41+ redcarpet (= 3.1.2)
42+ terminal-table (~> 1.4)
43+ github-pages-health-check (0.2.1)
44+ net-dns (~> 0.6)
45+ public_suffix (~> 1.4)
46+ hitimes (1.2.2)
47+ html-pipeline (1.9.0)
48+ activesupport (>= 2)
49+ nokogiri (~> 1.4)
50+ i18n (0.7.0)
51+ jekyll (2.4.0)
52+ classifier-reborn (~> 2.0)
53+ colorator (~> 0.1)
54+ jekyll-coffeescript (~> 1.0)
55+ jekyll-gist (~> 1.0)
56+ jekyll-paginate (~> 1.0)
57+ jekyll-sass-converter (~> 1.0)
58+ jekyll-watch (~> 1.1)
59+ kramdown (~> 1.3)
60+ liquid (~> 2.6.1)
61+ mercenary (~> 0.3.3)
62+ pygments.rb (~> 0.6.0)
63+ redcarpet (~> 3.1)
64+ safe_yaml (~> 1.0)
65+ toml (~> 0.1.0)
66+ jekyll-coffeescript (1.0.1)
67+ coffee-script (~> 2.2)
68+ jekyll-gist (1.1.0)
69+ jekyll-mentions (0.2.1)
70+ html-pipeline (~> 1.9.0)
71+ jekyll (~> 2.0)
72+ jekyll-paginate (1.1.0)
73+ jekyll-redirect-from (0.6.2)
74+ jekyll (~> 2.0)
75+ jekyll-sass-converter (1.2.0)
76+ sass (~> 3.2)
77+ jekyll-sitemap (0.6.3)
78+ jekyll-watch (1.2.0)
79+ listen (~> 2.7)
80+ jemoji (0.4.0)
81+ gemoji (~> 2.0)
82+ html-pipeline (~> 1.9)
83+ jekyll (~> 2.0)
84+ json (1.8.2)
85+ kramdown (1.3.1)
86+ liquid (2.6.1)
87+ listen (2.8.5)
88+ celluloid (>= 0.15.2)
89+ rb-fsevent (>= 0.9.3)
90+ rb-inotify (>= 0.9)
91+ maruku (0.7.0)
92+ mercenary (0.3.5)
93+ mini_portile (0.6.2)
94+ minitest (5.5.1)
95+ net-dns (0.8.0)
96+ nokogiri (1.6.5-x64-mingw32)
97+ mini_portile (~> 0.6.0)
98+ parslet (1.5.0)
99+ blankslate (~> 2.0)
100+ posix-spawn (0.3.9)
101+ public_suffix (1.4.6)
102+ pygments.rb (0.6.0)
103+ posix-spawn (~> 0.3.6)
104+ yajl-ruby (~> 1.1.0)
105+ rb-fsevent (0.9.4)
106+ rb-inotify (0.9.5)
107+ ffi (>= 0.5.0)
108+ rdiscount (2.1.7)
109+ redcarpet (3.1.2)
110+ safe_yaml (1.0.4)
111+ sass (3.4.10)
112+ terminal-table (1.4.5)
113+ thread_safe (0.3.4)
114+ timers (4.0.1)
115+ hitimes
116+ toml (0.1.2)
117+ parslet (~> 1.5.0)
118+ tzinfo (1.2.2)
119+ thread_safe (~> 0.1)
120+ wdm (0.1.0)
121+ yajl-ruby (1.1.0)
122+
123+PLATFORMS
124+ x64-mingw32
125+
126+DEPENDENCIES
127+ github-pages
128+ wdm (~> 0.1.0)
stylesheets/pygment_trac.cssView
@@ -1,70 +1,0 @@
1-.highlight .hll { background-color: #ffffcc }
2-.highlight { background: #f0f3f3; }
3-.highlight .c { color: #0099FF; font-style: italic } /* Comment */
4-.highlight .err { color: #AA0000; background-color: #FFAAAA } /* Error */
5-.highlight .k { color: #006699; font-weight: bold } /* Keyword */
6-.highlight .o { color: #555555 } /* Operator */
7-.highlight .cm { color: #0099FF; font-style: italic } /* Comment.Multiline */
8-.highlight .cp { color: #009999 } /* Comment.Preproc */
9-.highlight .c1 { color: #0099FF; font-style: italic } /* Comment.Single */
10-.highlight .cs { color: #0099FF; font-weight: bold; font-style: italic } /* Comment.Special */
11-.highlight .gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */
12-.highlight .ge { font-style: italic } /* Generic.Emph */
13-.highlight .gr { color: #FF0000 } /* Generic.Error */
14-.highlight .gh { color: #003300; font-weight: bold } /* Generic.Heading */
15-.highlight .gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */
16-.highlight .go { color: #AAAAAA } /* Generic.Output */
17-.highlight .gp { color: #000099; font-weight: bold } /* Generic.Prompt */
18-.highlight .gs { font-weight: bold } /* Generic.Strong */
19-.highlight .gu { color: #003300; font-weight: bold } /* Generic.Subheading */
20-.highlight .gt { color: #99CC66 } /* Generic.Traceback */
21-.highlight .kc { color: #006699; font-weight: bold } /* Keyword.Constant */
22-.highlight .kd { color: #006699; font-weight: bold } /* Keyword.Declaration */
23-.highlight .kn { color: #006699; font-weight: bold } /* Keyword.Namespace */
24-.highlight .kp { color: #006699 } /* Keyword.Pseudo */
25-.highlight .kr { color: #006699; font-weight: bold } /* Keyword.Reserved */
26-.highlight .kt { color: #007788; font-weight: bold } /* Keyword.Type */
27-.highlight .m { color: #FF6600 } /* Literal.Number */
28-.highlight .s { color: #CC3300 } /* Literal.String */
29-.highlight .na { color: #330099 } /* Name.Attribute */
30-.highlight .nb { color: #336666 } /* Name.Builtin */
31-.highlight .nc { color: #00AA88; font-weight: bold } /* Name.Class */
32-.highlight .no { color: #336600 } /* Name.Constant */
33-.highlight .nd { color: #9999FF } /* Name.Decorator */
34-.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
35-.highlight .ne { color: #CC0000; font-weight: bold } /* Name.Exception */
36-.highlight .nf { color: #CC00FF } /* Name.Function */
37-.highlight .nl { color: #9999FF } /* Name.Label */
38-.highlight .nn { color: #00CCFF; font-weight: bold } /* Name.Namespace */
39-.highlight .nt { color: #330099; font-weight: bold } /* Name.Tag */
40-.highlight .nv { color: #003333 } /* Name.Variable */
41-.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */
42-.highlight .w { color: #bbbbbb } /* Text.Whitespace */
43-.highlight .mf { color: #FF6600 } /* Literal.Number.Float */
44-.highlight .mh { color: #FF6600 } /* Literal.Number.Hex */
45-.highlight .mi { color: #FF6600 } /* Literal.Number.Integer */
46-.highlight .mo { color: #FF6600 } /* Literal.Number.Oct */
47-.highlight .sb { color: #CC3300 } /* Literal.String.Backtick */
48-.highlight .sc { color: #CC3300 } /* Literal.String.Char */
49-.highlight .sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */
50-.highlight .s2 { color: #CC3300 } /* Literal.String.Double */
51-.highlight .se { color: #CC3300; font-weight: bold } /* Literal.String.Escape */
52-.highlight .sh { color: #CC3300 } /* Literal.String.Heredoc */
53-.highlight .si { color: #AA0000 } /* Literal.String.Interpol */
54-.highlight .sx { color: #CC3300 } /* Literal.String.Other */
55-.highlight .sr { color: #33AAAA } /* Literal.String.Regex */
56-.highlight .s1 { color: #CC3300 } /* Literal.String.Single */
57-.highlight .ss { color: #FFCC33 } /* Literal.String.Symbol */
58-.highlight .bp { color: #336666 } /* Name.Builtin.Pseudo */
59-.highlight .vc { color: #003333 } /* Name.Variable.Class */
60-.highlight .vg { color: #003333 } /* Name.Variable.Global */
61-.highlight .vi { color: #003333 } /* Name.Variable.Instance */
62-.highlight .il { color: #FF6600 } /* Literal.Number.Integer.Long */
63-
64-.type-csharp .highlight .k { color: #0000FF }
65-.type-csharp .highlight .kt { color: #0000FF }
66-.type-csharp .highlight .nf { color: #000000; font-weight: normal }
67-.type-csharp .highlight .nc { color: #2B91AF }
68-.type-csharp .highlight .nn { color: #000000 }
69-.type-csharp .highlight .s { color: #A31515 }
70-.type-csharp .highlight .sc { color: #A31515 }
stylesheets/stylesheet.cssView
@@ -1,423 +1,0 @@
1-/*******************************************************************************
2-Slate Theme for GitHub Pages
3-by Jason Costello, @jsncostello
4-*******************************************************************************/
5-
6-@import url(pygment_trac.css);
7-
8-/*******************************************************************************
9-MeyerWeb Reset
10-*******************************************************************************/
11-
12-html, body, div, span, applet, object, iframe,
13-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
14-a, abbr, acronym, address, big, cite, code,
15-del, dfn, em, img, ins, kbd, q, s, samp,
16-small, strike, strong, sub, sup, tt, var,
17-b, u, i, center,
18-dl, dt, dd, ol, ul, li,
19-fieldset, form, label, legend,
20-table, caption, tbody, tfoot, thead, tr, th, td,
21-article, aside, canvas, details, embed,
22-figure, figcaption, footer, header, hgroup,
23-menu, nav, output, ruby, section, summary,
24-time, mark, audio, video {
25- margin: 0;
26- padding: 0;
27- border: 0;
28- font: inherit;
29- vertical-align: baseline;
30-}
31-
32-/* HTML5 display-role reset for older browsers */
33-article, aside, details, figcaption, figure,
34-footer, header, hgroup, menu, nav, section {
35- display: block;
36-}
37-
38-ol, ul {
39- list-style: none;
40-}
41-
42-table {
43- border-collapse: collapse;
44- border-spacing: 0;
45-}
46-
47-/*******************************************************************************
48-Theme Styles
49-*******************************************************************************/
50-
51-body {
52- box-sizing: border-box;
53- color:#373737;
54- background: #212121;
55- font-size: 16px;
56- font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif;
57- line-height: 1.5;
58- -webkit-font-smoothing: antialiased;
59-}
60-
61-h1, h2, h3, h4, h5, h6 {
62- margin: 10px 0;
63- font-weight: 700;
64- color:#222222;
65- font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif;
66- letter-spacing: -1px;
67-}
68-
69-h1 {
70- font-size: 36px;
71- font-weight: 700;
72-}
73-
74-h2 {
75- padding-bottom: 10px;
76- font-size: 32px;
77- background: url('../images/bg_hr.png') repeat-x bottom;
78-}
79-
80-h3 {
81- font-size: 24px;
82-}
83-
84-h4 {
85- font-size: 21px;
86-}
87-
88-h5 {
89- font-size: 18px;
90-}
91-
92-h6 {
93- font-size: 16px;
94-}
95-
96-p {
97- margin: 10px 0 15px 0;
98-}
99-
100-footer p {
101- color: #f2f2f2;
102-}
103-
104-a {
105- text-decoration: none;
106- color: #007edf;
107- text-shadow: none;
108-
109- transition: color 0.5s ease;
110- transition: text-shadow 0.5s ease;
111- -webkit-transition: color 0.5s ease;
112- -webkit-transition: text-shadow 0.5s ease;
113- -moz-transition: color 0.5s ease;
114- -moz-transition: text-shadow 0.5s ease;
115- -o-transition: color 0.5s ease;
116- -o-transition: text-shadow 0.5s ease;
117- -ms-transition: color 0.5s ease;
118- -ms-transition: text-shadow 0.5s ease;
119-}
120-
121-a:hover, a:focus {text-decoration: underline;}
122-
123-footer a {
124- color: #F2F2F2;
125- text-decoration: underline;
126-}
127-
128-em {
129- font-style: italic;
130-}
131-
132-strong {
133- font-weight: bold;
134-}
135-
136-img {
137- position: relative;
138- margin: 0 auto;
139- max-width: 739px;
140- padding: 5px;
141- margin: 10px 0 10px 0;
142- border: 1px solid #ebebeb;
143-
144- box-shadow: 0 0 5px #ebebeb;
145- -webkit-box-shadow: 0 0 5px #ebebeb;
146- -moz-box-shadow: 0 0 5px #ebebeb;
147- -o-box-shadow: 0 0 5px #ebebeb;
148- -ms-box-shadow: 0 0 5px #ebebeb;
149-}
150-
151-p img {
152- display: inline;
153- margin: 0;
154- padding: 0;
155- vertical-align: middle;
156- text-align: center;
157- border: none;
158-}
159-
160-pre, code {
161- width: 100%;
162- color: #222;
163- background-color: #fff;
164-
165- font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
166- font-size: 14px;
167-
168- border-radius: 2px;
169- -moz-border-radius: 2px;
170- -webkit-border-radius: 2px;
171-}
172-
173-pre {
174- width: 100%;
175- padding: 10px;
176- box-shadow: 0 0 10px rgba(0,0,0,.1);
177- overflow: auto;
178-}
179-
180-code {
181- padding: 3px;
182- margin: 0 3px;
183- box-shadow: 0 0 10px rgba(0,0,0,.1);
184-}
185-
186-pre code {
187- display: block;
188- box-shadow: none;
189-}
190-
191-blockquote {
192- color: #666;
193- margin-bottom: 20px;
194- padding: 0 0 0 20px;
195- border-left: 3px solid #bbb;
196-}
197-
198-
199-ul, ol, dl {
200- margin-bottom: 15px
201-}
202-
203-ul {
204- list-style: inside;
205- padding-left: 20px;
206-}
207-
208-ol {
209- list-style: decimal inside;
210- padding-left: 20px;
211-}
212-
213-dl dt {
214- font-weight: bold;
215-}
216-
217-dl dd {
218- padding-left: 20px;
219- font-style: italic;
220-}
221-
222-dl p {
223- padding-left: 20px;
224- font-style: italic;
225-}
226-
227-hr {
228- height: 1px;
229- margin-bottom: 5px;
230- border: none;
231- background: url('../images/bg_hr.png') repeat-x center;
232-}
233-
234-table {
235- border: 1px solid #373737;
236- margin-bottom: 20px;
237- text-align: left;
238- }
239-
240-th {
241- font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
242- padding: 10px;
243- background: #373737;
244- color: #fff;
245- }
246-
247-td {
248- padding: 10px;
249- border: 1px solid #373737;
250- }
251-
252-form {
253- background: #f2f2f2;
254- padding: 20px;
255-}
256-
257-/*******************************************************************************
258-Full-Width Styles
259-*******************************************************************************/
260-
261-.outer {
262- width: 100%;
263-}
264-
265-.inner {
266- position: relative;
267- max-width: 640px;
268- padding: 20px 10px;
269- margin: 0 auto;
270-}
271-
272-#forkme_banner {
273- display: block;
274- position: absolute;
275- top:0;
276- right: 10px;
277- z-index: 10;
278- padding: 10px 50px 10px 10px;
279- color: #fff;
280- background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%;
281- font-weight: 700;
282- box-shadow: 0 0 10px rgba(0,0,0,.5);
283- border-bottom-left-radius: 2px;
284- border-bottom-right-radius: 2px;
285-}
286-
287-#header_wrap {
288- background: #212121;
289- background: -moz-linear-gradient(top, #373737, #212121);
290- background: -webkit-linear-gradient(top, #373737, #212121);
291- background: -ms-linear-gradient(top, #373737, #212121);
292- background: -o-linear-gradient(top, #373737, #212121);
293- background: linear-gradient(top, #373737, #212121);
294-}
295-
296-#header_wrap .inner {
297- padding: 50px 10px 30px 10px;
298-}
299-
300-#project_title {
301- margin: 0;
302- color: #fff;
303- font-size: 42px;
304- font-weight: 700;
305- text-shadow: #111 0px 0px 10px;
306-}
307-
308-#project_tagline {
309- color: #fff;
310- font-size: 24px;
311- font-weight: 300;
312- background: none;
313- text-shadow: #111 0px 0px 10px;
314-}
315-
316-#downloads {
317- position: absolute;
318- width: 210px;
319- z-index: 10;
320- bottom: -40px;
321- right: 0;
322- height: 70px;
323- background: url('../images/icon_download.png') no-repeat 0% 90%;
324-}
325-
326-.zip_download_link {
327- display: block;
328- float: right;
329- width: 90px;
330- height:70px;
331- text-indent: -5000px;
332- overflow: hidden;
333- background: url(../images/sprite_download.png) no-repeat bottom left;
334-}
335-
336-.tar_download_link {
337- display: block;
338- float: right;
339- width: 90px;
340- height:70px;
341- text-indent: -5000px;
342- overflow: hidden;
343- background: url(../images/sprite_download.png) no-repeat bottom right;
344- margin-left: 10px;
345-}
346-
347-.zip_download_link:hover {
348- background: url(../images/sprite_download.png) no-repeat top left;
349-}
350-
351-.tar_download_link:hover {
352- background: url(../images/sprite_download.png) no-repeat top right;
353-}
354-
355-#main_content_wrap {
356- background: #f2f2f2;
357- border-top: 1px solid #111;
358- border-bottom: 1px solid #111;
359-}
360-
361-#main_content {
362- padding-top: 40px;
363-}
364-
365-#footer_wrap {
366- background: #212121;
367-}
368-
369-
370-
371-/*******************************************************************************
372-Small Device Styles
373-*******************************************************************************/
374-
375-@media screen and (max-width: 480px) {
376- body {
377- font-size:14px;
378- }
379-
380- #downloads {
381- display: none;
382- }
383-
384- .inner {
385- min-width: 320px;
386- max-width: 480px;
387- }
388-
389- #project_title {
390- font-size: 32px;
391- }
392-
393- h1 {
394- font-size: 28px;
395- }
396-
397- h2 {
398- font-size: 24px;
399- }
400-
401- h3 {
402- font-size: 21px;
403- }
404-
405- h4 {
406- font-size: 18px;
407- }
408-
409- h5 {
410- font-size: 14px;
411- }
412-
413- h6 {
414- font-size: 12px;
415- }
416-
417- code, pre {
418- min-width: 320px;
419- max-width: 480px;
420- font-size: 11px;
421- }
422-
423-}
LICENSE.mdView
@@ -1,0 +1,9 @@
1+# Released under MIT License
2+
3+Copyright (c) 2013 Mark Otto.
4+
5+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6+
7+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8+
9+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
_config.ymlView
@@ -1,0 +1,35 @@
1+# Dependencies
2+markdown: redcarpet
3+redcarpet:
4+ extensions: [with_toc_data]
5+highlighter: pygments
6+#highlighter: rouge
7+
8+# Permalinks
9+permalink: :title.html
10+relative_permalinks: true
11+
12+# Setup
13+title: MyDev
14+tagline: 'Laman Kolaborasi Komuniti MyDev'
15+description: 'Suatu projek untuk memperkaya bahan berkenaan pembangunan perisian dan web dalam Bahasa Melayu.'
16+url: http://www.mydev.my
17+baseurl: ''
18+paginate: 5
19+excerpt_separator: '<!--more-->'
20+
21+authors:
22+ kamalmustafa:
23+ name: Kamal Mustafa
24+ short_bio: Seorang web developer dengan lebih 10 tahun pengalaman dalam bidang pembangunan aplikasi web (PHP/Python) dan IT secara umum.
25+ full_bio_ms: '<a name="Kamal Mustafa" href="http://my.linkedin.com/in/mk4ml" style="font-weight:bold;">Kamal Mustafa</a> adalah Web developer dengan lebih 10 tahun pengalaman dalam bidang pembangunan aplikasi web (PHP/Python) dan IT secara umum. Bersedia untuk berkongsi ilmu berkaitan IT dan pengaturcaraan melalui penulisan, bengkel, seminar atau <i>personal coaching</i>. Aktif menulis di blog peribadi <a href="http://k4ml.blogspot.com/">Tadika Hidup</a> dan Twitter <a href="http://twitter.com/k4ml">@k4ml</a>.'
26+ full_bio_en: '<a href="http://my.linkedin.com/in/mk4ml">Kamal Mustafa</a> is a Web Developer with more than 10 years experience in web application development (PHP/Python) and IT in general. Interested in sharing knowledge about IT and programming through writing, workshop, seminar or personal coaching. Actively sharing his thought at personal blog <a href="http://k4ml.blogspot.com/">Tadika Hidup</a> and Twitter <a href="http://twitter.com/k4ml">@k4ml</a>.'
27+ gravatar: dab3052b18c86b0884341d9c2c67a4f3
28+ pic: http://m.c.lnkd.licdn.com/mpr/pub/image-Xi3rdNhL21LXnFhIZ9ai-2TuhAQVtL47Xi3e-Ut6hszrbxGYXi3eI8yLh7vHUjxRwIF7/mohd-kamal-mustafa.jpg
29+ ikhwanhayat:
30+ name: Ikhwan Hayat
31+ short_bio: Telah membina perisian secara professional sejak 2004. Kebanyakan masa dia bergelumang dalam platform .NET. Namun kadangkala tersesat pergi ke dunia PHP, Python, Ruby, Java, dan bahasa-bahasa pengaturcaraan lain.
32+ full_bio_ms: '<a name="Ikhwan Hayat" href="http://www.ikhwanhayat.net" style="font-weight:bold;">Ikhwan Hayat</a> telah membina perisian secara professional sejak 2004. Kebanyakan masa dia bergelumang dalam platform .NET. Namun kadangkala tersesat pergi ke dunia PHP, Python, Ruby, Java, dan bahasa-bahasa pengaturcaraan lain. Sekarang berkerja sebagai pengaturcara secara <i>freelance</i> sepenuh masa.'
33+ full_bio_en: '<a href="http://www.ikhwanhayat.net">Ikhwan Hayat</a> has been developing softwares professionally since 2004. Main area of expertise is .NET, but often found getting lost in the world of PHP, Python, Ruby, Java, or some esoteric programming language. Available as a full-time freelance developer.'
34+ gravatar: ffed0be2a9908059be3df617338579af
35+ pic: https://www.linkedin.com/mpr/pub/image-1DO7sqVdaGYQIGHO5I5hUW5IQjdWz7sri-OC8gPmQLKqcs_Z1DOC2_bdQ9CdcIWX7rwU/ikhwan-hayat.jpg
_includes/head.htmlView
@@ -1,0 +1,31 @@
1+<head>
2+ <link href="http://gmpg.org/xfn/11" rel="profile">
3+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
4+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
5+
6+ <!-- Enable responsiveness on mobile devices-->
7+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
8+
9+ <title>
10+ {% if page.title == "Home" %}
11+ {{ site.title }} &middot; {{ site.tagline }}
12+ {% else %}
13+ {{ page.title }} &middot; {{ site.title }}
14+ {% endif %}
15+ </title>
16+
17+ <!-- CSS -->
18+ <link rel="stylesheet" href="{{ site.baseurl }}/public/css/poole.css">
19+ <link rel="stylesheet" href="{{ site.baseurl }}/public/css/syntax.css">
20+ <link rel="stylesheet" href="{{ site.baseurl }}/public/css/hyde.css">
21+ <link rel="stylesheet" href="{{ site.baseurl }}/public/css/custom.css">
22+ <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=PT+Sans:400,400italic,700|Abril+Fatface">
23+ <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css">
24+
25+ <!-- Icons -->
26+ <link rel="apple-touch-icon-precomposed" sizes="144x144" href="{{ site.baseurl }}/public/apple-touch-icon-144-precomposed.png">
27+ <link rel="shortcut icon" href="{{ site.baseurl }}/public/favicon.ico">
28+
29+ <!-- RSS -->
30+ <link rel="alternate" type="application/rss+xml" title="RSS" href="{{ site.baseurl }}/atom.xml">
31+</head>
_includes/sidebar.htmlView
@@ -1,0 +1,37 @@
1+<div class="sidebar">
2+ <div class="container sidebar-sticky">
3+ <div class="sidebar-about">
4+ <h1>
5+ <a href="{{ site.baseurl }}/index.html">
6+ {{ site.title }}
7+ </a>
8+ </h1>
9+ <p class="lead">{{ site.description }}</p>
10+ </div>
11+
12+ <nav class="sidebar-nav">
13+ <a class="sidebar-nav-item{% if page.url == "/index.html" %} active{% endif %}" href="{{ site.baseurl }}/index.html">Utama</a>
14+
15+ {% comment %}
16+ The code below dynamically generates a sidebar nav of pages with
17+ `layout: page` in the front-matter. See readme for usage.
18+ {% endcomment %}
19+
20+ {% assign pages_list = site.pages %}
21+ {% for node in pages_list %}
22+ {% if node.title != null %}
23+ {% if node.layout == "page" %}
24+ <a class="sidebar-nav-item{% if page.url == node.url %} active{% endif %}" href="{{ site.baseurl }}{{ node.url }}">{{ node.title }}</a>
25+ {% endif %}
26+ {% endif %}
27+ {% endfor %}
28+
29+ <a class="sidebar-nav-item" href="https://plus.google.com/communities/104883828501447858589">Google+</a>
30+ <a class="sidebar-nav-item" href="http://github.com/mydevcommunity">GitHub</a>
31+ <a class="sidebar-nav-item" href="{{ site.baseurl }}/atom.xml">Atom Feed &nbsp;<i class="fa fa-rss-square"></i></a>
32+ <!-- <span class="sidebar-nav-item">Currently v{{ site.version }}</span> -->
33+ </nav>
34+
35+ <p style="font-size:70%">Except where otherwise noted, content on this site is licensed under a <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International</a> license.</p>
36+ </div>
37+</div>
_includes/toc.htmlView
@@ -1,0 +1,3 @@
1+ <div id="toc_toggle"><i class="fa fa-list"></i> Kandungan</div>
2+ <div id="toc"></div>
3+ <div style="display:table;clear:both"></div>
_layouts/default.htmlView
@@ -1,0 +1,28 @@
1+<!DOCTYPE html>
2+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us">
3+
4+ {% include head.html %}
5+
6+ <body class="theme-base-08">
7+
8+ {% include sidebar.html %}
9+
10+ <div class="content container">
11+ {{ content }}
12+ </div>
13+
14+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
15+ <script src="{{ site.baseurl }}/public/js/toc.js"></script>
16+ <script type="text/javascript">
17+ $(function() {
18+ $('#toc').toc({
19+ title: ""
20+ });
21+ $('#toc').hide();
22+ $('#toc_toggle').click(function(){
23+ $('#toc').toggle();
24+ })
25+ });
26+ </script>
27+ </body>
28+</html>
_layouts/page.htmlView
@@ -1,0 +1,10 @@
1+---
2+layout: default
3+---
4+
5+{% include toc.html %}
6+
7+<div class="page">
8+ <h1 class="page-title">{{ page.title }}</h1>
9+ {{ content }}
10+</div>
_layouts/post.htmlView
@@ -1,0 +1,42 @@
1+---
2+layout: default
3+---
4+
5+{% include toc.html %}
6+
7+<div class="post">
8+ <h1 class="post-title">{{ page.title }}</h1>
9+ <span class="post-date">{{ page.date | date_to_string }}</span>
10+ {{ content }}
11+</div>
12+
13+{% assign author = site.authors[page.author] %}
14+{% if author %}
15+<div class="author">
16+ <div style="margin-bottom:10px; font-style:italic">Mengenai penulis</div>
17+ <img class="gravatar" src="http://www.gravatar.com/avatar/{{ author.gravatar }}" />
18+ <div class="detail">
19+ <div class="name">{{ author.name }}</div>
20+ <div class="bio">
21+ {{ author.short_bio }}
22+ <a href="{{ site.baseurl }}/authors.html#{{page.author}}">(lagi)</a>
23+ </div>
24+ </div>
25+</div>
26+{% endif %}
27+
28+<div class="related">
29+ <h2>Artikel Berkaitan</h2>
30+ <ul class="related-posts">
31+ {% for post in site.related_posts limit:3 %}
32+ <li>
33+ <h3>
34+ <a href="{{ site.baseurl }}{{ post.url }}">
35+ {{ post.title }}
36+ <small>{{ post.date | date_to_string }}</small>
37+ </a>
38+ </h3>
39+ </li>
40+ {% endfor %}
41+ </ul>
42+</div>
_posts/2012-12-15-automated-testing.mdView
@@ -1,0 +1,237 @@
1+---
2+layout: post
3+title: "Automated Testing Dalam Pembangunan Perisian"
4+date: 2012-12-15 01:19
5+permalink: /automated-testing-dalam-pembangunan-perisian.html
6+---
7+
8+_Testing_ adalah sebahagian daripada proses pembangunan perisian komputer. Setiap kali baris-baris kod ditulis, diubah atau dipadam, ia mesti melalui proses testing bagi memastikan program tersebut masih lagi berjalan sebagaimana yang diharapkan. Ini bermakna kita sama sekali tidak boleh mengelak daripada melakukan _testing_ terhadap program atau aplikasi yang kita bangunkan.
9+
10+<!--more-->
11+
12+## Manual Testing
13+Testing biasanya dilakukan secara manual dengan pengaturcara cuba menjalankan aturcara atau aplikasi yang dibangunkan dan memerhatikan sama ada ia mengeluarkan output yang dikehendaki ataupun semua _features_ berfungsi sebagai mana diharapkan. Ambil contoh aturcara ringkas berikut:-
14+
15+{% highlight python %}
16+ function add(num1, num2) {
17+ return num1 + num2;
18+ }
19+
20+ print add(1, 2) . "\n" # akan paparkan 3
21+ print add(2, 2) . "\n" # akan paparkan 4
22+{% endhighlight %}
23+
24+Andaikan aturcara diatas ditulis menggunakan bahasa PHP dan disimpan dalam fail bernama `add.php`. Untuk menguji aturcara ini, pengaturcara akan `execute` fail tersebut dan memerhatikan sama ada ia memaparkan out yang diharapkan iaitu:-
25+
26+ 3
27+ 4
28+
29+Aturcara tersebut mungkin boleh dijalankan seperti berikut:-
30+
31+{% highlight bash %}
32+ php add.php
33+ 3
34+ 4
35+{% endhighlight %}
36+
37+Di atas kita dapati aturcara tersebut memaparkan output yang kita kehendaki. Sekarang kita andaikan berlaku sedikit kesilapan dalam kod tersebut. Katakan ia ditulis seperti berikut:-
38+
39+{% highlight python %}
40+ function add(num1, num2) {
41+ return num1 * num2;
42+ }
43+
44+ print add(1, 2) . "\n"; # akan paparkan 3
45+ print add(2, 2) . "\n"; # akan paparkan 4
46+{% endhighlight %}
47+
48+Apabila dijalankan, kita akan dapati outputnya berlainan:-
49+
50+ 2
51+ 4
52+
53+Ini bermakna program tersebut gagal dalam proses _testing_ kita. Cara _testing_ seperti diatas walaupun mudah untuk difahami dan diamalkan ia menjadi amat tidak efektif apabila program semakin berkembang dan kompleks. Ia juga tidak efektif kerana bergantung semata-mata kepada keupayaan mata kita untuk mengesan perbezaan pada output yang dipaparkan. Bukan mahu menidakkan keupayaan mata namun manusia sememangnya tidak sesuai untuk melakukan kerja-kerja leceh dan remeh seperti ini. Disinilah fungsi komputer supaya manusia boleh menumpukan kepada kerja-kerja yang lebih memerlukan daya fikir, intelek serta kreativiti yang tinggi.
54+
55+## Automated Testing
56+Dalam proses _testing_ secara manual di atas, kita bergantung kepada tenaga manusia untuk memerhatikan semasa program dijalankan, ia menghasilkan output yang dikehendaki atau tidak. Dalam _automated testing_ kita akan menulis satu aturcara lain bagi menguji aturcara yang dibangunkan. Ini membolehkan kita untuk _delegate_ tugas-tugas menguji tersebut kepada komputer yang sudah semestinya lebih efisyen untuk melaksanakannya.
57+
58+Contoh kod sebelum ini boleh ditulis seperti berikut untuk <fill in>:-
59+
60+{% highlight php %}
61+ function add($num1, $num2) {
62+ return $num1 * $num2;
63+ }
64+
65+ assert(add(1, 2) === 3);
66+ assert(add(2, 2) === 4);
67+{% endhighlight %}
68+
69+Apabila dijalankan kita akan melihat output seperti berikut:-
70+
71+ Warning: assert(): Assertion failed in /home/rkiteratai/add.php on line 6
72+
73+Aah, sekarang anda sudah dapat melihat bagaimana komputer sudah mula mengambil peranan manusia dalam menguji kod aturcara.
74+
75+Kod automated testing boleh ditulis dengan 2 cara, sama ada selepas kod aturcara perisian siap ditulis atau sebelum kod aturcara perisian ditulis.
76+
77+## Kategori _Test_
78+* Unit Test
79+* Functional Test
80+* Integration Test
81+* Stress Test
82+
83+## Test Framework
84+...
85+
86+## Contoh Test mengikut bahasa pengaturcaraan
87+
88+### Unit Test dalam C# (.NET)
89+
90+Dalam dunia .NET, antara _unit testing framework_ yang paling awal dan paling meluas digunakan ialah NUnit. Berikut adalah contoh bagaimana ia digunakan.
91+
92+Katakan kod yang ingin diuji adalah seperti berikut:
93+
94+{% highlight csharp %}
95+class Calculator
96+{
97+ public int Add(int operand1, int operand2)
98+ {
99+ return operand1 + operand2;
100+ }
101+
102+ public int Minus(int operand1, int operand2)
103+ {
104+ return operand1 + operand2;
105+ }
106+}
107+{% endhighlight %}
108+
109+Kita boleh membuat _test fixture_ seperti ini untuk mengujinya:
110+
111+{% highlight csharp %}
112+using NUnit.Framework
113+
114+[TestFixture]
115+public class CalculatorTest
116+{
117+ [Test]
118+ public void AddShouldDoSum()
119+ {
120+ var calc = new Calculator();
121+ var result = calc.Add(2, 1);
122+
123+ Assert.AreEqual(3, result);
124+ }
125+
126+ [Test]
127+ public void MinusShouldDoSubtraction()
128+ {
129+ var calc = new Calculator();
130+ var result = calc.Minus(2, 1);
131+
132+ Assert.AreEqual(1, result);
133+ }
134+}
135+{% endhighlight %}
136+
137+Setelah _test code_ di atas dikompil menjadi _assembly_ (DLL) atau _executable_, larikan ia menggunakan sama ada _console runner_ (nunit-console.exe) atau _GUI runner_ (nunit-gui.exe).
138+
139+Di bawah adalah contoh apa bila ia dilarikan menggunakan _GUI NUnit runner_. Kita dapat lihat bahawa _test_ untuk fungsi _Add()_ berjaya, tetapi _test_ untuk _Minus()_ gagal kerana terdapat kesilapan dalam _code_ kita.
140+
141+![Contoh antaramuka NUnit GUI Runner](http://i.imgur.com/m8z2n.png)
142+
143+### Unit Test Python
144+Kod untuk testing dalam Python boleh ditulis dengan bantuan module `unittest` dalam Python Standard Library. Katakan kod yang ingin diuji adalah seperti berikut:
145+
146+{% highlight python %}
147+class Calculator(object):
148+ def add(self, num1, num2):
149+ return num1 + num2
150+
151+ def minus(self, num1, num2):
152+ return num1 + num2
153+{% endhighlight %}
154+
155+Simpan kod di atas dalam fail bernama `calculator.py`. Seterusnya kod untuk testing boleh ditulis seperti berikut:-
156+
157+{% highlight python %}
158+import unittest
159+
160+from calculator import Calculator
161+
162+class CalculatorTest(unittest.TestCase):
163+ def test_add_should_do_sum(self):
164+ calc = Calculator()
165+ result = calc.add(2, 1)
166+
167+ self.assertEqual(result, 3)
168+
169+ def test_minus_should_do_substraction(self):
170+ calc = Calculator()
171+ result = calc.minus(2, 1)
172+
173+ self.assertEqual(result, 1)
174+
175+if __name__ == '__main__':
176+ unittest.main()
177+{% endhighlight %}
178+Simpan kod di atas dalam fail bernama `tests.py`. Seterusnya kita boleh jalankan test dengan melancarkan arahan berikut melalui console:-
179+
180+{% highlight console %}
181+python tests.py
182+{% endhighlight %}
183+Anda akan dapati outputnya seperti berikut:-
184+
185+{% highlight console %}
186+.F
187+======================================================================
188+FAIL: test_minus_should_do_substraction (__main__.CalculatorTest)
189+----------------------------------------------------------------------
190+Traceback (most recent call last):
191+ File "tests.py", line 16, in test_minus_should_do_substraction
192+ self.assertEqual(result, 1)
193+AssertionError: 3 != 1
194+
195+----------------------------------------------------------------------
196+Ran 2 tests in 0.000s
197+
198+FAILED (failures=1)
199+{% endhighlight %}
200+
201+Di atas kita dapati satu test gagal kerana terdapat kesilapan dalam kod kita sebelum ini. Setelah kesilapan itu dibetulkan, kita akan dapati outputnya seperti berikut:-
202+
203+{% highlight console %}
204+..
205+----------------------------------------------------------------------
206+Ran 2 tests in 0.000s
207+
208+OK
209+{% endhighlight %}
210+
211+## Soalan Lazim
212+
213+### Apa itu _assert_ ?
214+_Assertion_ merupakan satu proses menguji nilai pada bahagian-bahagian tertentu aturcara bagi memastikan ia sentiasa benar sebagaimana yang diharapkan oleh pengaturcara. Kegagalan pada _assertion_ boleh dianggap sebagai kegagalan langsung aturcara tersebut dan ia mesti dibetulkan. Ini berbeza dengan _error handling_ dimana ia sesuatu yang dijangka akan berlaku dan pengaturcara hanya perlu memastikan langkah-langkah sepatutnya dilakukan untuk menangani _error_ tersebut.[^1]
215+
216+### Apa itu _regression_ ?
217+_Regress_ adalah berlawanan kepada _progress_, maksudnya kita bergerak ke belakang. Bug yang sudah dibetulkan muncul balik akibat penambahan baru pada code. Ia biasa berlaku dalam development apabila kita fix sesuatu bug dan kemudian deploy code tersebut ke server live, selepas beberapa ketika akan dapat komplen akan isu baru dan bila diselidiki ia adalah disebabkan oleh fix sebelum ini. Satu kelebihan automated tests adalah boleh detect regression dengan lebih cepat, sebelum code sampai ke production.
218+
219+### Bagaimana menguruskan test yang melibatkan beberapa data berlainan tapi logik yang sama ?
220+Boleh gunakan teknik seperti [data provider][1] (minit 19:13) atau [test generator][2].
221+
222+### Boleh tulis test dulu sebelum menulis kode ?
223+Ya boleh. Ia dinamakan Test Driven Development (TDD). Dalam TDD, kita akan mulakan menulis satu set test terhadap komponen yang hendak dibangunkan. Test biasanya akan pass input-input yang diperlukan oleh function atau class terbabit dan akan check _return value_ sama ada menepati requirement atau tidak. Pada peringkat ini kesemua function atau class yang hendak di test adalah stub dan test akan fail. Seterusnya kita akan mula implement function atau class berkenaan sehingga semua test pass. Bagaimanapun secara realiti TDD jarang dapat dipraktikkan sepenuhnya. Code biasanya ditulis tanpa sebarang test dan bila ia mula mencapai peringkat tertentu barulah test ditulis untuk memastikan ia berfungsi sebagaimana diharapkan.
224+
225+## Penulis
226+Nama-nama di bawah adalah penyumbang kepada tulisan ini:-
227+
228+* Mohd. Kamal bin Mustafa (k4ml) - http://k4ml.github.com/
229+* Mohd Amree (amree) - http://ieatbinary.com/
230+* Mior Muhammad Zaki (crynobone) - http://crynobone.com/
231+* Irwan Azam Ahmad (ryzam) - https://github.com/ryzam
232+* Ikhwan Hayat (ikhwanhayat) - https://github.com/ikhwanhayat
233+
234+[^1]: http://en.wikipedia.org/wiki/Assertion_(computing)
235+
236+[1]:http://www.youtube.com/watch?v=84j61_aI0q8&feature=player_embedded#t=1130s
237+[2]:https://gist.github.com/k4ml/5165424
_posts/2012-12-22-buku-pilihan.mdView
@@ -1,0 +1,30 @@
1+---
2+layout: post
3+title: Buku-buku Pilihan
4+date: 2012-12-22 16:13:00
5+permalink: /buku-buku-pilihan.html
6+---
7+
8+Senarai buku-buku yang direkomen oleh ahli-ahli komuniti MyDev. Senarai ini adalah berdasarkan [topik perbincangan][1] di laman [komuniti G+ MyDev][2].
9+
10+<!--more-->
11+
12+1. [The Pragmatic Programmer](http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X)
13+1. [Head First Design Patterns](http://shop.oreilly.com/product/9780596007126.do)
14+1. [Ship It](http://pragprog.com/book/prj/ship-it)
15+1. [Write Great Code - Understanding Machine](http://www.amazon.com/Write-Great-Code-Understanding-Machine/dp/1593270038/ref=pd_sim_b_1)
16+1. [Write Great Code, Volume 2: Thinking Low-Level, Writing High-Level](http://www.amazon.com/Write-Great-Code-Volume-High-Level/dp/1593270658/ref=pd_sim_b_1)
17+1. [Eric Sink on the Business of Software](http://www.amazon.com/Eric-Business-Software-Experts-Voice/dp/1590596234)
18+1. [Refactoring](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672)
19+1. [Patterns of Enterprise Application Architecture](http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420)
20+1. [Domain-Driven Design](http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/)
21+1. [Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd Edition)](http://www.amazon.com/Applying-UML-Patterns-Introduction-Object-Oriented/dp/0131489062)
22+1. [Design Patterns: Elements of Reusable Object-Oriented Software](http://www.amazon.com/Design-Patterns-Object-Oriented-Professional-Computing/dp/0201634988)
23+1. [High Performance MySQL: Optimization, Backups, and Replication](http://www.amazon.com/High-Performance-MySQL-Optimization-Replication/dp/1449314287)
24+1. [Enterprise Integration Patterns](http://www.amazon.com/o/asin/0321200683/ref=nosim/enterpriseint-20)
25+
26+Sebarang tambahan kepada senarai di atas adalah dialu-alukan. Anda boleh melakukannya sama ada dengan 'fork' [repo mydev][3] di github dan membuat 'pull request' atau menambahnya ke [topik perbincangan][1] di [komuniti G+][2].
27+
28+[1]:https://plus.google.com/u/0/105721265741813048018/posts/chsdf4ekQ8S
29+[2]:https://plus.google.com/u/0/communities/104883828501447858589
30+[3]:https://github.com/mydevcommunity/mydev
_posts/2012-12-28-jargon-pengaturcaraan.mdView
@@ -1,0 +1,78 @@
1+---
2+layout: post
3+title: Jargon Pengaturcaraan
4+date: 2012-12-28 10:14
5+permalink: /jargon-pengaturcaraan.html
6+---
7+
8+**Jargon** adalah perkataan atau frasa istimewa yang sukar difahami. Dalam bidang pembangunan perisian, seperti bidang profesional lain, seringkali terdapat perkataan-perkataan sukar ini. Artikel ini bertujuan untuk mengumpulkan jargon tersebut berserta dengan penerangan ringkas mengenainya sebagai rujukan mudah untuk semua.
9+
10+<!--more-->
11+
12+Gunakan fungsi _find_ (Ctrl+F) dalam pelayar web anda untuk membuat carian dan untuk navigasi.
13+
14+---
15+
16+1. **Automated Testing** : Ujian yang diautomasikan. Satu program tertentu dijalankan dan ia akan melakukan ujian terhadap sistem.
17+
18+1. **Bug** : Ralat atau kecacatan di dalam sistem.
19+
20+1. **Business Layer** : Salah satu layer dalam N-Layered Architecture. Menempatkan aturcara yang menjalankan kerja utama dalam sistem tersebut.
21+
22+1. **Class Diagram** : Rajah berbentuk blok-blok yang mewakili `class`. Ia menunjukkan struktur `class` dan hubungan antaranya. Sebahagian dari UML.
23+
24+1. **Cloud Computing** : Penggunaan sumber komputer (hardware dan software) yang dihantar sebagai servis melalui network (Internet)
25+
26+1. **Data Layer** : Salah satu layer dalam N-Layered Architecture. Menempatkan aturcara yang berinteraksi dengan storan/simpanan/pangkalan data.
27+
28+1. **Data Transfer Object (DTO)** : Struktur yang dipermudahkan untuk tujuan penghantaran data dari satu bahagian ke bahagian lain. Suatu domain class yang kompleks mungkin dipermudahkan untuk menghantaran melalui web service atau paparan di UI.
29+
30+1. **Domain Expert** : Pihak yang pakar tentang keperluan sistem dan masalah yang ingin diselesaikan. Biasanya terlibat dalam System Requirements Study (SRS). Juga dipanggil Subject Matter Expert (SME).
31+
32+1. **Entity Relationship Diagram (ERD)** : Rajah yang menunjukkan table di dalam pangkalan data, column yang terdapat di dalamnya, dan hunbungan antara table-table tersebut.
33+
34+1. **Integrated Development Environment (IDE)** : Suatu pakej aplikasi yang digunakan untuk membina aturcara. Mungkin di dalam satu program atau berbilang program. Biasanya mengandungi editor, compiler, debugger dan sokongan lain seperti bantuan utk melayari dokumentasi, code completion dan sebagainya.
35+
36+1. **Model View Controller (MVC)** : Satu senibina sistem di mana ia dipecahkan kepada 3 komponen. Model mewakili entiti di dalam sistem. View adalah UI yang dipaparkan kepada pengguna. Controller adalah mengantara dan pemudahcara antara Model dan View, ia berperanan menerima input dan mengarahkan komponen lain bergerak.
37+
38+1. **Monkey Patching** : Suatu teknik dalam dynamic programming di mana suatu function/method disuntik ke dalam objek semasa runtime, walaupun class asalnya tidak memiliki function/method tersebut.
39+
40+1. **N-Layered Architecture** : Pendekatan merekabentuk sistem dengan membahagikan kepada bahagian yang dinamakan _layer_. Kebiasaannya 2-Layer, 3-Layer, atau 4-Layer.
41+
42+1. **Persistence** : Storan atau simpanan. Biasanya pangkalan data, sistem fail dan sebagainya.
43+
44+1. **Platform as a Service (PaaS)** : Satu kategori servis komputer cloud di mana ia membekal platform dan kaedah komputer sebagai servis. Ia adalah salah satu model servis pengkomputeran cloud. Dalam model ini, pembekal membekalkan rangkaian, pelayan, storan dan servis servis lain. Pengguna pula menggunakan alatan dan sebagainya yang dibekalkan pembekal untuk membina software.
45+
46+1. **Presentation Layer** : Salah satu layer dalam N-Layered Architecture. Menempatkan antaramuka pengguna (UI).
47+
48+1. **Representational State Transfer (REST)** : Adalah gaya seni bina perisian untuk sistem seperti World Wide Web. Semua permintaan kepada penghubung mesti mengandungi maklumat yang diperlukan seperti method dan data yang diperlukan. Berlawanan dengan cara laman web yang biasa menggunakan cookies dan session untuk menyelenggara data diantara sesi.
49+
50+1. **Sequence Diagram** : Rajah yang menunjukkan aliran perjalanan sistem
51+
52+1. **Service Layer** : Salah satu layer dalam N-Layered Architecture.
53+
54+1. **Service Oriented Architecture (SOA)** : ?
55+
56+1. **Simple Object Access Protocol (SOAP)** : ?
57+
58+1. **Software as a Service (SaaS)** : Software sebagai servis. Satu model penghantaran software di mana software dan data berkaitan dihos pada cloud. SaaS biasanya diakses pengguna menggunakan thin client seperti web browser. Ia telah menjadi satu model penghantaran software yang biasa bagi banyak aplikasi perniagaan seperti akaun, kolaborasi, pengurusan hubungan pengguna (CRM), sistem pengurusan informasi (MIS), perancangan sumber enterprise (ERP), invoice, pengurusan sumber pengguna (HRM), pengurusan kandungan (CM), dan pengurusan helpdesk. Salah satu modal untuk menjual bagi syarikat syarikat ini ialah potensi untuk mengurangkan kos sokongan IT dengan melepaskan sokongan hardware, penyelenggaraan software, dan sokongan kepada pembekal SaaS.
59+
60+1. **Subject Matter Expert** : Rujuk _Domain Expert_.
61+
62+1. **Unified Modeling Language (UML)** : UML menyediakan tatabahasa (seperti Use Case, Actor, dan sebagainya) yang dapat digunakan untuk memodelkan sistem berdasarkan Object-Oriented Design. Ia menetapkan rajah yang boleh digunakan untuk menggambarkan sistem seperti Use Case Diagram, Class Diagram, Sequence Diagram, Activity Diagram, dan lain-lain.
63+
64+1. **Unit Test** : Kod yang ditulis untuk menguji satu "unit" kecil dalam sistem. Unit ini biasanya merujuk kepada satu business class. Unit test ini biasanya tidak termasuk dalam sistem sebenarnya.
65+
66+1. **Use Case** : Satu scenario antara pengguna dan sistem. Contohnya dalam sistem kedai online, ada use case administrator memasukkan produk, use case pelanggan melayari produk, use case pelanggan membuat pembelian, dan sebagainya.
67+
68+1. **User Story** : Satu ayat pendek yang menerangkan interaksi dalam sistem. Ia menunjukkan siapa, apa, dan mengapa sesuatu berlaku/dilakukan. Contohnya, "Sebagai pelanggan, saya ingin melihat produk yang dijual, supaya saya boleh membuat pilihan".
69+
70+1. **Version Control System (VCS)** : Sistem untuk menyimpan fail-fail aturcara. Ia membenarkan perubahan demi perubahan (versi) disimpan dan pengguna boleh mengambil mana-mana versi yang terdahulu untuk digunakan. Jika digunakan dalam team, ia memudahkan perkongsian kod dan mengelakkan pertembungan perubahan (_conflict_) antara berbilang pengguna melalui proses _merge_. Antara VCS yang popular ialah CVS (nama product, Concurrent Versioning System), Subversion, Mercurial, Git, dan Bazaar.
71+
72+1. **Web Service** : Satu method standard untuk komputer di internet untuk memberi akses program atau fungsi yang boleh dicapai dan digunakan dari komputer lain
73+
74+1. **Z-Index** : ?
75+
76+---
77+
78+Untuk menyumbang, sila isikan perkataan/frasa di kiri dan maksudnya di sebelah kanan. Jargon boleh jadi dalam Bahasa Melayu atau Inggeris, tapi penerangannya mesti dibuat dalam Bahasa Melayu. Susun jargon mengikut abjad.
_posts/2013-03-22-memahami-dependency-injection.mdView
@@ -1,0 +1,338 @@
1+---
2+layout: post
3+title: Memahami Dependency Injection
4+date: 2013-03-22
5+author: ikhwanhayat
6+permalink: /memahami-dependency-injection.html
7+---
8+
9+__Dependency Injection__ adalah suatu teknik rekabentuk perisian untuk menjadikannya lebih _modular_ dan _flexible_. Ia kadangkala juga disebut sebagai __Dependency Inversion__ atau __Inversion of Control (IoC)__. Maksud sebenar setiap satu frasa sedikit berbeza, namun untuk permulaan bolehlah dianggap semuanya membawa maksud yang hampir serupa.
10+
11+<!--more-->
12+
13+## Apa Itu Dependency
14+
15+Untuk memahami apa itu _Dependency Injection_ (DI), kita perlu terlebih dahulu mengetahui apa yang dimaksudkan dengan _dependency_.
16+
17+Dalam suatu sistem yang besar, perkara pertama yang perlu dilakukan ialah pecahkan ia kepada bahagian-bahagian yang lebih kecil supaya mudah untuk kita selesaikan dan yang lebih penting mudah untuk kita senggara (_mantainable_).
18+
19+Katakan kita ingin membina suatu sistem _online_ yang akan memaparkan cuaca bagi suatu tempat. Keperluan yang telah ditetapkan ialah sistem mesti mampu memberitahu pengguna cuaca di bandar mereka melalui alamat IP yang dikesan.
20+
21+Jadi kita akan buatkan suatu _class_ `WeatherService` untuk tujuan ini. Katakan kita sudah mempunyai pangkalan data yang akan memberikan kita nama bandar berdasarkan IP. Ada pangkalan data lain pula yang diberikan pada kita oleh Jabatan Meteorologi yang menyenaraikan ramalan cuaca untuk satu-satu bandar.
22+
23+Untuk memudahkan pemahaman, kita buatkan dulu ia sebagai applikasi konsol. Kita akan gunakan bahasa C# untuk contoh ini.
24+
25+```csharp
26+public class WeatherService
27+{
28+ public void ShowForIp(string ip)
29+ {
30+ Console.WriteLine("Your IP is " + ip);
31+
32+ // Hubungi pangkalan data geolocation
33+ // Dan larikan query untuk dapatkan bandar berdasarkan IP
34+
35+ var connGeo = new SqlConnection("server1...");
36+ connGeo.Open();
37+ var sqlCity = new SqlCommand("select top 1 city from IpCity where ip='" + ip + "'", connGeo);
38+
39+ var city = (string)sqlCity.ExecuteScalar();
40+ Console.WriteLine("City: " + city);
41+
42+ connGeo.Close();
43+
44+ // Hubungi pula pangakalan data untuk cuaca
45+ // Dan dapatkan cuaca terkini untuk bandar
46+
47+ var connWeather = new SqlConnection("server2...");
48+ connWeather.Open();
49+ var sqlWeather = new SqlCommand("select top 1 weather from CityWeather where city='" + city + "' and day=" + DateTime.Now.DayOfYear, connWeather);
50+
51+ var weather = (string)sqlWeather.ExecuteScalar();
52+ Console.WriteLine("Weather: " + weather);
53+
54+ connWeather.Close();
55+ }
56+}
57+
58+// Panggil dari applikasi utama
59+
60+var svc = new WeatherService();
61+svc.ShowForIp("10.10.10.10");
62+
63+// Contoh output
64+Your IP is 10.10.10.10
65+City: Kuala Lumpur
66+Weather: Heavy Rain
67+```
68+
69+Kita dapati _class_ ini perlu melakukan beberapa perkara iaitu pertama ia menerima input, kemudian ia mencari bandar pengguna, lalu mencari cuaca, dan akhirnya memaparkannya.
70+
71+Bila dilihat kembali, terlalu banyak kerja yang perlu dilakukan oleh _class_ ini. _Class_ yang baik ialah ianya fokus pada kerjanya sahaja. Bila kita kecilkan skop tugas suatu _class_, kita dapat menjadikan ia lebih "cohesive", tugasnya lebih fokus.
72+
73+Tugas asasi _class_ ini ialah menerima IP dan memaparkan cuaca bagi IP tersebut. Namun ia tidak dapat berfungsi jika ia tidak dapat mencari bandar untuk IP itu dan seterusnya mencari cuaca untuk bandar tersebut. Apa kata jika kita buatkan _class_ lain untuk melakukan dua tugas tersebut untuknya. _Class_ `WeatherService` pula nanti hanya perlu gunakan _class_ baru yang kita akan buat ini supaya objektifnya dapat dicapai.
74+
75+```csharp
76+public class CityFinder
77+{
78+ public string FindFromIp(string ip)
79+ {
80+ // Hubungi pangkalan data geolocation
81+ // Dan larikan query untuk dapatkan bandar berdasarkan IP
82+
83+ var connGeo = new SqlConnection("server1...");
84+ connGeo.Open();
85+ var sqlCity = new SqlCommand("select top 1 city from IpCity where ip='" + ip + "'", connGeo);
86+
87+ var city = (string)sqlCity.ExecuteScalar();
88+
89+ connGeo.Close();
90+
91+ return city;
92+ }
93+}
94+
95+public class WeatherFinder
96+{
97+ public string FindForCity(string city)
98+ {
99+ // Hubungi pangakalan data untuk cuaca
100+ // Dan dapatkan cuaca terkini untuk bandar
101+
102+ var connWeather = new SqlConnection("server2...");
103+ connWeather.Open();
104+ var sqlWeather = new SqlCommand("select top 1 weather from CityWeather where city='" + city + "' and day=" + DateTime.Now.DayOfYear, connWeather);
105+
106+ var weather = (string)sqlWeather.ExecuteScalar();
107+
108+ connWeather.Close();
109+
110+ return weather;
111+ }
112+}
113+
114+
115+public class WeatherService
116+{
117+ public void ShowForIp(string ip)
118+ {
119+ Console.WriteLine("Your IP is " + ip);
120+
121+ var city = new CityFinder().FindFromIp(ip);
122+ Console.WriteLine("City: " + city);
123+
124+ var weather = new WeatherFinder().FindForCity(city);
125+ Console.WriteLine("Weather: " + weather);
126+ }
127+}
128+
129+// Panggil dari applikasi utama
130+
131+var svc = new WeatherService();
132+svc.ShowForIp("10.10.10.10");
133+
134+```
135+
136+Cuba lihat, _class_ `WeatherService` nampak lebih bersih bukan? Kurang berserabut apabila tugasnya telah dipecahkan kepada _class_ lain. Baik, pada tahap ini anda dapat lihat bagaimana satu _class_ besar dipecahkan kepada _class_ lebih kecil. Aturcara yang baru ini boleh dikatakan lebih _modular_ dari sebelumnya.
137+
138+
139+Namun, _class_ `WeatherService` ini **bergantung kepada** _class_ `CityFinder` dan `WeatherFinder` untuk berfungsi. Untuk mencapai _modularity_, kita menghadapi satu masalah lain pula iaitu _dependency_ (kebergantungan). Adanya _dependency_ membuatkan perubahan sukar dilakukan, kerana perubahan pada satu tempat akan mempengaruhi tempat lain. Namun jika tiada _dependency_ langsung maka _class_ `WeatherService` ini langsung tidak dapat berfungsi!
140+
141+## Mengurus Dependency
142+
143+Kita perlukan cara untuk menguruskan _dependency_ ini. Salah satu caranya ialah menggunakan teknik _Dependency Injection_.
144+
145+Dalam _class_ `WeatherService` ini, _dependency_ pada CityFinder dan WeatherFinder adalah kuat kerana ia perlu _instantiate_ _class-class_ ini sendiri sebelum menggunakannya. Jika kita ingin mengubahnya pada masa akan datang, kita perlu korek semula _class_ `WeatherService` ini dan lakukan perubahan di dalamnya.
146+
147+Lebih baik jika tugas untuk _instantiate_ _class-class_ ini dilakukan oleh "orang lain". "Orang lain" ini kemudiannya akan memberikan _instance_ _class-class_ yang diperlukan kepada `WeatherService` untuk digunakan. Mari kita lihat apa yang saya maksudkan.
148+
149+```csharp
150+
151+// Anggapkan tiada perubahan pada class CityFinder dan WeatherFinder
152+
153+public class WeatherService
154+{
155+ private CityFinder cityFinder;
156+ private WeatherFinder weatherFinder;
157+
158+ public WeatherService(CityFinder cityFinder, WeatherFinder weatherFinder)
159+ {
160+ this.cityFinder = cityFinder;
161+ this.weatherFinder = weatherFinder;
162+ }
163+
164+ public void ShowForIp(string ip)
165+ {
166+ Console.WriteLine("Your IP is " + ip);
167+
168+ var city = cityFinder.FindFromIp(ip);
169+ Console.WriteLine("City: " + city);
170+
171+ var weather = weatherFinder.FindForCity(city);
172+ Console.WriteLine("Weather: " + weather);
173+ }
174+}
175+
176+// Panggil dari applikasi utama
177+
178+var cityFinder = new CityFinder();
179+var weatherFinder = new WeatherFinder();
180+
181+var svc = new WeatherService(cityFinder, weatherFinder);
182+svc.ShowForIp("10.10.10.10");
183+
184+```
185+
186+Kita dapat lihat, applikasi utama yang perlu _instantiate_ _class_ `CityFinder` dan `WeatherFinder`, dan kemudiannya _inject_ mereka ke dalam `WeatherService`. Nah, inilah yang dinamakan __Dependency Inversion__ (mengalihkan tugas mengurus _dependency_ ke tempat lain) atau __Dependency Injection__ (memasukkan _dependency_ ke dalam _class_ yang memerlukannya).
187+
188+Tugas mengawal _dependency_ biasanya diserahkan kepada kod yang berada lebih atas dalam hierarki panggilan kerana ia lebih mudah dikonfigurasikan.
189+
190+
191+## Lebih Panjang dan Sukar?
192+
193+Nampaknya ia hanya memanjangkan kod aturcara kita sahaja? Apa bagusnya begini? Untuk mendemonstrasikan kelebihannya, mari kita wujudkan satu situasi perubahan yang biasa berlaku dalam sistem perisian.
194+
195+Katakan pada suatu hari, Jabatan Meteorologi telah meningkat taraf perkhidmatan IT mereka. Cuaca sekarang boleh diperolehi menggunakan web service yang telah mereka sediakan. Lebih tepat dan terkini. Kita ingin mengubahkan sistem kita supaya dapat menggunakan web service ini dan tidak perlu bersusah-payah mengambil data dari mereka setiap minggu :)
196+
197+```csharp
198+
199+//
200+// Dalam C#, cara yang saya tunjukkan ini menggunakan interface. Dalam bahasa lain mungkin ia tidak diperlukan.
201+//
202+public interface IWeatherFinder
203+{
204+ string FindForCity(string city);
205+}
206+
207+//
208+// Ubah sedikit untuk class WeatherFinder asal supaya ia masih dapat digunakan
209+//
210+public class WeatherFinderFromDb : IWeatherFinder
211+{
212+ public string FindForCity(string city)
213+ {
214+ // ... kod sama
215+ }
216+}
217+
218+//
219+// Class yang baru untuk mencari menggunakan web service
220+//
221+public class WeatherWebService : IWeatherFinder
222+{
223+ public string FindForCity(string city)
224+ {
225+ // Hubungi web service
226+ // Dapatkan cuaca untuk bandar yang diberi
227+ // Anggaplah kod selengkapnya ada di sini :)
228+
229+ return weather;
230+ }
231+}
232+
233+public class WeatherService
234+{
235+ private CityFinder cityFinder;
236+
237+ private IWeatherFinder weatherFinder; // gunakan interface, bukan concrete class lagi
238+
239+ public WeatherService(CityFinder cityFinder, IWeatherFinder weatherFinder)
240+ {
241+ this.cityFinder = cityFinder;
242+ this.weatherFinder = weatherFinder;
243+ }
244+
245+ public void ShowForIp(string ip)
246+ {
247+ Console.WriteLine("Your IP is " + ip);
248+
249+ var city = cityFinder.FindFromIp(ip);
250+ Console.WriteLine("City: " + city);
251+
252+ var weather = weatherFinder.FindForCity(city);
253+ Console.WriteLine("Weather: " + weather);
254+ }
255+}
256+
257+// Panggil dari applikasi utama
258+
259+var cityFinder = new CityFinder();
260+var weatherFinder = new WeatherWebService(); // gunakan class yang baru
261+
262+var svc = new WeatherService(cityFinder, weatherFinder);
263+svc.ShowForIp("10.10.10.10");
264+
265+```
266+
267+Kita dapat lihat bahawa hanya perubahan yang sedikit perlu dilakukan pada `WeatherService`. Malah jika anda menggunakan interface dari awal (satu lagi prinsip yang baik untuk digunakan), maka perubahan langsung tidak dilakukan dalam _class_ `WeatherService` tersebut.
268+
269+Melalui teknik ini juga, pengujian dapat dilakukan dengan lebih mudah. Katakan kita buatkan satu _unit test_ untuk `WeatherService` ini. Kita tidak mahu web service itu dipanggil setiap kali, kerana ia pastilah lambat. Kita anggapkan sahaja web service ini sudah terbukti berfungsi kerana kita telah lakukan satu lagi _unit test_ untuknya ditempat lain.
270+
271+Maka kita buatkan satu `WeatherFinderStub` yang memulangkan cuaca yang sudah kita tentukan. _Stub_ ini kemudiannya kita gunakan untuk menguji `WeatherService`.
272+
273+```csharp
274+
275+public class WeatherFinderStub : IWeatherFinder
276+{
277+ public string FindForCity(string city)
278+ {
279+ return "Cloudy";
280+ }
281+
282+}
283+
284+// Dalam unit test
285+
286+void TestWeatherServiceCanReturnWeatherForIp()
287+{
288+ var svc = new WeatherService(new CityFinder(), new WeatherFinderStub()); // gunakan stub
289+
290+ // Lakukan asserts
291+}
292+
293+```
294+
295+
296+## Dependency Injection Container
297+
298+_Depedency_ mungkin boleh jadi kompleks contohnya jika `WeatherFinder` itu sendiri perlu bergantung pada _value_ atau _object_ lain. Namun _dependency chain_ seperti ini sebenarnya adalah perkara biasa dalam sistem perisian. Agak sukar sebenarnya jika kita perlu susun sendiri semua _dependency_ ini setiap kali ingin menggunakan _class_ kita.
299+
300+Katakan _class_ `CityFinder` telah kita ubah supaya _constructor_nya menerima suatu `ConnectionPool` yang menguruskan hubungan ke pangkalan data. Jadi `CityFinder` tidak perlu tahu server mana yang perlu dihubungi. `WeatherWebService` pula menerima URL untuk webservice itu supaya kita mudah melakukan konfigurasi. Ini bermakna _dependency_ kepada hubungan pangkalan data atau URL ditelah dilonggarkan dari _class_ yang asal.
301+
302+Situasi seperti ini dapat dipermudahkan dengan menggunakan _framework-framework_ _DI Container_ atau kadangkala disebut _IoC Container_. _DI Container_ biasanya ada fungsi automatic injection untuk menguruskan _dependency_ secara automatik. Contoh _framework_ seperti ini yang ada di dalam dunia .NET adalah seperti Castle Windsor, Autofac, Ninject, dan sebagainya.
303+
304+_Container_ ini biasanya berfungsi seperti berikut:
305+
306+```csharp
307+
308+// DiContainer adalah sebuah framework khayalan
309+
310+var container = new DiContainer();
311+
312+container.Register<IConnectionPool>().Using<ConnectionPool>()
313+ .WithParamater("connString", "server1...");
314+
315+container.Register<ICityFinder>().Using<CityFinder>();
316+
317+container.Register<IWeatherFinder>().Using<WeatherWebService>()
318+ .WithParameter("url", "http://webservice/...");
319+
320+container.Register<IWeatherService>().Using<WeatherService>();
321+
322+// Panggil dari applikasi utama
323+
324+var svc = container.GetObject<IWeatherService>(); // Dapatkan WeatherService dari container
325+svc.ShowForIp("10.10.10.10");
326+
327+```
328+
329+Container akan mengambil tugas membina `WeatherService` dan menyambungkan semua _dependency_ nya supaya ia dapat hidup dan berfungsi. Kita tidak perlu menguruskannya sendiri.
330+
331+
332+## Kesimpulan
333+
334+_Dependency Injection_ tidak akan dapat difahami jika kita tidak memahami apa itu _dependency_ dan bagaimana ia boleh wujud. Setelah memahaminya, _Dependency Injection_ dapat digunakan untuk mengurus _dependency_ dan seterusnya membantu kita mencapai _modularity_ dan _flexibility_ yang diidam-idamkan dalam sistem kita. Gunakan juga _DI Container_ untuk memudahkan tugas kita menghubungkan _dependency_ antara _object_.
335+
336+_NOTA: Kod dalam artikel ini adalah khusus untuk memahami Dependency Injection. Ia mungkin mengabaikan aspek lain seperti keselamatan dan sebagainya._
337+
338+Perbincangan mengenai artikel ini ada di [sini](https://plus.google.com/105721265741813048018/posts/Av85xxdHXUx).
_posts/2014-09-13-memahami-session.mdView
@@ -1,0 +1,85 @@
1+---
2+layout: post
3+title: Memahami Session dalam Aplikasi Web
4+date: 2014-09-13
5+author: kamalmustafa
6+permalink: /memahami-session-dalam-aplikasi-web.html
7+---
8+
9+_Session_ dalam aplikasi web adalah untuk mengatasi masalah yang berkaitan dengan sifat _stateless_ dalam protokol HTTP. Contohnya apabila kita melayari satu laman web, dan membuka laman utama dan kemudian laman yang kedua, server tidak akan dapat mengenalpasti orang yang mengakses laman kedua adalah orang yang sama mengakses laman pertama tadi. Ini menyebabkan masalah apabila kita ingin membangunkan aplikasi di mana sebahagian daripada laman kita adalah untuk pengguna tertentu sahaja.
10+
11+<!--more-->
12+
13+Atau pun aplikasi yang perlu menyimpan data apa yang user lakukan pada laman pertama, dan seterusnya memaparkan di laman yang kedua atau seterusnya. Contohnya sebuah laman _e-commerce_ yang mempunyai fungsi _shopping cart_. Di laman pertama, pengguna akan _add_ barangan yang ingin dibeli ke dalam _cart_. Bila pengguna membuka laman lain di website tersebut, kita mungkin ingin memaparkan kepada pengguna apa yang telah mereka masukkan ke dalam _cart_.
14+
15+[Protokol HTTP][1] mempunyai konsep _cookie_, di mana apabila pengguna mengakses laman web kita, kita boleh 'tanam' data yang akan disimpan dalam komputer pengguna. Setiap kali mereka mengakses laman kita, data tersebut akan dihantar sekali. Ini membolehkan kita mengenalpasti pengguna ini telah pun melawat laman kita sebelum ini. Jadi secara teori, kita boleh menggunakan _cookie_ ini untuk menyelesaikan masalah berkaitan _shopping cart_ sebelum ini. Kita boleh simpan barang yang pengguna masukkan ke dalam _cart_ di dalam _cookie_. _Cookie_ bagaimana pun mempunyai beberapa masalah seperti saiz yang terhad (4K) dan juga pengguna boleh mengubah data yang disimpan di dalam _cookie_ sesuka hati mereka. Ada cara untuk mengelakkan data dalam _cookie_ diubah namun ia di luar skop artikel ini.
16+
17+Jadi satu teknik baru untuk menyimpan data pengguna digunakan - ia dipanggil _session_. Ia masih menggunakan _cookie_ tetapi tidak menyimpan kesemua data ke dalam cookie. Sebaliknya apa yang disimpan dalam _cookie_ hanyalah rujukan (reference / pointer) kepada data sebenar yang di simpan di bahagian server. Apa yang disimpan dalam _cookie_ hanyalah ID unik yang boleh digunakan untuk _query_ _data store_ di server bagi mendapatkan data sebenar. _data store_ ini boleh jadi berbentuk _file_ (default storage PHP session), row dalam database dan sebagainya. Dalam tulisan ini, saya cuba menunjukkan konsep asas implementasi _session_ menggunakan bahasa pengaturcaraan PHP.
18+
19+Berikut adalah kod utama yang akan _implement_ _session_ bagi web aplikasi kita. Kod ini boleh disimpan dalam fail bernama `mysession.php`:-
20+
21+```php
22+<?php
23+/* This is for learning purpose only - just to show how session in theory being
24+implemented. For real session usage, use the session provided by your web framework.
25+*/
26+
27+$HERE = realpath(dirname(__FILE__));
28+$SESSION_CLOSED = False;
29+
30+function end_session() {
31+ if (!$GLOBALS['SESSION_CLOSED']) {
32+ $session_file = $GLOBALS['HERE'] . '/' . $GLOBALS['_MYSESSID'] . '.session';
33+ file_put_contents($session_file, serialize($GLOBALS['_MYSESSION']));
34+ $GLOBALS['SESSION_CLOSED'] = True;
35+ }
36+}
37+
38+function start_session() {
39+ if (array_key_exists('mysessid', $_COOKIE)) {
40+ $mysessid = $_COOKIE['mysessid'];
41+ $session_file = $GLOBALS['HERE'] . '/' . $mysessid . '.session';
42+ if (file_exists($session_file)) {
43+ $GLOBALS['_MYSESSION'] = unserialize(file_get_contents($session_file));
44+ }
45+ else {
46+ $GLOBALS['_MYSESSION'] = array();
47+ }
48+ }
49+ else {
50+ $mysessid = uniqid('MYSESSID');
51+ setcookie('mysessid', $mysessid);
52+ $GLOBALS['_MYSESSION'] = array();
53+ }
54+ $GLOBALS['_MYSESSID'] = $mysessid;
55+ register_shutdown_function('end_session');
56+}
57+```
58+
59+Dan bagi setiap _page_ yang ingin menggunakan fungsi _session_ ini, contohnya `index.php`:-
60+
61+```php
62+<?php
63+
64+include 'mysession.php';
65+
66+start_session();
67+print_r($_MYSESSION);
68+$_MYSESSION['name'] = 'kamal';
69+```
70+
71+Page yang kedua, `index2.php`:-
72+
73+```php
74+<?php
75+
76+include 'mysession.php';
77+
78+start_session();
79+print_r($_MYSESSION);
80+$_MYSESSION['on_index2'] = True;
81+```
82+
83+Dalam contoh di atas, apabila pengguna melawat `index2.php`, data dalam `$_MYSESSION['name']` yang disetkan pada laman pertama akan dipaparkan. Dalam function `start_session()`, apa yang berlaku adalah kita check jika pengguna mempunyai nilai cookie `mysessid`, jika ada kita akan cuba load data yang disimpan dalam _file_ `$mysessid.session` ke dalam _variable_ global `$_MYSESSION`. Manakala setiap kali _script_ tersebut berakhir, kita akan simpan balik data dalam variable `$_MYSESSION` ke dalam _file_ `$mysessid.session`. Ini adalah konsep asas bagaimana _session_ berfungsi. Di sini kita menyimpan data di dalam _file_ namun boleh saja data tersebut disimpan di dalam database table dengan `mysessid` berfungsi sebagai _primary key_ bagi rekod tersebut.
84+
85+[1]:http://tools.ietf.org/html/rfc2616
_posts/2014-09-15-belajar-javascript-part-1.mdView
@@ -1,0 +1,148 @@
1+---
2+layout: post
3+title: 'Belajar Javascript: Bhg 1'
4+date: 2014-09-15
5+author: kamalmustafa
6+permalink: /belajar-javascript-bhg-1.html
7+---
8+
9+Memetik kata-kata [Douglas Crockford][1], JavaScript adalah bahasa
10+pengaturcaraan yang sering disalahfahami walaupun ianya merupakan bahasa
11+pengaturcaraan yang paling popular sekali dengan penggunaan yang paling meluas.
12+
13+<!--more-->
14+
15+JavaScript, sebelum penggunaannya yang begitu meluas seperti sekarang biasanya
16+menjadi bahasa kelas kedua bagi kebanyakkan programmer. Saya katakan kelas
17+kedua kerana ia jarang dipelajari secara formal sepertimana bahasa lain seperti
18+PHP, Python, Ruby, Perl, Java, C dan sebagainya. Maksud 'formal' disini ialah
19+kita mengambil masa untuk berkenalan dengan bahasa tersebut bermula daripada
20+ciri-ciri asas seperti *data type*, *control structure* dan sebagainya.
21+
22+Seringkali apabila terpaksa menggunakan JavaScript, kita akan mendapatkan
23+library ataupun *code snippet* di Internet, ubah beberapa baris dan sekiranya
24+ia melakukan apa yang kita kehendaki, selesai ! Akhirnya JavaScript sering
25+menjadi cercaan apabila beberapa masalahnya yang tidak dijangka kita temui
26+dalam aplikasi yang kita bangunkan.
27+
28+Saya bercadang untuk mula mempelajari JavaScript secara lebih tersusun dan
29+berharap dapat berkongsi pengalaman tersebut melalui beberapa siri tulisan
30+dalam blog ini. Untuk proses pembelajaran ini, saya akan cuba membina sebuah
31+aplikasi JavaScript ringkas dan akan cuba meneroka ciri-ciri asas JavaScript.
32+
33+Ini bagi saya lebih menarik dan tidak menjemukan berbanding mencuba satu demi
34+satu contoh kod bagi setiap *features* yang ada. Sebaliknya kita akan
35+mengenalpasti masalah yang perlu diselesaikan dan cuba cari *features*
36+JavaScript yang boleh digunakan untuk menyelesaikan masalah tersebut.
37+
38+Aplikasi yang saya ingin bangunkan adalah fungsi *autocomplete* ringkas. Kita
39+selalu temui *features* ini dalam banyak laman web, terutamanya yang melibatkan
40+fungsi carian. Saya juga banyak menggunakan *autocomplete* dalam aplikasi yang
41+saya bangunkan. Namun sehingga ke hari ini saya tidak pernah mengambil tahu
42+bagaimana sebenarya fungsi autocomplete ini berfungsi dalam JavaScript.
43+
44+Kita mulakan aplikasi ini dengan kod html ringkas seperti berikut:-
45+
46+```html
47+<html>
48+<head>
49+<script src="app.js"></script>
50+</head>
51+<body>
52+<input type="text" name="keyword" id="keyword" value="" size="20" />
53+</body>
54+</html>
55+```
56+
57+`app.js` pula akan kelihatan seperti di bawah:-
58+
59+```js
60+(function() {
61+ var keyword = document.getElementById('keyword');
62+ alert (keyword);
63+}());
64+```
65+
66+Daripada kod seringkas ini pun sebenarnya banyak yang dapat dipelajari
67+berkaitan JavaScript. Pertama sekali adalah cara kod itu sendiri ditulis. Ia
68+mungkin sedikit pelik bagi yang telah biasa menulis kod aturcara dalam bahasa
69+pengaturcaraan lain seperti PHP, Python, Perl, Java atau C. Sebenarnya kod
70+JavaScript digalakkan ditulis dalam bentuk sedemikian rupa untuk mengelakkan
71+*variable-variable* yang digunakan daripada bocor (*leaked*) ke dalam skop
72+global program. Ini antara satu kekurangan JavaScript dimana semua unit
73+aturcara hanya boleh wujud dalam satu skop iaitu global. Tidak wujud *module*
74+atau *namespace* dalam JavaScript. Bagaimanapun kita agak bernasib baik kerana
75+*function* dalam JavaScript adalah agak fleksibel jadi kita boleh
76+menggunakannya untuk mengehadkan skop variable yang kita gunakan.
77+
78+Walaupun *function* dalam JavaScript boleh digunakan untuk mengehadkan skop,
79+masih terdapat satu lagi keburukan JavaScript yang mesti diambil perhatian oleh
80+semua programmer iaitu kesemua variable yang digunakan dalam *function* mesti
81+diisytiharkan menggunakan *keyword* `var` sepertimana yang kita lihat dalam
82+contoh kod di atas. Jika tidak, ia akan turut wujud dalam skop global walaupun
83+hanya digunakan dalam *function* ! Sebagai contoh, perhatikan kod di bawah:-
84+
85+```js
86+function add(num1, num2) {
87+ _tmp1 = parseInt(num1);
88+ _tmp2 = parseInt(num2);
89+
90+ return _tmp1 + _tmp2;
91+}
92+
93+total = add(1, 2);
94+console.log(_tmp1);
95+```
96+
97+Dalam kod di atas, `tmp1` dan `_tmp2` hanyalah *variable* sementara dan
98+sepatutnya wujud dalam function `add` sahaja. Namun anda akan dapati
99+`console.log` tetap memaparkan nilai 2 iaitu nilai `_tmp2` di dalam function
100+`add` ! Ini tidak sepatutnya berlaku kerana dalam satu aturcara yang besar, ia
101+akan menyebabkan bug yang sukar dijejaki di mana puncanya kerana variable
102+`_tmp1` kini boleh dicapai oleh mana-mana bahagian aturcara sekalipun. Untuk
103+membetulkan keadaan di atas, *keyword* `var` mesti sentiasa digunakan untuk
104+mengisytiharkan *variable* dalam *function*. Contoh:-
105+
106+```js
107+function add(num1, num2) {
108+ var _tmp1 = parseInt(num1);
109+ var _tmp2 = parseInt(num2);
110+
111+ return _tmp1 + _tmp2;
112+}
113+```
114+
115+Seterusnya mengapa contoh kod sebelum ini ditulis dalam bentuk function ? Ini
116+juga melibatkan isu berkaitan global variable dalam JavaScript. Untuk
117+meminimumkan bilangan *variable* yang didedahkan kepada skop global, kita
118+*wrap* kod tersebut dalam function yang terus dipanggil apabila fail tersebut
119+dibuka oleh *JavaScript engine*. Kod sebelum ini contohnya, tidak mendedahkan
120+sebarang variable kepada skop global berbanding sekiranya ia ditulis seperti
121+berikut:-
122+
123+```js
124+function init() {
125+ var keyword = document.getElementById('keyword');
126+ alert (keyword);
127+}
128+
129+init();
130+```
131+
132+Dalam contoh ini kita telah mendedahkan satu nama baru ke dalam skop global
133+iaitu `init` walaupun `init` mungkin hanya akan digunakan sekali iaitu untuk
134+*run* kod dalam function tersebut. Jika kita perhatikan library JavaScript yang
135+besar seperti JQuery, YUI, Backbone dan sebagainya mereka hanya mendedahkan
136+satu nama ke dalam skop global seperti jQuery/$ utk JQuery dan YUI untuk YUI. *Function-function* lain kesemuanya diakses melalui *top level* namespace
137+tersebut seperti `$.getJSON`, `YUI.dom` dan sebagainya. Walaupun JavaScript
138+tidak mempunyai sokongan *namespace* atau *module*, function dan object boleh
139+digunakan untuk *simulate* namespace. Lagi yang boleh dipelajari daripada contoh
140+ringkas ini adalah perbezaan antara *function declaration* dan *function expression* tetapi saya tidak bercadang untuk mengulasnya dalam bahagian ini.
141+
142+Setakat ini sahaja untuk bahagian pertama. Saya berharap akan dapat terus menulis dan berkongsi bahagian seterusnya, Insya Allah.
143+
144+[1]:http://javascript.crockford.com/
145+[2]:http://stackoverflow.com/questions/1634268/explain-javascripts-encapsulated-anonymous-function-syntax
146+[3]:http://stackoverflow.com/questions/9342122/javascript-on-load-execution
147+[4]:https://plus.google.com/104286962752255423480/posts
148+[5]:https://plus.google.com/u/0/104286962752255423480/posts/Tb1ffbfzZdM
_posts/2014-11-04-belajar-javascript-part-2.mdView
@@ -1,0 +1,139 @@
1+---
2+layout: post
3+title: 'Belajar Javascript: Bhg 2'
4+date: 2014-11-04
5+author: kamalmustafa
6+permalink: /belajar-javascript-bhg-2.html
7+---
8+
9+Sebelum ini kita telah menulis kod JavaScript asas seperti berikut:-
10+
11+```js
12+(function() {
13+ var keyword = document.getElementById('keyword');
14+ alert keyword;
15+})();
16+```
17+
18+Bagi yang biasa dengan JavaScript pasti menyedari ada masalah dengan kod di
19+atas. Malah jika anda membuka fail `index.html` melalui browser, anda akan
20+dapati nilai yang dipaparkan dalam `alert` adalah `null`. Ini sudah pasti bukan
21+yang kita harapkan kerana nilai yang sepatutnya adalah reference kepada DOM
22+object HTMLInput. Ini adalah disebabkan kod tersebut terus dijalankan apabila
23+ia dibaca dalam browser. Bagaimanapun sentiasa ada kemungkinan semasa kod
24+tersebut dijalankan, DOM element yang kita cuba dapatkan masih belum disediakan
25+sepenuhnya oleh browser.
26+
27+<!--more-->
28+
29+Untuk membetulkan masalah di atas, kita perlu attach function tersebut kepada
30+`load` event sama ada pada object `window` ataupun pada element `body`. Contohnya adalah seperti berikut:-
31+
32+```js
33+window.onload = function() {
34+ var keyword = document.getElementById('keyword');
35+ alert('using window.onload');
36+ alert (keyword);
37+}
38+```
39+
40+Atau:-
41+
42+```js
43+function init() {
44+ var keyword = document.getElementById('keyword');
45+ alert('using body.onload');
46+ alert (keyword);
47+}
48+```
49+
50+```html
51+// dalam fail index.html
52+<body onload="init()">
53+</body>
54+```
55+
56+Tidak ada DOM object untuk `body` dan saya pada mulanya mencuba seperti
57+berikut:-
58+
59+```js
60+document.body.onload = function() {
61+ var keyword = document.getElementById('keyword');
62+ alert('using document.body.onload');
63+ alert (keyword);
64+}
65+```
66+
67+tetapi mendapat error `Uncaught TypeError: Cannot set property 'onload' of
68+null`. Menggunakan `body onload=init()` bagaimanapun memerlukan untuk kita
69+declare satu function pada skop global, sesuatu yang kita cuba elakkan seperti
70+yang telah dibincangkan dalam tulisan yang lalu. Bagi browser moden pada hari
71+ini, cara yang direkomenkan adalah dengan menggunakan event listener seperti
72+berikut:-
73+
74+```js
75+(function() {
76+ window.addEventListener('load', function() {
77+ var keyword = document.getElementById('keyword');
78+ alert (keyword);
79+ }, false);
80+}());
81+```
82+
83+Kelebihan cara di atas adalah struktur kod kita masih kekal sebagaimana asal
84+dipermulaan siri ini. Bagaimanapun menggunakan `load` event tetap mempunyai
85+satu masalah iaitu kod tersebut hanya akan dijalankan apabila kesemua elemen
86+dan juga *resource* seperti imej telah selesai dimuat-turun oleh browser. Kebanyakkan kod JavaScript adalah untuk memanipulasi DOM jadi agak membuang
87+masa dan juga mungkin menghasilkan kesan yang tidak diingini jika terpaksa
88+menunggu kesemua *resource* selesai dimuat-turun sebelum kod JavaScript kita
89+boleh memainkan peranan. Alternatif kepada `load` event adalah
90+`DOMContentLoaded` dan kod di atas boleh ditulis seperti berikut:-
91+
92+```js
93+(function() {
94+ window.addEventListener('DOMContentLoaded', function() {
95+ var keyword = document.getElementById('keyword');
96+ alert (keyword);
97+ }, false);
98+}());
99+```
100+
101+Kelebihan `DOMContentLoaded` adalah ia akan terus *execute* kod kita sebaik
102+sahaja kesemua struktur DOM telah dibina dalam memori. Namun hidup dalam dunia
103+JavaScript adalah sangat tidak menentu dan sukar diduga. Tidak semua browser
104+menyokong event `DOMContentLoaded` ini jadi kod kita perlu melakukan beberapa
105+adaptasi bagi membolehkan ia berfungsi pada semua browser. Atas sebab inilah
106+library seperti JQuery menyediakan function khas untuk mengatasi masalah ini. Menggunakan JQuery, kod di atas boleh ditulis seperti berikut:-
107+
108+```js
109+(function() {
110+ $(document).ready(function() {
111+ var keyword = document.getElementById('keyword');
112+ alert (keyword);
113+ });
114+}());
115+```
116+
117+Untuk membaca dengan lebih lanjut berkaitan isu yang dibincangkan dalam
118+bahagian ini boleh rujuk perbincangan di laman stackoverflow:-
119+
120+1. http://stackoverflow.com/questions/3698200/window-onload-vs-document-ready
121+1. http://stackoverflow.com/questions/3474037/window-onload-vs-body-onload-vs-document-onready
122+
123+## Nota
124+Saudara [Zulfa Juniadi][zulfa] memberikan komen dalam grup FB [JomWeb] bahawa penggunaan
125+`$.ready()` adalah tidak perlu sekiranya kod JavaScript kita diletakkan pada pengakhiran dokumen, sebelum tag `</body>`. Ini
126+kerana apabila kod tersebut dijalankan oleh browser, kesemua kandungan DOM telah pun diproses
127+oleh browser, menghasilkan kesan yang sama seperti `DOMContentLoaded` yang dibincangkan di atas.
128+Perbincangan berkaitan di Stackoverflow - http://stackoverflow.com/q/4643990/139870.
129+
130+[Cadangan lain] di Stackoverflow adalah untuk load JavaScript pada bahagian `<head>` tapi menggunakan `async` atau `defer`
131+attribute. Cara ini juga tidak akan *block* browser daripada terus memproses laman HTML kita dan disokong oleh
132+80% browser moden pada hari ini.
133+
134+Sekian untuk kali ini, sehingga berjumpa lagi untuk siri akan datang, Insya
135+Allah.
136+
137+[zulfa]:https://github.com/zulfajuniadi
138+[JomWeb]:https://www.facebook.com/groups/jomweb/
139+[Cadangan lain]:http://stackoverflow.com/questions/436411/where-is-the-best-place-to-put-script-tags-in-html-markup/24070373#24070373
_posts/2014-11-09-belajar-javascript-part-3.mdView
@@ -1,0 +1,190 @@
1+---
2+layout: post
3+title: 'Belajar Javascript: Bhg 3'
4+date: 2014-11-09
5+author: kamalmustafa
6+permalink: /belajar-javascript-bhg-3.html
7+---
8+
9+Alhamdulillah, kita dapat bertemu lagi dalam bahagian ke-3, siri belajar bahasa
10+pengaturcaraan JavaScript. Untuk bahagian ke-3 ini bagaimanapun saya memohon maaf
11+terlebih dahulu kerana fokusnya bukan pada JavaScript secara umum tetapi lebih
12+kepada 'browser DOM programming' kerana saya ingin memulakan apa yang saya rancang
13+pada bahagian 1 iaitu membina sebuah *autocomplete* ringkas.
14+
15+<!--more-->
16+
17+Kita mulakan dengan dokumen HTML ringkas seperti di bawah:-
18+
19+```html
20+<html>
21+<head>
22+<style>
23+</style>
24+</head>
25+<body>
26+<input type="text" name="keyword" id="keyword" value="" size="20" />
27+<script src="app.js"></script>
28+</body>
29+</html>
30+```
31+Manakala `app.js` adalah seperti berikut:-
32+
33+```js
34+(function() {
35+ var keyword_elm = document.getElementById('keyword');
36+}());
37+```
38+!!! info "Nota" "info-sign"
39+ Saya akan menggunakan *suffix* `_elm` bagi setiap *variable* dalam tutorial ini
40+ bagi menunjukkan yang ia adalah *DOM element*.
41+
42+Sebelum itu mari kita lihat dulu perkara-perkara yang perlu kita lakukan untuk membina
43+fungsi *auto complete* ini:-
44+
45+* Apabila pengguna menaip beberapa karakter di dalam kotak carian, satu *pop-up* akan
46+ dipaparkan di bawah kotak carian tersebut, memaparkan beberapa cadangan yang berkaitan.
47+* Pengguna boleh klik mana-mana cadangan yang dipaparkan dan ia akan dimasukkan ke dalam
48+ kotak carian.
49+* Pengguna juga boleh skroll *pop-up* cadangan dan memilih hanya dengan menekan butang
50+ Enter pada *keyboard*.
51+
52+Bagi keperluan pertama, kita boleh menggunakan *event* `keyup` pada elemen input kotak
53+carian. *Event* `keyup` ini akan dijana oleh browser apabila pengguna menekan sesuatu
54+kekunci pada *keyboard* dan melepaskannya. Jadi kita boleh menulis kod JavaScript seperti
55+berikut:-
56+
57+```js
58+(function() {
59+ var keyword_elm = document.getElementById('keyword');
60+ keyword_elm.addEventListener('keyup', function(evt) {
61+ var keyword = evt.target.value;
62+ console.log(keyword);
63+ });
64+}());
65+```
66+
67+!!! warning "Nota" "exclamation-sign"
68+ Method `.addEventListener()` tidak disokong oleh IE7 dan IE6. Kebanyakkan contoh dalam
69+ tutorial ini menganggap anda menggunakan browser moden yang terkini.
70+
71+Setiap *event handler function* akan di*pass* satu *argument* berbentuk *event object*
72+yang mengandungi maklumat terperinci berkaitan *event* yang dijana oleh browser.
73+Maklumat lanjut berkaitan *event handler* ini boleh dirujuk kepada laman [Eloquent
74+JavaScript][eloquent]. Melalui *event object* ini, kita akan dapat merujuk kembali
75+kepada elemen asal di mana *event* tersebut dijana. Ini membolehkan kita untuk meraih
76+nilai yang dimasukkan oleh pengguna pada elemen input kotak carian.
77+
78+*Event* `keyup` akan dijana oleh browser setiap kali pengguna menaip sesuatu karakter
79+pada *keyboard* dan ini juga bermakna setiap kali itulah juga kod JavaScript kita
80+perlu *handle* dan memproses *event* tersebut. Ia agak tidak efisien dan antara cadangan
81+yang saya jumpa adalah dengan menggunakan function `setTimeout` untuk [mengesan hanya
82+setelah pengguna berhenti menaip baru kod JavaScript kita bertindak][settimeout]. Saya
83+bagaimanapun akan mengabaikan isu ini buat seketika.
84+
85+Kita teruskan dengan melaksanakan apa yang diperlukan pada syarat pertama fungsi ini
86+iaitu memaparkan *pop-up* apabila pengguna menaip sesuatu pada kotak carian. Untuk
87+permulaan ini, saya akan menggunakan cara yang paling naif terlebih dahulu. Kita akan
88+sama-sama menambah baik menggunakan teknik yang lebih sesuai dan canggih pada siri yang
89+akan datang, setelah kita semakin menguasai teknik pengaturcaraan `browser DOM`
90+menggunakan JavaScript ini.
91+
92+Cara naif pertama yang saya gunakan adalah dengan meletakkan *hidden div* di bawah
93+kotak carian untuk dipaparkan sebagai *pop-up*:-
94+
95+```html
96+<html>
97+<head>
98+<style>
99+#keyword-result {
100+ visibility: hidden;
101+ border: 1px solid;
102+ width: 170px;
103+}
104+</style>
105+</head>
106+<body>
107+<input type="text" name="keyword" id="keyword" value="" size="20" />
108+<div id="keyword-result">
109+</div>
110+<script src="app.js"></script>
111+</body>
112+</html>
113+```
114+
115+Kod JavaScript adalah seperti berikut:-
116+
117+```js
118+(function() {
119+ var keyword_elm = document.getElementById('keyword');
120+ keyword_elm.addEventListener('keyup', function(evt) {
121+ var keyword = evt.target.value;
122+ var keyword_result_elm = document.getElementById('keyword-result');
123+ var list_elm = document.createElement('ul');
124+ if (keyword.length > 2) {
125+ for (var i = 0; i < 5; i++) {
126+ var list_item_elm = document.createElement('li');
127+ var list_item = document.createTextNode('result ' + i);
128+ list_item_elm.appendChild(list_item);
129+ list_elm.appendChild(list_item_elm);
130+ }
131+ }
132+ keyword_result_elm.appendChild(list_elm);
133+ keyword_result_elm.style.visibility = 'visible';
134+ });
135+}());
136+```
137+
138+Dalam kod di atas, apa yang ia lakukan adalah bertindak balas terhadap *event* `keyup`
139+pada kotak carian dan kemudian secara dinamik membina sebuah *unordered list* (`<ul>`).
140+List tersebut kemudian dimasukkan ke dalam elemen `div` yang pada asalnya adalah *hidden*.
141+Elemen `div` tersebut kemudian dipaparkan dengan mengeset *properties* *visibility* kepada
142+`visible`, memberikan efek seperti element tersebut *pop-up* pada bahagian bawah kotak
143+carian.
144+
145+Setelah dapat memaparkan *pop-up*, kita beralih kepada syarat kedua iaitu membolehkan
146+setiap elemen dalam *list* yang kita jana sebelum ini boleh di'klik' dan nilainya
147+dipaparkan pada kotak carian. Ianya boleh dilakukan dengan meng'attach' *event* `click`
148+pada setiap item dalam list tersebut:-
149+
150+```javascript
151+list_item_elm.addEventListener('click', function(evt) {
152+ keyword_elm.value = evt.target.textContent;
153+ keyword_result_elm.style.display = 'none';
154+});
155+```
156+Di sini kita raih nilai string yang ada pada setiap item dalam list dan setkan sebagai
157+*value* kepada kotak carian. Seterusnya kita set *properties* *display* pada *pop-up*
158+kepada `none` untuk memberikan kesan seperti ia hilang.
159+
160+Syarat ketiga adalah untuk membolehkan pengguna memilih menggunakan *keyboard* berbanding
161+mengklik menggunakan *mouse*. Saya masih belum dapat mencari penyelesaian kepada masalah
162+ini. Cubaan pertama saya adalah dengan *properties* `scroll` pada `div`:-
163+
164+```css
165+#keyword-result {
166+ display:hidden;
167+ border: 1px solid;
168+ width: 170px;
169+ overflow-y: scroll;
170+}
171+```
172+Ia akan meletakkan *scroll bar* pada `div` tersebut tetapi kita masih belum dapat skroll
173+seperti fungsi *auto complete* yang biasa kita temui. Ia mungkin sebab *focus* masih
174+pada kotak carian. Jadi saya cuba set *fokus* pada *pop-up* tersebut tetapi ini akan
175+menghalang saya daripada terus menaip pada kotak carian kerana kini *focus* adalah pada
176+*pop-up*. Ini adalah satu masalah yang menarik, saya masih lagi meneliti [script ini][autoComplt]
177+dan [ini][completely] untuk mengenalpasti bagaimana ia menyelesaikan masalah *scroll* ini.
178+
179+Sekiranya anda mempunyai sebarang idea, saya mengalu-alukan idea dan cadangan anda ! Kod penuh untuk
180+tutorial ini boleh dilihat pada laman [codepen].
181+
182+[eloquent]:http://eloquentjavascript.net/14_event.html
183+[settimeout]:http://davidwalsh.name/javascript-settimeout
184+[autoComplt]:https://github.com/Fischer-L/autoComplt
185+[completely]:http://complete-ly.appspot.com/
186+[codepen]:http://codepen.io/k4ml/pen/zxxzJq
187+
188+### Rujukan
189+* http://stackoverflow.com/questions/9707397/making-a-div-vertically-scrollable-using-css
190+* http://stackoverflow.com/questions/6754275/set-keyboard-focus-to-a-div
about.mdView
@@ -1,0 +1,62 @@
1+---
2+layout: page
3+title: Mengenai Kami
4+---
5+
6+<p class="message">
7+ Maklumat di halaman ini belum dikemaskini sepenuhnya.
8+</p>
9+## Tentang MyDev
10+
11+MyDev adalah komuniti pembangun perisian dan web di Malaysia. Anda dijemput untuk menyertai kami dan menyumbang dalam perbincangan sekitar topik pembangunan perisian dan web, teknologi maklumat, kerjaya, dan sebagainya. Atau paling tidak boleh melepak dengan geng-geng sekepala :)
12+
13+Sertai kami di [MyDev Google+ Community](https://plus.google.com/communities/104883828501447858589)
14+
15+
16+## Tentang Laman Kolaborasi MyDev
17+
18+Ini adalah satu inisiatif MyDev untuk memperkayakan sumber maklumat dalam Bahasa Melayu tentang pembangunan perisian dan web. Laman ini diinspirasikan dari [laman html5rocks](http://www.html5rocks.com/) yang mana kandungannya adalah disumbangkan oleh orang ramai. Semua kandungan termasuk kod sumber untuk laman ini kami letakkan di dalam [GitHub](http://github.org). Orang ramai boleh menambah atau mengubah artikel melalui perisian Git version control system.
19+
20+
21+## Ingin Menyumbang?
22+
23+Kami menjemput sumbangan artikel berkaitan pembangunan perisian dan web dari semua. Syaratnya cuma satu, artikel perlu di dalam Bahasa Melayu. Artikel boleh jadi hasil asli ataupun terjemahan artikel dari bahasa lain (sila hormati hakcipta jika ada). Anda juga digalakkan melakukan pembetulan untuk artikel sedia ada.
24+
25+Anda perlu tahu menggunakan [Markdown](http://daringfireball.net/projects/markdown/syntax) untuk menulis artikel. Anda juga perlu tahu bagaimana menggunakan [Git](http://git-scm.com) dan melakukan pull request dalam [GitHub](http://github.org). Kami menggunakan [Pelican](http://getpelican.com) sebagai CMS, jadi mungkin anda perlu tahu serba sedikit mengenainya juga.
26+
27+Secara umumnya, langkah untuk menyumbang adalah seperti berikut:
28+
29+1. _Fork repository_ [https://github.com/mydevcommunity/mydev](https://github.com/mydevcommunity/mydev).
30+1. Lakukan proses menulis atau mengedit. Buat satu fail dalam _folder_ `site\content` atau ubah fail sedia ada. Lihat artikel lain sebagai contoh atau rujuk panduan di [sini](http://docs.getpelican.com/en/3.1.1/getting_started.html#writing-articles-using-pelican).
31+1. Bila selesai, hantarkan satu _pull request_ ke _repository_ asal.
32+1. Admin akan menilai _pull request_ anda. Ia kemudiannya akan _dipublish_ ke laman ini.
33+
34+Untuk mengedit (proses 2. di atas), anda boleh `git clone` ke komputer anda dan gunakan editor kegemaran anda. Anda juga boleh menggunakan fitur di dalam GitHub sendiri untuk mengedit. Selain itu anda boleh menggunakan _online IDE_ seperti [Cloud9](http://c9.io).
35+
36+Jika anda memerlukan editor WYSIWYG untuk Markdown, salah satu _online editor_ yang boleh dicuba ialah [Dillinger.io](http://dillinger.io/)
37+
38+Jika anda ingin membuat perubahan terhadap _theme_ atau perkara lain yang bukan _content_. Anda mungkin perlu _generate_ laman ini sendiri di komputer anda untuk memastikan semuanya baik sebelum melakukan pull request. Caranya ialah:
39+
40+* Pastikan Python sudah diinstall. Dapatkan Python dari distribusi rasmi [Python.org](http://python.org/download/) atau lain-lain seperti [Portable Python](http://portablepython.com/).
41+* Larikan arahan ini pada terminal/command line:-
42+
43+```console
44+mkdir -p app-root && ln -s ../ app-root/repo
45+OPENSHIFT_HOMEDIR=. OPENSHIFT_DATA_DIR=.env .openshift/action_hooks/build
46+PORT=9090 IP=127.0.0.1 python server.py
47+```
48+
49+* Anda boleh buka akses melalui browser http://127.0.0.1:9090/
50+
51+Jika anda menggunakan Cloud9, arahan sama boleh dilarikan di terminal dalam workspace Cloud9 anda. Cloud9 sudah terbina dalam dengan Python dan Git.
52+
53+Dengan menyumbang ke laman ini bermakna anda menerima untuk melesenkan artikel anda dibawah [Creative Commons Attribution 4.0 License](http://creativecommons.org/licenses/by/4.0/).
54+
55+## Kenapa Git dan GitHub?
56+
57+Kami letakkan kandungan dan kod sumber laman ini di GitHub supaya jika ditakdirkan suatu hari nanti laman ini tidak dapat diteruskan, semua ilmu yang telah dikongsikan tidak terpendam begitu sahaja. Ia masih dapat diperolehi dari GitHub dan dari _clone_ yang ada pada orang ramai, lalu masih dapat dimanfaatkan oleh semua.
58+
59+Melalui _pull request_ dalam GitHub juga boleh digunakan sebagai suatu sistem penilaian yang _ad-hoc_ oleh admin untuk mengawal kualiti laman ini.
60+
61+Lagi pula, pada yang orang-orang baru, melalui cara ini mereka dapat belajar teknik-teknik menggunakan _distributed version control system_ dan berkolaborasi secara online.
62+
archive.htmlView
@@ -1,0 +1,17 @@
1+---
2+layout: page
3+title: Arkib
4+---
5+
6+<ul class="related-posts">
7+ {% for post in site.posts %}
8+ <li>
9+ <h3>
10+ <a href="{{ site.baseurl}}{{ post.url }}">
11+ {{ post.title }}
12+ <small>{{ post.date | date_to_string }}</small>
13+ </a>
14+ </h3>
15+ </li>
16+ {% endfor %}
17+</ul>
atom.xmlView
@@ -1,0 +1,28 @@
1+---
2+layout: null
3+---
4+
5+<?xml version="1.0" encoding="utf-8"?>
6+<feed xmlns="http://www.w3.org/2005/Atom">
7+
8+ <title>{{ site.title }}</title>
9+ <link href="{{ site.url }}/atom.xml" rel="self"/>
10+ <link href="{{ site.url }}/"/>
11+ <updated>{{ site.time | date_to_xmlschema }}</updated>
12+ <id>{{ site.url }}</id>
13+ <author>
14+ <name>{{ site.author.name }}</name>
15+ <email>{{ site.author.email }}</email>
16+ </author>
17+
18+ {% for post in site.posts %}
19+ <entry>
20+ <title>{{ post.title }}</title>
21+ <link href="{{ site.url }}{{ post.url }}"/>
22+ <updated>{{ post.date | date_to_xmlschema }}</updated>
23+ <id>{{ site.url }}{{ post.id }}</id>
24+ <content type="html">{{ post.content | xml_escape }}</content>
25+ </entry>
26+ {% endfor %}
27+
28+</feed>
authors.htmlView
@@ -1,0 +1,56 @@
1+---
2+layout: page
3+title: Penulis
4+---
5+
6+<style>
7+.pic {
8+ float: left;
9+ width: 120px;
10+ padding-right: 0 !important;
11+ padding-top: 20px !important;
12+}
13+
14+.pic img {
15+ border-radius: 50% !important;
16+ -webkit-border-radius: 50% !important;
17+ -moz-border-radius: 50% !important;
18+ width: 100px;
19+ height: 100px;
20+
21+}
22+
23+.bio {
24+ float: left;
25+ width: 558px;
26+ padding-left: 0 !important;
27+ text-align: justify;
28+}
29+
30+.clear {
31+ clear: both;
32+ margin-bottom: 30px;
33+}
34+</style>
35+
36+
37+
38+{% for author_item in site.authors %}
39+ {% assign key = author_item[0] %}
40+ {% assign author = author_item[1] %}
41+
42+ <div class="clear"></div>
43+
44+ <div class="pic">
45+ <a name="{{ key }}" />
46+ <img src="{{ author.pic }}" />
47+ </div>
48+ <div class="bio">
49+ <p>
50+ {{ author.full_bio_ms }}
51+ <p>
52+ <p style="font-style:italic">
53+ {{ author.full_bio_en }}
54+ </p>
55+ </div>
56+{% endfor %}
public/apple-touch-icon-144-precomposed.png
public/apple-touch-icon-144-precomposed.png
public/css/custom.cssView
@@ -1,0 +1,71 @@
1+/*
2+ * Author
3+ */
4+
5+.author {
6+ margin-bottom: 1rem;
7+ padding: 1rem;
8+ color: #717171;
9+ background-color: #f9f9f9;
10+}
11+
12+.author:after {
13+ content: "";
14+ display: table;
15+ clear: both;
16+}
17+
18+.author .gravatar {
19+ float: left;
20+}
21+
22+.author .detail {
23+ margin-left: 90px;
24+}
25+
26+.author .name {
27+ font-weight: bold;
28+}
29+
30+.author .bio {
31+ line-height: 1rem;
32+ font-size: 90%;
33+}
34+
35+/*
36+ * TOC
37+ */
38+
39+#toc_toggle {
40+ float: right;
41+ font-size: 90%;
42+ font-style: italic;
43+ cursor: pointer;
44+ margin-right: 5px;
45+}
46+
47+#toc {
48+ display: none;
49+ background: #f9f9f9;
50+ padding: 20px;
51+ margin-bottom: 20px;
52+}
53+
54+.clickable-header {
55+ cursor: pointer;
56+}
57+
58+.clickable-header:hover {
59+ text-decoration: underline;
60+}
61+
62+.top-level-header {
63+ display: inline;
64+}
65+
66+.back-to-top {
67+ margin: 12px 0;
68+ cursor: pointer;
69+ float: right;
70+ color: #aaa;
71+}
public/css/hyde.cssView
@@ -1,0 +1,250 @@
1+/*
2+ * __ __
3+ * /\ \ /\ \
4+ * \ \ \___ __ __ \_\ \ __
5+ * \ \ _ `\/\ \/\ \ /'_` \ /'__`\
6+ * \ \ \ \ \ \ \_\ \/\ \_\ \/\ __/
7+ * \ \_\ \_\/`____ \ \___,_\ \____\
8+ * \/_/\/_/`/___/> \/__,_ /\/____/
9+ * /\___/
10+ * \/__/
11+ *
12+ * Designed, built, and released under MIT license by @mdo. Learn more at
13+ * https://github.com/poole/hyde.
14+ */
15+
16+
17+/*
18+ * Contents
19+ *
20+ * Global resets
21+ * Sidebar
22+ * Container
23+ * Reverse layout
24+ * Themes
25+ */
26+
27+
28+/*
29+ * Global resets
30+ *
31+ * Update the foundational and global aspects of the page.
32+ */
33+
34+html {
35+ font-family: "PT Sans", Helvetica, Arial, sans-serif;
36+}
37+@media (min-width: 48em) {
38+ html {
39+ font-size: 16px;
40+ }
41+}
42+@media (min-width: 58em) {
43+ html {
44+ font-size: 20px;
45+ }
46+}
47+
48+
49+/*
50+ * Sidebar
51+ *
52+ * Flexible banner for housing site name, intro, and "footer" content. Starts
53+ * out above content in mobile and later moves to the side with wider viewports.
54+ */
55+
56+.sidebar {
57+ text-align: center;
58+ padding: 2rem 1rem;
59+ color: rgba(255,255,255,.5);
60+ background-color: #202020;
61+}
62+@media (min-width: 48em) {
63+ .sidebar {
64+ position: fixed;
65+ top: 0;
66+ left: 0;
67+ bottom: 0;
68+ width: 18rem;
69+ text-align: left;
70+ }
71+}
72+
73+/* Sidebar links */
74+.sidebar a {
75+ color: #fff;
76+}
77+
78+/* About section */
79+.sidebar-about h1 {
80+ color: #fff;
81+ margin-top: 0;
82+ font-family: "Abril Fatface", serif;
83+ font-size: 3.25rem;
84+}
85+
86+/* Sidebar nav */
87+.sidebar-nav {
88+ margin-bottom: 1rem;
89+}
90+.sidebar-nav-item {
91+ display: block;
92+ line-height: 1.75;
93+}
94+a.sidebar-nav-item:hover,
95+a.sidebar-nav-item:focus {
96+ text-decoration: underline;
97+}
98+.sidebar-nav-item.active {
99+ font-weight: bold;
100+}
101+
102+/* Sticky sidebar
103+ *
104+ * Add the `sidebar-sticky` class to the sidebar's container to affix it the
105+ * contents to the bottom of the sidebar in tablets and up.
106+ */
107+
108+@media (min-width: 48em) {
109+ .sidebar-sticky {
110+ position: absolute;
111+ right: 1rem;
112+ bottom: 1rem;
113+ left: 1rem;
114+ }
115+}
116+
117+
118+/* Container
119+ *
120+ * Align the contents of the site above the proper threshold with some margin-fu
121+ * with a 25%-wide `.sidebar`.
122+ */
123+
124+.content {
125+ padding-top: 4rem;
126+ padding-bottom: 4rem;
127+}
128+
129+@media (min-width: 48em) {
130+ .content {
131+ max-width: 38rem;
132+ margin-left: 20rem;
133+ margin-right: 2rem;
134+ }
135+}
136+
137+@media (min-width: 64em) {
138+ .content {
139+ margin-left: 22rem;
140+ margin-right: 4rem;
141+ }
142+}
143+
144+
145+/*
146+ * Reverse layout
147+ *
148+ * Flip the orientation of the page by placing the `.sidebar` on the right.
149+ */
150+
151+@media (min-width: 48em) {
152+ .layout-reverse .sidebar {
153+ left: auto;
154+ right: 0;
155+ }
156+ .layout-reverse .content {
157+ margin-left: 2rem;
158+ margin-right: 20rem;
159+ }
160+}
161+
162+@media (min-width: 64em) {
163+ .layout-reverse .content {
164+ margin-left: 4rem;
165+ margin-right: 22rem;
166+ }
167+}
168+
169+
170+
171+/*
172+ * Themes
173+ *
174+ * As of v1.1, Hyde includes optional themes to color the sidebar and links
175+ * within blog posts. To use, add the class of your choosing to the `body`.
176+ */
177+
178+/* Base16 (http://chriskempson.github.io/base16/#default) */
179+
180+/* Red */
181+.theme-base-08 .sidebar {
182+ background-color: #ac4142;
183+}
184+.theme-base-08 .content a,
185+.theme-base-08 .related-posts li a:hover {
186+ color: #ac4142;
187+}
188+
189+/* Orange */
190+.theme-base-09 .sidebar {
191+ background-color: #d28445;
192+}
193+.theme-base-09 .content a,
194+.theme-base-09 .related-posts li a:hover {
195+ color: #d28445;
196+}
197+
198+/* Yellow */
199+.theme-base-0a .sidebar {
200+ background-color: #f4bf75;
201+}
202+.theme-base-0a .content a,
203+.theme-base-0a .related-posts li a:hover {
204+ color: #f4bf75;
205+}
206+
207+/* Green */
208+.theme-base-0b .sidebar {
209+ background-color: #90a959;
210+}
211+.theme-base-0b .content a,
212+.theme-base-0b .related-posts li a:hover {
213+ color: #90a959;
214+}
215+
216+/* Cyan */
217+.theme-base-0c .sidebar {
218+ background-color: #75b5aa;
219+}
220+.theme-base-0c .content a,
221+.theme-base-0c .related-posts li a:hover {
222+ color: #75b5aa;
223+}
224+
225+/* Blue */
226+.theme-base-0d .sidebar {
227+ background-color: #6a9fb5;
228+}
229+.theme-base-0d .content a,
230+.theme-base-0d .related-posts li a:hover {
231+ color: #6a9fb5;
232+}
233+
234+/* Magenta */
235+.theme-base-0e .sidebar {
236+ background-color: #aa759f;
237+}
238+.theme-base-0e .content a,
239+.theme-base-0e .related-posts li a:hover {
240+ color: #aa759f;
241+}
242+
243+/* Brown */
244+.theme-base-0f .sidebar {
245+ background-color: #8f5536;
246+}
247+.theme-base-0f .content a,
248+.theme-base-0f .related-posts li a:hover {
249+ color: #8f5536;
250+}
public/css/poole.cssView
@@ -1,0 +1,430 @@
1+/*
2+ * ___
3+ * /\_ \
4+ * _____ ___ ___\//\ \ __
5+ * /\ '__`\ / __`\ / __`\\ \ \ /'__`\
6+ * \ \ \_\ \/\ \_\ \/\ \_\ \\_\ \_/\ __/
7+ * \ \ ,__/\ \____/\ \____//\____\ \____\
8+ * \ \ \/ \/___/ \/___/ \/____/\/____/
9+ * \ \_\
10+ * \/_/
11+ *
12+ * Designed, built, and released under MIT license by @mdo. Learn more at
13+ * https://github.com/poole/poole.
14+ */
15+
16+
17+/*
18+ * Contents
19+ *
20+ * Body resets
21+ * Custom type
22+ * Messages
23+ * Container
24+ * Masthead
25+ * Posts and pages
26+ * Pagination
27+ * Reverse layout
28+ * Themes
29+ */
30+
31+
32+/*
33+ * Body resets
34+ *
35+ * Update the foundational and global aspects of the page.
36+ */
37+
38+* {
39+ -webkit-box-sizing: border-box;
40+ -moz-box-sizing: border-box;
41+ box-sizing: border-box;
42+}
43+
44+html,
45+body {
46+ margin: 0;
47+ padding: 0;
48+}
49+
50+html {
51+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
52+ font-size: 16px;
53+ line-height: 1.5;
54+}
55+@media (min-width: 38em) {
56+ html {
57+ font-size: 20px;
58+ }
59+}
60+
61+body {
62+ color: #515151;
63+ background-color: #fff;
64+ -webkit-text-size-adjust: 100%;
65+ -ms-text-size-adjust: 100%;
66+}
67+
68+/* No `:visited` state is required by default (browsers will use `a`) */
69+a {
70+ color: #268bd2;
71+ text-decoration: none;
72+}
73+a strong {
74+ color: inherit;
75+}
76+/* `:focus` is linked to `:hover` for basic accessibility */
77+a:hover,
78+a:focus {
79+ text-decoration: underline;
80+}
81+
82+/* Headings */
83+h1, h2, h3, h4, h5, h6 {
84+ margin-bottom: .5rem;
85+ font-weight: bold;
86+ line-height: 1.25;
87+ color: #313131;
88+ text-rendering: optimizeLegibility;
89+}
90+h1 {
91+ font-size: 2rem;
92+}
93+h2 {
94+ margin-top: 1rem;
95+ font-size: 1.5rem;
96+}
97+h3 {
98+ margin-top: 1.5rem;
99+ font-size: 1.25rem;
100+}
101+h4, h5, h6 {
102+ margin-top: 1rem;
103+ font-size: 1rem;
104+}
105+
106+/* Body text */
107+p {
108+ margin-top: 0;
109+ margin-bottom: 1rem;
110+}
111+
112+strong {
113+ color: #303030;
114+}
115+
116+
117+/* Lists */
118+ul, ol, dl {
119+ margin-top: 0;
120+ margin-bottom: 1rem;
121+}
122+
123+dt {
124+ font-weight: bold;
125+}
126+dd {
127+ margin-bottom: .5rem;
128+}
129+
130+/* Misc */
131+hr {
132+ position: relative;
133+ margin: 1.5rem 0;
134+ border: 0;
135+ border-top: 1px solid #eee;
136+ border-bottom: 1px solid #fff;
137+}
138+
139+abbr {
140+ font-size: 85%;
141+ font-weight: bold;
142+ color: #555;
143+ text-transform: uppercase;
144+}
145+abbr[title] {
146+ cursor: help;
147+ border-bottom: 1px dotted #e5e5e5;
148+}
149+
150+/* Code */
151+code,
152+pre {
153+ font-family: Menlo, Monaco, "Courier New", monospace;
154+}
155+code {
156+ padding: .25em .5em;
157+ font-size: 85%;
158+ color: #bf616a;
159+ background-color: #f0f0f0;
160+ border-radius: 3px;
161+}
162+pre {
163+ display: block;
164+ margin-top: 0;
165+ margin-bottom: 1rem;
166+ padding: 1rem;
167+ font-size: .8rem;
168+ line-height: 1.4;
169+ white-space: pre;
170+ white-space: pre-wrap;
171+ word-break: break-all;
172+ word-wrap: break-word;
173+ background-color: #f0f0f0;
174+}
175+pre code {
176+ padding: 0;
177+ font-size: 100%;
178+ color: inherit;
179+ background-color: transparent;
180+}
181+
182+/* Pygments via Jekyll */
183+.highlight {
184+ margin-bottom: 1rem;
185+ border-radius: 4px;
186+}
187+.highlight pre {
188+ margin-bottom: 0;
189+}
190+
191+/* Gist via GitHub Pages */
192+.gist .gist-file {
193+ font-family: Menlo, Monaco, "Courier New", monospace !important;
194+}
195+.gist .markdown-body {
196+ padding: 15px;
197+}
198+.gist pre {
199+ padding: 0;
200+ background-color: transparent;
201+}
202+.gist .gist-file .gist-data {
203+ font-size: .8rem !important;
204+ line-height: 1.4;
205+}
206+.gist code {
207+ padding: 0;
208+ color: inherit;
209+ background-color: transparent;
210+ border-radius: 0;
211+}
212+
213+/* Quotes */
214+blockquote {
215+ padding: .5rem 1rem;
216+ margin: .8rem 0;
217+ color: #7a7a7a;
218+ border-left: .25rem solid #e5e5e5;
219+}
220+blockquote p:last-child {
221+ margin-bottom: 0;
222+}
223+@media (min-width: 30em) {
224+ blockquote {
225+ padding-right: 5rem;
226+ padding-left: 1.25rem;
227+ }
228+}
229+
230+img {
231+ display: block;
232+ max-width: 100%;
233+ margin: 0 0 1rem;
234+ border-radius: 5px;
235+}
236+
237+/* Tables */
238+table {
239+ margin-bottom: 1rem;
240+ width: 100%;
241+ border: 1px solid #e5e5e5;
242+ border-collapse: collapse;
243+}
244+td,
245+th {
246+ padding: .25rem .5rem;
247+ border: 1px solid #e5e5e5;
248+}
249+tbody tr:nth-child(odd) td,
250+tbody tr:nth-child(odd) th {
251+ background-color: #f9f9f9;
252+}
253+
254+
255+/*
256+ * Custom type
257+ *
258+ * Extend paragraphs with `.lead` for larger introductory text.
259+ */
260+
261+.lead {
262+ font-size: 1.25rem;
263+ font-weight: 300;
264+}
265+
266+
267+/*
268+ * Messages
269+ *
270+ * Show alert messages to users. You may add it to single elements like a `<p>`,
271+ * or to a parent if there are multiple elements to show.
272+ */
273+
274+.message {
275+ margin-bottom: 1rem;
276+ padding: 1rem;
277+ color: #717171;
278+ background-color: #f9f9f9;
279+}
280+
281+
282+/*
283+ * Container
284+ *
285+ * Center the page content.
286+ */
287+
288+.container {
289+ max-width: 38rem;
290+ padding-left: 1rem;
291+ padding-right: 1rem;
292+ margin-left: auto;
293+ margin-right: auto;
294+}
295+
296+
297+/*
298+ * Masthead
299+ *
300+ * Super small header above the content for site name and short description.
301+ */
302+
303+.masthead {
304+ padding-top: 1rem;
305+ padding-bottom: 1rem;
306+ margin-bottom: 3rem;
307+}
308+.masthead-title {
309+ margin-top: 0;
310+ margin-bottom: 0;
311+ color: #505050;
312+}
313+.masthead-title a {
314+ color: #505050;
315+}
316+.masthead-title small {
317+ font-size: 75%;
318+ font-weight: 400;
319+ color: #c0c0c0;
320+ letter-spacing: 0;
321+}
322+
323+
324+/*
325+ * Posts and pages
326+ *
327+ * Each post is wrapped in `.post` and is used on default and post layouts. Each
328+ * page is wrapped in `.page` and is only used on the page layout.
329+ */
330+
331+.page,
332+.post {
333+ margin-bottom: 4em;
334+}
335+
336+/* Blog post or page title */
337+.page-title,
338+.post-title,
339+.post-title a {
340+ color: #303030;
341+}
342+.page-title,
343+.post-title {
344+ margin-top: 0;
345+}
346+
347+/* Meta data line below post title */
348+.post-date {
349+ display: block;
350+ margin-top: -.5rem;
351+ margin-bottom: 1rem;
352+ color: #9a9a9a;
353+}
354+
355+/* Related posts */
356+.related {
357+ padding-top: 2rem;
358+ padding-bottom: 2rem;
359+ /*border-top: 1px solid #eee;*/
360+}
361+.related-posts {
362+ padding-left: 0;
363+ list-style: none;
364+}
365+.related-posts h3 {
366+ margin-top: 0;
367+}
368+.related-posts li small {
369+ font-size: 75%;
370+ color: #999;
371+}
372+.related-posts li a:hover {
373+ color: #268bd2;
374+ text-decoration: none;
375+}
376+.related-posts li a:hover small {
377+ color: inherit;
378+}
379+
380+
381+/*
382+ * Pagination
383+ *
384+ * Super lightweight (HTML-wise) blog pagination. `span`s are provide for when
385+ * there are no more previous or next posts to show.
386+ */
387+
388+.pagination {
389+ overflow: hidden; /* clearfix */
390+ margin-left: -1rem;
391+ margin-right: -1rem;
392+ font-family: "PT Sans", Helvetica, Arial, sans-serif;
393+ color: #ccc;
394+ text-align: center;
395+}
396+
397+/* Pagination items can be `span`s or `a`s */
398+.pagination-item {
399+ display: block;
400+ padding: 1rem;
401+ border: 1px solid #eee;
402+}
403+.pagination-item:first-child {
404+ margin-bottom: -1px;
405+}
406+
407+/* Only provide a hover state for linked pagination items */
408+a.pagination-item:hover {
409+ background-color: #f5f5f5;
410+}
411+
412+@media (min-width: 30em) {
413+ .pagination {
414+ margin: 3rem 0;
415+ }
416+ .pagination-item {
417+ float: left;
418+ width: 50%;
419+ }
420+ .pagination-item:first-child {
421+ margin-bottom: 0;
422+ border-top-left-radius: 4px;
423+ border-bottom-left-radius: 4px;
424+ }
425+ .pagination-item:last-child {
426+ margin-left: -1px;
427+ border-top-right-radius: 4px;
428+ border-bottom-right-radius: 4px;
429+ }
430+}
public/css/syntax.cssView
@@ -1,0 +1,65 @@
1+.highlight .hll { background-color: #ffc; }
2+.highlight .c { color: #999; } /* Comment */
3+.highlight .err { color: #a00; background-color: #faa } /* Error */
4+.highlight .k { color: #069; } /* Keyword */
5+.highlight .o { color: #555 } /* Operator */
6+.highlight .cm { color: #09f; font-style: italic } /* Comment.Multiline */
7+.highlight .cp { color: #099 } /* Comment.Preproc */
8+.highlight .c1 { color: #999; } /* Comment.Single */
9+.highlight .cs { color: #999; } /* Comment.Special */
10+.highlight .gd { background-color: #fcc; border: 1px solid #c00 } /* Generic.Deleted */
11+.highlight .ge { font-style: italic } /* Generic.Emph */
12+.highlight .gr { color: #f00 } /* Generic.Error */
13+.highlight .gh { color: #030; } /* Generic.Heading */
14+.highlight .gi { background-color: #cfc; border: 1px solid #0c0 } /* Generic.Inserted */
15+.highlight .go { color: #aaa } /* Generic.Output */
16+.highlight .gp { color: #009; } /* Generic.Prompt */
17+.highlight .gs { } /* Generic.Strong */
18+.highlight .gu { color: #030; } /* Generic.Subheading */
19+.highlight .gt { color: #9c6 } /* Generic.Traceback */
20+.highlight .kc { color: #069; } /* Keyword.Constant */
21+.highlight .kd { color: #069; } /* Keyword.Declaration */
22+.highlight .kn { color: #069; } /* Keyword.Namespace */
23+.highlight .kp { color: #069 } /* Keyword.Pseudo */
24+.highlight .kr { color: #069; } /* Keyword.Reserved */
25+.highlight .kt { color: #078; } /* Keyword.Type */
26+.highlight .m { color: #f60 } /* Literal.Number */
27+.highlight .s { color: #d44950 } /* Literal.String */
28+.highlight .na { color: #4f9fcf } /* Name.Attribute */
29+.highlight .nb { color: #366 } /* Name.Builtin */
30+.highlight .nc { color: #0a8; } /* Name.Class */
31+.highlight .no { color: #360 } /* Name.Constant */
32+.highlight .nd { color: #99f } /* Name.Decorator */
33+.highlight .ni { color: #999; } /* Name.Entity */
34+.highlight .ne { color: #c00; } /* Name.Exception */
35+.highlight .nf { color: #c0f } /* Name.Function */
36+.highlight .nl { color: #99f } /* Name.Label */
37+.highlight .nn { color: #0cf; } /* Name.Namespace */
38+.highlight .nt { color: #2f6f9f; } /* Name.Tag */
39+.highlight .nv { color: #033 } /* Name.Variable */
40+.highlight .ow { color: #000; } /* Operator.Word */
41+.highlight .w { color: #bbb } /* Text.Whitespace */
42+.highlight .mf { color: #f60 } /* Literal.Number.Float */
43+.highlight .mh { color: #f60 } /* Literal.Number.Hex */
44+.highlight .mi { color: #f60 } /* Literal.Number.Integer */
45+.highlight .mo { color: #f60 } /* Literal.Number.Oct */
46+.highlight .sb { color: #c30 } /* Literal.String.Backtick */
47+.highlight .sc { color: #c30 } /* Literal.String.Char */
48+.highlight .sd { color: #c30; font-style: italic } /* Literal.String.Doc */
49+.highlight .s2 { color: #c30 } /* Literal.String.Double */
50+.highlight .se { color: #c30; } /* Literal.String.Escape */
51+.highlight .sh { color: #c30 } /* Literal.String.Heredoc */
52+.highlight .si { color: #a00 } /* Literal.String.Interpol */
53+.highlight .sx { color: #c30 } /* Literal.String.Other */
54+.highlight .sr { color: #3aa } /* Literal.String.Regex */
55+.highlight .s1 { color: #c30 } /* Literal.String.Single */
56+.highlight .ss { color: #fc3 } /* Literal.String.Symbol */
57+.highlight .bp { color: #366 } /* Name.Builtin.Pseudo */
58+.highlight .vc { color: #033 } /* Name.Variable.Class */
59+.highlight .vg { color: #033 } /* Name.Variable.Global */
60+.highlight .vi { color: #033 } /* Name.Variable.Instance */
61+.highlight .il { color: #f60 } /* Literal.Number.Integer.Long */
62+
63+.css .o,
64+.css .o + .nt,
65+.css .nt + .nt { color: #999; }
public/favicon.ico
public/favicon.ico
public/js/toc.jsView
@@ -1,0 +1,82 @@
1+// https://github.com/ghiculescu/jekyll-table-of-contents
2+(function($){
3+ $.fn.toc = function(options) {
4+ var defaults = {
5+ noBackToTopLinks: false,
6+ title: '<i>Jump to...</i>',
7+ minimumHeaders: 3,
8+ headers: 'h1, h2, h3, h4, h5, h6',
9+ listType: 'ol', // values: [ol|ul]
10+ showEffect: 'show', // values: [show|slideDown|fadeIn|none]
11+ showSpeed: 'slow' // set to 0 to deactivate effect
12+ },
13+ settings = $.extend(defaults, options);
14+
15+ var headers = $(settings.headers).filter(function() {
16+ // get all headers with an ID
17+ var previousSiblingName = $(this).prev().attr( "name" );
18+ if (!this.id && previousSiblingName) {
19+ this.id = $(this).attr( "id", previousSiblingName.replace(/\./g, "-") );
20+ }
21+ return this.id;
22+ }), output = $(this);
23+ if (!headers.length || headers.length < settings.minimumHeaders || !output.length) {
24+ return;
25+ }
26+
27+ if (0 === settings.showSpeed) {
28+ settings.showEffect = 'none';
29+ }
30+
31+ var render = {
32+ show: function() { output.hide().html(html).show(settings.showSpeed); },
33+ slideDown: function() { output.hide().html(html).slideDown(settings.showSpeed); },
34+ fadeIn: function() { output.hide().html(html).fadeIn(settings.showSpeed); },
35+ none: function() { output.html(html); }
36+ };
37+
38+ var get_level = function(ele) { return parseInt(ele.nodeName.replace("H", ""), 10); }
39+ var highest_level = headers.map(function(_, ele) { return get_level(ele); }).get().sort()[0];
40+ var return_to_top = '<i class="fa fa-arrow-up back-to-top"> </i>';
41+
42+ var level = get_level(headers[0]),
43+ this_level,
44+ html = settings.title + " <"+settings.listType+">";
45+ headers.on('click', function() {
46+ if (!settings.noBackToTopLinks) {
47+ window.location.hash = this.id;
48+ }
49+ })
50+ .addClass('clickable-header')
51+ .each(function(_, header) {
52+ this_level = get_level(header);
53+ if (!settings.noBackToTopLinks && this_level === highest_level) {
54+ $(header).addClass('top-level-header').after(return_to_top);
55+ }
56+ if (this_level === level) // same level as before; same indenting
57+ html += "<li><a href='#" + header.id + "'>" + header.innerHTML + "</a>";
58+ else if (this_level <= level){ // higher level than before; end parent ol
59+ for(i = this_level; i < level; i++) {
60+ html += "</li></"+settings.listType+">"
61+ }
62+ html += "<li><a href='#" + header.id + "'>" + header.innerHTML + "</a>";
63+ }
64+ else if (this_level > level) { // lower level than before; expand the previous to contain a ol
65+ for(i = this_level; i > level; i--) {
66+ html += "<"+settings.listType+"><li>"
67+ }
68+ html += "<a href='#" + header.id + "'>" + header.innerHTML + "</a>";
69+ }
70+ level = this_level; // update for the next one
71+ });
72+ html += "</"+settings.listType+">";
73+ if (!settings.noBackToTopLinks) {
74+ $(document).on('click', '.back-to-top', function() {
75+ $(window).scrollTop(0);
76+ window.location.hash = '';
77+ });
78+ }
79+
80+ render[settings.showEffect]();
81+ };
82+})(jQuery);

Built with git-ssb-web