6 | {{else}}
7 |
8 | {{/if}}
9 |
10 |
--------------------------------------------------------------------------------
/package.js:
--------------------------------------------------------------------------------
1 | Package.describe({
2 | name: 'aldeed:autoform-bs-datepicker',
3 | summary: 'Custom bootstrap-datepicker input type for AutoForm',
4 | version: '2.1.0',
5 | git: 'https://github.com/aldeed/meteor-autoform-bs-datepicker.git'
6 | });
7 |
8 | Package.onUse(function(api) {
9 | api.versionsFrom('2.16');
10 | api.use('templating@1.0.0 || 1.4.4');
11 | api.use('blaze@2.0.0 || 2.9.0 || 3.0.1');
12 | api.use('aldeed:autoform@6.0.0 || 7.1.0 || 8.0.0');
13 | api.addFiles([
14 | 'autoform-bs-datepicker.html',
15 | 'autoform-bs-datepicker.js'
16 | ], 'client');
17 | });
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014-2017 Eric Dobbertin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/.versions:
--------------------------------------------------------------------------------
1 | aldeed:autoform@6.0.0
2 | aldeed:autoform-bs-datepicker@2.0.2
3 | babel-compiler@7.10.5
4 | babel-runtime@1.5.1
5 | base64@1.0.12
6 | blaze@2.1.5
7 | blaze-tools@1.0.10
8 | boilerplate-generator@1.7.2
9 | caching-compiler@1.2.2
10 | caching-html-compiler@1.0.4
11 | callback-hook@1.5.1
12 | check@1.4.1
13 | ddp@1.4.1
14 | ddp-client@2.6.2
15 | ddp-common@1.4.1
16 | ddp-server@2.7.1
17 | deps@1.0.12
18 | diff-sequence@1.1.2
19 | dynamic-import@0.7.3
20 | ecmascript@0.16.8
21 | ecmascript-runtime@0.8.1
22 | ecmascript-runtime-client@0.12.1
23 | ecmascript-runtime-server@0.11.0
24 | ejson@1.1.3
25 | fetch@0.1.4
26 | html-tools@1.0.11
27 | htmljs@1.0.11
28 | id-map@1.1.1
29 | inter-process-messaging@0.1.1
30 | jquery@1.11.6
31 | livedata@1.0.18
32 | logging@1.3.4
33 | meteor@1.11.5
34 | modern-browsers@0.1.10
35 | modules@0.20.0
36 | modules-runtime@0.13.1
37 | momentjs:moment@2.10.6
38 | mongo-id@1.0.8
39 | observe-sequence@1.0.16
40 | promise@0.12.2
41 | random@1.2.1
42 | react-fast-refresh@0.2.8
43 | reactive-dict@1.3.1
44 | reactive-var@1.0.12
45 | reload@1.3.1
46 | retry@1.1.0
47 | routepolicy@1.1.1
48 | socket-stream-client@0.5.2
49 | spacebars@1.0.9
50 | spacebars-compiler@1.1.0
51 | templating@1.1.7
52 | templating-tools@1.1.1
53 | tracker@1.3.3
54 | typescript@4.9.5
55 | ui@1.0.9
56 | underscore@1.6.1
57 | webapp@1.13.8
58 | webapp-hashing@1.1.1
59 |
--------------------------------------------------------------------------------
/.github/workflows/comment-issue.yml:
--------------------------------------------------------------------------------
1 | name: Add immediate comment on new issues
2 |
3 | on:
4 | issues:
5 | types: [opened]
6 |
7 | jobs:
8 | createComment:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Create Comment
12 | uses: peter-evans/create-or-update-comment@v1.4.2
13 | with:
14 | issue-number: ${{ github.event.issue.number }}
15 | body: |
16 | Thank you for submitting this issue!
17 |
18 | We, the Members of Meteor Community Packages take every issue seriously.
19 | Our goal is to provide long-term lifecycles for packages and keep up
20 | with the newest changes in Meteor and the overall NodeJs/JavaScript ecosystem.
21 |
22 | However, we contribute to these packages mostly in our free time.
23 | Therefore, we can't guarantee your issues to be solved within certain time.
24 |
25 | If you think this issue is trivial to solve, don't hesitate to submit
26 | a pull request, too! We will accompany you in the process with reviews and hints
27 | on how to get development set up.
28 |
29 | Please also consider sponsoring the maintainers of the package.
30 | If you don't know who is currently maintaining this package, just leave a comment
31 | and we'll let you know
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | aldeed:autoform-bs-datepicker
2 | =========================
3 |
4 | An add-on Meteor package for [aldeed:autoform](https://github.com/aldeed/meteor-autoform). Provides a single custom input type, "bootstrap-datepicker", which renders an input using the [bootstrap-datepicker](http://bootstrap-datepicker.readthedocs.org/en/release/index.html) plugin.
5 |
6 | ## Prerequisites
7 |
8 | Bootstrap and the plugin library must be installed separately.
9 |
10 | In a Meteor app directory, enter:
11 |
12 | ```
13 | $ meteor add twbs:bootstrap
14 | $ meteor add rajit:bootstrap3-datepicker
15 | $ meteor add aldeed:autoform
16 | ```
17 |
18 | ## Installation
19 |
20 | In a Meteor app directory, enter:
21 |
22 | ```
23 | $ meteor add aldeed:autoform-bs-datepicker
24 | ```
25 |
26 | ## Usage
27 |
28 | Specify "bootstrap-datepicker" for the `type` attribute of any input. This can be done in a number of ways:
29 |
30 | In the schema, which will then work with a `quickForm` or `afQuickFields`:
31 |
32 | ```js
33 | {
34 | date: {
35 | type: Date,
36 | autoform: {
37 | type: "bootstrap-datepicker",
38 | datePickerOptions: {
39 | autoclose: true
40 | }
41 | }
42 | }
43 | }
44 | ```
45 | Options for the bs-datepicker plugin can be found [here](https://bootstrap-datepicker.readthedocs.org/en/latest/options.html).
46 |
47 | Or on the `afFieldInput` component or any component that passes along attributes to `afFieldInput`:
48 |
49 | ```js
50 | {{> afQuickField name="typeTest" type="bootstrap-datepicker"}}
51 |
52 | {{> afFormGroup name="typeTest" type="bootstrap-datepicker"}}
53 |
54 | {{> afFieldInput name="typeTest" type="bootstrap-datepicker"}}
55 | ```
56 |
57 | ## Automatic Type Conversions
58 |
59 | This input type is intended to be used with `type: Date` schema keys, but it also works with other schema types. Here's a list:
60 |
61 | * `Date`: Value is stored as a `Date` object representing midnight in the UTC timezone on the morning of the selected date.
62 | * `String`: Value is stored as a string representation of the selected date in ISO format, e.g., "2014-11-25".
63 | * `Number`: Value is stored as the result of calling `getTime()` on the `Date` object (representing midnight in the UTC timezone on the morning of the selected date).
64 | * `Array`: If the schema expects an array of `Date` or `String` or `Number`, the value is converted to a one-item array and stored.
65 |
66 | To provide bootstrap-datepicker options, set a `datePickerOptions` attribute equal to a helper that returns the options object. Most of the `data-date` attributes that the plugin recognizes should also work.
67 |
68 | ## Customizing Appearance
69 |
70 | To easily add an input group add-on after the field, just provide the classes for the span in a `buttonClasses` attribute:
71 |
72 | ```js
73 | {{> afFieldInput name="typeTest" type="bootstrap-datepicker" buttonClasses="glyphicon glyphicon-calendar"}}
74 | ```
75 |
76 | If you want to customize the appearance of the input more, for example to use input group add-ons both before and after the field, use the [aldeed:template-extension](https://atmospherejs.com/aldeed/template-extension) package to replace the "afBootstrapDatepicker" template, like this:
77 |
78 | ```html
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | ```
88 |
89 | ```js
90 | Template.dpReplacement.replaces("afBootstrapDatepicker");
91 | ```
92 |
93 | ## Demo
94 |
95 | [Live](http://autoform.meteor.com/types)
96 |
97 | ## Contributing
98 |
99 | Anyone is welcome to contribute. Fork, make your changes, and then submit a pull request.
100 |
--------------------------------------------------------------------------------
/autoform-bs-datepicker.js:
--------------------------------------------------------------------------------
1 | /* global AutoForm, $ */
2 |
3 | AutoForm.addInputType('bootstrap-datepicker', {
4 | template: 'afBootstrapDatepicker',
5 | valueOut: function () {
6 | var val;
7 | if (this.val()) {
8 | val = this.datepicker('getUTCDate');
9 | }
10 | return (val instanceof Date) ? val : this.val();
11 | },
12 | valueConverters: {
13 | string: function (val) {
14 | return (val instanceof Date) ? AutoForm.valueConverters.dateToDateStringUTC(val) : val;
15 | },
16 | stringArray: function (val) {
17 | if (val instanceof Date) {
18 | return [AutoForm.valueConverters.dateToDateStringUTC(val)];
19 | }
20 | return val;
21 | },
22 | number: function (val) {
23 | return (val instanceof Date) ? val.getTime() : val;
24 | },
25 | numberArray: function (val) {
26 | if (val instanceof Date) {
27 | return [val.getTime()];
28 | }
29 | return val;
30 | },
31 | dateArray: function (val) {
32 | var valArray = this.datepicker('getUTCDates');
33 | if (allArrayItemsAreDates(valArray)) return valArray;
34 | return val;
35 | },
36 | },
37 | });
38 |
39 | Template.afBootstrapDatepicker.helpers({
40 | atts: function addFormControlAtts() {
41 | var atts = { ...this.atts };
42 | // Add bootstrap class
43 | atts = AutoForm.Utility.addClass(atts, 'form-control');
44 | delete atts.datePickerOptions;
45 | return atts;
46 | }
47 | });
48 |
49 | Template.afBootstrapDatepicker.onRendered(function onRendered() {
50 | var $input = this.data.atts.buttonClasses ? this.$('.input-group.date') : this.$('input');
51 | var data = this.data;
52 |
53 | // instanciate datepicker
54 | $input.datepicker(data.atts.datePickerOptions);
55 |
56 | // set and reactively update values
57 | var previousValue;
58 | this.autorun(function () {
59 | var data = Template.currentData();
60 | var nextValue = data.value;
61 |
62 | // set field value
63 | if (String(previousValue) !== String(nextValue)) {
64 | if (typeof nextValue === 'string' && AutoForm.Utility.isValidDateString(nextValue)) {
65 | nextValue = utcToLocal(new Date(nextValue + 'T00:00:00.000Z'));
66 | }
67 |
68 | if (nextValue instanceof Date) {
69 | $input.datepicker('setUTCDate', nextValue);
70 | } else if (typeof nextValue === 'string') {
71 | $input.datepicker('update', nextValue);
72 | }
73 |
74 | if (Array.isArray(nextValue)) {
75 | if (allArrayItemsAreDates(nextValue)) {
76 | $input.datepicker('setUTCDates', nextValue);
77 | } else if (allArrayItemsAreValidDateStrings(nextValue)) {
78 | var nextUTCDates = nextValue.map(function (dateString) {
79 | return utcToLocal(new Date(dateString + 'T00:00:00.000Z'));
80 | });
81 | $input.datepicker('setUTCDates', nextUTCDates);
82 | } else {
83 | $input.datepicker('update', nextValue);
84 | }
85 | }
86 |
87 | previousValue = nextValue;
88 | }
89 |
90 | // set start date if there's a min in the schema
91 | if (data.min instanceof Date) {
92 | // datepicker plugin expects local Date object,
93 | // so convert UTC Date object to local
94 | var startDate = utcToLocal(data.min);
95 | $input.datepicker('setStartDate', startDate);
96 | }
97 |
98 | // set end date if there's a max in the schema
99 | if (data.max instanceof Date) {
100 | // datepicker plugin expects local Date object,
101 | // so convert UTC Date object to local
102 | var endDate = utcToLocal(data.max);
103 | $input.datepicker('setEndDate', endDate);
104 | }
105 | });
106 | });
107 |
108 | Template.afBootstrapDatepicker.onDestroyed(function () {
109 | var $input = this.data.atts.buttonClasses ? this.$('.input-group.date') : this.$('input');
110 | $input.datepicker('remove');
111 | });
112 |
113 | function utcToLocal(utcDate) {
114 | var localDateObj = new Date();
115 | localDateObj.setDate(utcDate.getUTCDate());
116 | localDateObj.setMonth(utcDate.getUTCMonth());
117 | localDateObj.setFullYear(utcDate.getUTCFullYear());
118 | localDateObj.setHours(0);
119 | localDateObj.setMinutes(0);
120 | localDateObj.setSeconds(0);
121 | localDateObj.setMilliseconds(0);
122 | return localDateObj;
123 | }
124 |
125 | function allArrayItemsAreDates(items) {
126 | var nonDates = items.filter(function(val) { return !(val instanceof Date); });
127 | return nonDates.length === 0;
128 | }
129 |
130 | function allArrayItemsAreValidDateStrings(items) {
131 | var nonValid = items.filter(function(val) {
132 | return !(typeof val === 'string' && AutoForm.Utility.isValidDateString(val));
133 | });
134 | return nonValid.length === 0;
135 | }
136 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | //.jshintrc
2 | {
3 | // JSHint Meteor Configuration File
4 | // Match the Meteor Style Guide
5 | //
6 | // By @raix with contributions from @aldeed and @awatson1978
7 | // Source https://github.com/raix/Meteor-jshintrc
8 | //
9 | // See http://jshint.com/docs/ for more details
10 |
11 | "maxerr" : 50, // {int} Maximum error before stopping
12 |
13 | // Enforcing
14 | "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
15 | "camelcase" : true, // true: Identifiers must be in camelCase
16 | "curly" : true, // true: Require {} for every new block or scope
17 | "eqeqeq" : true, // true: Require triple equals (===) for comparison
18 | "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
19 | "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
20 | "indent" : 2, // {int} Number of spaces to use for indentation
21 | "latedef" : false, // true: Require variables/functions to be defined before being used
22 | "newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()`
23 | "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
24 | "noempty" : true, // true: Prohibit use of empty blocks
25 | "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment)
26 | "plusplus" : false, // true: Prohibit use of `++` & `--`
27 | "quotmark" : false, // Quotation mark consistency:
28 | // false : do nothing (default)
29 | // true : ensure whatever is used is consistent
30 | // "single" : require single quotes
31 | // "double" : require double quotes
32 | "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
33 | "unused" : true, // true: Require all defined variables be used
34 | "strict" : false, // true: Requires all functions run in ES5 Strict Mode
35 | "trailing" : true, // true: Prohibit trailing whitespaces
36 | "maxparams" : false, // {int} Max number of formal params allowed per function
37 | "maxdepth" : false, // {int} Max depth of nested blocks (within functions)
38 | "maxstatements" : false, // {int} Max number statements per function
39 | "maxcomplexity" : false, // {int} Max cyclomatic complexity per function
40 | "maxlen" : 80, // {int} Max number of characters per line
41 |
42 | // Relaxing
43 | "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
44 | "boss" : false, // true: Tolerate assignments where comparisons would be expected
45 | "debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
46 | "eqnull" : false, // true: Tolerate use of `== null`
47 | "es5" : true, // true: Allow ES5 syntax (ex: getters and setters)
48 | "esnext" : true, // true: Allow ES.next (ES6) syntax (ex: `const`)
49 | "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
50 | // (ex: `for each`, multiple try/catch, function expression…)
51 | "evil" : false, // true: Tolerate use of `eval` and `new Function()`
52 | "expr" : false, // true: Tolerate `ExpressionStatement` as Programs
53 | "funcscope" : false, // true: Tolerate defining variables inside control statements"
54 | "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
55 | "iterator" : false, // true: Tolerate using the `__iterator__` property
56 | "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
57 | "laxbreak" : false, // true: Tolerate possibly unsafe line breakings
58 | "laxcomma" : false, // true: Tolerate comma-first style coding
59 | "loopfunc" : false, // true: Tolerate functions being defined in loops
60 | "multistr" : false, // true: Tolerate multi-line strings
61 | "proto" : false, // true: Tolerate using the `__proto__` property
62 | "scripturl" : false, // true: Tolerate script-targeted URLs
63 | "smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
64 | "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
65 | "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
66 | "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
67 | "validthis" : false, // true: Tolerate using this in a non-constructor function
68 |
69 | // Environments
70 | "browser" : true, // Web Browser (window, document, etc)
71 | "couch" : false, // CouchDB
72 | "devel" : true, // Development/debugging (alert, confirm, etc)
73 | "dojo" : false, // Dojo Toolkit
74 | "jquery" : false, // jQuery
75 | "mootools" : false, // MooTools
76 | "node" : false, // Node.js
77 | "nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
78 | "prototypejs" : false, // Prototype and Scriptaculous
79 | "rhino" : false, // Rhino
80 | "worker" : false, // Web Workers
81 | "wsh" : false, // Windows Scripting Host
82 | "yui" : false, // Yahoo User Interface
83 | //"meteor" : false, // Meteor.js
84 |
85 | // Legacy
86 | "nomen" : false, // true: Prohibit dangling `_` in variables
87 | "onevar" : false, // true: Allow only one `var` statement per function
88 | "passfail" : false, // true: Stop on first error
89 | "white" : false, // true: Check against strict whitespace and indentation rules
90 |
91 | // Custom Globals
92 | "predef" : [
93 | "Meteor",
94 | "Accounts",
95 | "Session",
96 | "Template",
97 | "check",
98 | "Match",
99 | "Deps",
100 | "EJSON",
101 | "Email",
102 | "Package",
103 | "Tinytest",
104 | "Npm",
105 | "Assets",
106 | "Packages",
107 | "process",
108 | "LocalCollection",
109 | "_",
110 | "Random",
111 | "HTTP"
112 | ] // additional predefined global variables
113 | }
114 |
--------------------------------------------------------------------------------