Skip to content

Commit

Permalink
Sets up the gist of emailauth-js
Browse files Browse the repository at this point in the history
  • Loading branch information
motdotla committed Oct 17, 2013
1 parent 7a9e34e commit c277df4
Show file tree
Hide file tree
Showing 14 changed files with 586 additions and 12 deletions.
27 changes: 26 additions & 1 deletion Gruntfile.coffee
@@ -1,4 +1,27 @@
module.exports = (grunt) ->
# custom task to embed css into the view
grunt.registerTask 'embedcss', 'Embed CSS.', ->
sqwish = require('sqwish')

src = grunt.file.read("src/css/application.css")
minified_css = sqwish.minify(src)

combined = "(function(EmailAuth){" +
"EmailAuth.prototype._drawCss = function() {" +
"this.css = '" + minified_css + "';" +
"var style = document.createElement('style');" +
"style.type = 'text/css';" +
"if (style.styleSheet) {" +
"style.styleSheet.cssText = this.css;" +
"} else {" +
"style.appendChild(document.createTextNode(this.css));" +
"}" +
"return document.body.appendChild(style);" +
"};" +
"}(EmailAuth));"

grunt.file.write("src/emailauth/css.js", combined)

grunt.initConfig
pkg: grunt.file.readJSON("package.json")
banner: "/*! <%= pkg.name %>.js - <%= pkg.version %> - <%= grunt.template.today(\"yyyy-mm-dd\") %> - <%= pkg.author %> */\n"
Expand All @@ -9,13 +32,15 @@ module.exports = (grunt) ->
uglify:
options:
banner: "<%= banner %>"
en:
src: ["build/emailauth.js"]
dest: "build/emailauth.min.js"
concat:
options:
banner: "<%= banner %>"
separator: '\n\n'
stripBanners : true
en:
src: "<%= files %>"
dest: "build/emailauth.js"
jshint:
Expand All @@ -38,7 +63,7 @@ module.exports = (grunt) ->
grunt.loadNpmTasks "grunt-contrib-jshint"

grunt.registerTask "test", ["simplemocha", "jshint"]
grunt.registerTask "default", ["jshint", "concat", "uglify", "connect"]
grunt.registerTask "default", ["embedcss", "jshint", "concat", "uglify", "connect"]

# Some available commands
# grunt
Expand Down
19 changes: 19 additions & 0 deletions README.md
@@ -1,5 +1,24 @@
# emailauth.js

## Usage

Place the following where you want your login form to be displayed in your application.

Replace the data-app_name value with your own and the root_url value with your own instance of emailauth. See [emailauth repo](https://github.com/scottmotte/emailauth) for more details.

```html
<script src='/build/emailauth.js'
data-app_name="emailauthjstest"
data-root_url="https://emailauth.herokuapp.com" />
<script>
emailauth.script.addEventListener('emailauth:login_confirm', function(e) {
console.log(e.data);
}, false);
</script>
```

In the addEventListener portion, add your own bit of logic to log someone in. For example, set a session or a cookie.

## Dev Setup

```
Expand Down
274 changes: 274 additions & 0 deletions build/emailauth.js
@@ -0,0 +1,274 @@
/*! emailauth-js.js - 0.0.1 - 2013-10-17 - scottmotte */
(function(exports){
var EmailAuth = function() {
if(!(this instanceof EmailAuth)){
return new EmailAuth();
}

this.uuid = this.Uuid();
this.script = this.CurrentlyExecutedScript();
this.init();

return this;
};

EmailAuth.prototype.init = function() {
if (this.script) {
this.script.className += " emailauth-script";
this.script.id = "emailauth-script-"+this.uuid;
this.app_name = this.script.getAttribute("data-app_name");
this.root_url = this.script.getAttribute("data-root_url");
this.confirm_url = this.script.getAttribute("data-confirm_url") || "/login/request.json";

if (!this.app_name || this.app_name.length < 1) {
console.error("Warning: data-app_name not set on script tag. Set to the app_name you setup.");
}
if (!this.root_url || this.root_url.length < 1) {
console.error("Warning: data-root_url not set on script tag. Set to the root url where you deployed emailauth. Likely, https://somedomain.herokuapp.com.");
}

this.draw();
this.events();
} else {
console.error("ERROR: Could not find script tag to initialize on.");
}
};

exports.EmailAuth = EmailAuth;

}(this));


(function(EmailAuth){EmailAuth.prototype._drawCss = function() {this.css = '@charset "utf-8";.emailauth-hidden{display:none}';var style = document.createElement('style');style.type = 'text/css';if (style.styleSheet) {style.styleSheet.cssText = this.css;} else {style.appendChild(document.createTextNode(this.css));}return document.body.appendChild(style);};}(EmailAuth));

(function(EmailAuth){
EmailAuth.prototype.draw = function() {
this._drawCss();
this._drawEmailForm();
this._drawEmailField();
this._drawEmailSubmitBtn();
this._drawAuthcodeForm();
this._drawAuthcodeField();
this._drawAuthcodeSubmitBtn();
};

EmailAuth.prototype._drawEmailForm = function() {
this.email_form = document.createElement('form');
this.email_form.className = "emailauth-email-form";
this.email_form.id = "emailauth-email-form-"+this.uuid;

return this.InsertAfter(this.script, this.email_form);
};

EmailAuth.prototype._drawEmailSubmitBtn = function() {
this.email_submit_btn = document.createElement('input');
this.email_submit_btn.className = "emailauth-email-submit-btn";
this.email_submit_btn.id = "emailauth-email-submit-btn-"+this.uuid;
this.email_submit_btn.type = "submit";
this.email_submit_btn.value = "Request Login";

return this.email_form.appendChild(this.email_submit_btn);
};

EmailAuth.prototype._drawEmailField = function() {
this.email_field = document.createElement('input');
this.email_field.className = "emailauth-email-field";
this.email_field.id = "emailauth-email-field-id-"+this.uuid;
this.email_field.placeholder = "email";

return this.email_form.appendChild(this.email_field);
};

EmailAuth.prototype._drawAuthcodeForm = function() {
this.authcode_form = document.createElement('form');
this.authcode_form.className = "emailauth-authcode-form emailauth-hidden";
this.authcode_form.id = "emailauth-authcode-form-"+this.uuid;

return this.InsertAfter(this.email_form, this.authcode_form);
};

EmailAuth.prototype._drawAuthcodeSubmitBtn = function() {
this.authcode_submit_btn = document.createElement('input');
this.authcode_submit_btn.className = "emailauth-authcode-submit-btn";
this.authcode_submit_btn.id = "emailauth-authcode-submit-btn-"+this.uuid;
this.authcode_submit_btn.type = "submit";
this.authcode_submit_btn.value = "Confirm Login";

return this.authcode_form.appendChild(this.authcode_submit_btn);
};

EmailAuth.prototype._drawAuthcodeField = function() {
this.authcode_field = document.createElement('input');
this.authcode_field.className = "emailauth-authcode-field";
this.authcode_field.id = "emailauth-authcode-field-id-"+this.uuid;
this.authcode_field.placeholder = "authcode";

return this.authcode_form.appendChild(this.authcode_field);
};

}(EmailAuth));


(function(EmailAuth){
var self;
var CLICK = "click";
var TOUCH_SUPPORTED = (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) ? true : false;
if (!!TOUCH_SUPPORTED) {
CLICK = "touchend";
}

EmailAuth.prototype.events = function() {
self = this;

this._submitEmailForm();
this._submitAuthcodeForm();
};

EmailAuth.prototype._submitEmailForm = function() {
this.email_form.addEventListener('submit', this.requestLogin, false);
};

EmailAuth.prototype._submitAuthcodeForm = function() {
this.authcode_form.addEventListener('submit', this.confirmLogin, false);
};

EmailAuth.prototype._showEmailFormOnly = function() {
this.removeClass(this.email_form, "emailauth-hidden");
this.addClass(this.authcode_form, "emailauth-hidden");
};

EmailAuth.prototype._showAuthcodeFormOnly = function() {
this.addClass(this.email_form, "emailauth-hidden");
this.removeClass(this.authcode_form, "emailauth-hidden");
};

EmailAuth.prototype.requestLogin = function(e) {
if (e) { e.preventDefault(); }

var payload = {
email: self.email_field.value,
app_name: self.app_name
};
var url = self.root_url+"/api/v0/login/request.json";

self.Post(url, payload, function(resp) {
if (!!resp.success) {
self._showAuthcodeFormOnly();
} else {
self._showEmailFormOnly();
alert(resp.error.message);
}
});
};

EmailAuth.prototype.confirmLogin = function(e) {
if (e) { e.preventDefault(); }

var payload = {
authcode: self.authcode_field.value,
email: self.email_field.value,
app_name: self.app_name
};
var url = self.root_url+"/api/v0/login/confirm.json";

self.Post(url, payload, function(resp) {
self.FireEvent("emailauth:login_confirm", self.script, resp);

if (!!resp.success) {
self.addClass(self.authcode_form, "emailauth-hidden");
} else {
self.removeClass(self.authcode_form, "emailauth-hidden");
alert(resp.error.message);
}
});
};

}(EmailAuth));


(function(EmailAuth){
EmailAuth.prototype.Uuid = function() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
var r, v;
r = Math.random() * 16 | 0;
v = (c === "x" ? r : r & 0x3 | 0x8);
return v.toString(16);
});
};

EmailAuth.prototype.CurrentlyExecutedScript = function() {
var script;

if (document) {
var scripts = document.getElementsByTagName('script');
script = scripts[scripts.length - 1];
}
return script;
};

EmailAuth.prototype.InsertAfter = function(reference_node, new_node) {
return reference_node.parentNode.insertBefore(new_node, reference_node.nextSibling);
};

EmailAuth.prototype.hasClass = function(el, name) {
return new RegExp('(\\s|^)'+name+'(\\s|$)').test(el.className);
};

EmailAuth.prototype.addClass = function(el, name) {
if (!this.hasClass(el, name)) {
el.className += (el.className ? ' ' : '') +name;
}
};

EmailAuth.prototype.removeClass = function(el, name) {
if (this.hasClass(el, name)) {
el.className=el.className.replace(new RegExp('(\\s|^)'+name+'(\\s|$)'),' ').replace(/^\s+|\s+$/g, '');
}
};

EmailAuth.prototype.FireEvent = function(name, target, data) {
//Create a generic event
var bubbles = true;
var cancelable = true;
var event = document.createEvent("Events");
//Initialize it to be the event we want
event.initEvent(name, bubbles, cancelable);
event.data = data;
//FIRE!
target.dispatchEvent(event);
};

EmailAuth.prototype.Post = function(url, data, callback){
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("post", url, true);
xmlhttp.setRequestHeader("Content-type", "application/json");
xmlhttp.onreadystatechange = function(){
if (xmlhttp.readyState==4){
if (xmlhttp.status==200){
callback(JSON.parse(xmlhttp.responseText));
} else {
console.error("You found an ajax error. Please create an issue at http://github.com/scottmotte/emailauth.");
}
}
};

xmlhttp.send(JSON.stringify(data));
};

EmailAuth.prototype.FireEvent = function(name, target, data) {
//Create a generic event
var bubbles = true;
var cancelable = true;
var event = document.createEvent("Events");
//Initialize it to be the event we want
event.initEvent(name, bubbles, cancelable);
event.data = data;
//FIRE!
target.dispatchEvent(event);
};

}(EmailAuth));


var emailauth = EmailAuth();

2 changes: 2 additions & 0 deletions build/emailauth.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -11,7 +11,8 @@
"grunt-contrib-connect": "~0.3.0",
"grunt-contrib-concat": "~0.3.0",
"grunt-simple-mocha": "~0.4.0",
"should": "~1.2.2"
"should": "~1.2.2",
"sqwish": "~0.2.0"
},
"scripts": {
"test": "grunt test --verbose"
Expand Down
1 change: 1 addition & 0 deletions public/build
16 changes: 16 additions & 0 deletions public/index.html
@@ -0,0 +1,16 @@
<html>
<head>
<title>Web Root</title>
</head>
<body>
<h1>Emailauth.js</h1>
<script src='/build/emailauth.js'
data-app_name="emailauthjstest"
data-root_url="https://emailauth.herokuapp.com" />
<script>
emailauth.script.addEventListener('emailauth:login_confirm', function(e) {
console.log(e.data);
}, false);
</script>
</body>
</html>
5 changes: 5 additions & 0 deletions src/css/application.css
@@ -0,0 +1,5 @@
@charset "utf-8";

.emailauth-hidden {
display: none;
}

0 comments on commit c277df4

Please sign in to comment.