The simple answer is to create a JSON file with all your chosen settings in it, put it on the internet somewhere and send a link including that JSON file. Simples.
So, we need to add two more features: one to download the current set of settings as a JSON file and the other to parse a JSON file and configure the settings.
It's fairly simple (these days) to download a file generated on the client. I simply stole an example function from StackOverflow and put it in download.txt. I then added a button and connected the button to a function which calls another to compute the desired settings and then calls the download function.
function initSharing() {
}
function shareJson() {
download("share-calendar.json", JSON.stringify(assemblePropertiesObject()));
}
function assemblePropertiesObject() {
return {};
}
// this function is from @johnpyp on stackoverflow - https://stackoverflow.com/a/45831280Of course, the flaw in this so far is that we haven't actually created the object to store. Fortunately, this is relatively simple: we just look at the controls and obtain the value of each one (I have opted not to save and restore the paper format controls because that usually ends badly).
function download(filename, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
function assemblePropertiesObject() {Obviously, if you want to share this, you either need to give it to someone (by email, thumb drive, carrier pigeon or otherwise) or put it somewhere on the internet where they can find it. Files and URLs are treated differently in JavaScript for security reasons, so we will give them two ways of loading it:
return {
start: start.value,
end: end.value,
firstDay: first.value,
calendars: Object.keys(calendars)
};
}
- From the UI, they can choose a local file and push a button to load it;
- In the UI, they can paste the URL into a text box and push a button to load it;
- They can pass it as an encoded URL as a query parameter, which makes it possible to share the whole URL directly.
First off, let's load the JSON from a file. I think this is basically all vanilla JavaScript and HTML, so I think I'm going to let it pass without comment:
<label for="sharing-file">Load JSON from:</label>
<input type="file" id="sharing-file" onchange="loadJsonFromFile()">
var sharingFile;
function initSharing() {
sharingFile = document.getElementById('sharing-file');
}
function loadJsonFromFile() {It isn't very different to load it from a URL:
sharingFile.files[0].text().then(tx => configureWith(JSON.parse(tx)));
}
function configureWith(json) {
start.value = json.start;
end.value = json.end;
first.value = json.firstDay;
for (var i=0;i<json.calendars.length;i++) {
loadCalendar(json.calendars[i]);
}
}
function loadCalendar(url) {
ajax(url, (status, response) => handleICS(url, status, response));
}
<input type="url" id="sharing-url" placeholder="https://calendar.com/sharing.json">
<input type="button" value="Load shared" onclick="loadSharedJson()">
function loadSharedJson() {And, again, it isn't very different to do the work from the URL itself. We want to do this during page load, so we want to attach it to the onload event. Given that we have already trapped that and called the initSharing method, that seems like the obvious place to attach the call to try and read the parameter.
var from = sharingURL.value;
ajax(from, handleConfig);
}
function handleConfig(status, response) {
if (status / 100 == 2) {
configureWith(JSON.parse(response));
} else {
console.log(status, response);
}
}
function initSharing() {We can use URLSearchParams to decode all the query information, which, in turn, comes from window.location.search. We need (obviously) to check that this parameter exists, and if so, we want to load it in exactly the same way that we did the explicitly provided URL.
sharingFile = document.getElementById('sharing-file');
sharingURL = document.getElementById('sharing-url');
readConfigFromParameter();
}
function readConfigFromParameter() {Everything is now checked in and tagged as PLANNING_CALENDAR_LOAD_SHARED_FROM_PARAMETER.
var params = new URLSearchParams(window.location.search);
if (params.has("config")) {
ajax(params.get("config"), handleConfig);
}
}
I'm going to carry on developing this, because, as I said, it's something I use, and you can see the latest on the head of the master branch of the repository.
It's also live at https://gmmapowell.com/calendar.
No comments:
Post a Comment