Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Development #1

Merged
merged 61 commits into from
Nov 13, 2014
Merged
Show file tree
Hide file tree
Changes from 56 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
33e48f0
[#MmLRZ2E2] [#MmLRZ2E2] [#MmLRZ2E2] Make README less opinionated, add…
localjo Sep 4, 2014
327f21b
[#MmLRZ2E2] Add templates and render into demo, add gulp
localjo Sep 5, 2014
79c0cfb
[#MmLRZ2E2] Add Universe Support
localjo Sep 9, 2014
5376e6f
[#MmLRZ2E2] Add Messaging and Events
localjo Sep 9, 2014
e8b4c40
[#MmLRZ2E2] Add option to override the template
localjo Sep 10, 2014
4760fdf
[#MmLRZ2E2] Add SendGrid Support
localjo Sep 10, 2014
84e90a5
[#MmLRZ2E2] refactor as node module
localjo Sep 12, 2014
4bc3e0f
[#MmLRZ2E2] package as UMD
localjo Sep 12, 2014
6cb8dfe
[#MmLRZ2E2] add derequire
localjo Sep 12, 2014
23d151e
[#MmLRZ2E2] move handlebars to dependencies instead of dev
localjo Sep 12, 2014
8cc6ab6
[#MmLRZ2E2] add default options and make template BEM
localjo Sep 15, 2014
897ae33
[#MmLRZ2E2] include instanceof check
localjo Sep 15, 2014
1b060b8
[#MmLRZ2E2] move hbsfy transform to gulp
localjo Sep 15, 2014
d95e7bc
[#MmLRZ2E2] Add events API, clean up docs
localjo Sep 16, 2014
419128f
[#MmLRZ2E2] update readme and simplify some things
localjo Sep 17, 2014
03f114e
[#MmLRZ2E2] Add tests
localjo Sep 17, 2014
a9127d3
[#MmLRZ2E2] Bind events to object instance
localjo Sep 17, 2014
83c0833
[#MmLRZ2E2] Update test configuration
localjo Sep 17, 2014
3938c81
[#MmLRZ2E2] add mailchimp support, jquery support, and events
localjo Sep 19, 2014
a51f83e
[#MmLRZ2E2] add IE9 fallbacks for all services
localjo Sep 22, 2014
383d295
[#MmLRZ2E2] Add Automated Mocha Tests
localjo Sep 23, 2014
e2f4c66
[#MmLRZ2E2] Add mocha task to gulp and make tests more DRY
localjo Sep 24, 2014
379f0af
[#MmLRZ2E2] Add tests for all supported browsers
localjo Sep 25, 2014
9dc885c
[#MmLRZ2E2] Add browserstack tunnel to gulp tasks
localjo Sep 25, 2014
93454fd
[#MmLRZ2E2] fire event on xhr failure
localjo Oct 3, 2014
2ae1cb9
[#MmLRZ2E2] use production api instead of staging
localjo Oct 3, 2014
088f4ee
[#MmLRZ2E2] fix JSONP in IE9, other cleanup
localjo Oct 7, 2014
5a6e78b
[#MmLRZ2E2] return success for JSONP requests
localjo Oct 7, 2014
5674bcd
[#MmLRZ2E2] add check for blank submission
localjo Oct 8, 2014
50ace19
[#MmLRZ2E2] change entry point to unbuilt src
localjo Oct 9, 2014
2e30380
[#MmLRZ2E2] ignore built version
localjo Oct 10, 2014
c72d3dc
[#MmLRZ2E2] remove console log
localjo Oct 13, 2014
5b8c183
[#MmLRZ2E2] remove testling badges
localjo Oct 15, 2014
9683f6a
[#MmLRZ2E2] add helpful error message for empty form
localjo Oct 15, 2014
17a8f0d
[#MmLRZ2E2] add template option to override template
localjo Oct 17, 2014
412d6bc
[#MmLRZ2E2] simplify hbsfy require
localjo Oct 17, 2014
0522ea9
[#MmLRZ2E2] add repo field, remove extra handlebars dep
localjo Oct 17, 2014
369f17f
[#MmLRZ2E2] add tests for template option, rm overrideTemplate
localjo Oct 17, 2014
91aa867
[#MmLRZ2E2] update default template markup
localjo Oct 17, 2014
ff4cd6f
[#MmLRZ2E2] remove responseElement from test
localjo Oct 17, 2014
6c4a383
[#MmLRZ2E2] switch to alerter module for messaging
localjo Oct 20, 2014
1725fb9
[#MmLRZ2E2] clear up private method definitions
localjo Oct 20, 2014
d209950
[#MmLRZ2E2] add in page mocha tests
localjo Oct 21, 2014
09b07ea
[#MmLRZ2E2] improve testing workflow and write pending tests
localjo Oct 22, 2014
1295b0e
[#MmLRZ2E2] add browser tests
localjo Oct 22, 2014
eab4133
[#MmLRZ2E2] add sinon fake server for universe and sendgrid
localjo Oct 23, 2014
5b46c7e
[#MmLRZ2E2] mock JSONP responses and more
localjo Oct 24, 2014
55c1d77
[#MmLRZ2E2] fix sinon XDomainRequest, clean up CORS request
localjo Oct 27, 2014
7766368
[#MmLRZ2E2] remove console logs
localjo Oct 27, 2014
da83586
[#MmLRZ2E2] test iPhone 6 instead of 5
localjo Oct 27, 2014
3593ab1
[#MmLRZ2E2] add doctype to mocha test page for ie9
localjo Oct 28, 2014
d969836
[#MmLRZ2E2] add event tests
localjo Oct 29, 2014
b1bc875
[#MmLRZ2E2] update readme
localjo Oct 29, 2014
05bdb24
[#MmLRZ2E2] replace placeholder with template
localjo Oct 30, 2014
eafad14
[#MmLRZ2E2] add friendlier message for mocha test errors
localjo Oct 30, 2014
72b7657
[#MmLRZ2E2] address review feedback
localjo Nov 12, 2014
9ba64cb
[#MmLRZ2E2] address review feedback
localjo Nov 12, 2014
8fb5dce
Merge branch 'MmLRZ2E2-development' of https://github.com/blocks/subs…
localjo Nov 12, 2014
86a23a8
[#MmLRZ2E2] change api urls to https
localjo Nov 12, 2014
4eaeffc
[#MmLRZ2E2] move hbsfy to package.json instead of gulp task
localjo Nov 13, 2014
d7090d9
[#MmLRZ2E2] update metadata
localjo Nov 13, 2014
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
build/*
test/mocha/tests.js
89 changes: 54 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,51 +1,70 @@
Subscribe Email is a UMD JavaScript module for rendering a mailing list sign up form quickly on a webpage.
Subscribe Email is a standalone UMD JavaScript module for rendering a mailing list sign up form quickly on a webpage.

It allows developers to quickly include an email collection form on a page without being concerned with the implementation details of a specific mailing list platform. We're currently aiming to support mailing lists on SendGrid, MailChimp and Universe.
It allows developers to quickly include an email collection form on a page without being concerned with the implementation details of a specific mailing list platform. It currently supports mailing lists on SendGrid, MailChimp and Universe.

# Including the Module in Your Project
You can include the module any way that fits with your workflow;
# Getting the Module
You can get the module in any one of the following ways;
- Download [the latest release](https://github.com/blocks/subscribe-email/releases) from GitHub
- Or install with npm; `npm install subscribe-email`
- Or install with Bower; `bower install subscribe-email`

**If you use bower (recommended):**
`bower install subscribe-email --save`
# Quick Start
To get started, you'll need to include the script on your page, create a `<form>` element, and initialize the module. After you include subscribe-email.js in your project, here's some minimal code you can use to get started quickly;

**If you use npm:**
`npm install subscribe-email --save`
```
<form id="subscribe-form"></form>
```

**If you're not using a package manager:**
Just copy and paste the `/dist` directory to wherever you want it in your project.

```
<script>
new SubscribeEmail({
element: '#subscribe-form',
service: 'universe',
key: 'your-api-key-here'
});
</script>
```

# Wiring Things Up
Once you've got the module included in your project, getting started using it is simple.
At a minimum, you'll need to change the `service` and `key` parameters to match your needs. *(Note: MailChimp uses `url` instead of `key`).*

1. Include subscribe-email.js in your page. You can use your preferred script loader, concatenate it with the rest of your scripts during your build process, or just drop `<script src="subscribe-email.min.js">` into your page. Just make sure you update the path to point to wherever you've saved or included it.
2. Create an empty placeholder element for the subscription form on the page; `<div id="subscribe-form"></div>`.
# Advanced Usage

## Quick Start
## Options
The module can be configured with several optional parameters passed to it's constructor. Here is the full list of options:

Create a new `SubscribeEmail` instance somewhere in the page's JavaScript. The only parameter that's required is the `element`. You can either use the ID of the placeholder HTML element you created or pass in a jQuery object;
```
new SubscribeEmail({
element: subscribe-form
});
```
### `element`
**(Required)** A DOM element, jQuery element, or selector string to refer to the placeholder element.

## Advanced Options
### `prependMessagesTo`
By default, responses from the different mailing list platforms will be prepended to the SubscribeEmail `element` as a dismissable alert, but you can use this option to override which element the alerts are prepended to. Accepts a query string or a jQuery object.

There are also some advanced configuration options available.
```
new SubscribeEmail({
element: subscribe-form, //required
template: 'minimal-BEM', //defaults to 'minimal-BEM'
async: true //defaults to false
});
```
### `service`
**(Required)** The mailing list platform you are using. Available options are `mailchimp`, `sendgrid` and `universe`.

### `key`
**(Required)** A string of the API key for your mailing list platform. *(This is not required for MailChimp. Instead, you'll have to use `url`).*

### `url`
**(Required for MailChimp)** A string of the `<form action="">` attribute generated by MailChimp which contains MailChimp authentication information. You can get this from MailChimp under "Signup forms > Embedded form code > Naked" and copying just the value from the `<form action="">` attribute. It should follow this format: `http://{username}.{data center}.list-manage.com/subscribe/post?u={user id}&id={list id}`.

### `submitText`
A string to be used on the form's submit button (defaults to "Subscribe").

## Customizing the Template
The Subscribe Email module comes with some compiled Handlebars templates that you can choose from. If you want to create custom HTML template(s), you can add a Handlebars template to `/src/templates` and run `gulp build` from the project directory to build the module from source and compile the template.
### `template`
If you want to customize the markup, you can override the default markup by passing in a *compiled* handlebars template using this option. See the default template for a starting point to work from. A custom template will not work without a form tag that contains `id="{{id}}"` and an email input that contains `name="{{emailName}}"`. (Defaults to `false`).

### `namespace`
Out of the box, the module will generate BEM markup with the namespace `subscribe-email`, but you can use this option to override the default without passing in a custom template.

## Events
Some mailing list platforms may send response messages for things like confirmation or validation errors. The default template will display these messages along-side the form, but alternatively you can easily integrate the messages into other parts of your page by listening for the following events to fire;
You can easily integrate the messages into other parts of your page by listening for the following events to be emitted from the SubscribeEmail instance;

### `subscriptionMessage`
Fires whenever the mailing list provider returns a response (both success and failure). The message will be passed to this event as a string.

### `subscriptionError`
This event will fire if the mailing list provider returns an error. Specific details about the error will be passed to the event as a payload object.

`subscriptionError`: This event will fire if the mailing list provider returns an error and fails to add the email address to the list. Specific details about the error will be included in a payload object when available.
`subscriptionSuccess`: This event will fire if the mailing list provider returns a confirmation that the email address has been added to the list. Specific details will be included in a payload object when available.
### `subscriptionSuccess`
This event will fire if the mailing list provider returns a confirmation that the email address has been added to the list. Specific details will be passed to the event as a payload object.
104 changes: 104 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
var gulp = require('gulp');
var runSequence = require('run-sequence');
var browserify = require('browserify');
var hbsfy = require('hbsfy');
var source = require('vinyl-source-stream');
var derequire = require('gulp-derequire');
var http = require('http');
var ecstatic = require('ecstatic');
var BrowserStackTunnel = require('browserstacktunnel-wrapper');
var mocha = require('gulp-spawn-mocha');

function handleError(err) {
console.log(err.message);
this.emit('end');
}

// Task groups
gulp.task('default', ['build', 'build-tests', 'start-server']);

gulp.task('test', function(cb) {
runSequence(
['build', 'build-tests', 'start-server', 'start-browserstack-tunnel'],
'run-selenium',
['stop-test-server', 'stop-browserstack-tunnel'],
cb
);
});

gulp.task('manual-test', ['default', 'start-browserstack-tunnel'])

gulp.task('build', function() {
var bundler = browserify({
entries: ['./src/subscribe-email.js'],
standalone: 'SubscribeEmail'
});
var bundle = function() {
return bundler
.transform(hbsfy)
.bundle()
.pipe(source('subscribe-email.js'))
.pipe(derequire())
.pipe(gulp.dest('./build/'));
};
return bundle();
});

gulp.task('build-tests', function() {
var bundler = browserify({
entries: ['./test/tests.js']
});
var bundle = function() {
return bundler
.transform({global: true}, hbsfy)
.bundle()
.pipe(source('tests.js'))
.pipe(derequire())
.pipe(gulp.dest('./test/mocha/'));
};
return bundle();
});

var devServer;
gulp.task('start-server', function(cb) {
devServer = http.createServer(
ecstatic({ root: './' })
).listen(8080);
console.log('Listening on :8080');
cb();
});

gulp.task('stop-test-server', function(cb) {
devServer.close(cb);
});

var browserStackTunnel;
gulp.task('start-browserstack-tunnel', function(cb) {
browserStackTunnel = new BrowserStackTunnel({
key: '',
hosts: [{
name: 'localhost',
port: 3000,
sslFlag: 0
}],
v: true
});
browserStackTunnel.start(function(error) {
if (error) {
console.log(error);
} else {
console.log('BrowserStack Tunnel Started');
cb();
}
});
});

gulp.task('stop-browserstack-tunnel', function(cb) {
browserStackTunnel.stop(cb);
});

gulp.task('run-selenium', function () {
return gulp.src('test/selenium-driver.js', {read: false})
.pipe(mocha({timeout: 55000}))
.on('error', handleError);
});
44 changes: 44 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "blocks-subscribe",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be blocks-subscribe-email?

"version": "1.0.0",
"description": "Subscribes an email address to a list. Supports a selection of email marketing services.",
"keywords": [
"email",
"subscription"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if adding ecosystem:blocks is the right way to go. It can't hurt, but from my understanding of npm's blog;

ecosystems: subsets of npm packages that all have a common foundation

I think that means ecosystems should be based on a "common foundation" module; something like ecosystem:browserify, ecosystem:gulp, ecosystem:solidus or maybe ecosystem:browser.

I kind of think Blocks is more semantically a "collection", since there's no foundational "Blocks" module that these modules depend on.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is still a bit nascent, but there are common threads for each block:

  • Implements a narrowly scoped capability
  • Structures UI following BEM methodology
  • Namespaces code with a convention reinforcing that structure
  • Templates markup with Handlebars
  • Exports JS as a UMD module
  • Emits events to facilitate PubSub between modules
  • Provides structural CSS only as needed
  • Guarantees browser support through automated and transparent testing
  • Documents all of the above in a consistent fashion

The foundation isn't our contribution, but rather an opinionated set of conventions that provides developers with a consistent experience and maximizes interoperability. There's some bias towards use with Solidus, and some blocks will have some pieces that may be used with the Solidus server, but there's nothing in that list that technically binds them to Solidus. We'll be using these ourselves on some static sites in addition to Solidus.

The goal is to develop a library of parts like Bootstrap, Foundation, etc. but keeping everything decoupled so that developers can easily take only the pieces they need. The conventions provide a path for extensibility, so developers can also incorporate their own pieces (and ideally contribute).

Planning to crystallize all this with the website, but that's where my head's at.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The goal is to develop a library of parts like Bootstrap, Foundation, etc.

It's basically all front-end modules. How do you feel about ecosystem:browser? I feel like that fits into npm's paradigm a little more than :blocks. We could also do both, and maybe include ecosystem:solidus as well. What do you think?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah true, just wanted to connect our modules together too, but covering all the bases doesn't hurt. We can reevaluate later if anyone's got a problem.

],
"repository": {
"type": "git",
"url": "https://github.com/blocks/subscribe-email.git"
},
"homepage": "https://github.com/blocks/subscribe-email",
"bugs": "https://github.com/blocks/subscribe-email/issues",
"license": "MIT",
"author": "Josiah Sprague <[email protected]>",
"main": "src/subscribe-email.js",
"devDependencies": {
"browserify": "^5.11.1",
"browserstack-webdriver": "^2.41.1",
"browserstacktunnel-wrapper": "~1.3.0",
"ecstatic": "^0.5.4",
"gulp": "^3.8.7",
"gulp-derequire": "^1.1.0",
"gulp-notify": "^1.5.1",
"gulp-spawn-mocha": "^0.4.1",
"handlebars": "1.3.x",
"hbsfy": "^2.1.0",
"istanbul": "^0.3.2",
"jquery": "^2.1.1",
"mocha": "^1.21.5",
"mocha-clean": "^0.3.0",
"object-merge": "~2.5.1",
"pretty-hrtime": "^0.2.1",
"require-dir": "^0.1.0",
"run-sequence": "~0.3.7",
"vinyl-source-stream": "^0.1.1"
},
"dependencies": {
"blocks-alerter": "^1.0.2",
"form-serialize": "^0.3.0",
"inherits": "^2.0.1"
}
}
Loading