├── app
├── .gitkeep
├── services
│ ├── csv.js
│ └── excel.js
├── initializers
│ ├── csv.js
│ └── excel.js
└── components
│ ├── export-selector.js
│ └── export-selector-onselect.js
├── addon
├── .gitkeep
├── templates
│ └── components
│ │ ├── export-selector.hbs
│ │ └── export-selector-onselect.hbs
├── initializers
│ ├── csv.js
│ └── excel.js
├── components
│ ├── export-selector-onselect.js
│ └── export-selector.js
├── utils
│ └── utils.js
└── services
│ ├── csv.js
│ └── excel.js
├── vendor
├── .gitkeep
├── FileSaver-1.3.3.js
└── Blob.js
├── tests
├── unit
│ ├── .gitkeep
│ └── services
│ │ └── csv-test.js
├── dummy
│ ├── app
│ │ ├── helpers
│ │ │ └── .gitkeep
│ │ ├── models
│ │ │ └── .gitkeep
│ │ ├── routes
│ │ │ └── .gitkeep
│ │ ├── styles
│ │ │ └── app.css
│ │ ├── components
│ │ │ └── .gitkeep
│ │ ├── controllers
│ │ │ └── .gitkeep
│ │ ├── templates
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ └── application.hbs
│ │ ├── router.js
│ │ ├── app.js
│ │ └── index.html
│ ├── public
│ │ ├── robots.txt
│ │ └── crossdomain.xml
│ └── config
│ │ └── environment.js
├── test-helper.js
├── helpers
│ ├── resolver.js
│ └── start-app.js
├── .jshintrc
└── index.html
├── .watchmanconfig
├── .bowerrc
├── blueprints
├── .jshintrc
└── ember-cli-data-export
│ └── index.js
├── config
├── environment.js
└── ember-try.js
├── bower.json
├── .github
└── CODEOWNERS
├── .npmignore
├── testem.json
├── .ember-cli
├── .gitignore
├── index.js
├── ember-cli-build.js
├── .editorconfig
├── .jshintrc
├── .travis.yml
├── README.md
├── LICENSE.md
└── package.json
/app/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addon/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vendor/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/unit/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/helpers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/styles/app.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {
2 | "ignore_dirs": ["tmp"]
3 | }
4 |
--------------------------------------------------------------------------------
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components",
3 | "analytics": false
4 | }
5 |
--------------------------------------------------------------------------------
/tests/dummy/public/robots.txt:
--------------------------------------------------------------------------------
1 | # http://www.robotstxt.org
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/app/services/csv.js:
--------------------------------------------------------------------------------
1 | export { default, initialize } from 'ember-cli-data-export/services/csv';
2 |
--------------------------------------------------------------------------------
/app/services/excel.js:
--------------------------------------------------------------------------------
1 | export { default, initialize } from 'ember-cli-data-export/services/excel';
2 |
--------------------------------------------------------------------------------
/blueprints/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": [
3 | "console"
4 | ],
5 | "strict": false
6 | }
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 |
Welcome to Ember
2 |
3 | {{outlet}}
4 |
--------------------------------------------------------------------------------
/app/initializers/csv.js:
--------------------------------------------------------------------------------
1 | export { default, initialize } from 'ember-cli-data-export/initializers/csv';
2 |
--------------------------------------------------------------------------------
/app/components/export-selector.js:
--------------------------------------------------------------------------------
1 | export { default } from 'ember-cli-data-export/components/export-selector';
2 |
--------------------------------------------------------------------------------
/app/initializers/excel.js:
--------------------------------------------------------------------------------
1 | export { default, initialize } from 'ember-cli-data-export/initializers/excel';
2 |
--------------------------------------------------------------------------------
/app/components/export-selector-onselect.js:
--------------------------------------------------------------------------------
1 | export { default } from 'ember-cli-data-export/components/export-selector-onselect';
2 |
--------------------------------------------------------------------------------
/config/environment.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(/* environment, appConfig */) {
4 | return { };
5 | };
6 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-cli-data-export",
3 | "dependencies": {
4 | "jquery": "^1.11.3"
5 | },
6 | "devDependencies": {
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tests/test-helper.js:
--------------------------------------------------------------------------------
1 | import resolver from './helpers/resolver';
2 | import {
3 | setResolver
4 | } from 'ember-qunit';
5 |
6 | setResolver(resolver);
7 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # These owners will be the default owners for everything in
2 | # the repo. Unless a later match takes precedence,
3 | * @roofstock/ember-cli-data-export-co
4 |
--------------------------------------------------------------------------------
/blueprints/ember-cli-data-export/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | description: 'Installs the underlying xlsx component using bower',
3 |
4 | normalizeEntityName: function() {} // no-op since we're just adding dependencies
5 | };
6 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | bower_components/
2 | tests/
3 | tmp/
4 | dist/
5 |
6 | .bowerrc
7 | .editorconfig
8 | .ember-cli
9 | .travis.yml
10 | .npmignore
11 | **/.gitkeep
12 | bower.json
13 | ember-cli-build.js
14 | Brocfile.js
15 | testem.json
16 |
--------------------------------------------------------------------------------
/testem.json:
--------------------------------------------------------------------------------
1 | {
2 | "framework": "qunit",
3 | "test_page": "tests/index.html?hidepassed",
4 | "disable_watching": true,
5 | "launch_in_ci": [
6 | "PhantomJS"
7 | ],
8 | "launch_in_dev": [
9 | "PhantomJS",
10 | "Chrome"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/tests/dummy/app/router.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import config from './config/environment';
3 |
4 | var Router = Ember.Router.extend({
5 | location: config.locationType
6 | });
7 |
8 | Router.map(function() {
9 | });
10 |
11 | export default Router;
12 |
--------------------------------------------------------------------------------
/addon/templates/components/export-selector.hbs:
--------------------------------------------------------------------------------
1 |
2 | {{select-list content=types value=selectedType action=(action (mut selectedType))}}
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.ember-cli:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | Ember CLI sends analytics information by default. The data is completely
4 | anonymous, but there are times when you might want to disable this behavior.
5 |
6 | Setting `disableAnalytics` to true will prevent any data from being sent.
7 | */
8 | "disableAnalytics": false
9 | }
10 |
--------------------------------------------------------------------------------
/tests/helpers/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from 'ember/resolver';
2 | import config from '../../config/environment';
3 |
4 | var resolver = Resolver.create();
5 |
6 | resolver.namespace = {
7 | modulePrefix: config.modulePrefix,
8 | podModulePrefix: config.podModulePrefix
9 | };
10 |
11 | export default resolver;
12 |
--------------------------------------------------------------------------------
/addon/templates/components/export-selector-onselect.hbs:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 |
7 | # dependencies
8 | /node_modules
9 | /bower_components
10 |
11 | # misc
12 | /.sass-cache
13 | /connect.lock
14 | /coverage/*
15 | /libpeerconnection.log
16 | npm-debug.log
17 | testem.log
18 | .idea/
19 |
--------------------------------------------------------------------------------
/addon/initializers/csv.js:
--------------------------------------------------------------------------------
1 | export function initialize() {
2 | var application = arguments[1] || arguments[0];
3 | application.inject('route', 'csv', 'service:csv');
4 | application.inject('component', 'csv', 'service:csv');
5 | application.inject('controller', 'csv', 'service:csv');
6 | }
7 |
8 | export default {
9 | name: 'csv',
10 | initialize: initialize
11 | };
12 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /* jshint node: true */
2 | 'use strict';
3 |
4 | module.exports = {
5 | name: 'ember-cli-data-export',
6 |
7 | included: function(app) {
8 | this._super.included(app);
9 | app.import('vendor/Blob.js');
10 | app.import('vendor/FileSaver-1.3.3.js');
11 | app.import('vendor/jszip-0.10.8.js');
12 | app.import('vendor/xlsx-0.10.8.js');
13 | }
14 | };
15 |
--------------------------------------------------------------------------------
/addon/initializers/excel.js:
--------------------------------------------------------------------------------
1 | export function initialize() {
2 | var application = arguments[1] || arguments[0];
3 | application.inject('route', 'excel', 'service:excel');
4 | application.inject('component', 'excel', 'service:excel');
5 | application.inject('controller', 'excel', 'service:excel');
6 | }
7 |
8 | export default {
9 | name: 'excel',
10 | initialize: initialize
11 | };
12 |
--------------------------------------------------------------------------------
/addon/components/export-selector-onselect.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import layout from '../templates/components/export-selector-onselect';
3 |
4 | export default Ember.Component.extend({
5 | layout: layout,
6 | selectPrompt: 'Export File',
7 |
8 | actions: {
9 | triggerExport: function(selectedType) {
10 | this.sendAction('exportData', selectedType);
11 | this.$('#exportTypes').val('');
12 | }
13 | }
14 | });
15 |
--------------------------------------------------------------------------------
/addon/utils/utils.js:
--------------------------------------------------------------------------------
1 | export default function optionize(options, defaultConfig){
2 | if (Object.prototype.toString.call( options ) === "[object Object]") {
3 | options = options || {};
4 | } else {
5 | options = {};
6 | }
7 |
8 | for (let property in defaultConfig) {
9 | options[property] = (typeof options[property] !== 'undefined') ?
10 | options[property] :
11 | defaultConfig[property];
12 | }
13 |
14 | return options;
15 | }
16 |
--------------------------------------------------------------------------------
/tests/dummy/app/app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Resolver from 'ember/resolver';
3 | import loadInitializers from 'ember/load-initializers';
4 | import config from './config/environment';
5 |
6 | var App;
7 |
8 | Ember.MODEL_FACTORY_INJECTIONS = true;
9 |
10 | App = Ember.Application.extend({
11 | modulePrefix: config.modulePrefix,
12 | podModulePrefix: config.podModulePrefix,
13 | Resolver: Resolver
14 | });
15 |
16 | loadInitializers(App, config.modulePrefix);
17 |
18 | export default App;
19 |
--------------------------------------------------------------------------------
/addon/components/export-selector.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import layout from '../templates/components/export-selector';
3 |
4 | export default Ember.Component.extend({
5 | layout: layout,
6 | types: Ember.computed(function() {
7 | return [this.get('selectPrompt'), 'Excel', 'CSV'];
8 | }),
9 | selectedType : null,
10 | actionText: 'Export',
11 | selectPrompt: 'Export File',
12 |
13 | actions: {
14 | triggerExport: function() {
15 | this.sendAction('exportData', this.get('selectedType'));
16 | }
17 | }
18 | });
19 |
--------------------------------------------------------------------------------
/ember-cli-build.js:
--------------------------------------------------------------------------------
1 | /* global require, module */
2 | var EmberApp = require('ember-cli/lib/broccoli/ember-addon');
3 |
4 | module.exports = function(defaults) {
5 | var app = new EmberApp(defaults, {
6 | // Add options here
7 | });
8 |
9 | /*
10 | This build file specifes the options for the dummy test app of this
11 | addon, located in `/tests/dummy`
12 | This build file does *not* influence how the addon or the app using it
13 | behave. You most likely want to be modifying `./index.js` or app's build file
14 | */
15 |
16 | return app.toTree();
17 | };
18 |
--------------------------------------------------------------------------------
/tests/helpers/start-app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Application from '../../app';
3 | import config from '../../config/environment';
4 |
5 | export default function startApp(attrs) {
6 | var application;
7 |
8 | var attributes = Ember.merge({}, config.APP);
9 | attributes = Ember.merge(attributes, attrs); // use defaults, but you can override;
10 |
11 | Ember.run(function() {
12 | application = Application.create(attributes);
13 | application.setupForTesting();
14 | application.injectTestHelpers();
15 | });
16 |
17 | return application;
18 | }
19 |
--------------------------------------------------------------------------------
/tests/dummy/public/crossdomain.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 |
8 | [*]
9 | end_of_line = lf
10 | charset = utf-8
11 | trim_trailing_whitespace = true
12 | insert_final_newline = true
13 | indent_style = space
14 | indent_size = 2
15 |
16 | [*.js]
17 | indent_style = space
18 | indent_size = 2
19 |
20 | [*.hbs]
21 | insert_final_newline = false
22 | indent_style = space
23 | indent_size = 2
24 |
25 | [*.css]
26 | indent_style = space
27 | indent_size = 2
28 |
29 | [*.html]
30 | indent_style = space
31 | indent_size = 2
32 |
33 | [*.{diff,md}]
34 | trim_trailing_whitespace = false
35 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": [
3 | "document",
4 | "window",
5 | "-Promise",
6 | "saveAs",
7 | "XLSX"
8 | ],
9 | "browser": true,
10 | "boss": true,
11 | "curly": true,
12 | "debug": false,
13 | "devel": true,
14 | "eqeqeq": true,
15 | "evil": true,
16 | "forin": false,
17 | "immed": false,
18 | "laxbreak": false,
19 | "newcap": true,
20 | "noarg": true,
21 | "noempty": false,
22 | "nonew": false,
23 | "nomen": false,
24 | "onevar": false,
25 | "plusplus": false,
26 | "regexp": false,
27 | "undef": true,
28 | "sub": true,
29 | "strict": false,
30 | "white": false,
31 | "eqnull": true,
32 | "esnext": true,
33 | "unused": true
34 | }
35 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | language: node_js
3 | node_js:
4 | - "0.12"
5 |
6 | sudo: false
7 |
8 | cache:
9 | directories:
10 | - node_modules
11 |
12 | env:
13 | - EMBER_TRY_SCENARIO=default
14 | - EMBER_TRY_SCENARIO=ember-release
15 | - EMBER_TRY_SCENARIO=ember-beta
16 | - EMBER_TRY_SCENARIO=ember-canary
17 |
18 | matrix:
19 | fast_finish: true
20 | allow_failures:
21 | - env: EMBER_TRY_SCENARIO=ember-canary
22 |
23 | before_install:
24 | - export PATH=/usr/local/phantomjs-2.0.0/bin:$PATH
25 | - "npm config set spin false"
26 | - "npm install -g npm@^2"
27 |
28 | install:
29 | - npm install -g bower
30 | - npm install
31 | - bower install
32 |
33 | script:
34 | - ember try $EMBER_TRY_SCENARIO test
35 |
--------------------------------------------------------------------------------
/tests/dummy/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy
7 |
8 |
9 |
10 | {{content-for 'head'}}
11 |
12 |
13 |
14 |
15 | {{content-for 'head-footer'}}
16 |
17 |
18 | {{content-for 'body'}}
19 |
20 |
21 |
22 |
23 | {{content-for 'body-footer'}}
24 |
25 |
26 |
--------------------------------------------------------------------------------
/config/ember-try.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | scenarios: [
3 | {
4 | name: 'default',
5 | dependencies: { }
6 | },
7 | {
8 | name: 'ember-release',
9 | dependencies: {
10 | 'ember': 'components/ember#release'
11 | },
12 | resolutions: {
13 | 'ember': 'release'
14 | }
15 | },
16 | {
17 | name: 'ember-beta',
18 | dependencies: {
19 | 'ember': 'components/ember#beta'
20 | },
21 | resolutions: {
22 | 'ember': 'beta'
23 | }
24 | },
25 | {
26 | name: 'ember-canary',
27 | dependencies: {
28 | 'ember': 'components/ember#canary'
29 | },
30 | resolutions: {
31 | 'ember': 'canary'
32 | }
33 | }
34 | ]
35 | };
36 |
--------------------------------------------------------------------------------
/tests/unit/services/csv-test.js:
--------------------------------------------------------------------------------
1 | import { moduleFor, test } from 'ember-qunit';
2 |
3 | moduleFor('service:csv', 'Unit | Service | csv', {
4 | // Specify the other units that are required for this test.
5 | // needs: ['service:foo']
6 | });
7 |
8 | // Replace this with your real tests.
9 | test('#jsonToCsv - with valid Array of Arrays, it should return an string with CSV format', function(assert) {
10 | const service = this.subject();
11 | const array = [
12 | [
13 | 'name',
14 | 'last_name',
15 | ],
16 | [
17 | 'Dale',
18 | 'Cooper'
19 | ],
20 | ];
21 | const expectedCSV = '\"name\",\"last_name\"\r\n\"Dale\",\"Cooper\"\r\n';
22 | const options = {
23 | separator: ',',
24 | withSeparator: false,
25 | };
26 |
27 | assert.deepEqual(service.jsonToCsv(array, options), expectedCSV);
28 | });
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ember-cli-data-export
2 |
3 | Addon that encapsulates ability to render a data set as either excel or csv.
4 |
5 | ## Installation
6 |
7 | - ember install ember-cli-data-export
8 |
9 | ## Usage
10 |
11 | - uses js-xlsx library for rendering excel content.
12 | - automatically injects a service for both excel and csv format
13 | - feed a datastructure that's an array of arrays, where each internal array is the set of data to be rendered for that row.
14 | - Example: [['Title 1', 'Title 2', 'Title 3'],['row1cell1', 'row1cell2', 'row1cell3'],['row2cell1', 'row2cell2', 'row2cell3']]
15 |
16 | ## Example
17 | ```javascript
18 |
19 | var data = [
20 | ['Title 1', 'Title 2', 'Title 3'],
21 | ['row1cell1', 'row1cell2', 'row1cell3'],
22 | ['row2cell1', 'row2cell2', 'row2cell3']
23 | ];
24 |
25 | if (type === 'Excel') {
26 | this.get('excel').export(data, {sheetName: 'sheet1', fileName: 'test.xlsx'});
27 | } else if (type === 'CSV') {
28 | this.get('csv').export(data, {fileName: 'test.csv'});
29 | }
30 | ```
--------------------------------------------------------------------------------
/tests/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": [
3 | "document",
4 | "window",
5 | "location",
6 | "setTimeout",
7 | "$",
8 | "-Promise",
9 | "define",
10 | "console",
11 | "visit",
12 | "exists",
13 | "fillIn",
14 | "click",
15 | "keyEvent",
16 | "triggerEvent",
17 | "find",
18 | "findWithAssert",
19 | "wait",
20 | "DS",
21 | "andThen",
22 | "currentURL",
23 | "currentPath",
24 | "currentRouteName"
25 | ],
26 | "node": false,
27 | "browser": false,
28 | "boss": true,
29 | "curly": true,
30 | "debug": false,
31 | "devel": false,
32 | "eqeqeq": true,
33 | "evil": true,
34 | "forin": false,
35 | "immed": false,
36 | "laxbreak": false,
37 | "newcap": true,
38 | "noarg": true,
39 | "noempty": false,
40 | "nonew": false,
41 | "nomen": false,
42 | "onevar": false,
43 | "plusplus": false,
44 | "regexp": false,
45 | "undef": true,
46 | "sub": true,
47 | "strict": false,
48 | "white": false,
49 | "eqnull": true,
50 | "esnext": true,
51 | "unused": true
52 | }
53 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016
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.
10 |
--------------------------------------------------------------------------------
/tests/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy Tests
7 |
8 |
9 |
10 | {{content-for 'head'}}
11 | {{content-for 'test-head'}}
12 |
13 |
14 |
15 |
16 |
17 | {{content-for 'head-footer'}}
18 | {{content-for 'test-head-footer'}}
19 |
20 |
21 |
22 | {{content-for 'body'}}
23 | {{content-for 'test-body'}}
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | {{content-for 'body-footer'}}
32 | {{content-for 'test-body-footer'}}
33 |
34 |
35 |
--------------------------------------------------------------------------------
/tests/dummy/config/environment.js:
--------------------------------------------------------------------------------
1 | /* jshint node: true */
2 |
3 | module.exports = function(environment) {
4 | var ENV = {
5 | modulePrefix: 'dummy',
6 | environment: environment,
7 | baseURL: '/',
8 | locationType: 'auto',
9 | EmberENV: {
10 | FEATURES: {
11 | // Here you can enable experimental features on an ember canary build
12 | // e.g. 'with-controller': true
13 | }
14 | },
15 |
16 | APP: {
17 | // Here you can pass flags/options to your application instance
18 | // when it is created
19 | }
20 | };
21 |
22 | if (environment === 'development') {
23 | // ENV.APP.LOG_RESOLVER = true;
24 | // ENV.APP.LOG_ACTIVE_GENERATION = true;
25 | // ENV.APP.LOG_TRANSITIONS = true;
26 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
27 | // ENV.APP.LOG_VIEW_LOOKUPS = true;
28 | }
29 |
30 | if (environment === 'test') {
31 | // Testem prefers this...
32 | ENV.baseURL = '/';
33 | ENV.locationType = 'none';
34 |
35 | // keep test console output quieter
36 | ENV.APP.LOG_ACTIVE_GENERATION = false;
37 | ENV.APP.LOG_VIEW_LOOKUPS = false;
38 |
39 | ENV.APP.rootElement = '#ember-testing';
40 | }
41 |
42 | if (environment === 'production') {
43 |
44 | }
45 |
46 | return ENV;
47 | };
48 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-cli-data-export",
3 | "version": "0.1.29",
4 | "author": "Matt Armstrong",
5 | "description": "Provides ability to export a set of json data as excel or csv file.",
6 | "directories": {
7 | "doc": "doc",
8 | "test": "tests"
9 | },
10 | "scripts": {
11 | "build": "ember build",
12 | "start": "ember server",
13 | "test": "ember try:each"
14 | },
15 | "repository": "https://github.com/roofstock/ember-cli-data-export",
16 | "engines": {
17 | "node": ">= 4"
18 | },
19 | "license": "MIT",
20 | "devDependencies": {
21 | "broccoli-asset-rev": "^2.4.5",
22 | "ember-ajax": "^2.4.1",
23 | "ember-cli": "^2.12.0",
24 | "ember-cli-app-version": "^2.0.0",
25 | "ember-cli-dependency-checker": "^1.3.0",
26 | "ember-cli-htmlbars": "^1.2.0",
27 | "ember-cli-htmlbars-inline-precompile": "^0.3.6",
28 | "ember-cli-inject-live-reload": "^1.4.1",
29 | "ember-cli-jshint": "^2.0.1",
30 | "ember-cli-qunit": "^3.0.1",
31 | "ember-cli-release": "1.0.0-beta.2",
32 | "ember-cli-shims": "^1.0.2",
33 | "ember-cli-sri": "^2.1.0",
34 | "ember-cli-test-loader": "^1.1.0",
35 | "ember-cli-uglify": "^1.2.0",
36 | "ember-data": "^2.11.0",
37 | "ember-disable-prototype-extensions": "^1.1.0",
38 | "ember-export-application-global": "^1.0.5",
39 | "ember-load-initializers": "^0.6.0",
40 | "ember-resolver": "^3.0.0",
41 | "ember-source": "~2.12.0",
42 | "loader.js": "^4.0.10"
43 | },
44 | "keywords": [
45 | "ember-addon",
46 | "ember-cli",
47 | "xlsx",
48 | "excel",
49 | "csv"
50 | ],
51 | "dependencies": {
52 | "ember-cli-htmlbars": "^1.2.0",
53 | "ember-cli-babel": "^5.1.7",
54 | "ember-select-list": "^0.9.5",
55 | "xlsx": "^0.9.0"
56 | },
57 | "ember-addon": {
58 | "configPath": "tests/dummy/config"
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/addon/services/csv.js:
--------------------------------------------------------------------------------
1 | import Ember from "ember";
2 | import optionize from "../utils/utils";
3 |
4 | const defaultConfig = {
5 | fileName: 'export.csv',
6 | separator: ',',
7 | withSeparator: true
8 | };
9 |
10 | export default Ember.Service.extend({
11 |
12 | export: function (data, options) {
13 | options = optionize(options, defaultConfig);
14 |
15 | var csv = this.jsonToCsv(data, options);
16 |
17 | saveAs(new Blob([csv],{type:"data:text/csv;charset=utf-8"}), options.fileName);
18 | },
19 |
20 | jsonToCsv(objArray, options) {
21 | var array = typeof objArray !== 'object' ? JSON.parse(objArray) : objArray;
22 |
23 | var str = '';
24 | var line = '';
25 | var value;
26 |
27 | if (options.withSeparator) {
28 | // add separator identifier;
29 | str += `sep=${options.separator}\r\n`;
30 | }
31 |
32 | // add heading row
33 | var head = array[0];
34 | for (var i = 0; i < head.length; i++) {
35 | value = head[i] + "";
36 | if (i > 0) {
37 | line += options.separator;
38 | }
39 | line += '"' + value.replace(/"/g, '""') + '"';
40 | }
41 |
42 | str += line + '\r\n';
43 |
44 | // add items
45 | for (i = 1; i < array.length; i++) {
46 | line = '';
47 |
48 | for (var index = 0; index < array[i].length; index++) {
49 | value = array[i][index];
50 |
51 | if (index > 0) {
52 | line += options.separator;
53 | }
54 | if (typeof value === 'object') {
55 | if (value) {
56 | var resolveValue;
57 | if (value._d instanceof Date) {
58 | // dealing with encoding issue in IE browsers.
59 | resolveValue = (value._d.getMonth() + 1) + '/' + value._d.getDate() + '/' + value._d.getFullYear();
60 | }
61 | else {
62 | resolveValue = value._d.toString();
63 | }
64 |
65 | line += '"' + resolveValue.replace(/"/g, '""') + '"';
66 | }
67 | else {
68 | line += '""';
69 | }
70 | }
71 | else {
72 | value = value + "";
73 | if (value && value !== 'undefined') {
74 | line += '"' + value.replace(/"/g, '""') + '"';
75 | }
76 | else {
77 | line += '""';
78 | }
79 | }
80 | }
81 |
82 | str += line + '\r\n';
83 | }
84 | return str;
85 | }
86 | });
87 |
--------------------------------------------------------------------------------
/addon/services/excel.js:
--------------------------------------------------------------------------------
1 | import Ember from "ember";
2 | import optionize from "../utils/utils";
3 |
4 | const defaultConfig = {
5 | sheetName: 'Sheet1',
6 | fileName: 'export.xlsx'
7 | };
8 |
9 | export default Ember.Service.extend({
10 |
11 | export : function(data, options) {
12 |
13 | options = optionize(options, defaultConfig);
14 |
15 | function s2ab(s) {
16 | var buf = new ArrayBuffer(s.length);
17 | var view = new Uint8Array(buf);
18 | for (var i=0; i!==s.length; ++i) { view[i] = s.charCodeAt(i) & 0xFF; }
19 | return buf;
20 | }
21 |
22 | function datenum(v, date1904) {
23 | if(date1904) { v+=1462; }
24 | var epoch = Date.parse(v);
25 | return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
26 | }
27 |
28 | function sheet_from_array_of_arrays(data) {
29 | var ws = {};
30 | var range = {s: {c:10000000, r:10000000}, e: {c:0, r:0 }};
31 | for(var R = 0; R !== data.length; ++R) {
32 | for(var C = 0; C !== data[R].length; ++C) {
33 | if(range.s.r > R) { range.s.r = R; }
34 | if(range.s.c > C) { range.s.c = C; }
35 | if(range.e.r < R) { range.e.r = R; }
36 | if(range.e.c < C) { range.e.c = C; }
37 | var cell = {v: data[R][C] };
38 | if(cell.v == null) { continue; }
39 | var cell_ref = XLSX.utils.encode_cell({c:C,r:R});
40 |
41 | if(typeof cell.v === 'number') { cell.t = 'n'; }
42 | else if(typeof cell.v === 'boolean') { cell.t = 'b'; }
43 | else if((typeof cell.v === 'object') && (cell.v._d instanceof Date)) {
44 | cell.t = 'n'; cell.z = XLSX.SSF._table[14];
45 | cell.v = datenum(cell.v._d);
46 | }
47 | else { cell.t = 's'; }
48 |
49 | ws[cell_ref] = cell;
50 | }
51 | }
52 | if(range.s.c < 10000000) { ws['!ref'] = XLSX.utils.encode_range(range); }
53 | return ws;
54 | }
55 |
56 | function Workbook() {
57 | if(!(this instanceof Workbook)) { return new Workbook(); }
58 | this.SheetNames = [];
59 | this.Sheets = {};
60 | }
61 |
62 | var wb = new Workbook(), ws = sheet_from_array_of_arrays(data);
63 |
64 | /* add worksheet to workbook */
65 | wb.SheetNames.push(options.sheetName);
66 | wb.Sheets[options.sheetName] = ws;
67 | var wbout = XLSX.write(wb, {bookType:'xlsx', bookSST:true, type: 'binary'});
68 |
69 | saveAs(new Blob([s2ab(wbout)],{type:"application/octet-stream"}), options.fileName);
70 |
71 | }
72 |
73 | });
74 |
--------------------------------------------------------------------------------
/vendor/FileSaver-1.3.3.js:
--------------------------------------------------------------------------------
1 | /* FileSaver.js
2 | * A saveAs() FileSaver implementation.
3 | * 1.3.2
4 | * 2016-06-16 18:25:19
5 | *
6 | * By Eli Grey, http://eligrey.com
7 | * License: MIT
8 | * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
9 | */
10 |
11 | /*global self */
12 | /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
13 |
14 | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
15 |
16 | var saveAs = saveAs || (function(view) {
17 | "use strict";
18 | // IE <10 is explicitly unsupported
19 | if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
20 | return;
21 | }
22 | var
23 | doc = view.document
24 | // only get URL when necessary in case Blob.js hasn't overridden it yet
25 | , get_URL = function() {
26 | return view.URL || view.webkitURL || view;
27 | }
28 | , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
29 | , can_use_save_link = "download" in save_link
30 | , click = function(node) {
31 | var event = new MouseEvent("click");
32 | node.dispatchEvent(event);
33 | }
34 | , is_safari = /constructor/i.test(view.HTMLElement) || view.safari
35 | , is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent)
36 | , throw_outside = function(ex) {
37 | (view.setImmediate || view.setTimeout)(function() {
38 | throw ex;
39 | }, 0);
40 | }
41 | , force_saveable_type = "application/octet-stream"
42 | // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
43 | , arbitrary_revoke_timeout = 1000 * 40 // in ms
44 | , revoke = function(file) {
45 | var revoker = function() {
46 | if (typeof file === "string") { // file is an object URL
47 | get_URL().revokeObjectURL(file);
48 | } else { // file is a File
49 | file.remove();
50 | }
51 | };
52 | setTimeout(revoker, arbitrary_revoke_timeout);
53 | }
54 | , dispatch = function(filesaver, event_types, event) {
55 | event_types = [].concat(event_types);
56 | var i = event_types.length;
57 | while (i--) {
58 | var listener = filesaver["on" + event_types[i]];
59 | if (typeof listener === "function") {
60 | try {
61 | listener.call(filesaver, event || filesaver);
62 | } catch (ex) {
63 | throw_outside(ex);
64 | }
65 | }
66 | }
67 | }
68 | , auto_bom = function(blob) {
69 | // prepend BOM for UTF-8 XML and text/* types (including HTML)
70 | // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
71 | if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
72 | return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type});
73 | }
74 | return blob;
75 | }
76 | , FileSaver = function(blob, name, no_auto_bom) {
77 | if (!no_auto_bom) {
78 | blob = auto_bom(blob);
79 | }
80 | // First try a.download, then web filesystem, then object URLs
81 | var
82 | filesaver = this
83 | , type = blob.type
84 | , force = type === force_saveable_type
85 | , object_url
86 | , dispatch_all = function() {
87 | dispatch(filesaver, "writestart progress write writeend".split(" "));
88 | }
89 | // on any filesys errors revert to saving with object URLs
90 | , fs_error = function() {
91 | if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {
92 | // Safari doesn't allow downloading of blob urls
93 | var reader = new FileReader();
94 | reader.onloadend = function() {
95 | var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
96 | var popup = view.open(url, '_blank');
97 | if(!popup) view.location.href = url;
98 | url=undefined; // release reference before dispatching
99 | filesaver.readyState = filesaver.DONE;
100 | dispatch_all();
101 | };
102 | reader.readAsDataURL(blob);
103 | filesaver.readyState = filesaver.INIT;
104 | return;
105 | }
106 | // don't create more object URLs than needed
107 | if (!object_url) {
108 | object_url = get_URL().createObjectURL(blob);
109 | }
110 | if (force) {
111 | view.location.href = object_url;
112 | } else {
113 | var opened = view.open(object_url, "_blank");
114 | if (!opened) {
115 | // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
116 | view.location.href = object_url;
117 | }
118 | }
119 | filesaver.readyState = filesaver.DONE;
120 | dispatch_all();
121 | revoke(object_url);
122 | }
123 | ;
124 | filesaver.readyState = filesaver.INIT;
125 |
126 | if (can_use_save_link) {
127 | object_url = get_URL().createObjectURL(blob);
128 | setTimeout(function() {
129 | save_link.href = object_url;
130 | save_link.download = name;
131 | click(save_link);
132 | dispatch_all();
133 | revoke(object_url);
134 | filesaver.readyState = filesaver.DONE;
135 | });
136 | return;
137 | }
138 |
139 | fs_error();
140 | }
141 | , FS_proto = FileSaver.prototype
142 | , saveAs = function(blob, name, no_auto_bom) {
143 | return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
144 | }
145 | ;
146 | // IE 10+ (native saveAs)
147 | if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
148 | return function(blob, name, no_auto_bom) {
149 | name = name || blob.name || "download";
150 |
151 | if (!no_auto_bom) {
152 | blob = auto_bom(blob);
153 | }
154 | return navigator.msSaveOrOpenBlob(blob, name);
155 | };
156 | }
157 |
158 | FS_proto.abort = function(){};
159 | FS_proto.readyState = FS_proto.INIT = 0;
160 | FS_proto.WRITING = 1;
161 | FS_proto.DONE = 2;
162 |
163 | FS_proto.error =
164 | FS_proto.onwritestart =
165 | FS_proto.onprogress =
166 | FS_proto.onwrite =
167 | FS_proto.onabort =
168 | FS_proto.onerror =
169 | FS_proto.onwriteend =
170 | null;
171 |
172 | return saveAs;
173 | }(
174 | typeof self !== "undefined" && self
175 | || typeof window !== "undefined" && window
176 | || this.content
177 | ));
178 | // `self` is undefined in Firefox for Android content script context
179 | // while `this` is nsIContentFrameMessageManager
180 | // with an attribute `content` that corresponds to the window
181 |
182 | if (typeof module !== "undefined" && module.exports) {
183 | module.exports.saveAs = saveAs;
184 | } else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) {
185 | define("FileSaver.js", function() {
186 | return saveAs;
187 | });
188 | }
189 |
--------------------------------------------------------------------------------
/vendor/Blob.js:
--------------------------------------------------------------------------------
1 | /* Blob.js
2 | * A Blob implementation.
3 | * 2014-07-24
4 | *
5 | * By Eli Grey, http://eligrey.com
6 | * By Devin Samarin, https://github.com/dsamarin
7 | * License: MIT
8 | * See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md
9 | */
10 |
11 | /*global self, unescape */
12 | /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
13 | plusplus: true */
14 |
15 | /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
16 |
17 | (function (view) {
18 | "use strict";
19 |
20 | view.URL = view.URL || view.webkitURL;
21 |
22 | if (view.Blob && view.URL) {
23 | try {
24 | new Blob;
25 | return;
26 | } catch (e) {}
27 | }
28 |
29 | // Internally we use a BlobBuilder implementation to base Blob off of
30 | // in order to support older browsers that only have BlobBuilder
31 | var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) {
32 | var
33 | get_class = function(object) {
34 | return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
35 | }
36 | , FakeBlobBuilder = function BlobBuilder() {
37 | this.data = [];
38 | }
39 | , FakeBlob = function Blob(data, type, encoding) {
40 | this.data = data;
41 | this.size = data.length;
42 | this.type = type;
43 | this.encoding = encoding;
44 | }
45 | , FBB_proto = FakeBlobBuilder.prototype
46 | , FB_proto = FakeBlob.prototype
47 | , FileReaderSync = view.FileReaderSync
48 | , FileException = function(type) {
49 | this.code = this[this.name = type];
50 | }
51 | , file_ex_codes = (
52 | "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
53 | + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
54 | ).split(" ")
55 | , file_ex_code = file_ex_codes.length
56 | , real_URL = view.URL || view.webkitURL || view
57 | , real_create_object_URL = real_URL.createObjectURL
58 | , real_revoke_object_URL = real_URL.revokeObjectURL
59 | , URL = real_URL
60 | , btoa = view.btoa
61 | , atob = view.atob
62 |
63 | , ArrayBuffer = view.ArrayBuffer
64 | , Uint8Array = view.Uint8Array
65 |
66 | , origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/
67 | ;
68 | FakeBlob.fake = FB_proto.fake = true;
69 | while (file_ex_code--) {
70 | FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
71 | }
72 | // Polyfill URL
73 | if (!real_URL.createObjectURL) {
74 | URL = view.URL = function(uri) {
75 | var
76 | uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
77 | , uri_origin
78 | ;
79 | uri_info.href = uri;
80 | if (!("origin" in uri_info)) {
81 | if (uri_info.protocol.toLowerCase() === "data:") {
82 | uri_info.origin = null;
83 | } else {
84 | uri_origin = uri.match(origin);
85 | uri_info.origin = uri_origin && uri_origin[1];
86 | }
87 | }
88 | return uri_info;
89 | };
90 | }
91 | URL.createObjectURL = function(blob) {
92 | var
93 | type = blob.type
94 | , data_URI_header
95 | ;
96 | if (type === null) {
97 | type = "application/octet-stream";
98 | }
99 | if (blob instanceof FakeBlob) {
100 | data_URI_header = "data:" + type;
101 | if (blob.encoding === "base64") {
102 | return data_URI_header + ";base64," + blob.data;
103 | } else if (blob.encoding === "URI") {
104 | return data_URI_header + "," + decodeURIComponent(blob.data);
105 | } if (btoa) {
106 | return data_URI_header + ";base64," + btoa(blob.data);
107 | } else {
108 | return data_URI_header + "," + encodeURIComponent(blob.data);
109 | }
110 | } else if (real_create_object_URL) {
111 | return real_create_object_URL.call(real_URL, blob);
112 | }
113 | };
114 | URL.revokeObjectURL = function(object_URL) {
115 | if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
116 | real_revoke_object_URL.call(real_URL, object_URL);
117 | }
118 | };
119 | FBB_proto.append = function(data/*, endings*/) {
120 | var bb = this.data;
121 | // decode data to a binary string
122 | if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
123 | var
124 | str = ""
125 | , buf = new Uint8Array(data)
126 | , i = 0
127 | , buf_len = buf.length
128 | ;
129 | for (; i < buf_len; i++) {
130 | str += String.fromCharCode(buf[i]);
131 | }
132 | bb.push(str);
133 | } else if (get_class(data) === "Blob" || get_class(data) === "File") {
134 | if (FileReaderSync) {
135 | var fr = new FileReaderSync;
136 | bb.push(fr.readAsBinaryString(data));
137 | } else {
138 | // async FileReader won't work as BlobBuilder is sync
139 | throw new FileException("NOT_READABLE_ERR");
140 | }
141 | } else if (data instanceof FakeBlob) {
142 | if (data.encoding === "base64" && atob) {
143 | bb.push(atob(data.data));
144 | } else if (data.encoding === "URI") {
145 | bb.push(decodeURIComponent(data.data));
146 | } else if (data.encoding === "raw") {
147 | bb.push(data.data);
148 | }
149 | } else {
150 | if (typeof data !== "string") {
151 | data += ""; // convert unsupported types to strings
152 | }
153 | // decode UTF-16 to binary string
154 | bb.push(unescape(encodeURIComponent(data)));
155 | }
156 | };
157 | FBB_proto.getBlob = function(type) {
158 | if (!arguments.length) {
159 | type = null;
160 | }
161 | return new FakeBlob(this.data.join(""), type, "raw");
162 | };
163 | FBB_proto.toString = function() {
164 | return "[object BlobBuilder]";
165 | };
166 | FB_proto.slice = function(start, end, type) {
167 | var args = arguments.length;
168 | if (args < 3) {
169 | type = null;
170 | }
171 | return new FakeBlob(
172 | this.data.slice(start, args > 1 ? end : this.data.length)
173 | , type
174 | , this.encoding
175 | );
176 | };
177 | FB_proto.toString = function() {
178 | return "[object Blob]";
179 | };
180 | FB_proto.close = function() {
181 | this.size = 0;
182 | delete this.data;
183 | };
184 | return FakeBlobBuilder;
185 | }(view));
186 |
187 | view.Blob = function(blobParts, options) {
188 | var type = options ? (options.type || "") : "";
189 | var builder = new BlobBuilder();
190 | if (blobParts) {
191 | for (var i = 0, len = blobParts.length; i < len; i++) {
192 | if (Uint8Array && blobParts[i] instanceof Uint8Array) {
193 | builder.append(blobParts[i].buffer);
194 | }
195 | else {
196 | builder.append(blobParts[i]);
197 | }
198 | }
199 | }
200 | var blob = builder.getBlob(type);
201 | if (!blob.slice && blob.webkitSlice) {
202 | blob.slice = blob.webkitSlice;
203 | }
204 | return blob;
205 | };
206 |
207 | var getPrototypeOf = Object.getPrototypeOf || function(object) {
208 | return object.__proto__;
209 | };
210 | view.Blob.prototype = getPrototypeOf(new view.Blob());
211 | }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));
212 |
--------------------------------------------------------------------------------