├── README.md
├── contract.png
├── index.html
├── manifest.json
├── myscripts.js
├── package.json
├── service-worker.js
└── style.css
/README.md:
--------------------------------------------------------------------------------
1 | # stick-it-notes
2 |
3 | ## How to download the project?
4 |
5 | Click on the clone/download button and download it as zip.
6 |
7 | Extract the zip by right clicking and extract it to your preferred location
8 |
9 | ## How to run the project
10 |
11 | Double click index.html file.
12 |
--------------------------------------------------------------------------------
/contract.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tharunShiv/stick-it-notes/9c5ad249823d59c63a8a7f3790f291c4d7eef7c6/contract.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Sticky notes
6 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
Stick-It Notes
18 |
By Tharun Shiv
19 |
20 |
21 |
43 |
44 |
45 | No Notes Found, Add one!
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Stick-it Notes by Tharun",
3 | "short_name": "Stick-it",
4 | "start_url": "index.html",
5 | "scope": "./",
6 | "icons": [
7 | {
8 | "src": "contract.png",
9 | "sizes": "192x192",
10 | "type": "image/png"
11 | },
12 | {
13 | "src": "contract.png",
14 | "sizes": "512x512",
15 | "type": "image/png"
16 | }
17 | ],
18 | "theme_color": "#ffd31d",
19 | "background_color": "#333",
20 | "display": "standalone"
21 | }
22 |
--------------------------------------------------------------------------------
/myscripts.js:
--------------------------------------------------------------------------------
1 | if ("serviceWorker" in navigator) {
2 | // register service worker
3 | navigator.serviceWorker.register("service-worker.js");
4 | }
5 |
6 | var itemList = document.getElementById("notes");
7 |
8 | itemList.addEventListener("click", removeItem);
9 |
10 | let count = Number(window.localStorage.getItem("count"));
11 | if (!count) {
12 | window.localStorage.setItem("count", "0");
13 | }
14 |
15 | console.log(count);
16 |
17 | let createNote = (noteTitle, noteBody) => {
18 | if (count > 0) {
19 | document.getElementById("no-notes").className = "hidden";
20 | }
21 |
22 | var li = document.createElement("li");
23 | var a = document.createElement("a");
24 | var h2 = document.createElement("h2");
25 | var p = document.createElement("p");
26 | var ul = document.getElementById("notes");
27 |
28 | let xButton = document.createElement("button");
29 | xButton.classList.add("delete");
30 | let xText = document.createTextNode("X");
31 | let h2TN = document.createTextNode(noteTitle);
32 | let pTN = document.createTextNode(noteBody);
33 |
34 | h2.appendChild(h2TN);
35 | p.appendChild(pTN);
36 | xButton.appendChild(xText);
37 |
38 | a.appendChild(h2);
39 | a.appendChild(xButton);
40 | a.appendChild(p);
41 | a.setAttribute("href", "#");
42 |
43 | li.appendChild(a);
44 | ul.appendChild(li);
45 | };
46 |
47 | let createNoteFromInput = (e) => {
48 | e.preventDefault();
49 | var noteTitle = document.getElementById("new-note-title-input").value;
50 | var noteBody = document.getElementById("new-note-body-input").value;
51 |
52 | document.getElementById("new-note-title-input").value = "";
53 | document.getElementById("new-note-body-input").value = "";
54 |
55 | console.log("yes");
56 | if (!noteTitle || !noteBody) {
57 | alert("Both Title and body of the note must be provided");
58 | return;
59 | }
60 | count += 1;
61 | window.localStorage.setItem("count", count);
62 |
63 | while (window.localStorage.getItem(noteTitle)) {
64 | noteTitle = noteTitle + " - 1";
65 | }
66 | window.localStorage.setItem(noteTitle, noteBody);
67 |
68 | createNote(noteTitle, noteBody);
69 | };
70 |
71 | function removeItem(e) {
72 | //console.log('2');
73 | if (e.target.classList.contains("delete")) {
74 | console.log(e);
75 | if (
76 | confirm(
77 | 'Are you sure to delete the "' +
78 | e.target.previousElementSibling.innerText +
79 | '" note?'
80 | )
81 | ) {
82 | //grab the parent
83 | // console.log(e.target.previousSibling.data);
84 | var li = e.target.parentElement.parentElement;
85 |
86 | itemList.removeChild(li);
87 | count -= 1;
88 | window.localStorage.setItem("count", count);
89 | window.localStorage.removeItem(e.target.previousElementSibling.innerText);
90 | if (count < 1) {
91 | document.getElementById("no-notes").className = "";
92 | }
93 | }
94 | }
95 | }
96 |
97 | for (i = 0; i < count + 1; i++) {
98 | console.log(window.localStorage.key(i));
99 | let noteTitle = window.localStorage.key(i);
100 | let noteBody = window.localStorage.getItem(noteTitle);
101 | if (noteTitle !== "count" && noteTitle) {
102 | createNote(noteTitle, noteBody);
103 | }
104 | }
105 |
106 | document
107 | .getElementById("inputForm")
108 | .addEventListener("submit", createNoteFromInput, false);
109 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "stick-it-notes",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "myscripts.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "sw-precache": "sw-precache"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/tharunShiv/stick-it-notes.git"
13 | },
14 | "author": "",
15 | "license": "ISC",
16 | "bugs": {
17 | "url": "https://github.com/tharunShiv/stick-it-notes/issues"
18 | },
19 | "homepage": "https://github.com/tharunShiv/stick-it-notes#readme",
20 | "dependencies": {
21 | "sw-precache": "^5.2.1"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/service-worker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2016 Google Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // DO NOT EDIT THIS GENERATED OUTPUT DIRECTLY!
18 | // This file should be overwritten as part of your build process.
19 | // If you need to extend the behavior of the generated service worker, the best approach is to write
20 | // additional code and include it using the importScripts option:
21 | // https://github.com/GoogleChrome/sw-precache#importscripts-arraystring
22 | //
23 | // Alternatively, it's possible to make changes to the underlying template file and then use that as the
24 | // new base for generating output, via the templateFilePath option:
25 | // https://github.com/GoogleChrome/sw-precache#templatefilepath-string
26 | //
27 | // If you go that route, make sure that whenever you update your sw-precache dependency, you reconcile any
28 | // changes made to this original template file with your modified copy.
29 |
30 | // This generated service worker JavaScript will precache your site's resources.
31 | // The code needs to be saved in a .js file at the top-level of your site, and registered
32 | // from your pages in order to be used. See
33 | // https://github.com/googlechrome/sw-precache/blob/master/demo/app/js/service-worker-registration.js
34 | // for an example of how you can register this script and handle various service worker events.
35 |
36 | /* eslint-env worker, serviceworker */
37 | /* eslint-disable indent, no-unused-vars, no-multiple-empty-lines, max-nested-callbacks, space-before-function-paren, quotes, comma-spacing */
38 | "use strict";
39 |
40 | var precacheConfig = [
41 | ["contract.png", "57f44c7e84e8db553271cc408bbaad22"],
42 | ["index.html", "09cfa67d0f55dd2591b9f9ed72f747a0"],
43 | ["manifest.json", "350a5c214307ff3d11eee259369449b7"],
44 | ["myscripts.js", "298e946e4029dce801f90d9c6ce3cc44"],
45 | ["package.json", "c3e2229df6083112cb941dd02a8eb9e2"],
46 | ["style.css", "265a2c3891fe945c12ce436f7fb85b5e"],
47 | ];
48 | var cacheName =
49 | "sw-precache-v3-sw-precache-" +
50 | (self.registration ? self.registration.scope : "");
51 |
52 | var ignoreUrlParametersMatching = [/^utm_/];
53 |
54 | var addDirectoryIndex = function (originalUrl, index) {
55 | var url = new URL(originalUrl);
56 | if (url.pathname.slice(-1) === "/") {
57 | url.pathname += index;
58 | }
59 | return url.toString();
60 | };
61 |
62 | var cleanResponse = function (originalResponse) {
63 | // If this is not a redirected response, then we don't have to do anything.
64 | if (!originalResponse.redirected) {
65 | return Promise.resolve(originalResponse);
66 | }
67 |
68 | // Firefox 50 and below doesn't support the Response.body stream, so we may
69 | // need to read the entire body to memory as a Blob.
70 | var bodyPromise =
71 | "body" in originalResponse
72 | ? Promise.resolve(originalResponse.body)
73 | : originalResponse.blob();
74 |
75 | return bodyPromise.then(function (body) {
76 | // new Response() is happy when passed either a stream or a Blob.
77 | return new Response(body, {
78 | headers: originalResponse.headers,
79 | status: originalResponse.status,
80 | statusText: originalResponse.statusText,
81 | });
82 | });
83 | };
84 |
85 | var createCacheKey = function (
86 | originalUrl,
87 | paramName,
88 | paramValue,
89 | dontCacheBustUrlsMatching
90 | ) {
91 | // Create a new URL object to avoid modifying originalUrl.
92 | var url = new URL(originalUrl);
93 |
94 | // If dontCacheBustUrlsMatching is not set, or if we don't have a match,
95 | // then add in the extra cache-busting URL parameter.
96 | if (
97 | !dontCacheBustUrlsMatching ||
98 | !url.pathname.match(dontCacheBustUrlsMatching)
99 | ) {
100 | url.search +=
101 | (url.search ? "&" : "") +
102 | encodeURIComponent(paramName) +
103 | "=" +
104 | encodeURIComponent(paramValue);
105 | }
106 |
107 | return url.toString();
108 | };
109 |
110 | var isPathWhitelisted = function (whitelist, absoluteUrlString) {
111 | // If the whitelist is empty, then consider all URLs to be whitelisted.
112 | if (whitelist.length === 0) {
113 | return true;
114 | }
115 |
116 | // Otherwise compare each path regex to the path of the URL passed in.
117 | var path = new URL(absoluteUrlString).pathname;
118 | return whitelist.some(function (whitelistedPathRegex) {
119 | return path.match(whitelistedPathRegex);
120 | });
121 | };
122 |
123 | var stripIgnoredUrlParameters = function (
124 | originalUrl,
125 | ignoreUrlParametersMatching
126 | ) {
127 | var url = new URL(originalUrl);
128 | // Remove the hash; see https://github.com/GoogleChrome/sw-precache/issues/290
129 | url.hash = "";
130 |
131 | url.search = url.search
132 | .slice(1) // Exclude initial '?'
133 | .split("&") // Split into an array of 'key=value' strings
134 | .map(function (kv) {
135 | return kv.split("="); // Split each 'key=value' string into a [key, value] array
136 | })
137 | .filter(function (kv) {
138 | return ignoreUrlParametersMatching.every(function (ignoredRegex) {
139 | return !ignoredRegex.test(kv[0]); // Return true iff the key doesn't match any of the regexes.
140 | });
141 | })
142 | .map(function (kv) {
143 | return kv.join("="); // Join each [key, value] array into a 'key=value' string
144 | })
145 | .join("&"); // Join the array of 'key=value' strings into a string with '&' in between each
146 |
147 | return url.toString();
148 | };
149 |
150 | var hashParamName = "_sw-precache";
151 | var urlsToCacheKeys = new Map(
152 | precacheConfig.map(function (item) {
153 | var relativeUrl = item[0];
154 | var hash = item[1];
155 | var absoluteUrl = new URL(relativeUrl, self.location);
156 | var cacheKey = createCacheKey(absoluteUrl, hashParamName, hash, false);
157 | return [absoluteUrl.toString(), cacheKey];
158 | })
159 | );
160 |
161 | function setOfCachedUrls(cache) {
162 | return cache
163 | .keys()
164 | .then(function (requests) {
165 | return requests.map(function (request) {
166 | return request.url;
167 | });
168 | })
169 | .then(function (urls) {
170 | return new Set(urls);
171 | });
172 | }
173 |
174 | self.addEventListener("install", function (event) {
175 | event.waitUntil(
176 | caches
177 | .open(cacheName)
178 | .then(function (cache) {
179 | return setOfCachedUrls(cache).then(function (cachedUrls) {
180 | return Promise.all(
181 | Array.from(urlsToCacheKeys.values()).map(function (cacheKey) {
182 | // If we don't have a key matching url in the cache already, add it.
183 | if (!cachedUrls.has(cacheKey)) {
184 | var request = new Request(cacheKey, {
185 | credentials: "same-origin",
186 | });
187 | return fetch(request).then(function (response) {
188 | // Bail out of installation unless we get back a 200 OK for
189 | // every request.
190 | if (!response.ok) {
191 | throw new Error(
192 | "Request for " +
193 | cacheKey +
194 | " returned a " +
195 | "response with status " +
196 | response.status
197 | );
198 | }
199 |
200 | return cleanResponse(response).then(function (
201 | responseToCache
202 | ) {
203 | return cache.put(cacheKey, responseToCache);
204 | });
205 | });
206 | }
207 | })
208 | );
209 | });
210 | })
211 | .then(function () {
212 | // Force the SW to transition from installing -> active state
213 | return self.skipWaiting();
214 | })
215 | );
216 | });
217 |
218 | self.addEventListener("activate", function (event) {
219 | var setOfExpectedUrls = new Set(urlsToCacheKeys.values());
220 |
221 | event.waitUntil(
222 | caches
223 | .open(cacheName)
224 | .then(function (cache) {
225 | return cache.keys().then(function (existingRequests) {
226 | return Promise.all(
227 | existingRequests.map(function (existingRequest) {
228 | if (!setOfExpectedUrls.has(existingRequest.url)) {
229 | return cache.delete(existingRequest);
230 | }
231 | })
232 | );
233 | });
234 | })
235 | .then(function () {
236 | return self.clients.claim();
237 | })
238 | );
239 | });
240 |
241 | self.addEventListener("fetch", function (event) {
242 | if (event.request.method === "GET") {
243 | // Should we call event.respondWith() inside this fetch event handler?
244 | // This needs to be determined synchronously, which will give other fetch
245 | // handlers a chance to handle the request if need be.
246 | var shouldRespond;
247 |
248 | // First, remove all the ignored parameters and hash fragment, and see if we
249 | // have that URL in our cache. If so, great! shouldRespond will be true.
250 | var url = stripIgnoredUrlParameters(
251 | event.request.url,
252 | ignoreUrlParametersMatching
253 | );
254 | shouldRespond = urlsToCacheKeys.has(url);
255 |
256 | // If shouldRespond is false, check again, this time with 'index.html'
257 | // (or whatever the directoryIndex option is set to) at the end.
258 | var directoryIndex = "index.html";
259 | if (!shouldRespond && directoryIndex) {
260 | url = addDirectoryIndex(url, directoryIndex);
261 | shouldRespond = urlsToCacheKeys.has(url);
262 | }
263 |
264 | // If shouldRespond is still false, check to see if this is a navigation
265 | // request, and if so, whether the URL matches navigateFallbackWhitelist.
266 | var navigateFallback = "";
267 | if (
268 | !shouldRespond &&
269 | navigateFallback &&
270 | event.request.mode === "navigate" &&
271 | isPathWhitelisted([], event.request.url)
272 | ) {
273 | url = new URL(navigateFallback, self.location).toString();
274 | shouldRespond = urlsToCacheKeys.has(url);
275 | }
276 |
277 | // If shouldRespond was set to true at any point, then call
278 | // event.respondWith(), using the appropriate cache key.
279 | if (shouldRespond) {
280 | event.respondWith(
281 | caches
282 | .open(cacheName)
283 | .then(function (cache) {
284 | return cache
285 | .match(urlsToCacheKeys.get(url))
286 | .then(function (response) {
287 | if (response) {
288 | return response;
289 | }
290 | throw Error(
291 | "The cached response that was expected is missing."
292 | );
293 | });
294 | })
295 | .catch(function (e) {
296 | // Fall back to just fetch()ing the request if some unexpected error
297 | // prevented the cached response from being valid.
298 | console.warn(
299 | 'Couldn\'t serve response for "%s" from cache: %O',
300 | event.request.url,
301 | e
302 | );
303 | return fetch(event.request);
304 | })
305 | );
306 | }
307 | }
308 | });
309 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | body {
7 | font-family: arial, sans-serif;
8 | font-size: 100%;
9 | margin: 3em;
10 | background: #333;
11 | color: #fff;
12 | }
13 |
14 | #heading {
15 | position: sticky;
16 | top: 0;
17 | background-color: #333;
18 | z-index: 7;
19 | padding: 15px 0px;
20 | margin-left: 15px;
21 | }
22 |
23 | #no-notes {
24 | padding: 100px 0px;
25 | text-align: center;
26 | }
27 |
28 | #ts {
29 | color: #ffd31d;
30 | }
31 |
32 | .inputText {
33 | padding: 10px;
34 | border-radius: 5px;
35 | border: 2px solid #ffd31d;
36 | width: 30%;
37 | margin: 15px;
38 | outline: none;
39 | }
40 |
41 | .hidden {
42 | display: none;
43 | }
44 |
45 | .btn {
46 | padding: 10px;
47 | border-radius: 20px;
48 | border: 2px solid #ffd31d;
49 | background-color: #ffd31d;
50 | color: #333;
51 | cursor: pointer;
52 | outline: none;
53 | -webkit-tap-highlight-color: transparent;
54 | }
55 |
56 | .btn:active {
57 | border: 2px solid #333;
58 | box-shadow: inset 0 0 5px #000000;
59 | }
60 |
61 | h2,
62 | p {
63 | font-size: 100%;
64 | font-weight: normal;
65 | }
66 |
67 | ul,
68 | li {
69 | list-style: none;
70 | }
71 |
72 | ul {
73 | overflow: hidden;
74 | padding: 3em 1em;
75 | }
76 |
77 | ul li a {
78 | text-decoration: none;
79 | color: #000;
80 | background: #ffd31d;
81 | display: block;
82 | height: 10em;
83 | width: 10em;
84 | padding: 1em;
85 | box-shadow: 5px 5px 7px rgba(33, 33, 33, 0.7);
86 | }
87 |
88 | ul li {
89 | margin: 1em;
90 | float: left;
91 | position: relative;
92 | }
93 |
94 | ul li h2 {
95 | font-size: 1.2rem;
96 | font-weight: bold;
97 | padding-bottom: 10px;
98 | }
99 |
100 | ul li p {
101 | font-family: "Reenie Beanie", cursive;
102 | font-size: 1.1rem;
103 | }
104 |
105 | .delete {
106 | float: right;
107 | position: absolute;
108 | top: 0;
109 | right: 0;
110 | width: 30px;
111 | height: 30px;
112 | background-color: red;
113 | border: 4px double white;
114 | font-weight: bold;
115 | cursor: pointer;
116 | }
117 |
118 | ul li a {
119 | transform: rotate(-6deg);
120 | -moz-transform: rotate(-6deg);
121 | cursor: default;
122 | }
123 |
124 | ul li:nth-child(even) a {
125 | transform: rotate(4deg);
126 | -moz-transform: rotate(4deg);
127 | position: relative;
128 | top: 5px;
129 | background: #ff5733;
130 | }
131 |
132 | ul li:nth-child(3n) a {
133 | transform: rotate(-3deg);
134 | -moz-transform: rotate(-3deg);
135 | position: relative;
136 | top: -5px;
137 | background: #77d8d8;
138 | }
139 |
140 | ul li:nth-child(5n) a {
141 | transform: rotate(5deg);
142 | -moz-transform: rotate(5deg);
143 | position: relative;
144 | top: -10px;
145 | }
146 |
147 | ul li a:hover,
148 | ul li a:focus {
149 | box-shadow: 10px 10px 7px rgba(0, 0, 0, 0.7);
150 | -moz-box-shadow: 10px 10px 7px rgba(0, 0, 0, 0.7);
151 | transform: scale(1.25);
152 | -moz-transform: scale(1.25);
153 | position: relative;
154 | z-index: 5;
155 | }
156 |
157 | ol {
158 | text-align: center;
159 | }
160 |
161 | ol li {
162 | display: inline;
163 | padding-right: 1em;
164 | }
165 |
166 | ol li a {
167 | color: #fff;
168 | }
169 |
170 | @media only screen and (max-width: 600px) {
171 | body {
172 | margin-top: 1em;
173 | }
174 | #new-note-title-input,
175 | #new-note-body-input {
176 | display: block;
177 | width: 90%;
178 | margin-left: 0px;
179 | }
180 |
181 | #heading {
182 | margin-left: 0px;
183 | }
184 |
185 | .btn {
186 | margin-left: 0px;
187 | }
188 | }
189 |
--------------------------------------------------------------------------------