add-to-calendar-button 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Gruntfile.js +52 -0
- package/README.md +52 -26
- package/assets/css/atcb.css +4 -1
- package/assets/css/atcb.min.css +2 -2
- package/assets/css/atcb.min.css.map +1 -8
- package/npm_dist/atcb_npm.js +53 -32
- package/package.json +13 -5
package/Gruntfile.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module.exports = function(grunt) {
|
|
2
|
+
|
|
3
|
+
// The config.
|
|
4
|
+
grunt.initConfig({
|
|
5
|
+
clean: { // cleans old built files
|
|
6
|
+
oldBuildFiles: ['assets/js/atcb.min.js', 'assets/js/atcb.min.js.map', 'assets/css/atcb.min.css', 'assets/css/atcb.min.css.map', 'npm_dist/']
|
|
7
|
+
},
|
|
8
|
+
copy: {
|
|
9
|
+
npm_dist: { // creates the source file for the npm version
|
|
10
|
+
src: 'assets/js/atcb.js',
|
|
11
|
+
dest: 'npm_dist/atcb_npm.js',
|
|
12
|
+
options: {
|
|
13
|
+
process: function (content) {
|
|
14
|
+
return content.replace(/\/\/ START INIT[\s\S]*?\/\/ END INIT/g,"export { atcb_init };");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
uglify: { // minifies the main js file
|
|
20
|
+
options: {
|
|
21
|
+
compress: true,
|
|
22
|
+
mangle: true,
|
|
23
|
+
sourceMap: true
|
|
24
|
+
},
|
|
25
|
+
newBuild: {
|
|
26
|
+
files: {
|
|
27
|
+
'assets/js/atcb.min.js': ['assets/js/atcb.js']
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
cssmin: {
|
|
32
|
+
options: {
|
|
33
|
+
sourceMap: true
|
|
34
|
+
},
|
|
35
|
+
newBuild: {
|
|
36
|
+
files: {
|
|
37
|
+
'assets/css/atcb.min.css': ['assets/css/atcb.css']
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Load the plugins.
|
|
44
|
+
grunt.loadNpmTasks('grunt-contrib-copy');
|
|
45
|
+
grunt.loadNpmTasks('grunt-contrib-clean');
|
|
46
|
+
grunt.loadNpmTasks('grunt-contrib-uglify');
|
|
47
|
+
grunt.loadNpmTasks('grunt-contrib-cssmin');
|
|
48
|
+
|
|
49
|
+
// Register task(s).
|
|
50
|
+
grunt.registerTask('default', ['clean', 'copy', 'uglify', 'cssmin']);
|
|
51
|
+
|
|
52
|
+
};
|
package/README.md
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|

|
|
3
3
|
|
|
4
4
|
_A convenient JavaScript snippet, which lets you create beautiful buttons, where people can add events to their calendars._
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
|
|
7
7
|
## Use case // Who this is for
|
|
8
8
|
|
|
9
9
|
This is for everybody, who wants to include a button at his/her website or app, which enables users to easily add a specific event to their calendars.
|
|
10
10
|
It's main goal is to keep this process as easy as possible. Simply define your button configuration via JSON and everything else is automatically generated by the script.
|
|
11
11
|
It is for this simple use case. No strings attached.
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
|
|
14
14
|
## Background // Why this repo exists
|
|
15
15
|
|
|
@@ -23,12 +23,12 @@ The problems with AddEvent.com:
|
|
|
23
23
|
* it brings some data privacy issues, since you basically send your users to their service.
|
|
24
24
|
* the UX/UI is not ideal (imho).
|
|
25
25
|
*Bottom line:* Pay for features, which I do not need - at additional privacy "cost" - that made me create this solution (for you).
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
|
|
28
28
|
## DEMO
|
|
29
29
|
|
|
30
30
|
See [jekuer.github.io/add-to-calendar-button](https://jekuer.github.io/add-to-calendar-button/) for a live demo.
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
|
|
33
33
|
## Features
|
|
34
34
|
|
|
@@ -45,12 +45,12 @@ See [jekuer.github.io/add-to-calendar-button](https://jekuer.github.io/add-to-ca
|
|
|
45
45
|
* Well documented code, to easily understand the processes.
|
|
46
46
|
|
|
47
47
|

|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
|
|
50
50
|
## Setup
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
### Option 1: simple
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
1. Simply **download** the code from GitHub **or clone** the git repository.
|
|
55
55
|
2. Copy the css (atcb.min.css) and js (atcb.min.js) files from the assets (not the "npm_dist"!) folders into your project (the **.min.** files are required, but it is recommended to also copy the raw and map files).
|
|
56
56
|
3. Include those files in your project. As usual, the css goes into the <head> (`<link rel="stylesheet" href="./assets/css/atcb.min.css">`), the js into the <body> footer (`<script src="./assets/js/atcb.min.js" defer></script>`). You can also combine them with other files, if you want to.
|
|
@@ -63,23 +63,23 @@ See [jekuer.github.io/add-to-calendar-button](https://jekuer.github.io/add-to-ca
|
|
|
63
63
|
2. Run **`npm install add-to-calendar-button`**.
|
|
64
64
|
3. Import the module into your project/component. For example with Angular/React: `import { atcb_init } from 'add-to-calendar-button';`.
|
|
65
65
|
4. Init the js after the DOM has been loaded. To determine the right moment and execute, ...
|
|
66
|
-
1. with Angular, you would use `ngAfterViewInit()` with `atcb_init();` (mind that, depending on your app, other hooks might be better);
|
|
67
|
-
2. with React, you might want to include an event listener like `document.addEventListener('DOMContentLoaded', atcb_init, false)
|
|
66
|
+
1. with Angular, you would use `ngAfterViewInit()` with `atcb_init();` (mind that, depending on your app, other hooks might be better);
|
|
67
|
+
2. with React, you might want to include an event listener like `document.addEventListener('DOMContentLoaded', atcb_init, false);` or using hooks in a functional component like `useEffect(() => atcb_init());`
|
|
68
68
|
5. Include the css. For example with Angular or React, add the following to the global style.css: `@import 'add-to-calendar-button/assets/css/atcb.min'`;
|
|
69
69
|
6. Create your button as can be seen in the "Configuration" section below.
|
|
70
70
|
7. That is it. The script takes care of all the rest. :)
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
|
|
73
73
|
## Configuration
|
|
74
74
|
|
|
75
|
-
A button can be easily created by placing a respective placeholder, wherever you want the button to appear.
|
|
75
|
+
A button can be easily created by placing a respective placeholder, wherever you want the button to appear.
|
|
76
76
|
(The `style="display:none;"` theoretically is not necessary, but should be used for better compatibility.)
|
|
77
77
|
```html
|
|
78
78
|
<div class="atcb" style="display:none;">
|
|
79
79
|
(...)
|
|
80
80
|
</div>
|
|
81
81
|
```
|
|
82
|
-
Within this placeholder, you can easily configure the button, by placing a respective JSON structure.
|
|
82
|
+
Within this placeholder, you can easily configure the button, by placing a respective JSON structure.
|
|
83
83
|
Mind that with Angular, you might need to escape the { with `{{ '{' }}` and } with `{{ '}' }}`; with React it would be `{ '{' }` and `{ '}' }`.
|
|
84
84
|
|
|
85
85
|
### Minimal structure (required)
|
|
@@ -88,8 +88,8 @@ Mind that with Angular, you might need to escape the { with `{{ '{' }}` and } wi
|
|
|
88
88
|
<div class="atcb" style="display:none;">
|
|
89
89
|
{
|
|
90
90
|
"name":"Add the title of your event",
|
|
91
|
-
"startDate":"02-21
|
|
92
|
-
"endDate":"03-24
|
|
91
|
+
"startDate":"2022-02-21",
|
|
92
|
+
"endDate":"2022-03-24",
|
|
93
93
|
"options":[
|
|
94
94
|
"Google"
|
|
95
95
|
]
|
|
@@ -104,8 +104,8 @@ Mind that with Angular, you might need to escape the { with `{{ '{' }}` and } wi
|
|
|
104
104
|
{
|
|
105
105
|
"name":"Add the title of your event",
|
|
106
106
|
"description":"A nice description does not hurt",
|
|
107
|
-
"startDate":"02-21
|
|
108
|
-
"endDate":"03-24
|
|
107
|
+
"startDate":"2022-02-21",
|
|
108
|
+
"endDate":"2022-03-24",
|
|
109
109
|
"startTime":"10:13",
|
|
110
110
|
"endTime":"17:57",
|
|
111
111
|
"location":"Somewhere over the rainbow",
|
|
@@ -139,8 +139,8 @@ You can use startTime and endTime in the event block, but it is recommended to r
|
|
|
139
139
|
"@type":"Event",
|
|
140
140
|
"name":"Add the title of your event",
|
|
141
141
|
"description":"A nice description does not hurt",
|
|
142
|
-
"startDate":"02-
|
|
143
|
-
"endDate":"03-
|
|
142
|
+
"startDate":"2022-02-21T10:13",
|
|
143
|
+
"endDate":"2022-03-24T17:57",
|
|
144
144
|
"location":"Somewhere over the rainbow"
|
|
145
145
|
},
|
|
146
146
|
"label":"Add to Calendar",
|
|
@@ -160,14 +160,35 @@ You can use startTime and endTime in the event block, but it is recommended to r
|
|
|
160
160
|
</script>
|
|
161
161
|
</div>
|
|
162
162
|
```
|
|
163
|
-
|
|
163
|
+
|
|
164
|
+
### React example
|
|
165
|
+
|
|
166
|
+
A simpler method uses `JSON.stringify()` where you define your config in an external file or variable and then
|
|
167
|
+
convert it to a string to be passed into the div.
|
|
168
|
+
|
|
169
|
+
```js
|
|
170
|
+
const AddToCalendar = () => {
|
|
171
|
+
|
|
172
|
+
useEffect(() => atcb_init());
|
|
173
|
+
|
|
174
|
+
const event = { /* Event data */}
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<div className='atcb'>
|
|
178
|
+
<script type="application/ld+json">
|
|
179
|
+
{JSON.stringify(event)}
|
|
180
|
+
</script>
|
|
181
|
+
</div>
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
```
|
|
164
185
|
|
|
165
186
|
### Important information and hidden features
|
|
166
187
|
|
|
167
188
|
* The "label" is optional, but enables you to customize the button text. Default: "Add to Calendar".
|
|
168
|
-
* Dates need to be formatted as MM-DD-
|
|
189
|
+
* Dates need to be formatted as YYYY-MM-DD ([ISO-8601](https://en.wikipedia.org/wiki/ISO_8601)).
|
|
169
190
|
* You can also use the word "today" as date. It will then dynamically use the current day at click.
|
|
170
|
-
* Add "+5" at the end of the date to dynamically add 5 days (or any other number). "01-30
|
|
191
|
+
* Add "+5" at the end of the date to dynamically add 5 days (or any other number). "2022-01-30+12" would generate the 11th of February 2022. This can be interesting, when combined with "today".
|
|
171
192
|
* Times need to be formatted as HH:MM.
|
|
172
193
|
* Times are optional. If not set, the button generates all-day events.
|
|
173
194
|
* 1 option is required. You can add as many as you want. The supported formats are listed above.
|
|
@@ -177,11 +198,13 @@ You can use startTime and endTime in the event block, but it is recommended to r
|
|
|
177
198
|
* If the timeZoneOffset is set, it will always override the timeZone. It is recommended to only use 1 of them at a time.
|
|
178
199
|
* The timeZone might not work in very old browsers, but also considers dynamic changes like summer/winter time.
|
|
179
200
|
* timeZoneOffset works with older browsers, but is quite static.
|
|
201
|
+
* Use "currentBrowser" as value for timeZone to dynamically use the time of the user's browser. Use this with caution, since it would mean that the date and time will differ per user, which should not be the usual case! (Requires all times to be set.)
|
|
180
202
|
* You can set the trigger to "click". This makes the button open on click at desktop. Otherwise, the default would be to open on hover. On touch devices, this makes no difference.
|
|
181
203
|
* If you want to define a specific name for any generated ics file (iCal), you can specify it via the "iCalFileName" option. The default would be "event-to-save-in-my-calendar".
|
|
182
204
|
* You can use the option "inline":true in order to make the button appear with inline-block instead of block style.
|
|
205
|
+
* Formatting a URL in the description like `[url]https://....[/url]` makes it clickable.
|
|
183
206
|
* If you require line breaks within the description, use `\n` or `<br>`.
|
|
184
|
-
|
|
207
|
+
|
|
185
208
|
|
|
186
209
|
## Contributing
|
|
187
210
|
|
|
@@ -190,21 +213,24 @@ Anyone is welcome to contribute, but mind the [guidelines](.github/CONTRIBUTING.
|
|
|
190
213
|
* [Bug reports](.github/CONTRIBUTING.md#bugs)
|
|
191
214
|
* [Feature requests](.github/CONTRIBUTING.md#features)
|
|
192
215
|
* [Pull requests](.github/CONTRIBUTING.md#pull-requests)
|
|
193
|
-
|
|
216
|
+
|
|
217
|
+
IMPORTANT NOTE: Run `npm install` and `npm run build` to create the minified js and css file, its sourcemap files as well as the npm_dist/ folder and content!
|
|
218
|
+
|
|
194
219
|
|
|
195
220
|
## License
|
|
196
221
|
|
|
197
|
-
The code is available under the [
|
|
198
|
-
|
|
222
|
+
The code is available under the [MIT license (with “Commons Clause” License Condition v1.0)](LICENSE.txt).
|
|
223
|
+
|
|
199
224
|
|
|
200
225
|
## Changelog (without bug fixes)
|
|
201
226
|
|
|
227
|
+
* v1.5 : update to date format and better accesibility
|
|
202
228
|
* v1.4 : schema.org support (also changed some keys in the JSON!)
|
|
203
229
|
* v1.3 : new license (MIT with “Commons Clause”)
|
|
204
230
|
* v1.2 : inline and line break support
|
|
205
231
|
* v1.1 : npm functionality
|
|
206
232
|
* v1.0 : initial release
|
|
207
|
-
|
|
233
|
+
|
|
208
234
|
|
|
209
235
|
## Kudos go to
|
|
210
236
|
* [github.com/dudewheresmycode](https://github.com/dudewheresmycodee)
|
package/assets/css/atcb.css
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Add-to-Calendar Button
|
|
4
4
|
* ++++++++++++++++++++++
|
|
5
5
|
*
|
|
6
|
-
* Version: 1.
|
|
6
|
+
* Version: 1.5.0
|
|
7
7
|
* Creator: Jens Kuerschner (https://jenskuerschner.de)
|
|
8
8
|
* Project: https://github.com/jekuer/add-to-calendar-button
|
|
9
9
|
* License: MIT with “Commons Clause” License Condition v1.0
|
|
@@ -45,6 +45,9 @@
|
|
|
45
45
|
-webkit-tap-highlight-color: transparent;
|
|
46
46
|
width: auto;
|
|
47
47
|
}
|
|
48
|
+
.atcb_button:hover {
|
|
49
|
+
background: rgb(255, 255, 255);
|
|
50
|
+
}
|
|
48
51
|
@media only screen and (max-width: 575px) {
|
|
49
52
|
.atcb_button {
|
|
50
53
|
font-size: 14px;
|
package/assets/css/atcb.min.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
.atcb{display:none}.atcb_button_wrapper{display:inline-block;position:relative}.atcb_button{background:#f5f5f5;border:1px solid #d2d2d2;border-radius:6px;-webkit-box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);color:#333;cursor:pointer;display:inline-block;font-size:16px;font-weight:600;line-height:24px;margin:10px auto;max-width:300px;min-width:150px;padding:10px 16px 11px 16px;position:relative;text-align:center;touch-action:manipulation;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;width:auto}@media only screen and (max-width:575px){.atcb_button{font-size:14px}}.atcb_button.active{background:#fff;border-radius:6px 6px 3px 3px;-webkit-box-shadow:1px 5px 15px 0 rgba(0,0,0,.5);box-shadow:1px 5px 15px 0 rgba(0,0,0,.5);margin:7px auto 9px auto;padding:12px 20px 13px 20px;z-index:90}.atcb_icon{height:16px;display:inline-flex;margin-bottom:4px;margin-right:10px;vertical-align:middle}.atcb_icon svg{height:100%;color:#333;width:auto}.atcb_list{box-sizing:border-box;color:#333;display:block;margin:-10px auto 0 auto;max-width:100%;position:absolute;padding:0 3px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%;z-index:80}.atcb_list_item{background:#fafafa;border:1px solid #d2d2d2;border-top:0;-webkit-box-shadow:1px 2px 8px 0 rgba(0,0,0,.3);box-shadow:1px 2px 8px 0 rgba(0,0,0,.3);box-sizing:border-box;cursor:pointer;font-size:16px;left:50%;position:relative;padding:12px 18px;text-align:left;transform:translate(-50%);touch-action:manipulation;-webkit-tap-highlight-color:transparent}.atcb_list_item:hover{background:#fff;-webkit-box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);color:#000}@media only screen and (max-width:575px){.atcb_list_item{font-size:14px}}.atcb_list_item:first-child{padding-top:25px}.atcb_list_item:last-child{border-radius:0 0 6px 6px}.atcb_list_item .atcb_icon{margin-right:8px}.atcb_bgoverlay{background:rgba(20,20,20,.2);backdrop-filter:blur(2px);height:100%;left:0;position:fixed;top:0;width:100%;z-index:70}
|
|
2
|
-
/*# sourceMappingURL=atcb.min.css.map */
|
|
1
|
+
.atcb{display:none}.atcb_button_wrapper{display:inline-block;position:relative}.atcb_button{background:#f5f5f5;border:1px solid #d2d2d2;border-radius:6px;-webkit-box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);color:#333;cursor:pointer;display:inline-block;font-size:16px;font-weight:600;line-height:24px;margin:10px auto;max-width:300px;min-width:150px;padding:10px 16px 11px 16px;position:relative;text-align:center;touch-action:manipulation;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;width:auto}.atcb_button:hover{background:#fff}@media only screen and (max-width:575px){.atcb_button{font-size:14px}}.atcb_button.active{background:#fff;border-radius:6px 6px 3px 3px;-webkit-box-shadow:1px 5px 15px 0 rgba(0,0,0,.5);box-shadow:1px 5px 15px 0 rgba(0,0,0,.5);margin:7px auto 9px auto;padding:12px 20px 13px 20px;z-index:90}.atcb_icon{height:16px;display:inline-flex;margin-bottom:4px;margin-right:10px;vertical-align:middle}.atcb_icon svg{height:100%;color:#333;width:auto}.atcb_list{box-sizing:border-box;color:#333;display:block;margin:-10px auto 0 auto;max-width:100%;position:absolute;padding:0 3px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%;z-index:80}.atcb_list_item{background:#fafafa;border:1px solid #d2d2d2;border-top:0;-webkit-box-shadow:1px 2px 8px 0 rgba(0,0,0,.3);box-shadow:1px 2px 8px 0 rgba(0,0,0,.3);box-sizing:border-box;cursor:pointer;font-size:16px;left:50%;position:relative;padding:12px 18px;text-align:left;transform:translate(-50%);touch-action:manipulation;-webkit-tap-highlight-color:transparent}.atcb_list_item:hover{background:#fff;-webkit-box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);color:#000}@media only screen and (max-width:575px){.atcb_list_item{font-size:14px}}.atcb_list_item:first-child{padding-top:25px}.atcb_list_item:last-child{border-radius:0 0 6px 6px}.atcb_list_item .atcb_icon{margin-right:8px}.atcb_bgoverlay{background:rgba(20,20,20,.2);backdrop-filter:blur(2px);height:100%;left:0;position:fixed;top:0;width:100%;z-index:70}
|
|
2
|
+
/*# sourceMappingURL=atcb.min.css.map */
|
|
@@ -1,8 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": [
|
|
4
|
-
"atcb.css"
|
|
5
|
-
],
|
|
6
|
-
"names": [],
|
|
7
|
-
"mappings": "AAYA,MACE,QAAS,KAGX,qBACE,QAAS,aACT,SAAU,SAGZ,aACE,WAAY,QACZ,OAAQ,IAAI,MAAM,QAClB,cAAe,IACf,mBAAoB,IAAI,IAAI,KAAK,EAAI,eACrC,WAAY,IAAI,IAAI,KAAK,EAAI,eAC7B,MAAO,KACP,OAAQ,QACR,QAAS,aACT,UAAW,KACX,YAAa,IACb,YAAa,KACb,OAAQ,KAAK,KACb,UAAW,MACX,UAAW,MACX,QAAS,KAAK,KAAK,KAAK,KACxB,SAAU,SACV,WAAY,OACZ,aAAc,aACd,oBAAqB,KACrB,iBAAkB,KAClB,gBAAiB,KACjB,YAAa,KACb,4BAA6B,YAC7B,MAAO,KAET,yCACE,aACE,UAAW,MAIf,oBACE,WAAY,KACZ,cAAe,IAAI,IAAI,IAAI,IAC3B,mBAAoB,IAAI,IAAI,KAAK,EAAI,eACrC,WAAY,IAAI,IAAI,KAAK,EAAI,eAC7B,OAAQ,IAAI,KAAK,IAAI,KACrB,QAAS,KAAK,KAAK,KAAK,KACxB,QAAS,GAGX,WACE,OAAQ,KACR,QAAS,YACT,cAAe,IACf,aAAc,KACd,eAAgB,OAElB,eACE,OAAQ,KACR,MAAO,KACP,MAAO,KAGT,WACE,WAAY,WACZ,MAAO,KACP,QAAS,MACT,OAAQ,MAAM,KAAK,EAAE,KACrB,UAAW,KACX,SAAU,SACV,QAAS,EAAE,IACX,oBAAqB,KACrB,iBAAkB,KAClB,gBAAiB,KACjB,YAAa,KACb,MAAO,KACP,QAAS,GAGX,gBACE,WAAY,QACZ,OAAQ,IAAI,MAAM,QAClB,WAAY,EACZ,mBAAoB,IAAI,IAAI,IAAI,EAAI,eACpC,WAAY,IAAI,IAAI,IAAI,EAAI,eAC5B,WAAY,WACZ,OAAQ,QACR,UAAW,KACX,KAAM,IACN,SAAU,SACV,QAAS,KAAK,KACd,WAAY,KACZ,UAAW,gBACX,aAAc,aACd,4BAA6B,YAE/B,sBACE,WAAY,KACZ,mBAAoB,IAAI,IAAI,KAAK,EAAI,eACrC,WAAY,IAAI,IAAI,KAAK,EAAI,eAC7B,MAAO,KAET,yCACE,gBACE,UAAW,MAIf,4BACE,YAAa,KAGf,2BACE,cAAe,EAAE,EAAE,IAAI,IAIzB,2BACE,aAAc,IAGhB,gBACE,WAAY,kBACZ,gBAAiB,UACjB,OAAQ,KACR,KAAM,EACN,SAAU,MACV,IAAK,EACL,MAAO,KACP,QAAS"
|
|
8
|
-
}
|
|
1
|
+
{"version":3,"sources":["assets\\css\\atcb.css"],"names":[],"mappings":"AAYA,MACE,QAAS,KAGX,qBACE,QAAS,aACT,SAAU,SAGZ,aACE,WAAY,QACZ,OAAQ,IAAI,MAAM,QAClB,cAAe,IACf,mBAAoB,IAAI,IAAI,KAAK,EAAI,eACrC,WAAY,IAAI,IAAI,KAAK,EAAI,eAC7B,MAAO,KACP,OAAQ,QACR,QAAS,aACT,UAAW,KACX,YAAa,IACb,YAAa,KACb,OAAQ,KAAK,KACb,UAAW,MACX,UAAW,MACX,QAAS,KAAK,KAAK,KAAK,KACxB,SAAU,SACV,WAAY,OACZ,aAAc,aACd,oBAAqB,KACrB,iBAAkB,KAClB,gBAAiB,KACjB,YAAa,KACb,4BAA6B,YAC7B,MAAO,KAET,mBACE,WAAY,KAEd,yCACE,aACE,UAAW,MAIf,oBACE,WAAY,KACZ,cAAe,IAAI,IAAI,IAAI,IAC3B,mBAAoB,IAAI,IAAI,KAAK,EAAI,eACrC,WAAY,IAAI,IAAI,KAAK,EAAI,eAC7B,OAAQ,IAAI,KAAK,IAAI,KACrB,QAAS,KAAK,KAAK,KAAK,KACxB,QAAS,GAGX,WACE,OAAQ,KACR,QAAS,YACT,cAAe,IACf,aAAc,KACd,eAAgB,OAElB,eACE,OAAQ,KACR,MAAO,KACP,MAAO,KAGT,WACE,WAAY,WACZ,MAAO,KACP,QAAS,MACT,OAAQ,MAAM,KAAK,EAAE,KACrB,UAAW,KACX,SAAU,SACV,QAAS,EAAE,IACX,oBAAqB,KACrB,iBAAkB,KAClB,gBAAiB,KACjB,YAAa,KACb,MAAO,KACP,QAAS,GAGX,gBACE,WAAY,QACZ,OAAQ,IAAI,MAAM,QAClB,WAAY,EACZ,mBAAoB,IAAI,IAAI,IAAI,EAAI,eACpC,WAAY,IAAI,IAAI,IAAI,EAAI,eAC5B,WAAY,WACZ,OAAQ,QACR,UAAW,KACX,KAAM,IACN,SAAU,SACV,QAAS,KAAK,KACd,WAAY,KACZ,UAAW,gBACX,aAAc,aACd,4BAA6B,YAE/B,sBACE,WAAY,KACZ,mBAAoB,IAAI,IAAI,KAAK,EAAI,eACrC,WAAY,IAAI,IAAI,KAAK,EAAI,eAC7B,MAAO,KAET,yCACE,gBACE,UAAW,MAIf,4BACE,YAAa,KAGf,2BACE,cAAe,EAAE,EAAE,IAAI,IAIzB,2BACE,aAAc,IAGhB,gBACE,WAAY,kBACZ,gBAAiB,UACjB,OAAQ,KACR,KAAM,EACN,SAAU,MACV,IAAK,EACL,MAAO,KACP,QAAS"}
|
package/npm_dist/atcb_npm.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Add-to-Calendar Button
|
|
4
4
|
* ++++++++++++++++++++++
|
|
5
5
|
*/
|
|
6
|
-
const atcbVersion = '1.
|
|
6
|
+
const atcbVersion = '1.5.0';
|
|
7
7
|
/* Creator: Jens Kuerschner (https://jenskuerschner.de)
|
|
8
8
|
* Project: https://github.com/jekuer/add-to-calendar-button
|
|
9
9
|
* License: MIT with “Commons Clause” License Condition v1.0
|
|
@@ -46,7 +46,7 @@ function atcb_init() {
|
|
|
46
46
|
atcbConfig['deleteJSON'] = true;
|
|
47
47
|
}
|
|
48
48
|
// rewrite config for backwards compatibility - you can remove this, if you did not use this script before v1.4.0.
|
|
49
|
-
atcbConfig =
|
|
49
|
+
atcbConfig = atcb_patch_config(atcbConfig);
|
|
50
50
|
// check, if all required data is available
|
|
51
51
|
if (atcb_check_required(atcbConfig)) {
|
|
52
52
|
// calculate the real date values in case that there are some special rules included (e.g. adding days dynamically)
|
|
@@ -91,7 +91,7 @@ function atcb_clean_schema_json(atcbConfig) {
|
|
|
91
91
|
|
|
92
92
|
|
|
93
93
|
// BACKWARDS COMPATIBILITY REWRITE - you can remove this, if you did not use this script before v1.4.0.
|
|
94
|
-
function
|
|
94
|
+
function atcb_patch_config(atcbConfig) {
|
|
95
95
|
const keyChanges = {
|
|
96
96
|
'title': 'name',
|
|
97
97
|
'dateStart': 'startDate',
|
|
@@ -138,11 +138,15 @@ function atcb_date_calculation(dateString) {
|
|
|
138
138
|
// check for any dynamic additions and adjust
|
|
139
139
|
const dateStringParts = dateString.split('+');
|
|
140
140
|
const dateParts = dateStringParts[0].split('-');
|
|
141
|
-
let newDate = new Date(dateParts[
|
|
141
|
+
let newDate = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);
|
|
142
|
+
if (dateParts[0].length < 4) {
|
|
143
|
+
// backwards compatibility for version <1.5.0
|
|
144
|
+
newDate = new Date(dateParts[2], dateParts[0] - 1, dateParts[1]);
|
|
145
|
+
}
|
|
142
146
|
if (dateStringParts[1] != null && dateStringParts[1] > 0) {
|
|
143
147
|
newDate.setDate(newDate.getDate() + parseInt(dateStringParts[1]));
|
|
144
148
|
}
|
|
145
|
-
return (((newDate.getMonth() + 1) < 10 ? '0' : '') + (newDate.getMonth() + 1)) + '-' + (newDate.getDate() < 10 ? '0' : '') + newDate.getDate()
|
|
149
|
+
return newDate.getFullYear() + '-' + (((newDate.getMonth() + 1) < 10 ? '0' : '') + (newDate.getMonth() + 1)) + '-' + (newDate.getDate() < 10 ? '0' : '') + newDate.getDate();
|
|
146
150
|
}
|
|
147
151
|
|
|
148
152
|
|
|
@@ -170,7 +174,7 @@ function atcb_validate(data) {
|
|
|
170
174
|
console.log("add-to-calendar button generation failed: date misspelled [" + date + ": " + data[date] + "]");
|
|
171
175
|
return false;
|
|
172
176
|
}
|
|
173
|
-
newDate[date] = new Date(dateParts[
|
|
177
|
+
newDate[date] = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);
|
|
174
178
|
return true;
|
|
175
179
|
})) {
|
|
176
180
|
return false;
|
|
@@ -231,7 +235,7 @@ function atcb_generate(button, buttonId, data) {
|
|
|
231
235
|
buttonTriggerWrapper.classList.add('atcb_button_wrapper');
|
|
232
236
|
button.appendChild(buttonTriggerWrapper);
|
|
233
237
|
// generate the button trigger div
|
|
234
|
-
let buttonTrigger = document.createElement('
|
|
238
|
+
let buttonTrigger = document.createElement('button');
|
|
235
239
|
buttonTrigger.id = 'atcb_button_' + buttonId;
|
|
236
240
|
buttonTrigger.classList.add('atcb_button');
|
|
237
241
|
buttonTrigger.dataset.atcbtn = buttonId;
|
|
@@ -240,13 +244,21 @@ function atcb_generate(button, buttonId, data) {
|
|
|
240
244
|
buttonTrigger.innerHTML += '<span class="atcb_text">' + (data['label'] || 'Add to Calendar') + '</span>';
|
|
241
245
|
// set event listeners for the button trigger
|
|
242
246
|
if (data['trigger'] == 'click') {
|
|
243
|
-
buttonTrigger.addEventListener('
|
|
247
|
+
buttonTrigger.addEventListener('mousedown', atcb_toggle);
|
|
244
248
|
} else {
|
|
245
249
|
buttonTrigger.addEventListener('touchstart', atcb_toggle, {passive: true});
|
|
246
|
-
buttonTrigger.addEventListener('mouseenter', atcb_open
|
|
250
|
+
buttonTrigger.addEventListener('mouseenter', atcb_open);
|
|
247
251
|
}
|
|
248
|
-
|
|
252
|
+
buttonTrigger.addEventListener('focus', atcb_open);
|
|
253
|
+
buttonTrigger.addEventListener('keydown', function(event) { // trigger click on enter as well
|
|
254
|
+
if (event.key == 'Enter') {
|
|
255
|
+
atcb_toggle.call(event.target);
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
// standardize any line breaks in the description and transform URLs (but keep a clean copy without the URL magic for iCal)
|
|
249
259
|
data['description'] = data['description'].replace(/<br\s*\/?>/gmi, '\n');
|
|
260
|
+
data['description_iCal'] = data['description'].replace('[url]','').replace('[/url]','');
|
|
261
|
+
data['description'] = data['description'].replace(/\[url\](.*?)\[\/url\]/g, "<a href='$1' target='_blank' rel='noopener'>$1</a>");
|
|
250
262
|
// generate the options list
|
|
251
263
|
let optionsList = document.createElement('div');
|
|
252
264
|
optionsList.id = 'atcb_list_' + buttonId;
|
|
@@ -257,7 +269,8 @@ function atcb_generate(button, buttonId, data) {
|
|
|
257
269
|
data['options'].forEach(function(option) {
|
|
258
270
|
let optionParts = option.split('|');
|
|
259
271
|
let optionItem = document.createElement('div');
|
|
260
|
-
optionItem.classList.add('atcb_list_item');
|
|
272
|
+
optionItem.classList.add('atcb_list_item');
|
|
273
|
+
optionItem.tabIndex = 0;
|
|
261
274
|
optionsList.appendChild(optionItem);
|
|
262
275
|
switch (optionParts[0]) {
|
|
263
276
|
case "Apple":
|
|
@@ -268,7 +281,7 @@ function atcb_generate(button, buttonId, data) {
|
|
|
268
281
|
optionItem.addEventListener('click', function() {
|
|
269
282
|
atcb_generate_ical(data);
|
|
270
283
|
atcb_close_all();
|
|
271
|
-
}
|
|
284
|
+
});
|
|
272
285
|
break;
|
|
273
286
|
case "Google":
|
|
274
287
|
optionItem.innerHTML = '<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.88 122.88"><path d="M93.78 29.1H29.1v64.68h64.68V29.1z" fill="#fff"/><path d="M93.78 122.88l29.1-29.1h-29.1v29.1z" fill="#f72a25"/><path d="M122.88 29.1h-29.1v64.68h29.1V29.1z" fill="#fbbc04"/><path d="M93.78 93.78H29.1v29.1h64.68v-29.1z" fill="#34a853"/><path d="M0 93.78v19.4c0 5.36 4.34 9.7 9.7 9.7h19.4v-29.1H0h0z" fill="#188038"/><path d="M122.88 29.1V9.7c0-5.36-4.34-9.7-9.7-9.7h-19.4v29.1h29.1 0z" fill="#1967d2"/><path d="M93.78 0H9.7C4.34 0 0 4.34 0 9.7v84.08h29.1V29.1h64.67V0h.01z" fill="#4285f4"/><path d="M42.37 79.27c-2.42-1.63-4.09-4.02-5-7.17l5.61-2.31c.51 1.94 1.4 3.44 2.67 4.51 1.26 1.07 2.8 1.59 4.59 1.59 1.84 0 3.41-.56 4.73-1.67 1.32-1.12 1.98-2.54 1.98-4.26 0-1.76-.7-3.2-2.09-4.32s-3.14-1.67-5.22-1.67H46.4v-5.55h2.91c1.79 0 3.31-.48 4.54-1.46 1.23-.97 1.84-2.3 1.84-3.99 0-1.5-.55-2.7-1.65-3.6s-2.49-1.35-4.18-1.35c-1.65 0-2.96.44-3.93 1.32s-1.7 2-2.12 3.24l-5.55-2.31c.74-2.09 2.09-3.93 4.07-5.52s4.51-2.39 7.58-2.39c2.27 0 4.32.44 6.13 1.32s3.23 2.1 4.26 3.65c1.03 1.56 1.54 3.31 1.54 5.25 0 1.98-.48 3.65-1.43 5.03-.95 1.37-2.13 2.43-3.52 3.16v.33c1.79.74 3.36 1.96 4.51 3.52 1.17 1.58 1.76 3.46 1.76 5.66s-.56 4.16-1.67 5.88c-1.12 1.72-2.66 3.08-4.62 4.07s-4.17 1.49-6.62 1.49c-2.84 0-5.46-.81-7.88-2.45h0 0zm34.46-27.84l-6.16 4.45-3.08-4.67 11.05-7.97h4.24v37.6h-6.05V51.43h0z" fill="#1a73e8"/></svg></span>';
|
|
@@ -278,7 +291,7 @@ function atcb_generate(button, buttonId, data) {
|
|
|
278
291
|
optionItem.addEventListener('click', function() {
|
|
279
292
|
atcb_generate_google(data);
|
|
280
293
|
atcb_close_all();
|
|
281
|
-
}
|
|
294
|
+
});
|
|
282
295
|
break;
|
|
283
296
|
case "iCal":
|
|
284
297
|
optionItem.innerHTML = '<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.88 122.88"><path d="M81.61 4.73c0-2.61 2.58-4.73 5.77-4.73s5.77 2.12 5.77 4.73v20.72c0 2.61-2.58 4.73-5.77 4.73s-5.77-2.12-5.77-4.73V4.73h0zm-15.5 99.08c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2H81.9c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H66.11h0zM15.85 67.09c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H15.85h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H40.98h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2H81.9c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H66.11h0zm25.14 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H91.25h0zm-75.4 18.36c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H15.85h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H40.98h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2H81.9c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H66.11h0zm25.14 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H91.25h0zm-75.4 18.36c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H15.85h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H40.98h0zM29.61 4.73c0-2.61 2.58-4.73 5.77-4.73s5.77 2.12 5.77 4.73v20.72c0 2.61-2.58 4.73-5.77 4.73s-5.77-2.12-5.77-4.73V4.73h0zM6.4 45.32h110.07V21.47c0-.8-.33-1.53-.86-2.07-.53-.53-1.26-.86-2.07-.86H103c-1.77 0-3.2-1.43-3.2-3.2s1.43-3.2 3.2-3.2h10.55c2.57 0 4.9 1.05 6.59 2.74s2.74 4.02 2.74 6.59v27.06 65.03c0 2.57-1.05 4.9-2.74 6.59s-4.02 2.74-6.59 2.74H9.33c-2.57 0-4.9-1.05-6.59-2.74-1.69-1.7-2.74-4.03-2.74-6.6V48.52 21.47c0-2.57 1.05-4.9 2.74-6.59s4.02-2.74 6.59-2.74H20.6c1.77 0 3.2 1.43 3.2 3.2s-1.43 3.2-3.2 3.2H9.33c-.8 0-1.53.33-2.07.86-.53.53-.86 1.26-.86 2.07v23.85h0zm110.08 6.41H6.4v61.82c0 .8.33 1.53.86 2.07.53.53 1.26.86 2.07.86h104.22c.8 0 1.53-.33 2.07-.86.53-.53.86-1.26.86-2.07V51.73h0zM50.43 18.54c-1.77 0-3.2-1.43-3.2-3.2s1.43-3.2 3.2-3.2h21.49c1.77 0 3.2 1.43 3.2 3.2s-1.43 3.2-3.2 3.2H50.43h0z"/></svg></span>';
|
|
@@ -288,7 +301,7 @@ function atcb_generate(button, buttonId, data) {
|
|
|
288
301
|
optionItem.addEventListener('click', function() {
|
|
289
302
|
atcb_generate_ical(data);
|
|
290
303
|
atcb_close_all();
|
|
291
|
-
}
|
|
304
|
+
});
|
|
292
305
|
break;
|
|
293
306
|
case "Microsoft365":
|
|
294
307
|
optionItem.innerHTML = '<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 278050 333334" shape-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd"><path fill="#ea3e23" d="M278050 305556l-29-16V28627L178807 0 448 66971l-448 87 22 200227 60865-23821V80555l117920-28193-17 239519L122 267285l178668 65976v73l99231-27462v-316z"/></svg></span>';
|
|
@@ -298,7 +311,7 @@ function atcb_generate(button, buttonId, data) {
|
|
|
298
311
|
optionItem.addEventListener('click', function() {
|
|
299
312
|
atcb_generate_microsoft(data, '365');
|
|
300
313
|
atcb_close_all();
|
|
301
|
-
}
|
|
314
|
+
});
|
|
302
315
|
break;
|
|
303
316
|
case "Outlook.com":
|
|
304
317
|
optionItem.innerHTML = '<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-0.129793726981 0 33.251996719421 32" width="2500" height="2397"><path d="M28.596 2H11.404A1.404 1.404 0 0 0 10 3.404V5l9.69 3L30 5V3.404A1.404 1.404 0 0 0 28.596 2z" fill="#0364b8"/><path d="M31.65 17.405A11.341 11.341 0 0 0 32 16a.666.666 0 0 0-.333-.576l-.013-.008-.004-.002L20.812 9.24a1.499 1.499 0 0 0-1.479-.083 1.49 1.49 0 0 0-.145.082L8.35 15.415l-.004.002-.012.007A.666.666 0 0 0 8 16a11.344 11.344 0 0 0 .35 1.405l11.492 8.405z" fill="#0a2767"/><path d="M24 5h-7l-2.021 3L17 11l7 6h6v-6z" fill="#28a8ea"/><path d="M10 5h7v6h-7z" fill="#0078d4"/><path d="M24 5h6v6h-6z" fill="#50d9ff"/><path d="M24 17l-7-6h-7v6l7 6 10.832 1.768z" fill="#0364b8"/><path d="M17 11h7v6h-7z" fill="#0078d4"/><path d="M10 17h7v6h-7z" fill="#064a8c"/><path d="M24 17h6v6h-6z" fill="#0078d4"/><path d="M20.19 25.218l-11.793-8.6.495-.87 10.909 6.212a.528.528 0 0 0 .42-.012l10.933-6.23.496.869z" fill="#0a2767" opacity=".5"/><path d="M31.667 16.577l-.014.008-.003.002-10.838 6.174a1.497 1.497 0 0 1-1.46.091l3.774 5.061 8.254 1.797v.004A1.498 1.498 0 0 0 32 28.5V16a.666.666 0 0 1-.333.577z" fill="#1490df"/><path d="M32 28.5v-.738l-9.983-5.688-1.205.687a1.497 1.497 0 0 1-1.46.091l3.774 5.061 8.254 1.797v.004A1.498 1.498 0 0 0 32 28.5z" opacity=".05"/><path d="M31.95 28.883L21.007 22.65l-.195.11a1.497 1.497 0 0 1-1.46.092l3.774 5.061 8.254 1.797v.004a1.501 1.501 0 0 0 .57-.83z" opacity=".1"/><path d="M8.35 16.59v-.01h-.01l-.03-.02A.65.65 0 0 1 8 16v12.5A1.498 1.498 0 0 0 9.5 30h21a1.503 1.503 0 0 0 .37-.05.637.637 0 0 0 .18-.06.142.142 0 0 0 .06-.02 1.048 1.048 0 0 0 .23-.13c.02-.01.03-.01.04-.03z" fill="#28a8ea"/><path d="M18 24.667V8.333A1.337 1.337 0 0 0 16.667 7H10.03v7.456l-1.68.958-.005.002-.012.007A.666.666 0 0 0 8 16v.005V16v10h8.667A1.337 1.337 0 0 0 18 24.667z" opacity=".1"/><path d="M17 25.667V9.333A1.337 1.337 0 0 0 15.667 8H10.03v6.456l-1.68.958-.005.002-.012.007A.666.666 0 0 0 8 16v.005V16v11h7.667A1.337 1.337 0 0 0 17 25.667z" opacity=".2"/><path d="M17 23.667V9.333A1.337 1.337 0 0 0 15.667 8H10.03v6.456l-1.68.958-.005.002-.012.007A.666.666 0 0 0 8 16v.005V16v9h7.667A1.337 1.337 0 0 0 17 23.667z" opacity=".2"/><path d="M16 23.667V9.333A1.337 1.337 0 0 0 14.667 8H10.03v6.456l-1.68.958-.005.002-.012.007A.666.666 0 0 0 8 16v.005V16v9h6.667A1.337 1.337 0 0 0 16 23.667z" opacity=".2"/><path d="M1.333 8h13.334A1.333 1.333 0 0 1 16 9.333v13.334A1.333 1.333 0 0 1 14.667 24H1.333A1.333 1.333 0 0 1 0 22.667V9.333A1.333 1.333 0 0 1 1.333 8z" fill="#0078d4"/><path d="M3.867 13.468a4.181 4.181 0 0 1 1.642-1.814A4.965 4.965 0 0 1 8.119 11a4.617 4.617 0 0 1 2.413.62 4.14 4.14 0 0 1 1.598 1.733 5.597 5.597 0 0 1 .56 2.55 5.901 5.901 0 0 1-.577 2.666 4.239 4.239 0 0 1-1.645 1.794A4.8 4.8 0 0 1 7.963 21a4.729 4.729 0 0 1-2.468-.627 4.204 4.204 0 0 1-1.618-1.736 5.459 5.459 0 0 1-.567-2.519 6.055 6.055 0 0 1 .557-2.65zm1.75 4.258a2.716 2.716 0 0 0 .923 1.194 2.411 2.411 0 0 0 1.443.435 2.533 2.533 0 0 0 1.541-.449 2.603 2.603 0 0 0 .897-1.197 4.626 4.626 0 0 0 .286-1.665 5.063 5.063 0 0 0-.27-1.686 2.669 2.669 0 0 0-.866-1.24 2.387 2.387 0 0 0-1.527-.473 2.493 2.493 0 0 0-1.477.439 2.741 2.741 0 0 0-.944 1.203 4.776 4.776 0 0 0-.007 3.44z" fill="#fff"/></svg></span>';
|
|
@@ -308,7 +321,7 @@ function atcb_generate(button, buttonId, data) {
|
|
|
308
321
|
optionItem.addEventListener('click', function() {
|
|
309
322
|
atcb_generate_microsoft(data, 'outlook');
|
|
310
323
|
atcb_close_all();
|
|
311
|
-
}
|
|
324
|
+
});
|
|
312
325
|
break;
|
|
313
326
|
case "Yahoo":
|
|
314
327
|
optionItem.innerHTML = '<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3386.34 3010.5" shape-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd"><path d="M0 732.88h645.84l376.07 962.1 380.96-962.1h628.76l-946.8 2277.62H451.98l259.19-603.53L.02 732.88zm2763.84 768.75h-704.26L2684.65 0l701.69.03-622.5 1501.6zm-519.78 143.72c216.09 0 391.25 175.17 391.25 391.22 0 216.06-175.16 391.23-391.25 391.23-216.06 0-391.19-175.17-391.19-391.23 0-216.05 175.16-391.22 391.19-391.22z" fill="#5f01d1" fill-rule="nonzero"/></svg></span>';
|
|
@@ -318,19 +331,26 @@ function atcb_generate(button, buttonId, data) {
|
|
|
318
331
|
optionItem.addEventListener('click', function() {
|
|
319
332
|
atcb_generate_yahoo(data);
|
|
320
333
|
atcb_close_all();
|
|
321
|
-
}
|
|
334
|
+
});
|
|
322
335
|
break;
|
|
323
336
|
}
|
|
337
|
+
optionItem.addEventListener('keydown', function(event) { // trigger click on enter as well
|
|
338
|
+
if (event.key == 'Enter') {
|
|
339
|
+
this.click();
|
|
340
|
+
}
|
|
341
|
+
});
|
|
324
342
|
});
|
|
325
343
|
// create the background overlay, which also acts as trigger to close any dropdowns
|
|
326
344
|
let bgOverlay = document.createElement('div');
|
|
327
345
|
bgOverlay.id = 'atcb_bgoverlay_' + buttonId;
|
|
328
346
|
bgOverlay.classList.add('atcb_bgoverlay');
|
|
329
|
-
bgOverlay.style.display = 'none';
|
|
347
|
+
bgOverlay.style.display = 'none';
|
|
348
|
+
bgOverlay.tabIndex = 0;
|
|
330
349
|
button.appendChild(bgOverlay);
|
|
331
|
-
bgOverlay.addEventListener('click', atcb_close_all
|
|
350
|
+
bgOverlay.addEventListener('click', atcb_close_all);
|
|
332
351
|
bgOverlay.addEventListener('touchstart', atcb_close_all, {passive: true});
|
|
333
|
-
bgOverlay.addEventListener('
|
|
352
|
+
bgOverlay.addEventListener('mousemove', atcb_close_all);
|
|
353
|
+
bgOverlay.addEventListener('focus', atcb_close_all);
|
|
334
354
|
// update the placeholder class to prevent multiple initializations
|
|
335
355
|
button.classList.remove('atcb');
|
|
336
356
|
button.classList.add('atcb_initialized');
|
|
@@ -372,7 +392,6 @@ function atcb_close() {
|
|
|
372
392
|
document.getElementById('atcb_bgoverlay_' + this.dataset.atcbtn).style.display = 'none';
|
|
373
393
|
}
|
|
374
394
|
|
|
375
|
-
|
|
376
395
|
function atcb_close_all() {
|
|
377
396
|
// get all buttons
|
|
378
397
|
let atcButtons = document.querySelectorAll('.atcb_button');
|
|
@@ -479,7 +498,7 @@ function atcb_generate_ical(data) {
|
|
|
479
498
|
"DTSTAMP:" + formattedDate['start'],
|
|
480
499
|
"DTSTART" + timeslot + ":" + formattedDate['start'],
|
|
481
500
|
"DTEND" + timeslot + ":" + formattedDate['end'],
|
|
482
|
-
"DESCRIPTION:" + data['
|
|
501
|
+
"DESCRIPTION:" + data['description_iCal'].replace(/\n/g, '\\n'),
|
|
483
502
|
"SUMMARY:" + data['name'],
|
|
484
503
|
"LOCATION:" + data['location'],
|
|
485
504
|
"STATUS:CONFIRMED",
|
|
@@ -488,7 +507,7 @@ function atcb_generate_ical(data) {
|
|
|
488
507
|
"END:VEVENT",
|
|
489
508
|
"END:VCALENDAR"
|
|
490
509
|
];
|
|
491
|
-
let dlurl = 'data:text/calendar;base64,'+btoa(ics_lines.join('\r\n'));
|
|
510
|
+
let dlurl = 'data:text/calendar;base64,'+btoa(ics_lines.join('\r\n').replace(/[\u00A0-\u2666]/g, function(c) { return '&#' + c.charCodeAt(0) + ';'; })); // includes a fix to not throw an error with non-Latin1 characters. However, still needs improvement, since it shows up encoded in the iCal file.
|
|
492
511
|
try {
|
|
493
512
|
if (!window.ActiveXObject) {
|
|
494
513
|
let save = document.createElement('a');
|
|
@@ -500,7 +519,7 @@ function atcb_generate_ical(data) {
|
|
|
500
519
|
'bubbles': true,
|
|
501
520
|
'cancelable': false
|
|
502
521
|
});
|
|
503
|
-
save.dispatchEvent(evt);
|
|
522
|
+
save.dispatchEvent(evt);
|
|
504
523
|
(window.URL || window.webkitURL).revokeObjectURL(save.href);
|
|
505
524
|
}
|
|
506
525
|
} catch(e) {
|
|
@@ -521,8 +540,8 @@ function atcb_generate_time(data, style = 'delimiters', targetCal = 'general') {
|
|
|
521
540
|
// Adjust for timezone, if set (see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for either the TZ name or the offset)
|
|
522
541
|
if (data['timeZoneOffset'] != null && data['timeZoneOffset'] != '') {
|
|
523
542
|
// if we have a timezone offset given, consider it
|
|
524
|
-
start = new Date( startDate[
|
|
525
|
-
end = new Date( endDate[
|
|
543
|
+
start = new Date( startDate[0] + '-' + startDate[1] + '-' + startDate[2] + 'T' + data['startTime'] + ':00.000' + data['timeZoneOffset'] );
|
|
544
|
+
end = new Date( endDate[0] + '-' + endDate[1] + '-' + endDate[2] + 'T' + data['endTime'] + ':00.000' + data['timeZoneOffset'] );
|
|
526
545
|
start = start.toISOString().replace('.000', '');
|
|
527
546
|
end = end.toISOString().replace('.000', '');
|
|
528
547
|
if (style == 'clean') {
|
|
@@ -531,11 +550,14 @@ function atcb_generate_time(data, style = 'delimiters', targetCal = 'general') {
|
|
|
531
550
|
}
|
|
532
551
|
} else {
|
|
533
552
|
// if there is no offset, we prepare the time, assuming it is UTC formatted
|
|
534
|
-
start = new Date( startDate[
|
|
535
|
-
end = new Date( endDate[
|
|
553
|
+
start = new Date( startDate[0] + '-' + startDate[1] + '-' + startDate[2] + 'T' + data['startTime'] + ':00.000+00:00' );
|
|
554
|
+
end = new Date( endDate[0] + '-' + endDate[1] + '-' + endDate[2] + 'T' + data['endTime'] + ':00.000+00:00' );
|
|
536
555
|
if (data['timeZone'] != null && data['timeZone'] != '') {
|
|
537
556
|
// if a timezone is given, we adjust dynamically with the modern toLocaleString function
|
|
538
557
|
let utcDate = new Date(start.toLocaleString('en-US', { timeZone: "UTC" }));
|
|
558
|
+
if (data['timeZone'] == 'currentBrowser') {
|
|
559
|
+
data['timeZone'] = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
560
|
+
}
|
|
539
561
|
let tzDate = new Date(start.toLocaleString('en-US', { timeZone: data['timeZone'] }));
|
|
540
562
|
let offset = utcDate.getTime() - tzDate.getTime();
|
|
541
563
|
start.setTime( start.getTime() + offset );
|
|
@@ -550,10 +572,10 @@ function atcb_generate_time(data, style = 'delimiters', targetCal = 'general') {
|
|
|
550
572
|
}
|
|
551
573
|
} else { // would be an allday event then
|
|
552
574
|
allday = true;
|
|
553
|
-
start = new Date( startDate[
|
|
575
|
+
start = new Date( startDate[0], startDate[1] - 1, startDate[2]);
|
|
554
576
|
start.setDate(start.getDate() + 1); // increment the day by 1
|
|
555
577
|
let breakStart = start.toISOString().split('T');
|
|
556
|
-
end = new Date( endDate[
|
|
578
|
+
end = new Date( endDate[0], endDate[1] - 1, endDate[2]);
|
|
557
579
|
if (targetCal == 'google' || targetCal == 'microsoft' || targetCal == 'ical') {
|
|
558
580
|
end.setDate(end.getDate() + 2); // increment the day by 2 for Google Calendar, iCal and Outlook
|
|
559
581
|
} else {
|
|
@@ -573,5 +595,4 @@ function atcb_generate_time(data, style = 'delimiters', targetCal = 'general') {
|
|
|
573
595
|
|
|
574
596
|
|
|
575
597
|
|
|
576
|
-
|
|
577
|
-
export { atcb_init };
|
|
598
|
+
export { atcb_init };
|
package/package.json
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "add-to-calendar-button",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "A convenient JavaScript snippet, which lets you create beautiful buttons, where people can add events to their calendars.",
|
|
5
5
|
"main": "npm_dist/atcb_npm.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"style": "assets/css/atcb.css",
|
|
8
|
-
"scripts": {
|
|
9
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
10
|
-
},
|
|
11
8
|
"repository": {
|
|
12
9
|
"type": "git",
|
|
13
10
|
"url": "git+https://github.com/jekuer/add-to-calendar-button.git"
|
|
@@ -41,5 +38,16 @@
|
|
|
41
38
|
"bugs": {
|
|
42
39
|
"url": "https://github.com/jekuer/add-to-calendar-button/issues"
|
|
43
40
|
},
|
|
44
|
-
"homepage": "https://github.com/jekuer/add-to-calendar-button"
|
|
41
|
+
"homepage": "https://github.com/jekuer/add-to-calendar-button",
|
|
42
|
+
"scripts": {
|
|
43
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
44
|
+
"build": "grunt"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"grunt": "^1.4.1",
|
|
48
|
+
"grunt-contrib-clean": "^2.0.0",
|
|
49
|
+
"grunt-contrib-copy": "^1.0.0",
|
|
50
|
+
"grunt-contrib-cssmin": "^4.0.0",
|
|
51
|
+
"grunt-contrib-uglify": "^5.0.1"
|
|
52
|
+
}
|
|
45
53
|
}
|