44 |
--------------------------------------------------------------------------------
/tests/dummy/config/environment.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | 'use strict';
3 |
4 | module.exports = function(environment) {
5 | let ENV = {
6 | modulePrefix: 'dummy',
7 | environment,
8 | rootURL: '/',
9 | locationType: 'auto',
10 | EmberENV: {
11 | FEATURES: {
12 | // Here you can enable experimental features on an ember canary build
13 | // e.g. 'with-controller': true
14 | },
15 | EXTEND_PROTOTYPES: {
16 | // Prevent Ember Data from overriding Date.parse.
17 | Date: false
18 | }
19 | },
20 |
21 | APP: {
22 | // Here you can pass flags/options to your application instance
23 | // when it is created
24 | }
25 | };
26 |
27 | if (environment === 'development') {
28 | // ENV.APP.LOG_RESOLVER = true;
29 | // ENV.APP.LOG_ACTIVE_GENERATION = true;
30 | // ENV.APP.LOG_TRANSITIONS = true;
31 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
32 | // ENV.APP.LOG_VIEW_LOOKUPS = true;
33 | }
34 |
35 | if (environment === 'test') {
36 | // Testem prefers this...
37 | ENV.locationType = 'none';
38 |
39 | // keep test console output quieter
40 | ENV.APP.LOG_ACTIVE_GENERATION = false;
41 | ENV.APP.LOG_VIEW_LOOKUPS = false;
42 |
43 | ENV.APP.rootElement = '#ember-testing';
44 | }
45 |
46 | if (environment === 'production') {
47 | ENV.locationType = 'hash';
48 | ENV.rootURL = '/emberx-file-input/';
49 |
50 | }
51 |
52 | return ENV;
53 | };
54 |
--------------------------------------------------------------------------------
/addon/components/x-file-input.js:
--------------------------------------------------------------------------------
1 | import { computed } from '@ember/object';
2 | import Component from '@ember/component';
3 | import layout from '../templates/components/x-file-input';
4 |
5 | export default Component.extend({
6 | classNameBindings: [':x-file-input', 'disabled:x-file-input--disabled'],
7 | attributeBindings: ['accept'],
8 | tagName: 'span',
9 | layout: layout,
10 | tabindex: 0,
11 |
12 | /**
13 | * The text displayed when no block is passed.
14 | *
15 | * @property alt
16 | * @default "Upload"
17 | */
18 | alt: "Upload",
19 |
20 | /**
21 | * Listens for change events on the native file input and dispatches
22 | * the corresponding action up the context chain.
23 | *
24 | * @private
25 | * @method
26 | * @param {$.Event} e Native change event
27 | */
28 | change(e) {
29 | this.sendAction("action", this.files(e), this.resetInput.bind(this));
30 | },
31 |
32 | /**
33 | * Resets the value of the input so you can select the same file
34 | * multiple times.
35 | *
36 | * @method
37 | */
38 | resetInput() {
39 | this.$('.x-file--input').val('');
40 | },
41 |
42 | /**
43 | * Generates a random ID to relate the label to the input.
44 | *
45 | * @method
46 | * @private
47 | */
48 | randomId: computed(function() {
49 | return Math.random().toString(36).substring(7);
50 | }),
51 |
52 | /**
53 | * Gets files from event object.
54 | *
55 | * @method
56 | * @private
57 | * @param {$.Event || Event}
58 | */
59 | files(e) {
60 | if (e.target.files) {
61 | return e.target.files;
62 | } else if (e.testingFiles) {
63 | return e.testingFiles;
64 | } else {
65 | // testingFiles will not exist on e
66 | // when it is a JQuery.Event
67 | return e.originalEvent.testingFiles;
68 | }
69 | }
70 | });
71 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "emberx-file-input",
3 | "version": "1.2.1",
4 | "description": "A tiny Ember component which does one thing and only: select files beautifully.",
5 | "keywords": [
6 | "ember-addon",
7 | "file input",
8 | "file selector",
9 | "custom file input"
10 | ],
11 | "license": "MIT",
12 | "author": "",
13 | "directories": {
14 | "doc": "doc",
15 | "test": "tests"
16 | },
17 | "repository": "https://github.com/adopted-ember-addons/emberx-file-input",
18 | "scripts": {
19 | "build": "ember build",
20 | "lint": "npm-run-all --aggregate-output --continue-on-error --parallel \"lint:!(fix)\"",
21 | "lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
22 | "lint:hbs": "ember-template-lint .",
23 | "lint:hbs:fix": "ember-template-lint . --fix",
24 | "lint:js": "eslint . --cache",
25 | "lint:js:fix": "eslint . --fix",
26 | "start": "ember serve",
27 | "test": "npm-run-all lint test:*",
28 | "test:ember": "ember test",
29 | "test:ember-compatibility": "ember try:each"
30 | },
31 | "dependencies": {
32 | "chai-jquery": "^2.0.0",
33 | "ember-cli-babel": "^7.26.11",
34 | "ember-cli-htmlbars": "^6.0.1"
35 | },
36 | "devDependencies": {
37 | "@embroider/test-setup": "^1.0.0",
38 | "broccoli-asset-rev": "^3.0.0",
39 | "ember-ajax": "^3.0.0",
40 | "ember-auto-import": "^2.4.1",
41 | "ember-cli": "~3.18.0",
42 | "ember-cli-chai": "^0.4.0",
43 | "ember-cli-dependency-checker": "^3.3.1",
44 | "ember-cli-eslint": "^5.1.0",
45 | "ember-cli-github-pages": "^0.1.2",
46 | "ember-cli-inject-live-reload": "^1.4.1",
47 | "ember-cli-mocha": "^0.15.0",
48 | "ember-cli-release": "^1.0.0-beta.2",
49 | "ember-cli-shims": "^1.2.0",
50 | "ember-cli-sri": "^2.1.0",
51 | "ember-cli-terser": "^4.0.2",
52 | "ember-export-application-global": "^2.0.0",
53 | "ember-load-initializers": "^2.1.2",
54 | "ember-resolver": "^8.0.3",
55 | "ember-sinon": "^5.0.0",
56 | "ember-source": "~3.16.0",
57 | "ember-template-lint": "^4.4.2",
58 | "ember-try": "^2.0.0",
59 | "loader.js": "^4.7.0",
60 | "npm-run-all": "^4.1.5",
61 | "webpack": "^5.72.0"
62 | },
63 | "engines": {
64 | "node": ">= 12"
65 | },
66 | "ember-addon": {
67 | "configPath": "tests/dummy/config",
68 | "demoURL": "http://thefrontside.github.io/emberx-file-input/"
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/config/ember-try.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const getChannelURL = require('ember-source-channel-url');
4 | const { embroiderSafe, embroiderOptimized } = require('@embroider/test-setup');
5 |
6 | module.exports = async function () {
7 | return {
8 | useYarn: true,
9 | scenarios: [
10 | {
11 | name: 'ember-lts-3.16',
12 | npm: {
13 | devDependencies: {
14 | 'ember-source': '~3.16.0',
15 | },
16 | },
17 | },
18 | {
19 | name: 'ember-lts-3.20',
20 | npm: {
21 | devDependencies: {
22 | 'ember-source': '~3.20.5',
23 | },
24 | },
25 | },
26 | {
27 | name: 'ember-lts-3.24',
28 | npm: {
29 | devDependencies: {
30 | 'ember-source': '~3.24.3',
31 | },
32 | },
33 | },
34 | {
35 | name: 'ember-lts-3.28',
36 | npm: {
37 | devDependencies: {
38 | 'ember-source': '~3.28.0',
39 | },
40 | },
41 | },
42 | {
43 | name: 'ember-release',
44 | npm: {
45 | devDependencies: {
46 | 'ember-source': await getChannelURL('release'),
47 | },
48 | },
49 | },
50 | {
51 | name: 'ember-beta',
52 | npm: {
53 | devDependencies: {
54 | 'ember-source': await getChannelURL('beta'),
55 | },
56 | },
57 | },
58 | {
59 | name: 'ember-canary',
60 | npm: {
61 | devDependencies: {
62 | 'ember-source': await getChannelURL('canary'),
63 | },
64 | },
65 | },
66 | {
67 | name: 'ember-default-with-jquery',
68 | env: {
69 | EMBER_OPTIONAL_FEATURES: JSON.stringify({
70 | 'jquery-integration': true,
71 | }),
72 | },
73 | npm: {
74 | devDependencies: {
75 | '@ember/jquery': '^1.1.0',
76 | },
77 | },
78 | },
79 | {
80 | name: 'ember-classic',
81 | env: {
82 | EMBER_OPTIONAL_FEATURES: JSON.stringify({
83 | 'application-template-wrapper': true,
84 | 'default-async-observers': false,
85 | 'template-only-glimmer-components': false,
86 | }),
87 | },
88 | npm: {
89 | ember: {
90 | edition: 'classic',
91 | },
92 | },
93 | },
94 | embroiderSafe(),
95 | embroiderOptimized(),
96 | ],
97 | };
98 | };
99 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Code of Conduct
2 |
3 | As contributors and maintainers of this project, and in the interest of
4 | fostering an open and welcoming community, we pledge to respect all people who
5 | contribute through reporting issues, posting feature requests, updating
6 | documentation, submitting pull requests or patches, and other activities.
7 |
8 | We are committed to making participation in this project a harassment-free
9 | experience for everyone, regardless of level of experience, gender, gender
10 | identity and expression, sexual orientation, disability, personal appearance,
11 | body size, race, ethnicity, age, religion, or nationality.
12 |
13 | Examples of unacceptable behavior by participants include:
14 |
15 | * The use of sexualized language or imagery
16 | * Personal attacks
17 | * Trolling or insulting/derogatory comments
18 | * Public or private harassment
19 | * Publishing other's private information, such as physical or electronic
20 | addresses, without explicit permission
21 | * Other unethical or unprofessional conduct
22 |
23 | Project maintainers have the right and responsibility to remove, edit, or
24 | reject comments, commits, code, wiki edits, issues, and other contributions
25 | that are not aligned to this Code of Conduct, or to ban temporarily or
26 | permanently any contributor for other behaviors that they deem inappropriate,
27 | threatening, offensive, or harmful.
28 |
29 | By adopting this Code of Conduct, project maintainers commit themselves to
30 | fairly and consistently applying these principles to every aspect of managing
31 | this project. Project maintainers who do not follow or enforce the Code of
32 | Conduct may be permanently removed from the project team.
33 |
34 | This Code of Conduct applies both within project spaces and in public spaces
35 | when an individual is representing the project or its community.
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
38 | reported by contacting a project maintainer at code-of-conduct@frontside.io. All
39 | complaints will be reviewed and investigated and will result in a response that
40 | is deemed necessary and appropriate to the circumstances. Maintainers are
41 | obligated to maintain confidentiality with regard to the reporter of an
42 | incident.
43 |
44 |
45 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
46 | version 1.3.0, available at
47 | [http://contributor-covenant.org/version/1/3/0/][version]
48 |
49 | [homepage]: http://contributor-covenant.org
50 | [version]: http://contributor-covenant.org/version/1/3/0/
51 |
--------------------------------------------------------------------------------
/tests/acceptance/x-file-input-test.js:
--------------------------------------------------------------------------------
1 | /* jshint expr:true */
2 | import { run } from '@ember/runloop';
3 |
4 | import {
5 | describe,
6 | it,
7 | beforeEach,
8 | afterEach
9 | } from 'mocha';
10 | import { expect } from 'chai';
11 | import Ember from 'ember';
12 | import startApp from '../helpers/start-app';
13 | import sinon from 'sinon';
14 |
15 | var App;
16 |
17 | describe('Acceptance: XFileInput', function() {
18 | beforeEach(function() {
19 | App = startApp();
20 | });
21 |
22 | afterEach(function() {
23 | run(App, 'destroy');
24 | });
25 |
26 | beforeEach(function() {
27 | return visit('/');
28 | });
29 |
30 | beforeEach(function() {
31 | this.component = getComponentById('spec-file-input');
32 | });
33 |
34 | it('renders', function() {
35 | expect(this.component).not.to.be.undefined;
36 | });
37 |
38 | it('has a custom class', function() {
39 | expect(this.component.$()).to.have.class('x-file-input');
40 | });
41 |
42 | it('has 0 tab index', function() {
43 | expect(this.component.$('input[type=file]')).to.have.attr('tabindex', '0');
44 | });
45 |
46 | it('has contains its yielded content', function() {
47 | expect(this.component.$('.spec-file-input__content :contains("Shall you upload?")')).not.to.be.empty;
48 | });
49 |
50 | describe('With no block passed', function() {
51 | beforeEach(function() {
52 | this.blocklessComponent = getComponentById('spec-file-input-blockless');
53 | });
54 |
55 | it('should provide default alt text', function() {
56 | expect(this.blocklessComponent.$().text().trim()).to.equal('Upload');
57 | });
58 |
59 | });
60 |
61 |
62 | describe('Bound Attributes', function() {
63 | beforeEach(function(){
64 | this.component.setProperties({
65 | disabled: true,
66 | multiple: true,
67 | name: "taco-cat",
68 | accept: "image/jpg"
69 | });
70 | });
71 |
72 | it('binds disabled attribute on the native file input', function() {
73 | expect(this.component.$('input[type=file]')).not.to.be.enabled;
74 | });
75 |
76 | it('binds the disabled css class on the whole component', function() {
77 | expect(this.component.$()).to.have.class('x-file-input--disabled');
78 | });
79 |
80 | it('binds the multiple attribute on the native file input', function() {
81 | expect(this.component.$('input[type=file]')).to.have.attr('multiple');
82 | });
83 |
84 | it('binds the tabindex attribut on the native file input', function() {
85 | expect(this.component.$('input[type=file]')).to.have.attr('name', 'taco-cat');
86 | });
87 |
88 | it("binds the accept attribute on the native file input", function() {
89 | expect(this.component.$('input[type=file]')).to.have.attr('accept', 'image/jpg');
90 | });
91 | });
92 |
93 | describe("Resetting the input", function() {
94 |
95 | /*
96 | * Since testing file inputs is basically impossible due to
97 | * security reasons, this test just asserts that when you trigger
98 | * the "change" event on the input it invokes the action & sends
99 | * the reset function with it. In that action we invoke the
100 | * `reset` method. Then we spy on that method and assert that it was
101 | * called. That's about all we can do to test this.
102 | *
103 | */
104 | beforeEach(function() {
105 | let _this = this;
106 | this.resetComponent = getComponentById('spec-file-input-reset');
107 | // Spy on the resetInput method
108 | this.resetContext = null;
109 | // Warning, using a fat arrow function will not work. It will set
110 | // `this.resetContext` to the mocha test runner contect every time.
111 | this.resetComponent.resetInput = sinon.spy(function() {
112 | _this.resetContext = this;
113 | });
114 |
115 | this.resetComponent.$('.x-file--input').trigger('change');
116 | });
117 |
118 | it("calls the reset method", function() {
119 | expect(this.resetComponent.resetInput).to.have.been.called;
120 | });
121 |
122 | it("has the correct context sent", function() {
123 | expect(this.resetContext).to.deep.equal(this.resetComponent);
124 | });
125 | });
126 | });
127 |
128 | function getComponentById(id) {
129 | var registry = App.__container__.lookup('-view-registry:main');
130 | if (registry) {
131 | return registry[id];
132 | } else {
133 | return Ember.View.views[id];
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | # This file was autogenerated by create-github-actions-setup-for-ember-addons.
2 | #
3 | # You can upgrade the GitHub Actions workflow to the latest blueprints used
4 | # by Create GitHub Actions setup for Ember Addons by running it again:
5 | #
6 | # - `yarn create github-actions-setup-for-ember-addons` if using yarn and
7 | # - `npm init github-actions-setup-for-ember-addons` if using NPM.
8 | #
9 | # See https://github.com/jelhan/create-github-actions-setup-for-ember-addon for
10 | # details.
11 | #
12 | # The following lines contain the configuration used in the last run. Please do
13 | # not change them. Doing so could break upgrade flow.
14 | #
15 | #$ browsers:
16 | #$ - Chrome
17 | #$ emberTryScenarios:
18 | #$ - scenario: ember-lts-3.20
19 | #$ - scenario: ember-lts-3.24
20 | #$ - scenario: ember-release
21 | #$ - scenario: ember-beta
22 | #$ - scenario: ember-canary
23 | #$ - scenario: ember-default-with-jquery
24 | #$ - scenario: ember-classic
25 | #$ - scenario: embroider-safe
26 | #$ - scenario: embroider-optimized
27 | #$ nodeVersion: '12'
28 | #$ packageManager: yarn
29 | #
30 |
31 | name: CI
32 |
33 | on:
34 | push:
35 | branches:
36 | - master
37 | pull_request:
38 |
39 | env:
40 | NODE_VERSION: '14'
41 |
42 | jobs:
43 | lint:
44 | name: Lint
45 | runs-on: ubuntu-latest
46 | steps:
47 | - uses: actions/checkout@v2
48 | with:
49 | fetch-depth: 1
50 |
51 | - uses: actions/setup-node@v2
52 | with:
53 | node-version: '${{ env.NODE_VERSION }}'
54 |
55 | - name: Get package manager's global cache path
56 | id: global-cache-dir-path
57 | run: echo "::set-output name=dir::$(yarn cache dir)"
58 |
59 | - name: Cache package manager's global cache and node_modules
60 | id: cache-dependencies
61 | uses: actions/cache@v2
62 | with:
63 | path: |
64 | ${{ steps.global-cache-dir-path.outputs.dir }}
65 | node_modules
66 | key: ${{ runner.os }}-${{ matrix.node-version }}-${{
67 | hashFiles('**/yarn.lock'
68 | ) }}
69 | restore-keys: |
70 | ${{ runner.os }}-${{ matrix.node-version }}-
71 | - name: Install Dependencies
72 | run: yarn install --frozen-lockfile
73 | if: |
74 | steps.cache-dependencies.outputs.cache-hit != 'true'
75 | - name: Lint
76 | run: yarn lint
77 |
78 |
79 | test:
80 | name: Tests
81 | runs-on: ${{ matrix.os }}
82 | needs: lint
83 |
84 | strategy:
85 | matrix:
86 | os: [ubuntu-latest]
87 | browser: [Chrome]
88 |
89 | steps:
90 | - uses: actions/checkout@v2
91 | with:
92 | fetch-depth: 1
93 |
94 | - uses: actions/setup-node@v2
95 | with:
96 | node-version: '${{ env.NODE_VERSION }}'
97 |
98 | - name: Get package manager's global cache path
99 | id: global-cache-dir-path
100 | run: echo "::set-output name=dir::$(yarn cache dir)"
101 |
102 | - name: Cache package manager's global cache and node_modules
103 | id: cache-dependencies
104 | uses: actions/cache@v2
105 | with:
106 | path: |
107 | ${{ steps.global-cache-dir-path.outputs.dir }}
108 | node_modules
109 | key: ${{ runner.os }}-${{ matrix.node-version }}-${{
110 | hashFiles('**/yarn.lock'
111 | ) }}
112 | restore-keys: |
113 | ${{ runner.os }}-${{ matrix.node-version }}-
114 | - name: Install Dependencies
115 | run: yarn install --frozen-lockfile
116 | if: |
117 | steps.cache-dependencies.outputs.cache-hit != 'true'
118 | - name: Test
119 | run: yarn test:ember --launch ${{ matrix.browser }}
120 |
121 |
122 | floating-dependencies:
123 | name: Floating Dependencies
124 | runs-on: ${{ matrix.os }}
125 | needs: lint
126 |
127 | strategy:
128 | matrix:
129 | os: [ubuntu-latest]
130 | browser: [Chrome]
131 |
132 | steps:
133 | - uses: actions/checkout@v2
134 | with:
135 | fetch-depth: 1
136 |
137 | - uses: actions/setup-node@v2
138 | with:
139 | node-version: '${{ env.NODE_VERSION }}'
140 |
141 | - name: Get package manager's global cache path
142 | id: global-cache-dir-path
143 | run: echo "::set-output name=dir::$(yarn cache dir)"
144 |
145 | - name: Cache package manager's global cache and node_modules
146 | id: cache-dependencies
147 | uses: actions/cache@v2
148 | with:
149 | path: |
150 | ${{ steps.global-cache-dir-path.outputs.dir }}
151 | node_modules
152 | key: ${{ runner.os }}-${{ matrix.node-version }}-floating-deps
153 | restore-keys: |
154 | ${{ runner.os }}-${{ matrix.node-version }}-
155 | - name: Install Dependencies
156 | run: yarn install --no-lockfile --non-interactive
157 |
158 | - name: Test
159 | run: yarn test:ember --launch ${{ matrix.browser }}
160 |
161 |
162 | try-scenarios:
163 | name: Tests - ${{ matrix.ember-try-scenario }}
164 | runs-on: ubuntu-latest
165 | continue-on-error: true
166 | needs: test
167 |
168 | strategy:
169 | fail-fast: true
170 | matrix:
171 | ember-try-scenario: [
172 | ember-lts-3.16,
173 | ember-lts-3.20,
174 | ember-lts-3.24,
175 | ember-lts-3.28,
176 | ember-release,
177 | ember-beta,
178 | ember-canary,
179 | ember-default-with-jquery,
180 | ember-classic,
181 | embroider-safe,
182 | embroider-optimized
183 | ]
184 |
185 | steps:
186 | - uses: actions/checkout@v2
187 | with:
188 | fetch-depth: 1
189 |
190 | - uses: actions/setup-node@v2
191 | with:
192 | node-version: '${{ env.NODE_VERSION }}'
193 |
194 | - name: Get package manager's global cache path
195 | id: global-cache-dir-path
196 | run: echo "::set-output name=dir::$(yarn cache dir)"
197 |
198 | - name: Cache package manager's global cache and node_modules
199 | id: cache-dependencies
200 | uses: actions/cache@v2
201 | with:
202 | path: |
203 | ${{ steps.global-cache-dir-path.outputs.dir }}
204 | node_modules
205 | key: ${{ runner.os }}-${{ matrix.node-version }}-${{
206 | hashFiles('**/yarn.lock'
207 | ) }}
208 | restore-keys: |
209 | ${{ runner.os }}-${{ matrix.node-version }}-
210 | - name: Install Dependencies
211 | run: yarn install --frozen-lockfile
212 | if: |
213 | steps.cache-dependencies.outputs.cache-hit != 'true'
214 | - name: Test
215 | env:
216 | EMBER_TRY_SCENARIO: ${{ matrix.ember-try-scenario }}
217 | run: node_modules/.bin/ember try:one $EMBER_TRY_SCENARIO
218 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | ## [v1.1.2](https://github.com/thefrontside/emberx-file-input/tree/v1.1.2) (2017-03-17)
4 | [Full Changelog](https://github.com/thefrontside/emberx-file-input/compare/v1.1.1...v1.1.2)
5 |
6 | **Merged pull requests:**
7 |
8 | - The white space causes some visual inconsistency [\#50](https://github.com/thefrontside/emberx-file-input/pull/50) ([treelite](https://github.com/treelite))
9 |
10 | ## [v1.1.1](https://github.com/thefrontside/emberx-file-input/tree/v1.1.1) (2017-01-04)
11 | [Full Changelog](https://github.com/thefrontside/emberx-file-input/compare/v1.1.0...v1.1.1)
12 |
13 | **Closed issues:**
14 |
15 | - Publish New Release Soon? [\#42](https://github.com/thefrontside/emberx-file-input/issues/42)
16 | - Action Handler [\#22](https://github.com/thefrontside/emberx-file-input/issues/22)
17 |
18 | **Merged pull requests:**
19 |
20 | - Use a plain \ instead of {{input}} [\#48](https://github.com/thefrontside/emberx-file-input/pull/48) ([cibernox](https://github.com/cibernox))
21 | - Reinstall gh-pages addon [\#46](https://github.com/thefrontside/emberx-file-input/pull/46) ([Robdel12](https://github.com/Robdel12))
22 | - Update changelog for 1.1.0 [\#45](https://github.com/thefrontside/emberx-file-input/pull/45) ([Robdel12](https://github.com/Robdel12))
23 |
24 | ## [v1.1.0](https://github.com/thefrontside/emberx-file-input/tree/v1.1.0) (2016-08-30)
25 | [Full Changelog](https://github.com/thefrontside/emberx-file-input/compare/v1.0.0...v1.1.0)
26 |
27 | **Implemented enhancements:**
28 |
29 | - Action not firing when selecting the same file twice [\#23](https://github.com/thefrontside/emberx-file-input/issues/23)
30 | - Use an import strategy that supports more ember cli versions [\#41](https://github.com/thefrontside/emberx-file-input/pull/41) ([Robdel12](https://github.com/Robdel12))
31 | - Add the ability to reset the file input [\#37](https://github.com/thefrontside/emberx-file-input/pull/37) ([Robdel12](https://github.com/Robdel12))
32 |
33 | **Fixed bugs:**
34 |
35 | - TypeError: this.import is not a function [\#35](https://github.com/thefrontside/emberx-file-input/issues/35)
36 | - width: 0px on hidden file input is treated like not there [\#33](https://github.com/thefrontside/emberx-file-input/issues/33)
37 | - Importing emberx-file-input in an addon [\#30](https://github.com/thefrontside/emberx-file-input/issues/30)
38 | - Provide default `alt` attribute [\#21](https://github.com/thefrontside/emberx-file-input/issues/21)
39 | - Chrome CSS bug fix: make width 1px, not 0. [\#43](https://github.com/thefrontside/emberx-file-input/pull/43) ([Robdel12](https://github.com/Robdel12))
40 | - Add default `alt` attribute & test for it [\#39](https://github.com/thefrontside/emberx-file-input/pull/39) ([Robdel12](https://github.com/Robdel12))
41 | - Remove `ember-cli-import-polyfill` addon [\#38](https://github.com/thefrontside/emberx-file-input/pull/38) ([Robdel12](https://github.com/Robdel12))
42 |
43 | **Closed issues:**
44 |
45 | - Usage in embedded scenario \(Wordpress Plugin Application\) [\#34](https://github.com/thefrontside/emberx-file-input/issues/34)
46 | - Setting file format [\#32](https://github.com/thefrontside/emberx-file-input/issues/32)
47 | - Warning when installed in Ember v2.6.2 [\#29](https://github.com/thefrontside/emberx-file-input/issues/29)
48 | - Overriding init without calling this.\_super is deprecated [\#27](https://github.com/thefrontside/emberx-file-input/issues/27)
49 | - Limited support \(Ember 1.13+ only\) [\#19](https://github.com/thefrontside/emberx-file-input/issues/19)
50 | - Add badges for NPM and ember-observer [\#18](https://github.com/thefrontside/emberx-file-input/issues/18)
51 | - Hidden file input styling bug in mobile Safari [\#16](https://github.com/thefrontside/emberx-file-input/issues/16)
52 | - Release on npm ? [\#2](https://github.com/thefrontside/emberx-file-input/issues/2)
53 |
54 | **Merged pull requests:**
55 |
56 | - Document the `accept` property [\#44](https://github.com/thefrontside/emberx-file-input/pull/44) ([Robdel12](https://github.com/Robdel12))
57 | - Update ember cli 2.7 [\#40](https://github.com/thefrontside/emberx-file-input/pull/40) ([Robdel12](https://github.com/Robdel12))
58 | - Add ember-cli-import-polyfill back \(fixes \#30\) [\#31](https://github.com/thefrontside/emberx-file-input/pull/31) ([Robdel12](https://github.com/Robdel12))
59 | - Update ember CLI and deps [\#28](https://github.com/thefrontside/emberx-file-input/pull/28) ([Robdel12](https://github.com/Robdel12))
60 | - Update included hook for nested addons [\#26](https://github.com/thefrontside/emberx-file-input/pull/26) ([xcambar](https://github.com/xcambar))
61 | - Add Changelog [\#25](https://github.com/thefrontside/emberx-file-input/pull/25) ([Robdel12](https://github.com/Robdel12))
62 | - npm and ember observer badges [\#20](https://github.com/thefrontside/emberx-file-input/pull/20) ([cowboyd](https://github.com/cowboyd))
63 | - Fix mobile Safari styling bug for hidden file input element [\#17](https://github.com/thefrontside/emberx-file-input/pull/17) ([timiyay](https://github.com/timiyay))
64 |
65 | ## [v1.0.0](https://github.com/thefrontside/emberx-file-input/tree/v1.0.0) (2015-10-09)
66 | **Closed issues:**
67 |
68 | - Fill out package.json [\#11](https://github.com/thefrontside/emberx-file-input/issues/11)
69 | - Add docs about how to style the input [\#7](https://github.com/thefrontside/emberx-file-input/issues/7)
70 | - Set up Travis CI builds [\#4](https://github.com/thefrontside/emberx-file-input/issues/4)
71 |
72 | **Merged pull requests:**
73 |
74 | - Add `accept` attribute to the native file input [\#15](https://github.com/thefrontside/emberx-file-input/pull/15) ([Robdel12](https://github.com/Robdel12))
75 | - Adding a multi file input example [\#14](https://github.com/thefrontside/emberx-file-input/pull/14) ([Robdel12](https://github.com/Robdel12))
76 | - Fill out package.json [\#13](https://github.com/thefrontside/emberx-file-input/pull/13) ([Robdel12](https://github.com/Robdel12))
77 | - Readme updates [\#12](https://github.com/thefrontside/emberx-file-input/pull/12) ([Robdel12](https://github.com/Robdel12))
78 | - Add docs on how to customize the css properly [\#10](https://github.com/thefrontside/emberx-file-input/pull/10) ([Robdel12](https://github.com/Robdel12))
79 | - Add gh-pages addon [\#9](https://github.com/thefrontside/emberx-file-input/pull/9) ([Robdel12](https://github.com/Robdel12))
80 | - Include example of firing actions from component [\#8](https://github.com/thefrontside/emberx-file-input/pull/8) ([lydiaguarino](https://github.com/lydiaguarino))
81 | - Use label to style input [\#6](https://github.com/thefrontside/emberx-file-input/pull/6) ([Robdel12](https://github.com/Robdel12))
82 | - Adding build status badge and small clean up [\#5](https://github.com/thefrontside/emberx-file-input/pull/5) ([Robdel12](https://github.com/Robdel12))
83 | - Upgrade ember-cli to 1.13.8 [\#3](https://github.com/thefrontside/emberx-file-input/pull/3) ([Robdel12](https://github.com/Robdel12))
84 | - Charge for glory [\#1](https://github.com/thefrontside/emberx-file-input/pull/1) ([lydiaguarino](https://github.com/lydiaguarino))
85 |
86 |
87 |
88 | \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # emberx-file-input
2 | [](https://badge.fury.io/js/emberx-file-input)
3 | [](http://emberobserver.com/addons/emberx-file-input)
4 | [](https://travis-ci.org/thefrontside/emberx-file-input)
5 |
6 | I select files well. I select files very, very well.
7 |
8 | `x-file-input` is a tiny re-usable component which does one thing and
9 | only: binds an action to the native html file selection dialog while
10 | allowing you to render arbitrary HTML to act as the trigger for that
11 | file selector.
12 |
13 | This allows you to compose it with whatever other components and
14 | application code you need to make that perfect workflow that involves
15 | selecting files: from uploads to imports.
16 |
17 | What you do with the files once they are selected? Welp, that's
18 | between you and your app.
19 |
20 | ## Installation
21 |
22 | `ember install emberx-file-input`
23 |
24 | ## Usage
25 |
26 | Bind an action to the file input:
27 |
28 | ```handlebars
29 | {{x-file-input name="files" multiple=true action=(action "didSelectFiles") alt="Choose a File"}}
30 | ```
31 |
32 | Whenever the user selects a file, the `didSelectfiles` action will be
33 | invoked with an array of [File][1] objects.
34 |
35 | > Note: Whether the file input is for a single file or mulitple files,
36 | > it will always return an array of `File` objects upon selection.
37 |
38 | In its blockless form, you will need to pass an `alt` attribute for
39 | the text you would like to be displayed inside the inputs label.
40 |
41 | ``` handlebars
42 | {{x-file-input alt="hello world"}}
43 | ```
44 |
45 | When passing a block, the HTML inside the block will be used as the
46 | trigger of the file input.
47 |
48 | ```hbs
49 | {{#x-file-input multiple=true action=(action "didSelectFiles")}}
50 |
51 | {{/x-file-input}}
52 | ```
53 |
54 | Instead of that boring old stock file selector, your users will see
55 | this:
56 |
57 |
58 |
59 |
60 |
61 |
62 | And don't worry, that custom trigger is a form label, so the file input remains
63 | 100% accessible.
64 |
65 | ### Configuring file formats with `accept`
66 | You can use the `accept` attribute to only allow specifc types of
67 | files. In this example we only allow `.png` & `.jpg` file types.
68 |
69 | ```hbs
70 | {{#x-file-input multiple=true action=(action "didSelectFiles") accept="image/png,image/jpg"}}
71 |
72 | {{/x-file-input}}
73 | ```
74 |
75 |
76 | ## Customizing the CSS
77 |
78 | The whole point of this component is for you to customize your inputs with CSS
79 | and make them look *much* better than the native inputs. Lets look at a simple
80 | example.
81 |
82 | Here is our component. You can see we have a custom class applied to the block
83 | called `custom-class`. We are going to use that class to apply our styles.
84 |
85 | ```hbs
86 | {{#x-file-input class="custom-class" action="uploadAPhoto"}}
87 |
Shall you upload?
88 | {{/x-file-input}}
89 | ```
90 |
91 | In our CSS we want to target `.custom-class label` because the label is the
92 | element that we're making look nice.
93 |
94 | ```css
95 | .custom-class label {
96 | background: #34495e;
97 | padding: 10px;
98 | color: white;
99 | border-radius: 5px;
100 | }
101 | ```
102 |
103 | This css will make our button look a little something like this:
104 | 
105 |
106 | We are not done yet! Since we're replicating a native input with
107 | HTML and CSS we have to make sure we replicate all of the "default"
108 | features we get when using a native file input. One of those things is a css
109 | `:hover` and `:focus` state. These are often overlooked but are critcal to add.
110 | In your CSS you need to add the following:
111 |
112 | ```css
113 | .x-file--input:focus + label,
114 | .x-file--input + label:hover {
115 | /* Apply your own hover state */
116 | background-color: #2C3E50;
117 | }
118 | ```
119 |
120 | And that's it! Your file input is now styled and decked to the nines!
121 | If you would like to see a real
122 | [life example checkout the demo page](http://thefrontside.github.io/emberx-file-input)
123 |
124 | ## Resetting the input
125 |
126 | To select the same file many times you need to call the `resetInput`
127 | method that's passed as an argument with the action. For example:
128 |
129 | ``` javascript
130 | actions: {
131 | myAction(files, resetInput) {
132 | // Do something with your files.
133 | // Once you're done, call the reset method:
134 | resetInput();
135 | // Now your input is reset!
136 | }
137 | }
138 | ```
139 |
140 | ## Acceptance Testing
141 |
142 | You can use the `selectFile` async helper in acceptance tests to simulate file uploads.
143 |
144 | First import the helper in your `test-helper.js` (or respective file that requires test dependencies)
145 |
146 | ```javascript
147 | import 'emberx-file-input/test-helpers/select-file-async'
148 |
149 | ...
150 |
151 | ```
152 |
153 | then in your test:
154 |
155 | ```javascript
156 | visit('/');
157 | selectFile('.x-file-input', {name: 'test.txt', type: 'text/plain'});
158 |
159 | andThen(function() {
160 |
161 | ...
162 | ```
163 |
164 | or if the code you're testing needs the object to be an actual file
165 |
166 | ```javascript
167 | visit('/');
168 |
169 | const file = new Blob(['test'], {type: 'image/jpeg'});
170 | selectFile('.x-file-input', file);
171 |
172 | andThen(function() {
173 |
174 | ...
175 | ```
176 |
177 | The first argument is the class of your x-file-input component. The second argument is an object in place of the file normally returned.
178 |
179 | ## Unit Testing
180 |
181 | There is a separate `selectFile` helper that works in unit/component tests.
182 |
183 | ```javascript
184 | import 'emberx-file-input/test-helpers/select-file-unit'
185 | ```
186 |
187 | then in your test:
188 |
189 | ```javascript
190 | selectFile('.x-file-input', {name: 'test.txt', type: 'text/plain'});
191 |
192 | assert.equal($('.something').length, 1, 'Element exists!');
193 | ```
194 |
195 | ## EmberX
196 |
197 | emberx-file-input is part of the "missing components of ember" collectively
198 | known as emberx:
199 |
200 | * [emberx-select](https://github.com/adopted-ember-addons/emberx-select)
201 | * [emberx-file-input](https://github.com/adopted-ember-addons/emberx-file-input)
202 |
203 |
204 | [1]: https://developer.mozilla.org/en-US/docs/Web/API/File
205 |
206 | ## Release Process
207 |
208 | Every commit to master is built on CircleCI and the demo url is built
209 | using github pages.
210 |
211 | Npm releases follow semver, and are ad-hoc and controlled by project
212 | owners.
213 |
214 |
215 | ## Code of Conduct
216 | Please note that this project is released with a Contributor Code of
217 | Conduct. By participating in this project you agree to abide by its
218 | terms, which can be found in the `CODE_OF_CONDUCT.md` file in this
219 | repository.
220 |
--------------------------------------------------------------------------------
/.lint-todo:
--------------------------------------------------------------------------------
1 | add|ember-template-lint|no-curly-component-invocation|7|4|7|4|f04318fd9767915cfe8059478671b55f118dba57|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
2 | add|ember-template-lint|no-implicit-this|1|24|1|24|075c0d8e6bf518d30bf46468a90fd7a8a3ac2941|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
3 | add|ember-template-lint|no-implicit-this|1|64|1|64|6ae999552a0d2dca14d62e2bc8b764d377b1dd6c|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
4 | add|ember-template-lint|no-implicit-this|2|13|2|13|07596f183f5e91b1778d5e47b2752b8d42aa763d|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
5 | add|ember-template-lint|no-implicit-this|2|35|2|35|88fc77e78f48fc9076f997582d6231dc838266b7|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
6 | add|ember-template-lint|no-implicit-this|2|57|2|57|f1f86b49f85dda13e0ab4c95c83f538d706f074f|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
7 | add|ember-template-lint|no-implicit-this|2|77|2|77|5fb801f2f30ac5b8a6671f1d04a959a51fc1671e|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
8 | add|ember-template-lint|no-implicit-this|3|14|3|14|075c0d8e6bf518d30bf46468a90fd7a8a3ac2941|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
9 | add|ember-template-lint|no-implicit-this|7|6|7|6|325562c769da3f80d0e63bb56514bc2e2723c9b5|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
10 | add|ember-template-lint|no-positive-tabindex|1|0|1|0|c1305f9a60115cda5d925f5f0b7e30825b53c643|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
11 | add|ember-template-lint|require-has-block-helper|4|8|4|8|bf562aead7b96b3369f2f96ff8c838387a268cc0|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
12 | add|ember-template-lint|no-curly-component-invocation|5|4|5|4|97c2580dd98aec46fd701eb9a98ab81ead21febb|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
13 | add|ember-template-lint|no-curly-component-invocation|12|4|12|4|a0c05bfc0accae9b23b0b43831239742a957b3ff|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
14 | add|ember-template-lint|no-curly-component-invocation|18|2|18|2|21d84480703b9f10b1bbe2331b8fccaa8cf44495|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
15 | add|ember-template-lint|no-curly-component-invocation|21|30|21|30|c2b66cfad2ffe1a265ba0b07aa7e2c16bbd986d9|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
16 | add|ember-template-lint|no-curly-component-invocation|29|2|29|2|baab54b47f5a868911922e661a0e4acfcfa7b419|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
17 | add|ember-template-lint|no-curly-component-invocation|41|2|41|2|67966d7e05ba983a05bacc0a035438a852ca6f51|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
18 | add|ember-template-lint|no-implicit-this|19|10|19|10|1d538fe2595eb641eb8ede22407dd7cc39951a62|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
19 | add|ember-template-lint|no-implicit-this|20|19|20|19|6ec81cfb17322a45e74faeb2af7c8b474aad1c6d|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
20 | add|ember-template-lint|no-implicit-this|21|32|21|32|1d538fe2595eb641eb8ede22407dd7cc39951a62|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
21 | add|ember-template-lint|no-implicit-this|32|10|32|10|451c79398635013449cd7de7c62a0a7ec56f8aed|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
22 | add|ember-template-lint|no-inline-styles|4|7|4|7|ef057772e8b72a16796a51d1fd39ef26d0ee4eb8|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
23 | remove|ember-template-lint|no-curly-component-invocation|7|4|7|4|f04318fd9767915cfe8059478671b55f118dba57|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
24 | remove|ember-template-lint|no-implicit-this|1|24|1|24|075c0d8e6bf518d30bf46468a90fd7a8a3ac2941|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
25 | remove|ember-template-lint|no-implicit-this|1|64|1|64|6ae999552a0d2dca14d62e2bc8b764d377b1dd6c|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
26 | remove|ember-template-lint|no-implicit-this|2|13|2|13|07596f183f5e91b1778d5e47b2752b8d42aa763d|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
27 | remove|ember-template-lint|no-implicit-this|2|35|2|35|88fc77e78f48fc9076f997582d6231dc838266b7|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
28 | remove|ember-template-lint|no-implicit-this|2|57|2|57|f1f86b49f85dda13e0ab4c95c83f538d706f074f|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
29 | remove|ember-template-lint|no-implicit-this|2|77|2|77|5fb801f2f30ac5b8a6671f1d04a959a51fc1671e|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
30 | remove|ember-template-lint|no-implicit-this|3|14|3|14|075c0d8e6bf518d30bf46468a90fd7a8a3ac2941|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
31 | remove|ember-template-lint|no-implicit-this|7|6|7|6|325562c769da3f80d0e63bb56514bc2e2723c9b5|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
32 | remove|ember-template-lint|no-positive-tabindex|1|0|1|0|c1305f9a60115cda5d925f5f0b7e30825b53c643|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
33 | remove|ember-template-lint|require-has-block-helper|4|8|4|8|bf562aead7b96b3369f2f96ff8c838387a268cc0|1645056000000|1647644400000|1650236400000|addon/templates/components/x-file-input.hbs
34 | remove|ember-template-lint|no-curly-component-invocation|5|4|5|4|97c2580dd98aec46fd701eb9a98ab81ead21febb|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
35 | remove|ember-template-lint|no-curly-component-invocation|12|4|12|4|a0c05bfc0accae9b23b0b43831239742a957b3ff|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
36 | remove|ember-template-lint|no-curly-component-invocation|18|2|18|2|21d84480703b9f10b1bbe2331b8fccaa8cf44495|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
37 | remove|ember-template-lint|no-curly-component-invocation|21|30|21|30|c2b66cfad2ffe1a265ba0b07aa7e2c16bbd986d9|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
38 | remove|ember-template-lint|no-curly-component-invocation|29|2|29|2|baab54b47f5a868911922e661a0e4acfcfa7b419|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
39 | remove|ember-template-lint|no-curly-component-invocation|41|2|41|2|67966d7e05ba983a05bacc0a035438a852ca6f51|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
40 | remove|ember-template-lint|no-implicit-this|19|10|19|10|1d538fe2595eb641eb8ede22407dd7cc39951a62|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
41 | remove|ember-template-lint|no-implicit-this|20|19|20|19|6ec81cfb17322a45e74faeb2af7c8b474aad1c6d|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
42 | remove|ember-template-lint|no-implicit-this|21|32|21|32|1d538fe2595eb641eb8ede22407dd7cc39951a62|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
43 | remove|ember-template-lint|no-implicit-this|32|10|32|10|451c79398635013449cd7de7c62a0a7ec56f8aed|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
44 | remove|ember-template-lint|no-inline-styles|4|7|4|7|ef057772e8b72a16796a51d1fd39ef26d0ee4eb8|1645056000000|1647644400000|1650236400000|tests/dummy/app/templates/application.hbs
45 | add|ember-template-lint|no-curly-component-invocation|7|4|7|4|f04318fd9767915cfe8059478671b55f118dba57|1650412800000|1653004800000|1655596800000|addon/templates/components/x-file-input.hbs
46 | add|ember-template-lint|no-implicit-this|1|24|1|24|075c0d8e6bf518d30bf46468a90fd7a8a3ac2941|1650412800000|1653004800000|1655596800000|addon/templates/components/x-file-input.hbs
47 | add|ember-template-lint|no-implicit-this|1|64|1|64|6ae999552a0d2dca14d62e2bc8b764d377b1dd6c|1650412800000|1653004800000|1655596800000|addon/templates/components/x-file-input.hbs
48 | add|ember-template-lint|no-implicit-this|2|13|2|13|07596f183f5e91b1778d5e47b2752b8d42aa763d|1650412800000|1653004800000|1655596800000|addon/templates/components/x-file-input.hbs
49 | add|ember-template-lint|no-implicit-this|2|35|2|35|88fc77e78f48fc9076f997582d6231dc838266b7|1650412800000|1653004800000|1655596800000|addon/templates/components/x-file-input.hbs
50 | add|ember-template-lint|no-implicit-this|2|57|2|57|f1f86b49f85dda13e0ab4c95c83f538d706f074f|1650412800000|1653004800000|1655596800000|addon/templates/components/x-file-input.hbs
51 | add|ember-template-lint|no-implicit-this|2|77|2|77|5fb801f2f30ac5b8a6671f1d04a959a51fc1671e|1650412800000|1653004800000|1655596800000|addon/templates/components/x-file-input.hbs
52 | add|ember-template-lint|no-implicit-this|3|14|3|14|075c0d8e6bf518d30bf46468a90fd7a8a3ac2941|1650412800000|1653004800000|1655596800000|addon/templates/components/x-file-input.hbs
53 | add|ember-template-lint|no-implicit-this|7|6|7|6|325562c769da3f80d0e63bb56514bc2e2723c9b5|1650412800000|1653004800000|1655596800000|addon/templates/components/x-file-input.hbs
54 | add|ember-template-lint|no-positive-tabindex|1|0|1|0|c1305f9a60115cda5d925f5f0b7e30825b53c643|1650412800000|1653004800000|1655596800000|addon/templates/components/x-file-input.hbs
55 | add|ember-template-lint|require-has-block-helper|4|8|4|8|bf562aead7b96b3369f2f96ff8c838387a268cc0|1650412800000|1653004800000|1655596800000|addon/templates/components/x-file-input.hbs
56 | add|ember-template-lint|no-curly-component-invocation|5|4|5|4|97c2580dd98aec46fd701eb9a98ab81ead21febb|1650412800000|1653004800000|1655596800000|tests/dummy/app/templates/application.hbs
57 | add|ember-template-lint|no-curly-component-invocation|12|4|12|4|a0c05bfc0accae9b23b0b43831239742a957b3ff|1650412800000|1653004800000|1655596800000|tests/dummy/app/templates/application.hbs
58 | add|ember-template-lint|no-curly-component-invocation|18|2|18|2|21d84480703b9f10b1bbe2331b8fccaa8cf44495|1650412800000|1653004800000|1655596800000|tests/dummy/app/templates/application.hbs
59 | add|ember-template-lint|no-curly-component-invocation|21|30|21|30|c2b66cfad2ffe1a265ba0b07aa7e2c16bbd986d9|1650412800000|1653004800000|1655596800000|tests/dummy/app/templates/application.hbs
60 | add|ember-template-lint|no-curly-component-invocation|29|2|29|2|baab54b47f5a868911922e661a0e4acfcfa7b419|1650412800000|1653004800000|1655596800000|tests/dummy/app/templates/application.hbs
61 | add|ember-template-lint|no-curly-component-invocation|41|2|41|2|67966d7e05ba983a05bacc0a035438a852ca6f51|1650412800000|1653004800000|1655596800000|tests/dummy/app/templates/application.hbs
62 | add|ember-template-lint|no-implicit-this|19|10|19|10|1d538fe2595eb641eb8ede22407dd7cc39951a62|1650412800000|1653004800000|1655596800000|tests/dummy/app/templates/application.hbs
63 | add|ember-template-lint|no-implicit-this|20|19|20|19|6ec81cfb17322a45e74faeb2af7c8b474aad1c6d|1650412800000|1653004800000|1655596800000|tests/dummy/app/templates/application.hbs
64 | add|ember-template-lint|no-implicit-this|21|32|21|32|1d538fe2595eb641eb8ede22407dd7cc39951a62|1650412800000|1653004800000|1655596800000|tests/dummy/app/templates/application.hbs
65 | add|ember-template-lint|no-implicit-this|32|10|32|10|451c79398635013449cd7de7c62a0a7ec56f8aed|1650412800000|1653004800000|1655596800000|tests/dummy/app/templates/application.hbs
66 | add|ember-template-lint|no-inline-styles|4|7|4|7|ef057772e8b72a16796a51d1fd39ef26d0ee4eb8|1650412800000|1653004800000|1655596800000|tests/dummy/app/templates/application.hbs
67 |
--------------------------------------------------------------------------------