";
88 | }
89 | divTarget.html(html);
90 | };
91 | /*
92 | * Show friend list
93 | */
94 | this.showFriendsList = function () {
95 | FB.api('/me/friends', _this.onFriendsListLoaded);
96 | };
97 | /*
98 | * Initialize Facebook
99 | */
100 | this.FBInit = function () {
101 | FB.init({
102 | appId : FBDemo.config.appId,
103 | status : true,
104 | cookie : true,
105 | xfbml : true
106 | });
107 |
108 | FB.Event.subscribe('auth.login', function (response) {
109 | _this.onFacebookInitialLoginStatus(response);
110 | });
111 |
112 | FB.getLoginStatus(_this.onFacebookInitialLoginStatus);
113 | };
114 | /*
115 | * Callback functions for 'auth.statusChange' event.
116 | */
117 | this.onFacebookInitialLoginStatus = function (response) {
118 | if (response.status === "connected") {
119 | $(FBDemo.config.FBLoginButton).hide();
120 | _this.showFriendsList();
121 | }
122 | };
123 | return this.init();
124 | }
125 |
126 | return new _facebook();
127 | }());
128 |
129 | /**
130 | * Check to evaluate whether 'FBDemo' exists in the global namespace - if not, assign window.FBDemo an object literal
131 | */
132 | }(window.FBDemo = window.FBDemo || {}, jQuery));
133 |
--------------------------------------------------------------------------------
/test/unit/_.mainSpec.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /* jasmine specs for _.main.js go here */
4 |
5 | /*Matchers Reference
6 | • toEqual checks for equality, not necessarily the same object.
7 | • toBe checks if two objects are the same.
8 | • toBeTruthy checks if a value is truthy (not just true).
9 | • toBeFalsy checks if a value is falsy (not just false).
10 | • toContain checks if a value is inside another.
11 | • toBeDefined checks if a value is defined.
12 | • toBeUndefined checks if a value is undefined.
13 | • toBeNull checks if a value is null.
14 | • toBeNaN checks if a value is NaN.
15 | • toBeCloseTo checks decimal proximity.
16 | • toMatch checks if a value matches a given regular expression.
17 | • toThrow checks if a function throws an error.
18 | • .not inverts the meaning of the following matcher.
19 | */
20 |
21 | /*Reserved Words in Jasmine
22 | • jasmine (and everything in its namespace)
23 | • describe
24 | • it
25 | • expect
26 | • beforeEach
27 | • afterEach
28 | • runs
29 | • waits
30 | • waitsFor
31 | • spyOn
32 | • xdescribe
33 | • xit
34 | */
35 |
36 | /*List of Falsy Values
37 | • false
38 | • 0
39 | • ""
40 | • undefined (note that the variable undefined isn’t always undefined!)
41 | • null
42 | • NaN
43 | */
44 |
45 | describe("Test main js file", function() {
46 |
47 | /**
48 | * Test logging function, for debugging mode
49 | */
50 | describe("test log function", function() { // suite
51 |
52 | it("JSB.config.debug should be true", function() { // specification or spec
53 | expect(JSB.config.debug).toBe(true); // matcher, if you want to make sure something is literally true or false and nothing else, use the
54 | //toEqual matcher
55 | });
56 |
57 | it("typeof window.console should be object", function() {
58 | expect(typeof window.console !== 'undefined').toEqual(true);
59 | });
60 |
61 | it("typeof window.console.log to be defined", function() {
62 | expect(typeof window.console.log !== 'undefined').toEqual(true);
63 | });
64 |
65 | it("console.debug should be available", function() {
66 | expect(console.debug).toBeDefined();
67 | });
68 | });
69 |
70 | /**
71 | * Test $.toType() function
72 | */
73 | describe("test toType function", function() {
74 | xit("test window object 'global'", function() {
75 | expect($.toType(window)).toEqual("global");
76 | });
77 |
78 | it("test array object", function() {
79 | expect($.toType([1, 2, 3])).toEqual("array");
80 | });
81 |
82 | it("test regex object", function() {
83 | expect($.toType(/a-z/)).toEqual("regexp");
84 | });
85 |
86 | it("test object", function() {
87 | expect($.toType({
88 | a: 4
89 | })).toEqual("object");
90 | });
91 |
92 | it("test error object", function() {
93 | expect($.toType(new ReferenceError)).toEqual("error");
94 | });
95 |
96 | it("test date object", function() {
97 | expect($.toType(new Date)).toEqual("date");
98 | });
99 |
100 | it("test Math object", function() {
101 | expect($.toType(Math)).toEqual("math");
102 | });
103 |
104 | it("test JSON object", function() {
105 | expect($.toType(JSON)).toEqual("json");
106 | });
107 |
108 | it("test Number object", function() {
109 | expect($.toType(3)).toEqual("number");
110 | });
111 |
112 | it("test String object", function() {
113 | expect($.toType("Arif")).toEqual("string");
114 | });
115 |
116 | it("test Boolean object", function() {
117 | expect($.toType(new Boolean(true))).toEqual("boolean");
118 | });
119 |
120 | xit("test null", function() {
121 | expect($.toType(null)).toEqual("null");
122 | });
123 |
124 | xit("test undefined", function() {
125 | expect($.toType(undefined)).toEqual("undefined");
126 | });
127 | });
128 |
129 | describe("test public method", function() {
130 | it("JSB.sayHello", function() {
131 | expect(JSB.sayHello()).toEqual("Hello World!");
132 | });
133 | });
134 |
135 | describe("let's get the domain name", function() {
136 | xit("test protocol", function() {
137 | expect(window.location.protocol).toContain("http");
138 | });
139 |
140 | });
141 |
142 | describe("test query strings", function() {
143 | var name;
144 | xit("check the output", function() {
145 | expect(JSB.subHelper.getQueryString(name, 'Arif')).toEqual("Arif");
146 | });
147 |
148 | beforeEach(function() {
149 | spyOn(JSB.subHelper, 'getQueryString');
150 | JSB.subHelper.getQueryString(name, 'Arif');
151 | });
152 |
153 | it("tracks that the spy was called", function() {
154 | //Let's tracks calls to it and all arguments through spyOn method.
155 | expect(JSB.subHelper.getQueryString).toHaveBeenCalled();
156 | });
157 |
158 | });
159 |
160 |
161 | // describe("Facebook", function() {
162 | // it("is FB available (i.e. is facebook library included)", function() {
163 | // expect(typeof FB != "undefined").not.toEqual(true);
164 | // });
165 |
166 | // it("do we have an application id", function() {
167 | // expect(JSB.config.appId != "").toEqual(true);
168 | // });
169 |
170 | // it("initialize the facebook library", function() {
171 | // JSB.subModule.fbReady();
172 | // });
173 |
174 | // xit("Checking for active facebook session", function() {
175 | // FB.getLoginStatus();
176 | // waitsFor(function() {
177 | // return FB.getLoginStatusResponse() && FB.getLoginStatusResponse().authResponse;
178 | // }, "response.authResponse", 7000);
179 | // });
180 | // });
181 |
182 | });
--------------------------------------------------------------------------------
/src/js/_.main.js:
--------------------------------------------------------------------------------
1 | /* JavaScript Boilerplate main scripting file *
2 | * @version 1.2
3 | * GIT URL - https://github.com/mdarif/JavaScript-Boilerplate
4 | * Author - Mohammed Arif
5 | */
6 |
7 | /* JSB (our namespace name) and undefined are passed here
8 | * to ensure 1. namespace can be modified locally and isn't
9 | * overwritten outside of our function context
10 | * 2. the value of undefined is guaranteed as being truly
11 | * undefined. This is to avoid issues with undefined being
12 | * mutable pre-ES5.
13 | */
14 |
15 | (function(JSB, $, undefined) {
16 | 'use strict';
17 |
18 | /**
19 | * Logging function, for debugging mode
20 | */
21 | $.log = function(message) {
22 | if (JSB.config.debug && (typeof window.console !== 'undefined' && typeof window.console.log !== 'undefined') && console.debug) {
23 | console.debug(message);
24 | }
25 | /*else {
26 | alert(message);
27 | }*/
28 | };
29 |
30 | /**
31 | * Angus Croll awesome typeof fix from http://goo.gl/GtvsU
32 | */
33 | $.toType = (function toType(global) {
34 | return function(obj) {
35 | if (obj === global) {
36 | return 'global';
37 | }
38 | return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
39 | };
40 | }(this));
41 |
42 | /*$.toType(window); //'global' (all browsers)
43 | $.toType([1,2,3]); //'array' (all browsers)
44 | $.toType(/a-z/); //'regexp' (all browsers)
45 | $.toType(JSON); //'json' (all browsers)
46 | $.toType(null); //'null' (all browsers)
47 | $.toType(undefined); //'undefined' (all browsers)*/
48 | //etc..
49 |
50 | /**
51 | * Private properties
52 | */
53 | var name = 'Mohammed Arif',
54 | age = 30;
55 |
56 | /**
57 | * Private method
58 | */
59 |
60 | /* Benefits:
61 | * 1. Makes it easier to understand 'functions as an object'.
62 | * 2. It enforces good semicolon habits.
63 | * 3. Doesn't have much of the baggage traditionally associated with functions and scope.
64 | */
65 | var getName = function() {
66 | return 'My name is ' + name + ', I am ' + age + ' old.';
67 | };
68 |
69 |
70 | /**
71 | * Public methods and properties
72 | */
73 | JSB.title = 'Interactive Developer';
74 | JSB.sayHello = function() {
75 | return "Hello World!";
76 | };
77 |
78 | /*
79 | * Singletons serve as a namespace provider which isolate implementation code
80 | * from the global namespace so as to provide a single point of access for functions,
81 | * this is useful for organizing code into logical sections.
82 | * It is possible to put parentheses around this structure to instantiate it immediately after it's parsed.
83 | * This way it's always present when the script is executed and doesn't have to be instantiated separately.
84 | */
85 | JSB.subHelper = (function() {
86 | function _subHelper() {
87 |
88 | /**
89 | * In non-strict mode, 'this' is bound to the global scope when it isn't bound to anything else.
90 | * In strict mode it is 'undefined'. That makes it an error to use it outside of a method.
91 | */
92 |
93 | /*jshint validthis: true */
94 | var _this = this;
95 | /* Store this to avoid scope conflicts */
96 |
97 | /*
98 | * Return the URI of site
99 | * Return protocol, hostname and port if found
100 | *
101 | */
102 | this.getDomain = function () {
103 | var port = "",
104 | url = "";
105 |
106 | if (window.location.port) {
107 | port = ":" + window.location.port;
108 | }
109 | url = window.location.protocol + "//" + window.location.hostname + port + "/";
110 | return url;
111 | };
112 |
113 | /*
114 | * This method will return the query string from the URL of the website
115 | * Accept two parameters key, default_
116 | * key : The name of the key who's value need to be fetch
117 | * default_ : The default value which will return when nothing will found or key does not exists.
118 | * If not pass anything then it will return blank value.
119 | */
120 | this.getQueryString = function (key, default_) {
121 | if (default_ === null) {
122 | default_ = "";
123 | }
124 |
125 | key = key.replace(/\[/,"\\[").replace(/\]/,"\\]");
126 | var regex = new RegExp("[\\?&]" + key + "=([^]*)"),
127 | qs = regex.exec(window.location.href);
128 |
129 | if (qs === null) {
130 | return default_;
131 | } else {
132 | return qs[1];
133 | }
134 | };
135 |
136 | /**
137 | * Init call
138 | */
139 | this.init = function() {
140 | _this.getDomain();
141 | return this; /*this refer to JSB.subHelper*/
142 | };
143 |
144 | return this.init(); /*initialize the init()*/
145 | }
146 | return new _subHelper(); /*creating a new object of subHelper rather then a funtion*/
147 | }());
148 |
149 | /**
150 | * Check to evaluate whether 'JSB' exists in the global namespace - if not, assign window.JSB an object literal
151 | */
152 | }(window.JSB = window.JSB || {}, jQuery));
--------------------------------------------------------------------------------
/src/js/libs/prism.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Prism: Lightweight, robust, elegant syntax highlighting
3 | * MIT license http://www.opensource.org/licenses/mit-license.php/
4 | * @author Lea Verou http://lea.verou.me
5 | */(function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},clone:function(e){var n=t.util.type(e);switch(n){case"Object":var r={};for(var i in e)e.hasOwnProperty(i)&&(r[i]=t.util.clone(e[i]));return r;case"Array":return e.slice()}return e}},languages:{extend:function(e,n){var r=t.util.clone(t.languages[e]);for(var i in n)r[i]=n[i];return r},insertBefore:function(e,n,r,i){i=i||t.languages;var s=i[e],o={};for(var u in s)if(s.hasOwnProperty(u)){if(u==n)for(var a in r)r.hasOwnProperty(a)&&(o[a]=r[a]);o[u]=s[u]}return i[e]=o},DFS:function(e,n){for(var r in e){n.call(e,r,e[r]);t.util.type(e)==="Object"&&t.languages.DFS(e[r],n)}}},highlightAll:function(e,n){var r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');for(var i=0,s;s=r[i++];)t.highlightElement(s,e===!0,n)},highlightElement:function(r,i,s){var o,u,a=r;while(a&&!e.test(a.className))a=a.parentNode;if(a){o=(a.className.match(e)||[,""])[1];u=t.languages[o]}if(!u)return;r.className=r.className.replace(e,"").replace(/\s+/g," ")+" language-"+o;a=r.parentNode;/pre/i.test(a.nodeName)&&(a.className=a.className.replace(e,"").replace(/\s+/g," ")+" language-"+o);var f=r.textContent;if(!f)return;f=f.replace(/&/g,"&").replace(/e.length)break e;if(p instanceof i)continue;a.lastIndex=0;var d=a.exec(p);if(d){l&&(c=d[1].length);var v=d.index-1+c,d=d[0].slice(c),m=d.length,g=v+m,y=p.slice(0,v+1),b=p.slice(g+1),w=[h,1];y&&w.push(y);var E=new i(u,f?t.tokenize(d,f):d);w.push(E);b&&w.push(b);Array.prototype.splice.apply(s,w)}}}return s},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[];r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(!r||!r.length)return;for(var i=0,s;s=r[i++];)s(n)}}},n=t.Token=function(e,t){this.type=e;this.content=t};n.stringify=function(e,r,i){if(typeof e=="string")return e;if(Object.prototype.toString.call(e)=="[object Array]")return e.map(function(t){return n.stringify(t,r,e)}).join("");var s={type:e.type,content:n.stringify(e.content,r,i),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:i};s.type=="comment"&&(s.attributes.spellcheck="true");t.hooks.run("wrap",s);var o="";for(var u in s.attributes)o+=u+'="'+(s.attributes[u]||"")+'"';return"<"+s.tag+' class="'+s.classes.join(" ")+'" '+o+">"+s.content+""+s.tag+">"};if(!self.document){self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,i=n.code;self.postMessage(JSON.stringify(t.tokenize(i,t.languages[r])));self.close()},!1);return}var r=document.getElementsByTagName("script");r=r[r.length-1];if(r){t.filename=r.src;document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)}})();;
6 | Prism.languages.markup={comment:/<!--[\w\W]*?-->/g,prolog:/<\?.+?\?>/,doctype:/<!DOCTYPE.+?>/,cdata:/<!\[CDATA\[[\w\W]*?]]>/i,tag:{pattern:/<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|\w+))?\s*)*\/?>/gi,inside:{tag:{pattern:/^<\/?[\w:-]+/i,inside:{punctuation:/^<\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi,inside:{punctuation:/=|>|"/g}},punctuation:/\/?>/g,"attr-name":{pattern:/[\w:-]+/g,inside:{namespace:/^[\w-]+?:/}}}},entity:/&#?[\da-z]{1,8};/gi};Prism.hooks.add("wrap",function(e){e.type==="entity"&&(e.attributes.title=e.content.replace(/&/,"&"))});;
7 | Prism.languages.css={comment:/\/\*[\w\W]*?\*\//g,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*{))/gi,inside:{punctuation:/[;:]/g}},url:/url\((["']?).*?\1\)/gi,selector:/[^\{\}\s][^\{\};]*(?=\s*\{)/g,property:/(\b|\B)[\w-]+(?=\s*:)/ig,string:/("|')(\\?.)*?\1/g,important:/\B!important\b/gi,ignore:/&(lt|gt|amp);/gi,punctuation:/[\{\};:]/g};Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{style:{pattern:/(<|<)style[\w\W]*?(>|>)[\w\W]*?(<|<)\/style(>|>)/ig,inside:{tag:{pattern:/(<|<)style[\w\W]*?(>|>)|(<|<)\/style(>|>)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.css}}});;
8 | Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,"function":{pattern:/[a-z0-9_]+\(/ig,inside:{punctuation:/\(/}}, number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|(&){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};
9 | ;
10 | Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(var|let|if|else|while|do|for|return|in|instanceof|function|new|with|typeof|try|throw|catch|finally|null|break|continue)\b/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g});Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0}});Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/(<|<)script[\w\W]*?(>|>)[\w\W]*?(<|<)\/script(>|>)/ig,inside:{tag:{pattern:/(<|<)script[\w\W]*?(>|>)|(<|<)\/script(>|>)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});
11 | ;
12 |
--------------------------------------------------------------------------------
/src/css/style.css:
--------------------------------------------------------------------------------
1 | /* =============================================================================
2 | HTML5 Boilerplate CSS: h5bp.com/css
3 | ========================================================================== */
4 | article, aside, details, figcaption, figure, footer, header, hgroup, nav, section {
5 | display: block;
6 | }
7 | audio, canvas, video {
8 | display: inline-block;
9 | *display: inline;
10 | *zoom: 1;
11 | }
12 | audio:not([controls]) {
13 | display: none;
14 | }
15 | [hidden] {
16 | display: none;
17 | }
18 | html {
19 | font-size: 100%;
20 | -webkit-text-size-adjust: 100%;
21 | -ms-text-size-adjust: 100%;
22 | }
23 | html, button, input, select, textarea {
24 | font-family: sans-serif;
25 | color: #222;
26 | }
27 | body {
28 | margin: 0;
29 | font-size: 1em;
30 | line-height: 1.4;
31 | }
32 | ::-moz-selection {
33 | background:#FF0;
34 | color:#000;
35 | text-shadow: none;
36 | }
37 | ::selection {
38 | background: #FF0;
39 | color:#000;
40 | text-shadow: none;
41 | }
42 | a {
43 | color: #00e;
44 | outline:none
45 | }
46 | a:visited {
47 | color: #551a8b;
48 | }
49 | a:hover {
50 | color: #06e;
51 | }
52 | a:focus {
53 | outline: thin dotted;
54 | }
55 | a:hover, a:active {
56 | outline: 0;
57 | }
58 | abbr[title] {
59 | border-bottom: 1px dotted;
60 | }
61 | b, strong {
62 | font-weight: bold;
63 | }
64 | blockquote {
65 | margin: 1em 40px;
66 | }
67 | dfn {
68 | font-style: italic;
69 | }
70 | hr {
71 | display: block;
72 | height: 1px;
73 | border: 0;
74 | border-top: 1px solid #ccc;
75 | margin: 1em 0;
76 | padding: 0;
77 | }
78 | ins {
79 | background: #ff9;
80 | color: #000;
81 | text-decoration: none;
82 | }
83 | mark {
84 | background: #ff0;
85 | color: #000;
86 | font-style: italic;
87 | font-weight: bold;
88 | }
89 | pre, code, kbd, samp {
90 | font-family: monospace, serif;
91 | _font-family:'courier new', monospace;
92 | font-size: 1em;
93 | }
94 | pre {
95 | white-space: pre;
96 | white-space: pre-wrap;
97 | word-wrap: break-word;
98 | }
99 | q {
100 | quotes: none;
101 | }
102 | q:before, q:after {
103 | content:"";
104 | content: none;
105 | }
106 | small {
107 | font-size: 85%;
108 | }
109 | sub, sup {
110 | font-size: 75%;
111 | line-height: 0;
112 | position: relative;
113 | vertical-align: baseline;
114 | }
115 | sup {
116 | top: -0.5em;
117 | }
118 | sub {
119 | bottom: -0.25em;
120 | }
121 | ul, ol {
122 | margin: 1em 0;
123 | padding: 0 0 0 40px;
124 | }
125 | dd {
126 | margin: 0 0 0 40px;
127 | }
128 | nav ul, nav ol {
129 | list-style: none;
130 | list-style-image: none;
131 | margin: 0;
132 | padding: 0;
133 | }
134 | img {
135 | border: 0;
136 | -ms-interpolation-mode: bicubic;
137 | vertical-align: middle;
138 | }
139 | svg:not(:root) {
140 | overflow: hidden;
141 | }
142 | figure {
143 | margin: 0;
144 | }
145 | form {
146 | margin: 0;
147 | }
148 | fieldset {
149 | border: 0;
150 | margin: 0;
151 | padding: 0;
152 | }
153 | label {
154 | cursor: pointer;
155 | }
156 | legend {
157 | border: 0;
158 | *margin-left: -7px;
159 | padding: 0;
160 | white-space: normal;
161 | }
162 | button, input, select, textarea {
163 | font-size: 100%;
164 | margin: 0;
165 | vertical-align: baseline;
166 | *vertical-align: middle;
167 | }
168 | button, input {
169 | line-height: normal;
170 | }
171 | button, input[type="button"], input[type="reset"], input[type="submit"] {
172 | cursor: pointer;
173 | -webkit-appearance: button;
174 | *overflow: visible;
175 | }
176 | button[disabled], input[disabled] {
177 | cursor: default;
178 | }
179 | input[type="checkbox"], input[type="radio"] {
180 | box-sizing: border-box;
181 | padding: 0;
182 | *width: 13px;
183 | *height: 13px;
184 | }
185 | input[type="search"] {
186 | -webkit-appearance: textfield;
187 | -moz-box-sizing: content-box;
188 | -webkit-box-sizing: content-box;
189 | box-sizing: content-box;
190 | }
191 | input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button {
192 | -webkit-appearance: none;
193 | }
194 | button::-moz-focus-inner, input::-moz-focus-inner {
195 | border: 0;
196 | padding: 0;
197 | }
198 | textarea {
199 | overflow: auto;
200 | vertical-align: top;
201 | resize: vertical;
202 | }
203 | input:valid, textarea:valid {
204 | }
205 | input:invalid, textarea:invalid {
206 | background-color: #f0dddd;
207 | }
208 | table {
209 | border-collapse: collapse;
210 | border-spacing: 0;
211 | }
212 | td {
213 | vertical-align: top;
214 | }
215 | .chromeframe {
216 | margin: 0.2em 0;
217 | background: #ccc;
218 | color: black;
219 | padding: 0.2em 0;
220 | }
221 | h1, h2, h3, h4, h5, h6, ul, li, pre {
222 | margin:0;
223 | padding:0
224 | }
225 | /* ===== Primary Styles ========================================================
226 | Author: SapientNitro (2011) (http://www.sapient.com)
227 | ========================================================================== */
228 |
229 | /** Basic settings **/
230 | body {
231 | background:#FFC;
232 | color:#171717;
233 | font-size:100%;
234 | font-family:Arial, Helvetica, sans-serif;
235 | font-weight:normal;
236 | line-height:1em;
237 | padding:10px
238 | }
239 | h1, h2, h3, h4, h5, h6, section, article, p {
240 | display:block;
241 | margin:0;
242 | padding:10px
243 | }
244 | h1 {
245 | font-size:2em
246 | }
247 | h2 {
248 | background:#F04E00;
249 | color:#FFF;
250 | font-size:1.7em;
251 | margin-bottom:10px
252 | }
253 | h3 {
254 | background:#666;
255 | color:#FFF;
256 | font-size:1.4emp;
257 | padding:8px;
258 | margin-bottom:10px
259 | }
260 | h4 {
261 | font-size:1.2em
262 | }
263 | h5 {
264 | font-size:1em
265 | }
266 | h6 {
267 | font-size:0.8em
268 | }
269 | a {
270 | text-decoration:none;
271 | outline:none
272 | }
273 | section {
274 | background:#FFF;
275 | font-size:1em;
276 | line-height:1.2em;
277 | padding:10px
278 | }
279 | section.example {
280 | background:#EEE
281 | }
282 | article {
283 | padding:0;
284 | margin-bottom:10px
285 | }
286 | p {
287 | font-size:1em;
288 | line-height:1.4em
289 | }
290 | ul {
291 | padding:0 50px
292 | }
293 | ul li {
294 | padding:5px 0;
295 | line-height:1.2em
296 | }
297 | #main {
298 | border:#FC0 1px dashed
299 | }
300 | /* =============================================================================
301 | Non-Semantic Helper Classes
302 | ========================================================================== */
303 | .ir {
304 | display: block;
305 | border: 0;
306 | text-indent: -999em;
307 | overflow: hidden;
308 | background-color: transparent;
309 | background-repeat: no-repeat;
310 | text-align: left;
311 | direction: ltr;
312 | *line-height: 0;
313 | }
314 | .ir br {
315 | display: none;
316 | }
317 | .hidden {
318 | display: none !important;
319 | visibility: hidden;
320 | }
321 | .visuallyhidden {
322 | border: 0;
323 | clip: rect(0 0 0 0);
324 | height: 1px;
325 | margin: -1px;
326 | overflow: hidden;
327 | padding: 0;
328 | position: absolute;
329 | width: 1px;
330 | }
331 | .visuallyhidden.focusable:active, .visuallyhidden.focusable:focus {
332 | clip: auto;
333 | margin: 0;
334 | overflow: visible;
335 | position: static
336 | }
337 | .invisible {
338 | visibility: hidden;
339 | }
340 | .clear_fix:before, .clear_fix:after {
341 | content:"";
342 | display: table;
343 | }
344 | .clear_fix:after {
345 | clear: both;
346 | }
347 | .clear_fix {
348 | *zoom: 1;
349 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JavaScript Boilerplate v1.2
2 |
3 | [![Build Status][build-image]][build-url] [![Dependency Status][dependencies-image]][dependencies-url] [![License][license-image]][license-url] [![Version][version-image]][version-url] [![Code Climate][codeclimate-image]] [codeclimate-url]
4 |
5 | JavaScript Boilerplate is the collection of best practices using a design pattern (Global Abatement) with the use of defined namespaces that would help you to protect our code. It is developed in a modular way with some commonly used utility methods provided that you would find useful for common operations. It is equipped with the configuration file in the form of an object literal that can be used to store global objects, config ids, URLs or textual strings. This framework has been designed to work as a ready to use template that you can build further in your projects as needed as it outlines the framework neatly and exhibits an approach to extend it.
6 |
7 | ## What's new in v1.2?
8 | * Have added the Jasmine Test Suite to unit test the boilerplate code with or without PhantomJS, one can fire up the same through Chrome as well
9 | * Grunt build has been enhanced tremendously
10 | * JavaScript syntax highlighting has been added
11 | * `MODULE` has renamed to `JSB` for better JavaScript semantics
12 | * Travis CI has been kicked off
13 | * Made several small changes like `use strict`, dir changes, css fixes, additional grunt plug-ins also have been added etc.
14 |
15 | ## Files in Repository
16 |
17 | 1. `src/index.html` - An html help file illustrating helper functions.
18 |
19 | 2. `src/js/_config.js` - Config is having general details that will be commonly used across the application. Parameters like URLs, services, theme to be used within the application.
20 |
21 | 3. `src/js/_helper.js` - Helper utility functions that are required across different modules or even within a single module.
22 |
23 | 4. `src/js/_main.js` - It defines the main module. We have used IIFE (Intermediately invoking function expression) namespacing and global abatement in this logic. JSB is main namespace that has been defined and JSB.helper is one of the components.
24 |
25 | 5. `src/css/style.css` - Style sheets for the html help file.
26 |
27 | ## Usage
28 |
29 | 1. Clone the repository using the quick start guide. To get started include the JS files in your js directory.
30 |
31 | The starting point is the `src/js/_main.js` file which has defined the main module and the component to be used. If you were to observe the code,
32 |
33 | (function (JSB, $, undefined) {
34 |
35 | ...... (2)
36 |
37 | })(window.JSB = window.JSB || {}, jQuery);
38 |
39 | The above code defines the `JSB` namespace and also passes true values of `jquery` and `undefined` to the inner component. Instead of `JSB` you can define your project name or application name as well and that would become your global namespace under which all the other components should be declared/defined. For e.g. if it is a project name `MYPROJECT` instead of `JSB` you can even write `MYPROJECT` as well.
40 |
41 | Once you have defined the wrapper (global namespace), you can start of modules inside the global namespace.
42 |
43 | 2. The second step would be to define the components, which can be page level or widget level too.
44 |
45 |
46 | JSB.subModule = (function () {
47 | function _subModule() {
48 | ... (3)
49 | }
50 | return new _subModule()
51 | })();
52 |
53 |
54 | The above code has defined a component called helper as a sub module of `JSB` namespace. `JSB.helper` holds an object that gets returned through `new _subModule()`. We can define all the functions that we want for the helper module inside the function `_subModule()`.
55 |
56 |
57 | 3. The third step would be to define the private values, private functions , privileged functions etc. within the `_subModule` function. Comments have been provided as to which one is a private function and which is a privileged one. At the end of the function the `init()` function is exposed which in turn returns the object itself. When the object is returned all the privileged functions are exposed along with it and are accessible outside.
58 |
59 |
60 |
61 | 4. Next is the `src/js/_config.js` file, which has all the global parameters that needs to be leveraged across the application. Think of this file/module as a container file to define your global variables, URLS etc. It is globally available inside the `JSB` namespace and we can access the parameters by specifying `JSB.config.param` to get its value in any other component. Here it has been primarily defined as an object literal as everything needs to be exposed globally.
62 |
63 | 5. For creating utility methods to be used across application, you can leverage the `src/js/_helper.js` file. It works on the same principle as the `src/js/_main.js`. For E.g. the way to access a helper function outside the module would be `JSB.helper.getCookie` for the `getCookie` function.
64 |
65 |
66 | ## Quick start
67 |
68 | Clone the git repo - `git clone git://github.com/mdarif/JavaScript-Boilerplate.git` - or [download it](https://github.com/mdarif/JavaScript-Boilerplate/zipball/master)
69 |
70 | You can also get the JavaScript Boilerplate through npm if you have already installed node.
71 |
72 | npm install javascript-boilerplate
73 |
74 | *Make sure, you should have [node](https://nodejs.org/download/) installed on your machine before running `npm` command
75 |
76 | ## Grunt Build
77 |
78 | Install [Grunt](http://gruntjs.com/getting-started).
79 |
80 | OR
81 |
82 | ###Follow the below instructions to install and setup the `Grunt`
83 |
84 | Install Grunt CLI, this will put the grunt command in your system path, allowing it to be run from any directory.
85 |
86 | $ npm install -g grunt-cli
87 |
88 | Now install Grunt
89 |
90 | $ npm install grunt
91 |
92 | You should also install all the dependencies
93 |
94 | $ npm install
95 |
96 | ###Follow the below instructions to install and setup the `compass task`
97 | _Run this task with the `grunt compass` command._
98 |
99 | [Compass](http://compass-style.org/) is an open-source authoring framework for the [Sass](http://sass-lang.com/) css preprocessor. It helps you build stylesheets faster with a huge library of Sass mixins and functions, advanced tools for spriting, and workflow improvements including file based Sass configuration and a simple pattern for building and using Compass extensions.
100 |
101 | This task requires you to have [Ruby](http://www.ruby-lang.org/en/downloads/), [Sass](http://sass-lang.com/tutorial.html), and [Compass](http://compass-style.org/install/) >=0.12.2 installed. If you're on OS X or Linux you probably already have Ruby installed; test with `ruby -v` in your terminal. When you've confirmed you have Ruby installed, run `gem update --system && gem install compass` to install Compass and Sass.
102 |
103 | ### Fire up the grunt server command and see the preview in browser with live-reload enabled for `app` folder content
104 |
105 | $ grunt server
106 |
107 | ### Build the Project
108 |
109 | $ grunt
110 |
111 | You should be able to see the below message for a successful build and a folder name `dist` has been created with all the expected output, parallel to `src` folder, with all the tasks completed.
112 |
113 | Done, without errors.
114 |
115 | ### Testing
116 |
117 | $ grunt test
118 |
119 | We use jasmine as a unit testing framework to test our boilerplate code, as of now it's been only done for `_.main.js`, you would get all the test done in the next release.
120 |
121 |
122 | ## Contributing
123 |
124 | Anyone and everyone is welcome to [contribute](#).
125 |
126 |
127 | ## Project information
128 |
129 | * Source: https://github.com/mdarif/JavaScript-Boilerplate
130 |
131 |
132 | ## License
133 | See [LICENSE](LICENSE)
134 |
135 |
136 | ## Author
137 |
138 | * Mohammed Arif [@arif_iq](http://twitter.com/arif_iq), [github](https://github.com/mdarif)
139 |
140 | [build-image]: http://img.shields.io/travis/mdarif/JavaScript-Boilerplate.svg?style=flat
141 | [build-url]: http://travis-ci.org/mdarif/JavaScript-Boilerplate
142 |
143 | [dependencies-image]: https://gemnasium.com/mdarif/JavaScript-Boilerplate.svg?style=flat
144 | [dependencies-url]: https://gemnasium.com/mdarif/JavaScript-Boilerplate
145 |
146 | [license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat
147 | [license-url]: LICENSE
148 |
149 | [version-image]: http://img.shields.io/github/tag/mdarif/JavaScript-Boilerplate.svg?style=flat
150 | [version-url]: https://github.com/mdarif/JavaScript-Boilerplate/tags
151 |
152 | [codeclimate-image]: https://codeclimate.com/repos/558392546956804e780009ea/badges/9cb6feeef61e41a567ad/gpa.svg?style=flat
153 | [codeclimate-url]: https://codeclimate.com/repos/558392546956804e780009ea/feed
154 |
155 |
--------------------------------------------------------------------------------
/src/js/_.helper.js:
--------------------------------------------------------------------------------
1 | /* JavaScript Boilerplate helper file *
2 | * @version 1.2
3 | * GIT URL - https://github.com/mdarif/JavaScript-Boilerplate
4 | * Author - Mohammed Arif
5 | */
6 |
7 | (function (JSB, $, undefined) {
8 | 'use strict';
9 |
10 | /*
11 | * Singletons serve as a namespace provider which isolate implementation code
12 | * from the global namespace so as to provide a single point of access for functions,
13 | * this is useful for organizing code into logical sections.
14 | * It is possible to put parentheses around this structure to instantiate it immediately after it's parsed.
15 | * This way it's always present when the script is executed and doesn't have to be instantiated separately.
16 | */
17 | JSB.helper = (function () {
18 | function _helper() {
19 |
20 | /**
21 | * In non-strict mode, 'this' is bound to the global scope when it isn't bound to anything else.
22 | * In strict mode it is 'undefined'. That makes it an error to use it outside of a method.
23 | */
24 |
25 | /*jshint validthis: true */
26 | var _this = this,
27 |
28 | /*
29 | * This method return the element using javaScript getElementById() method.
30 | * This is the private method not meant for use as a public method.
31 | */
32 | id = function (el) {
33 | return document.getElementById(el);
34 | },
35 |
36 | /*
37 | * Store information in a cookie
38 | * Accept three param name, value, days
39 | */
40 | setCookie = function (name, value, days) {
41 | var date = "",
42 | expires = "";
43 |
44 | if (days) {
45 | date = new Date();
46 | date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
47 | expires = "; expires=" + date.toGMTString();
48 | }
49 |
50 | document.cookie = name + "=" + value + expires + "; path=/";
51 | },
52 |
53 | /*
54 | * Get cookie from user machine
55 | * Accept one parameters name
56 | * name : name of the cookie
57 | */
58 | getCookie = function (name) {
59 | var nameEQ = name + "=",
60 | i,
61 | ca = document.cookie.split(';');
62 | for (i = 0; i < ca.length; i += 1) {
63 | var c = ca[i];
64 | while (c.charAt(0) === ' ') {
65 | c = c.substring(1, c.length);
66 | }
67 | if (c.indexOf(nameEQ) === 0) {
68 | return c.substring(nameEQ.length, c.length);
69 | }
70 | }
71 | return null;
72 | },
73 |
74 | /*
75 | * Erase or delete cookie from user machine
76 | * Accept one parameters name
77 | * name : name of the cookie
78 | */
79 | removeCookie = function (name) {
80 | setCookie(name, "", -1);
81 | };
82 |
83 | /*
84 | * Replace multiple value in a single string.
85 | * Accept two parameters str, hash
86 | * str : String on which replace operation is to be performed
87 | * hash : JSON object contain string to be replaced with there replaced value
88 | * Return the new string at the end.
89 | */
90 | this.multiReplace = function (str, hash) {
91 | var key;
92 | for (key in hash) {
93 | if (Object.prototype.hasOwnProperty.call(hash, key)) {
94 | str = str.replace(new RegExp(key, 'g'), hash[key]);
95 | }
96 | }
97 | return str;
98 | };
99 |
100 | /*
101 | * Set the CSS on a particular element
102 | * Accept two parameters el, styles
103 | * el : The name of element on which CSS is to be apply.
104 | * styles : Various CSS property with their values. Accept data in JSON format
105 | * This method calls a private method setStyle
106 | */
107 | this.setCSS = function (el, styles) {
108 | var prop;
109 | for (prop in styles) {
110 | if (styles.hasOwnProperty(prop)) {
111 | _this.setStyle(el, prop, styles[prop]);
112 | }
113 | }
114 | };
115 |
116 | /*
117 | * Apply the CSS to the given element
118 | * Accept three parameters elements, prop, val
119 | * element : The element on which CSS is to be apply.
120 | * This method will automatically search for element using getElementById() method.
121 | * prop : CSS properties
122 | * val : Vale for CSS property
123 | */
124 | this.setStyle = function (el, prop, val) {
125 | id(el).style[prop] = val;
126 | };
127 |
128 | /*
129 | * Check if the given element has given class assign or not.
130 | * Accept two parameters el, name
131 | * el : Element for testing. This method will search for element using JavaScript getElementById() method.
132 | * name : name of class to be test
133 | * This method return true and false
134 | */
135 | this.hasClass = function (el, name) {
136 | el = id(el);
137 | return new RegExp('(\\s|^)' + name + '(\\s|$)').test(el.className);
138 | };
139 |
140 | /*
141 | * Add class to the given element
142 | * Accept two parameters el, name
143 | * el : element on which class to be add
144 | * name : name of class
145 | */
146 | this.addClass = function (el, name) {
147 | if (!_this.hasClass(el, name)) {
148 | el = id(el);
149 | el.className += (el.className ? ' ' : '') + name;
150 | }
151 | };
152 |
153 | /*
154 | * Remove class from given element
155 | * Accept two parameters el, name
156 | * el : element from which class is to be remove
157 | * name : name of the class to be remove
158 | */
159 | this.removeClass = function (el, name) {
160 | if (_this.hasClass(el, name)) {
161 | el = id(el);
162 | el.className = el.className.replace(new RegExp('(\\s|^)' + name + '(\\s|$)'), ' ').replace(/^\s+|\s+$/g, '');
163 | }
164 | };
165 |
166 | /*
167 | * This method will check for blank value in the provided string
168 | * This will return true if provided string contain blank value and false if not
169 | */
170 | this.isBlank = function (string) {
171 | var isNonblank_re = /\S/;
172 | return String(string).search(isNonblank_re) === -1;
173 | };
174 |
175 | /*
176 | * Store information to client machine
177 | * Accept two parameters name, value
178 | * name : name of the localStorage
179 | * value : value for the localStorage
180 | * Store information in HTML5 localstorage if available
181 | * else store information in cookie
182 | */
183 | this.setInfo = function (name, value) {
184 | if (typeof window.localStorage !== 'undefined') {
185 | localStorage.setItem(name, value);
186 | } else {
187 | setCookie(name, value);
188 | }
189 | };
190 |
191 | /*
192 | * Get information from client machine
193 | * Accept two parameters name, checkCookie
194 | * name : name of the localstorage
195 | * checkCookie : This will either be true or false.
196 | * If set to true then scan cookie even if user system support localStorage
197 | * Get information for HTML5 localstorage if available
198 | * else get information from cookie
199 | */
200 | this.getInfo = function (name, checkCookie) {
201 | var value = "";
202 | if (typeof window.localStorage !== 'undefined') {
203 | value = localStorage.getItem(name);
204 | } else {
205 | value = getCookie(name);
206 | }
207 |
208 | if (checkCookie === true) {
209 | value = getCookie(name);
210 | }
211 | return value;
212 | };
213 |
214 | /*
215 | * Remove information from client machine
216 | * Accept two parameters name, checkCookie
217 | * name : name of the localstorage for removing it permanently
218 | * checkCookie : This will either be true or false.
219 | * If set to true then scan cookie and remove if found even if user system support localStorage
220 | * Remove information for HTML5 localstorage if available
221 | * else remove information from cookie
222 | */
223 | this.removeInfo = function (name, checkCookie) {
224 | if (typeof window.localStorage !== 'undefined') {
225 | localStorage.removeItem(name);
226 | } else {
227 | removeCookie(name);
228 | }
229 | if (checkCookie === true) {
230 | removeCookie(name);
231 | }
232 | };
233 |
234 | this.init = function () {
235 | return this; /*returning this from a method is a common way to allow "chaining" of methods together*/
236 | };
237 |
238 | return this.init(); /*this refer to JSB.helper.init()*/
239 | }
240 |
241 | return new _helper(); /*creating a new object of helper rather then a funtion*/
242 | }());
243 |
244 | /**
245 | * Check to evaluate whether 'JSB' exists in the global namespace - if not, assign window.JSB an object literal
246 | */
247 | }(window.JSB = window.JSB || {}, jQuery));
248 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | JavaScript Boilerplate
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
Public/Private Variables and Methods
28 |
29 |
30 | Private variables
31 | are declared with the 'var' keyword inside the object, and can only be accessed by private functions and privileged methods.
32 |
33 |
34 | Private functions
35 | are declared inline inside the object's constructor (or alternatively may be defined via var functionName=function(){...}) and may only be called by privileged methods (including the object's constructor).
36 |
37 |
38 | Privileged methods
39 | are declared with this.methodName=function(){...} and may invoked by code external to the object.
40 |
41 |
42 | Public properties
43 | are declared with this.variableName and may be read/written from outside the object.
44 |
45 |
46 | Public methods
47 | are defined by Classname.prototype.methodName = function(){...} and may be called from outside the object.
48 |
49 |
50 | Prototype properties
51 | are defined by Classname.prototype.propertyName = someValue
52 |
53 |
54 | Static properties
55 | are defined by Classname.propertyName = someValue
56 |
57 |
58 |
59 |
60 |
61 |
Privileged methods/Helper Functions
62 |
63 |
multiReplace(str, hash)
64 |
65 | Replace multiple value in a single string. Return the new string at the end. You can pass regExe also.
66 |
96 | Check if the given element has given class assign or not.
97 |
98 |
99 |
JSB.helper.hasClass("main", "my_element");
100 |
101 |
102 |
103 |
104 |
addClass(el, name)
105 |
106 | Add class to the given element.
107 |
108 |
109 |
JSB.helper.addClass("main", "my_element2");
110 |
111 |
112 |
113 |
114 |
removeClass(el, name)
115 |
116 | Remove class from the given element.
117 |
118 |
119 |
JSB.helper.removeClass("main", "my_element2");
120 |
121 |
122 |
123 |
124 |
getDomain()
125 |
126 | Return the URI of site. Return protocol, hostname and port if found.
127 |
128 |
129 |
JSB.helper.getDomain();
130 |
131 |
132 |
133 |
134 |
getQueryString(name, default_)
135 |
136 | This method will return the query string from the URL of the website.
137 |
138 |
139 |
Copy "?name=RSR&age=26" and paste this at the address bar of the website and press enter.
140 |
141 |
JSB.helper.getQueryString("name", "Not Found.");
142 |
143 |
144 |
145 |
146 |
isBlank(string)
147 |
148 | This method will check for blank value in the provided string. This will return true if provided string contain blank value and false if not.
149 |
150 |
151 |
var test = " ";
152 | JSB.helper.isBlank(test);
153 |
154 |
155 |
156 |
157 |
setInfo(name, value)
158 |
159 | Store information to client machine using HTML5 localStorate method.
160 |
161 |
162 |
JSB.helper.setInfo("name", "RSR");
163 |
164 |
165 |
166 |
167 |
getInfo(name, checkCookie)
168 |
169 | Get information from client machine. Get information for HTML5 localstorage if available else get information from cookie.
170 |
171 |
172 |
JSB.helper.getInfo("name");
173 |
174 |
175 |
176 |
177 |
removeInfo(name, checkCookie)
178 |
179 | Remove information from client machine.
180 |
181 |
182 |
JSB.helper.removeInfo("name");
183 |
184 |
185 |
186 |
187 |
Private methods
188 |
189 |
id(el)
190 |
191 | This method return the element using javaScript getElementById() method.
192 |
193 |
194 |
195 |
setCookie(name,value,days)
196 |
197 | Store informaiton in a cookie on user machine.
198 |
199 |
200 |
201 |
getCookie(name)
202 |
203 | Get value of cookie by using its name from user machine.
204 |
205 |
206 |
207 |
removeCookie(name)
208 |
209 | Remove or delete cookie from user machine by its name.
210 |