├── .github
└── FUNDING.yml
├── .gitignore
├── Gifs
├── gridview.gif
├── instasearch.gif
├── sorting.gif
├── sudoku.gif
└── todo.gif
├── Gridview
├── app.js
├── images
│ ├── a.jpg
│ ├── b.jpg
│ ├── c.jpg
│ ├── d.jpg
│ └── e.jpg
├── index.html
└── style.css
├── Instant search
├── app.js
├── index.html
└── style.css
├── LICENSE.MD
├── README.md
├── Sorting
├── app.js
├── index.html
├── sorting.js
└── style.css
├── Sudoku
├── app.js
├── fail.gif
├── index.html
├── style.css
├── success.gif
└── sudoku.js
└── Todo list application
├── app.js
├── index.html
└── style.css
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: https://paypal.me/fbonizzi?locale.x=it_IT
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015/2017 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # Visual Studio 2017 auto generated files
33 | Generated\ Files/
34 |
35 | # MSTest test Results
36 | [Tt]est[Rr]esult*/
37 | [Bb]uild[Ll]og.*
38 |
39 | # NUNIT
40 | *.VisualState.xml
41 | TestResult.xml
42 |
43 | # Build Results of an ATL Project
44 | [Dd]ebugPS/
45 | [Rr]eleasePS/
46 | dlldata.c
47 |
48 | # Benchmark Results
49 | BenchmarkDotNet.Artifacts/
50 |
51 | # .NET Core
52 | project.lock.json
53 | project.fragment.lock.json
54 | artifacts/
55 | **/Properties/launchSettings.json
56 |
57 | # StyleCop
58 | StyleCopReport.xml
59 |
60 | # Files built by Visual Studio
61 | *_i.c
62 | *_p.c
63 | *_i.h
64 | *.ilk
65 | *.meta
66 | *.obj
67 | *.iobj
68 | *.pch
69 | *.pdb
70 | *.ipdb
71 | *.pgc
72 | *.pgd
73 | *.rsp
74 | *.sbr
75 | *.tlb
76 | *.tli
77 | *.tlh
78 | *.tmp
79 | *.tmp_proj
80 | *.log
81 | *.vspscc
82 | *.vssscc
83 | .builds
84 | *.pidb
85 | *.svclog
86 | *.scc
87 |
88 | # Chutzpah Test files
89 | _Chutzpah*
90 |
91 | # Visual C++ cache files
92 | ipch/
93 | *.aps
94 | *.ncb
95 | *.opendb
96 | *.opensdf
97 | *.sdf
98 | *.cachefile
99 | *.VC.db
100 | *.VC.VC.opendb
101 |
102 | # Visual Studio profiler
103 | *.psess
104 | *.vsp
105 | *.vspx
106 | *.sap
107 |
108 | # Visual Studio Trace Files
109 | *.e2e
110 |
111 | # TFS 2012 Local Workspace
112 | $tf/
113 |
114 | # Guidance Automation Toolkit
115 | *.gpState
116 |
117 | # ReSharper is a .NET coding add-in
118 | _ReSharper*/
119 | *.[Rr]e[Ss]harper
120 | *.DotSettings.user
121 |
122 | # JustCode is a .NET coding add-in
123 | .JustCode
124 |
125 | # TeamCity is a build add-in
126 | _TeamCity*
127 |
128 | # DotCover is a Code Coverage Tool
129 | *.dotCover
130 |
131 | # AxoCover is a Code Coverage Tool
132 | .axoCover/*
133 | !.axoCover/settings.json
134 |
135 | # Visual Studio code coverage results
136 | *.coverage
137 | *.coveragexml
138 |
139 | # NCrunch
140 | _NCrunch_*
141 | .*crunch*.local.xml
142 | nCrunchTemp_*
143 |
144 | # MightyMoose
145 | *.mm.*
146 | AutoTest.Net/
147 |
148 | # Web workbench (sass)
149 | .sass-cache/
150 |
151 | # Installshield output folder
152 | [Ee]xpress/
153 |
154 | # DocProject is a documentation generator add-in
155 | DocProject/buildhelp/
156 | DocProject/Help/*.HxT
157 | DocProject/Help/*.HxC
158 | DocProject/Help/*.hhc
159 | DocProject/Help/*.hhk
160 | DocProject/Help/*.hhp
161 | DocProject/Help/Html2
162 | DocProject/Help/html
163 |
164 | # Click-Once directory
165 | publish/
166 |
167 | # Publish Web Output
168 | *.[Pp]ublish.xml
169 | *.azurePubxml
170 | # Note: Comment the next line if you want to checkin your web deploy settings,
171 | # but database connection strings (with potential passwords) will be unencrypted
172 | *.pubxml
173 | *.publishproj
174 |
175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
176 | # checkin your Azure Web App publish settings, but sensitive information contained
177 | # in these scripts will be unencrypted
178 | PublishScripts/
179 |
180 | # NuGet Packages
181 | *.nupkg
182 | # The packages folder can be ignored because of Package Restore
183 | **/[Pp]ackages/*
184 | # except build/, which is used as an MSBuild target.
185 | !**/[Pp]ackages/build/
186 | # Uncomment if necessary however generally it will be regenerated when needed
187 | #!**/[Pp]ackages/repositories.config
188 | # NuGet v3's project.json files produces more ignorable files
189 | *.nuget.props
190 | *.nuget.targets
191 |
192 | # Microsoft Azure Build Output
193 | csx/
194 | *.build.csdef
195 |
196 | # Microsoft Azure Emulator
197 | ecf/
198 | rcf/
199 |
200 | # Windows Store app package directories and files
201 | AppPackages/
202 | BundleArtifacts/
203 | Package.StoreAssociation.xml
204 | _pkginfo.txt
205 | *.appx
206 |
207 | # Visual Studio cache files
208 | # files ending in .cache can be ignored
209 | *.[Cc]ache
210 | # but keep track of directories ending in .cache
211 | !*.[Cc]ache/
212 |
213 | # Others
214 | ClientBin/
215 | ~$*
216 | *~
217 | *.dbmdl
218 | *.dbproj.schemaview
219 | *.jfm
220 | *.pfx
221 | *.publishsettings
222 | orleans.codegen.cs
223 |
224 | # Including strong name files can present a security risk
225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
226 | #*.snk
227 |
228 | # Since there are multiple workflows, uncomment next line to ignore bower_components
229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
230 | #bower_components/
231 |
232 | # RIA/Silverlight projects
233 | Generated_Code/
234 |
235 | # Backup & report files from converting an old project file
236 | # to a newer Visual Studio version. Backup files are not needed,
237 | # because we have git ;-)
238 | _UpgradeReport_Files/
239 | Backup*/
240 | UpgradeLog*.XML
241 | UpgradeLog*.htm
242 | ServiceFabricBackup/
243 | *.rptproj.bak
244 |
245 | # SQL Server files
246 | *.mdf
247 | *.ldf
248 | *.ndf
249 |
250 | # Business Intelligence projects
251 | *.rdl.data
252 | *.bim.layout
253 | *.bim_*.settings
254 | *.rptproj.rsuser
255 |
256 | # Microsoft Fakes
257 | FakesAssemblies/
258 |
259 | # GhostDoc plugin setting file
260 | *.GhostDoc.xml
261 |
262 | # Node.js Tools for Visual Studio
263 | .ntvs_analysis.dat
264 | node_modules/
265 |
266 | # Visual Studio 6 build log
267 | *.plg
268 |
269 | # Visual Studio 6 workspace options file
270 | *.opt
271 |
272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
273 | *.vbw
274 |
275 | # Visual Studio LightSwitch build output
276 | **/*.HTMLClient/GeneratedArtifacts
277 | **/*.DesktopClient/GeneratedArtifacts
278 | **/*.DesktopClient/ModelManifest.xml
279 | **/*.Server/GeneratedArtifacts
280 | **/*.Server/ModelManifest.xml
281 | _Pvt_Extensions
282 |
283 | # Paket dependency manager
284 | .paket/paket.exe
285 | paket-files/
286 |
287 | # FAKE - F# Make
288 | .fake/
289 |
290 | # JetBrains Rider
291 | .idea/
292 | *.sln.iml
293 |
294 | # CodeRush
295 | .cr/
296 |
297 | # Python Tools for Visual Studio (PTVS)
298 | __pycache__/
299 | *.pyc
300 |
301 | # Cake - Uncomment if you are using it
302 | # tools/**
303 | # !tools/packages.config
304 |
305 | # Tabs Studio
306 | *.tss
307 |
308 | # Telerik's JustMock configuration file
309 | *.jmconfig
310 |
311 | # BizTalk build output
312 | *.btp.cs
313 | *.btm.cs
314 | *.odx.cs
315 | *.xsd.cs
316 |
317 | # OpenCover UI analysis results
318 | OpenCover/
319 |
320 | # Azure Stream Analytics local run output
321 | ASALocalRun/
322 |
323 | # MSBuild Binary and Structured Log
324 | *.binlog
325 |
326 | # NVidia Nsight GPU debugger configuration file
327 | *.nvuser
328 |
329 | # MFractors (Xamarin productivity tool) working folder
330 | .mfractor/
331 |
--------------------------------------------------------------------------------
/Gifs/gridview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrancescoBonizzi/VueJs-Experiments/34c2386b461e326c77d04778f06244a7ca406853/Gifs/gridview.gif
--------------------------------------------------------------------------------
/Gifs/instasearch.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrancescoBonizzi/VueJs-Experiments/34c2386b461e326c77d04778f06244a7ca406853/Gifs/instasearch.gif
--------------------------------------------------------------------------------
/Gifs/sorting.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrancescoBonizzi/VueJs-Experiments/34c2386b461e326c77d04778f06244a7ca406853/Gifs/sorting.gif
--------------------------------------------------------------------------------
/Gifs/sudoku.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrancescoBonizzi/VueJs-Experiments/34c2386b461e326c77d04778f06244a7ca406853/Gifs/sudoku.gif
--------------------------------------------------------------------------------
/Gifs/todo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrancescoBonizzi/VueJs-Experiments/34c2386b461e326c77d04778f06244a7ca406853/Gifs/todo.gif
--------------------------------------------------------------------------------
/Gridview/app.js:
--------------------------------------------------------------------------------
1 | var cartData = {
2 | columns: [
3 | "Id",
4 | "Quantity",
5 | "Name",
6 | "Seller",
7 | "Price"
8 | ],
9 | data: [
10 | { Id: 1, Quantity: 1, Name: "SSD Super Fast 1TB", Seller: "Elektro Sell", Price: "123.00$", ImagePath: "images/a.jpg" },
11 | { Id: 2, Quantity: 1, Name: "Bottle of 1998 Barolo", Seller: "Very Nice Shop", Price: "50.00$", ImagePath: "images/b.jpg" },
12 | { Id: 3, Quantity: 3, Name: "Car Radio Player", Seller: "Elektro Sell", Price: "78.10$", ImagePath: "images/c.jpg" },
13 | { Id: 4, Quantity: 1, Name: "Video Game Console Super Powerful", Seller: "Elektro Sell", Price: "99.99$", ImagePath: "images/d.jpg" },
14 | { Id: 5, Quantity: 5, Name: "Book about vegetarianism", Seller: "Your Library", Price: "41.20$", ImagePath: "images/e.jpg" }
15 | ]
16 | };
17 |
18 | var booksData = {
19 | columns: [
20 | "Id",
21 | "Name",
22 | "Author",
23 | "Theme",
24 | "Rating"
25 | ],
26 | data: [
27 | { Id: 1, Name: "The look of love", Author: "George Blue", Theme: "Drama", Rating: "*****", ImagePath: "images/a.jpg" },
28 | { Id: 2, Name: "20 vegetarian dishes", Author: "Francesco Bonizzi", Theme: "Cooking", Rating: "****", ImagePath: "images/b.jpg" },
29 | { Id: 3, Name: "How to be happy", Author: "Asdrubale Anselmi", Theme: "Self help", Rating: "*", ImagePath: "images/c.jpg" },
30 | { Id: 4, Name: "The last bee", Author: "John Dorian", Theme: "Nature", Rating: "****", ImagePath: "images/d.jpg" }
31 | ]
32 | };
33 |
34 | var gridviewApp = new Vue({
35 |
36 | el: '#app-gridview',
37 |
38 | data: {
39 | gridData: cartData,
40 | buttonSwitchViewText: "Switch to ListView",
41 | buttonSwitchDataText: "Switch to books data",
42 | isGridView: true,
43 | isBookData: false
44 | },
45 |
46 | methods: {
47 |
48 | switchView: function() {
49 |
50 | if (this.isGridView) {
51 | this.buttonSwitchViewText = "Switch to GridView";
52 | }
53 | else {
54 | this.buttonSwitchViewText = "Switch to ListView";
55 | }
56 |
57 | this.isGridView = !this.isGridView;
58 | },
59 |
60 | switchData: function () {
61 |
62 | if (this.isBookData) {
63 | this.buttonSwitchDataText = "Switch to books data";
64 | this.gridData = cartData;
65 | }
66 | else {
67 | this.buttonSwitchDataText = "Switch to shop data";
68 | this.gridData = booksData;
69 | }
70 |
71 | this.isBookData = !this.isBookData;
72 | }
73 |
74 | }
75 |
76 | });
--------------------------------------------------------------------------------
/Gridview/images/a.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrancescoBonizzi/VueJs-Experiments/34c2386b461e326c77d04778f06244a7ca406853/Gridview/images/a.jpg
--------------------------------------------------------------------------------
/Gridview/images/b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrancescoBonizzi/VueJs-Experiments/34c2386b461e326c77d04778f06244a7ca406853/Gridview/images/b.jpg
--------------------------------------------------------------------------------
/Gridview/images/c.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrancescoBonizzi/VueJs-Experiments/34c2386b461e326c77d04778f06244a7ca406853/Gridview/images/c.jpg
--------------------------------------------------------------------------------
/Gridview/images/d.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrancescoBonizzi/VueJs-Experiments/34c2386b461e326c77d04778f06244a7ca406853/Gridview/images/d.jpg
--------------------------------------------------------------------------------
/Gridview/images/e.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrancescoBonizzi/VueJs-Experiments/34c2386b461e326c77d04778f06244a7ca406853/Gridview/images/e.jpg
--------------------------------------------------------------------------------
/Gridview/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Vue.js in action
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | Gridview - Listview
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
{{ row[name] }}
39 |
40 |
41 |
42 |
43 |
44 |
![]()
45 |
46 |
47 |
{{ name }}
48 |
{{ row[name] }}
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/Gridview/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | input:focus,
7 | select:focus,
8 | textarea:focus,
9 | button:focus {
10 | outline: none;
11 | }
12 |
13 | html {
14 | overflow-y:scroll;
15 | }
16 |
17 | body {
18 | display: grid;
19 | grid-template-rows: 120px 1fr;
20 | font-family: 'Lato', sans-serif;
21 | margin-bottom: 10px;
22 | background: #f6f6f6;
23 | }
24 |
25 | header {
26 | display: grid;
27 | color: black;
28 | box-shadow: 0 0 1px rgba(0,0,0,0.25);
29 | background: white;
30 | }
31 |
32 | header h1 {
33 | place-self: center;
34 | font-size: 42px;
35 | font-weight: lighter;
36 | }
37 |
38 | #app-gridview {
39 | place-self: center;
40 | margin-top: 30px;
41 | display: grid;
42 | justify-items: center;
43 | }
44 |
45 | .grid-wrapper {
46 | display: table;
47 | border: 4px solid #336699;
48 | border-radius: 6px;
49 | transition: all ease 0.5s;
50 | }
51 |
52 | .list-wrapper {
53 | transition: all ease 0.5s;
54 | }
55 |
56 | .grid-header {
57 | font-weight: bold;
58 | background: #336699;
59 | color: white;
60 | border-bottom: 4px solid #f6f6f6;
61 | }
62 |
63 | .grid-row {
64 | display: table-row;
65 | }
66 |
67 | .grid-row > div {
68 | display: table-cell;
69 | padding: 10px 20px;
70 | }
71 |
72 | .grid-wrapper > div:nth-child(even) {
73 | background: #f6f6f6;
74 | transition: all ease 0.4s;
75 | }
76 |
77 | .grid-wrapper > div:nth-child(odd) {
78 | background: #fafafa;
79 | transition: all ease 0.4s;
80 | }
81 |
82 | .grid-wrapper > div:hover {
83 | background: #a9d6ff;
84 | transition: all ease 0.4s;
85 | }
86 |
87 | .list-row {
88 | padding: 10px;
89 | margin: 10px;
90 | background: white;
91 | border-radius: 6px;
92 | -webkit-box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.37);
93 | -moz-box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.37);
94 | box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.37);
95 | display: grid;
96 | grid-template-columns: auto 1fr;
97 | width: 600px;
98 | }
99 |
100 | .list-row-item {
101 | display: grid;
102 | grid-template-columns: 150px 1fr;
103 | padding: 4px;
104 | transition: all 0.5s;
105 | }
106 |
107 | .list-property {
108 | display: flex;
109 | flex-direction: column;
110 | justify-content: space-between;
111 | }
112 |
113 | .list-property-name {
114 | font-weight: bold;
115 | transition: all 0.5s;
116 | }
117 |
118 | .list-image {
119 | width: 150px;
120 | border-radius: 6px;
121 | margin-right: 10px;
122 | }
123 |
124 | .button {
125 | display: inline-block;
126 | border-radius: 6px;
127 | background-color: #0095ff;
128 | border: none;
129 | color: #FFFFFF;
130 | text-align: center;
131 | font-size: 16px;
132 | padding: 10px;
133 | width: 230px;
134 | transition: all 0.5s;
135 | cursor: pointer;
136 | margin: 0px 0px 25px 0px;
137 | }
138 |
139 | .button span {
140 | cursor: pointer;
141 | display: inline-block;
142 | position: relative;
143 | transition: 0.5s;
144 | }
145 |
146 | .button span:after {
147 | content: '\00bb';
148 | position: absolute;
149 | opacity: 0;
150 | top: 0;
151 | right: -20px;
152 | transition: 0.5s;
153 | }
154 |
155 | .button:hover span {
156 | padding-right: 25px;
157 | }
158 |
159 | .button:hover span:after {
160 | opacity: 1;
161 | right: 0;
162 | }
--------------------------------------------------------------------------------
/Instant search/app.js:
--------------------------------------------------------------------------------
1 | var instasearchApp = new Vue({
2 |
3 | el: '#app-instasearch',
4 |
5 | data: {
6 | authorNameSearchString: "",
7 | photoFeed: null
8 | },
9 |
10 | mounted() {
11 | axios
12 | .get('https://picsum.photos/v2/list?page=2&limit=10')
13 | .then(response => {
14 | this.photoFeed = response.data;
15 | })
16 | .catch(error => console.log(error))
17 | },
18 |
19 | computed: {
20 |
21 | filteredPhotoFeed: function () {
22 |
23 | var photos = this.photoFeed;
24 | var authorNameSearchString = this.authorNameSearchString;
25 |
26 | if(!authorNameSearchString){
27 | return photos;
28 | }
29 |
30 | searchString = authorNameSearchString.trim().toLowerCase();
31 |
32 | photos = photos.filter(function(item){
33 | if(item.author.toLowerCase().indexOf(authorNameSearchString) !== -1){
34 | return item;
35 | }
36 | })
37 |
38 | return photos;
39 | }
40 | }
41 |
42 | });
--------------------------------------------------------------------------------
/Instant search/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Vue.js in action
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | {{ photo.author }}
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/Instant search/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | input:focus,
7 | select:focus,
8 | textarea:focus,
9 | button:focus {
10 | outline: none;
11 | }
12 |
13 | html {
14 | overflow-y:scroll;
15 | }
16 |
17 | body {
18 | display: grid;
19 | grid-template-rows: 150px 1fr;
20 | background-color: #f5f5f5;
21 | font-family: 'Roboto Slab', serif;
22 | margin-bottom: 10px;
23 | }
24 |
25 | header {
26 | display: grid;
27 | color: white;
28 | background: #6D25BC;
29 | }
30 |
31 | header h1 {
32 | place-self: center;
33 | font-size: 42px;
34 | }
35 |
36 | #app-instasearch {
37 | place-self: center;
38 | margin-top: 30px;
39 | width: 600px;
40 | }
41 |
42 | .input-container {
43 | border-radius: 5px;
44 | background: #677482;
45 | padding: 10px;
46 | }
47 |
48 | .input-container input {
49 | border: none;
50 | background: transparent;
51 | color: white;
52 | padding: 6px 15px;
53 | font-size: 18px;
54 | }
55 |
56 | ::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
57 | color: #a6b0ba;
58 | opacity: 1; /* Firefox */
59 | }
60 |
61 | .photo {
62 | list-style: none;
63 | display: grid;
64 | grid-template-columns: 200px auto;
65 | margin-top: 20px;
66 | align-items: center;
67 | background-color: #e9edf0;
68 | padding: 30px 50px;
69 | border-radius: 5px;
70 | border: 1px solid #e3e3e3;
71 | }
72 |
73 | .author {
74 | font-size: 25px;
75 | margin-left: 20px;
76 | color: #75818e;
77 | }
78 |
79 | .photo img {
80 | border-radius: 5px;
81 | width: 200px;
82 | }
83 |
84 | .photo-animated {
85 | transition: all 0.5s;
86 | }
87 |
88 | .list-animation-enter, .list-animation-leave-to {
89 | opacity: 0;
90 | transform: translateY(30px);
91 | }
92 |
93 | .list-animation-leave-active {
94 | position: absolute;
95 | }
--------------------------------------------------------------------------------
/LICENSE.MD:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Francesco
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, 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,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # VueJs-Experiments
2 | This repository contains some experiments with Vue.js framework.
3 |
4 |
5 |
6 | ## Todo list application
7 |
8 | An interactive to-do list with style and animations: add a todo item, set completed, remove it
9 |
10 | [The article with step-by-step tutorial](https://medium.com/better-programming/how-to-build-your-first-vue-js-application-469ed1ec4fde)
11 |
12 | 
13 |
14 |
15 |
16 | ## Instant search application
17 |
18 | Fetch data from a Web API and add a dynamic filter with computed properties
19 |
20 | [The article with step-by-step tutorial](https://medium.com/better-programming/instant-search-with-vue-js-and-axios-5b78a3a59f01)
21 |
22 | 
23 |
24 |
25 |
26 | ## Switchable GridView ListView
27 |
28 | Represent any array of data and switch between visualizations
29 |
30 | [The article with step-by-step tutorial](https://medium.com/better-programming/switching-between-grid-view-and-list-view-with-vue-js-90fcd578bbdf)
31 |
32 | 
33 |
34 |
35 |
36 | ## Sudoku
37 |
38 | How to code this simple game from A to Z
39 |
40 | [The article with step-by-step tutorial](https://medium.com/better-programming/how-to-build-sudoku-in-vue-js-f97509b523ed)
41 |
42 | 
43 |
44 | ## Visual representation of sorting Algorithms
45 |
46 | A little guide to animations with Vue.js
47 |
48 | [The article with step-by-step tutorial](https://medium.com/better-programming/a-visual-representation-of-sorting-algorithms-with-vue-js-f79b903fabbe)
49 |
50 | 
51 |
--------------------------------------------------------------------------------
/Sorting/app.js:
--------------------------------------------------------------------------------
1 | var sortingApp = new Vue({
2 |
3 | el: '#app-sorting',
4 |
5 | data: {
6 |
7 | arrayToBeSorted: [1, 2, 3, 4, 5, 6, 7, 8],
8 | isManipulatingArray: false,
9 |
10 | shuffleButtonText: "Shuffle!",
11 |
12 | sortAlgorithms: [
13 | { name: "Bubble sort", fn: bubbleSort },
14 | { name: "Selection sort", fn: selectionSort },
15 | { name: "Insertion sort", fn: insertionSort }
16 | ]
17 |
18 | },
19 |
20 | methods: {
21 |
22 | shuffle: function () {
23 | this.isManipulatingArray = true;
24 | shuffle(this.arrayToBeSorted).then(() => this.isManipulatingArray = false);
25 | },
26 |
27 | sort: function (sortAlgorithm) {
28 | this.isManipulatingArray = true;
29 | sortAlgorithm.fn(this.arrayToBeSorted).then(() => this.isManipulatingArray = false);
30 | }
31 |
32 | }
33 |
34 | });
35 |
--------------------------------------------------------------------------------
/Sorting/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Vue.js in action
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | {{ num }}
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Sorting/sorting.js:
--------------------------------------------------------------------------------
1 | function sleep() {
2 | return new Promise(resolve => setTimeout(resolve, 550));
3 | }
4 |
5 | function arraySetWithoutIndexes(array, index, value) {
6 | array.splice(index, 1, value);
7 | }
8 |
9 | function arraySwap(array, indexA, indexB) {
10 |
11 | var x = array[indexA];
12 | arraySetWithoutIndexes(array, indexA, array[indexB]);
13 | arraySetWithoutIndexes(array, indexB, x);
14 |
15 | }
16 |
17 | async function shuffle(a) {
18 |
19 | var j, i;
20 | for (i = a.length - 1; i > 0; i--) {
21 | j = Math.floor(Math.random() * (i + 1));
22 | arraySwap(a, i, j);
23 | await sleep();
24 | }
25 |
26 | }
27 |
28 | async function bubbleSort(a) {
29 |
30 | var len = a.length;
31 | for (var i = len - 1; i >= 0; i--) {
32 | for (var j = 1; j <= i; j++) {
33 | if (a[j - 1] > a[j]) {
34 | arraySwap(a, j - 1, j);
35 | await sleep();
36 | }
37 | }
38 | }
39 |
40 | }
41 |
42 | async function selectionSort(a) {
43 |
44 | var minIdx, temp,
45 | len = a.length;
46 |
47 | for (var i = 0; i < len; i++) {
48 | minIdx = i;
49 | for (var j = i + 1; j < len; j++) {
50 | if (a[j] < a[minIdx]) {
51 | minIdx = j;
52 | }
53 | }
54 |
55 | arraySwap(a, i, minIdx);
56 | await sleep();
57 | }
58 |
59 | }
60 |
61 | async function insertionSort(a) {
62 |
63 | var i, len = a.length, el, j;
64 |
65 | for (i = 1; i < len; i++) {
66 | el = a[i];
67 | j = i;
68 |
69 | while (j > 0 && a[j - 1] > el) {
70 | a[j] = a[j - 1];
71 | j--;
72 | }
73 |
74 | arraySetWithoutIndexes(a, j, el);
75 | await sleep();
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/Sorting/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | input:focus,
7 | select:focus,
8 | textarea:focus,
9 | button:focus {
10 | outline: none;
11 | }
12 |
13 | html {
14 | overflow-y: scroll;
15 | }
16 |
17 | body {
18 | display: grid;
19 | grid-template-rows: 80px 1fr;
20 | background-color: #fdef78;
21 | font-family: 'Roboto Slab', serif;
22 | margin-bottom: 10px;
23 | }
24 |
25 | header {
26 | display: grid;
27 | color: white;
28 | background: #2f2e2a;
29 | }
30 |
31 | header h1 {
32 | place-self: center;
33 | font-size: 42px;
34 | }
35 |
36 | #app-sorting {
37 | place-self: center;
38 | margin-top: 30px;
39 | display: grid;
40 | justify-items: center;
41 | align-items: center;
42 | grid-template-rows: 60px 1fr;
43 | justify-items: center;
44 | }
45 |
46 | .buttons-container {
47 | height: 60px;
48 | }
49 |
50 | .array-to-be-sorted {
51 | margin: 50px;
52 | display: grid;
53 | grid-template-columns: repeat(8, auto);
54 | justify-items: center;
55 | align-items: center;
56 | }
57 |
58 | .even {
59 | background-color: #f96167;
60 | }
61 |
62 | .odd {
63 | background-color: #2f2e2a;
64 | }
65 |
66 | .list-item {
67 | display: grid;
68 | justify-items: center;
69 | align-items: center;
70 | padding: 15px;
71 | width: 50px;
72 | height: 50px;
73 | border-radius: 100px;
74 | color: white;
75 | margin: 10px;
76 | font-size: 30px;
77 | font-family: 'Roboto Slab', serif;
78 | font-weight: bold;
79 | text-align: center;
80 | }
81 |
82 | .list-animation-item {
83 | transition: all ease 0.5s;
84 | }
85 |
86 | .fade-enter-active, .fade-leave-active {
87 | transition: all ease 1s;
88 | }
89 |
90 | .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
91 | opacity: 0;
92 | transform: translateY(-30px) scale(0.9);
93 | }
94 |
95 | .button {
96 | box-shadow: 0px 1px 0px 0px #f0f7fa;
97 | background-color: #33bdef;
98 | border-radius: 6px;
99 | border: 1px solid #057fd0;
100 | display: inline-block;
101 | cursor: pointer;
102 | color: #ffffff;
103 | font-family: Arial;
104 | font-size: 15px;
105 | font-weight: bold;
106 | padding: 6px 24px;
107 | text-decoration: none;
108 | text-shadow: 0px -1px 0px #5b6178;
109 | margin: 10px;
110 | }
111 |
112 | .button:hover {
113 | background-color: #019ad2;
114 | }
115 |
116 | .button:active {
117 | position: relative;
118 | top: 1px;
119 | }
120 |
121 |
--------------------------------------------------------------------------------
/Sudoku/app.js:
--------------------------------------------------------------------------------
1 | var sudokuApp = new Vue({
2 |
3 | el: '#app-sudoku',
4 |
5 | data: {
6 |
7 | sudokuMatrix: [],
8 | initializeGameText: "Start!",
9 | evaluateGameText: "Verify!",
10 | answerImage: "",
11 | isGameStarted: false,
12 | showAnswer: false
13 | },
14 |
15 | methods: {
16 |
17 | initializeGame() {
18 |
19 | var defaultSudokuMatrix = [
20 | [{ num: 5 }, { num: 3 }, { num: 4 }, { num: 6 }, { num: 7 }, { num: 8 }, { num: 9 }, { num: 1 }, { num: 2 }],
21 | [{ num: 6 }, { num: 7 }, { num: 2 }, { num: 1 }, { num: 9 }, { num: 5 }, { num: 3 }, { num: 4 }, { num: 8 }],
22 | [{ num: 1 }, { num: 9 }, { num: 8 }, { num: 3 }, { num: 4 }, { num: 2 }, { num: 5 }, { num: 6 }, { num: 7 }],
23 | [{ num: 8 }, { num: 5 }, { num: 9 }, { num: 7 }, { num: 6 }, { num: 1 }, { num: 4 }, { num: 2 }, { num: 3 }],
24 | [{ num: 4 }, { num: 2 }, { num: 6 }, { num: 8 }, { num: 5 }, { num: 3 }, { num: 7 }, { num: 9 }, { num: 1 }],
25 | [{ num: 7 }, { num: 1 }, { num: 3 }, { num: 9 }, { num: 2 }, { num: 4 }, { num: 8 }, { num: 5 }, { num: 6 }],
26 | [{ num: 9 }, { num: 6 }, { num: 1 }, { num: 5 }, { num: 3 }, { num: 7 }, { num: 2 }, { num: 8 }, { num: 4 }],
27 | [{ num: 2 }, { num: 8 }, { num: 7 }, { num: 4 }, { num: 1 }, { num: 9 }, { num: 6 }, { num: 3 }, { num: 5 }],
28 | [{ num: 3 }, { num: 4 }, { num: 5 }, { num: 2 }, { num: 8 }, { num: 6 }, { num: 1 }, { num: 7 }, { num: 9 }]
29 | ];
30 |
31 | // Empty two random cells per row
32 | for (var i = 0; i < defaultSudokuMatrix.length; ++i) {
33 | for (var k = 0; k < 2; ++k) {
34 | var randomColumnIndex = Math.floor(Math.random() * defaultSudokuMatrix.length);
35 | defaultSudokuMatrix[i][randomColumnIndex].num = "";
36 | }
37 | }
38 |
39 | this.sudokuMatrix = defaultSudokuMatrix;
40 | this.initializeGameText = "Restart";
41 | this.isGameStarted = true;
42 | },
43 |
44 | evaluateGame() {
45 |
46 | var copyOfSudokuMatrix = [];
47 | for (var i = 0; i < this.sudokuMatrix.length; ++i) {
48 |
49 | if (!copyOfSudokuMatrix[i])
50 | copyOfSudokuMatrix[i] = [];
51 |
52 | for (var k = 0; k < this.sudokuMatrix[i].length; ++k) {
53 | copyOfSudokuMatrix[i][k] = this.sudokuMatrix[i][k].num;
54 | }
55 |
56 | }
57 |
58 | var sudokuSolver = Sudoku.init(copyOfSudokuMatrix);
59 |
60 | if (sudokuSolver.isValid()) {
61 |
62 | this.answerImage = "success.gif";
63 | this.showAnswer = true;
64 | this.isGameStarted = false;
65 |
66 | setTimeout(() => {
67 | this.showAnswer = false;
68 | this.isGameStarted = true;
69 | }, 2000);
70 |
71 | }
72 | else {
73 |
74 | this.answerImage = "fail.gif";
75 | this.showAnswer = true;
76 | this.isGameStarted = false;
77 |
78 | setTimeout(() => {
79 | this.showAnswer = false;
80 | this.isGameStarted = true;
81 | }, 2000);
82 |
83 | }
84 |
85 | }
86 |
87 | }
88 | });
89 |
--------------------------------------------------------------------------------
/Sudoku/fail.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrancescoBonizzi/VueJs-Experiments/34c2386b461e326c77d04778f06244a7ca406853/Sudoku/fail.gif
--------------------------------------------------------------------------------
/Sudoku/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Vue.js in action
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
![]()
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Sudoku/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | input:focus,
7 | select:focus,
8 | textarea:focus,
9 | button:focus {
10 | outline: none;
11 | }
12 |
13 | body {
14 | display: grid;
15 | grid-template-rows: 150px 1fr;
16 | background-color: #ff5252;
17 | font-family: 'Dosis', sans-serif;
18 | }
19 |
20 | header {
21 | display: grid;
22 | color: white;
23 | }
24 |
25 | header h1 {
26 | place-self: center;
27 | }
28 |
29 | #app-sudoku {
30 | place-self: center;
31 | display: grid;
32 | grid-template-rows: auto 1fr;
33 | justify-items: center;
34 | }
35 |
36 | .buttons-container {
37 | display: grid;
38 | grid-template-rows: auto auto;
39 | }
40 |
41 | .button {
42 | display: inline-block;
43 | border-radius: 6px;
44 | background-color: whitesmoke;
45 | border: none;
46 | color: black;
47 | text-align: center;
48 | font-size: 16px;
49 | padding: 10px;
50 | width: 230px;
51 | transition: all 0.5s;
52 | cursor: pointer;
53 | margin: 0px 0px 25px 0px;
54 | font-family: 'Dosis', sans-serif;
55 | font-weight: bold;
56 | }
57 |
58 | .button span {
59 | cursor: pointer;
60 | display: inline-block;
61 | position: relative;
62 | transition: 0.5s;
63 | }
64 |
65 | .button span:after {
66 | content: '\00bb';
67 | position: absolute;
68 | opacity: 0;
69 | top: 0;
70 | right: -20px;
71 | transition: 0.5s;
72 | }
73 |
74 | .button:hover span {
75 | padding-right: 25px;
76 | }
77 |
78 | .button:hover span:after {
79 | opacity: 1;
80 | right: 0;
81 | }
82 |
83 | .grid-sudoku {
84 | display: table;
85 | background: white;
86 | border: 3px solid black;
87 | }
88 |
89 | .grid-sudoku > div:nth-child(3), .grid-sudoku > div:nth-child(6) {
90 | border-bottom: 3px solid black;
91 | }
92 |
93 | .grid-row > div:nth-child(3), .grid-row > div:nth-child(6) {
94 | border-right: 3px solid black;
95 | }
96 |
97 | .grid-cell {
98 | display: table-cell;
99 | padding: 10px;
100 | border: 1px solid gray;
101 | }
102 |
103 | .grid-cell-editor {
104 | border: none;
105 | width: 20px;
106 | height: 20px;
107 | font-family: 'Dosis', sans-serif;
108 | font-weight: bold;
109 | text-align: center;
110 | font-size: 18px;
111 | transition: all ease 1.0s;
112 | }
113 |
114 | .answer {
115 | position: absolute;
116 | top: 0;
117 | left: 0;
118 | right: 0;
119 | bottom: 0;
120 | display: flex;
121 | justify-content: center;
122 | align-items: center;
123 | }
124 |
125 | .answer-image {
126 | border: 2px solid black;
127 | width: 300px;
128 | height: 300px;
129 | }
130 |
131 | .list-animation-enter, .list-animation-leave-to {
132 | opacity: 0;
133 | transform: translateY(20px) translateX(20px) rotate(200deg) scale(0.5);
134 | }
135 |
136 | .list-animation-leave-active {
137 | position: absolute;
138 | }
139 |
140 | .fade-enter-active, .fade-leave-active {
141 | transition: opacity .5s;
142 | }
143 |
144 | .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
145 | opacity: 0;
146 | }
--------------------------------------------------------------------------------
/Sudoku/success.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrancescoBonizzi/VueJs-Experiments/34c2386b461e326c77d04778f06244a7ca406853/Sudoku/success.gif
--------------------------------------------------------------------------------
/Sudoku/sudoku.js:
--------------------------------------------------------------------------------
1 | var Sudoku = ( function (){
2 |
3 | var _rows, _cols, _grid;
4 |
5 | // initialize the module with input data
6 | init = function(data){
7 | _reorganizeData(data);
8 | return this;
9 | };
10 |
11 | // return true if sudoku is valid
12 | isValid = function(){
13 | return (_validate(_rows) && _validate(_cols) && _validate(_grid));
14 | };
15 |
16 | // validate rows
17 | _validate = function(data){
18 |
19 | for (var row = 0; row < 9; row++) {
20 |
21 | data[row].sort();
22 |
23 | for (var col = 0; col < 9; col++) {
24 |
25 | var value = data[row][col], next_value = data[row][col + 1];
26 |
27 | // check if value exists and is a valid number
28 | if (!(value && value > 0 && value < 10)){
29 | return false;
30 | }
31 |
32 | // check if numbers are unique
33 | if (col !== 8 && value === next_value){
34 | return false;
35 | }
36 |
37 | }
38 | }
39 | return true;
40 | };
41 |
42 | // reorganize data into three structures
43 | _reorganizeData = function(data){
44 | _rows = data;
45 | _cols = [];
46 | _grid = [];
47 |
48 | // Prefilling the structures with empty array objects
49 | for (var i = 0; i < 9; i++) {
50 | _cols.push([]);
51 | _grid.push([]);
52 | }
53 |
54 | for (var row = 0; row < 9; row++) {
55 |
56 | for (var col = 0; col < 9; col++) {
57 |
58 | // Save each column in a new row
59 | _cols[col][row] = data[row][col];
60 |
61 | // Calculate grid identifiers
62 | gridRow = Math.floor( row / 3 );
63 | gridCol = Math.floor( col / 3 );
64 | gridIndex = gridRow * 3 + gridCol;
65 |
66 | // Save each grid in a new row
67 | _grid[gridIndex].push(data[row][col]);
68 |
69 | }
70 | }
71 |
72 | };
73 |
74 | // make functions public
75 | return {
76 | init: init,
77 | isValid: isValid
78 | };
79 | })();
80 |
--------------------------------------------------------------------------------
/Todo list application/app.js:
--------------------------------------------------------------------------------
1 | var itemIndex = 0;
2 |
3 | function GetFreeItemIndex() {
4 | itemIndex++;
5 | return itemIndex;
6 | }
7 |
8 | var testData = [
9 | { Id: GetFreeItemIndex(), Text: "Lorem ipsum dolor sit amet", IsDone: false },
10 | { Id: GetFreeItemIndex(), Text: "Sed fringilla tellus nec finibus maximus. Duis venenatis risus purus. Duis magna odio, eleifend vitae dignissim gravida, semper volutpat nisl", IsDone: false },
11 | { Id: GetFreeItemIndex(), Text: "Ut nec erat non nulla ultricies condimentum", IsDone: true }
12 | ];
13 |
14 | var todoListApp = new Vue({
15 |
16 | el: '#app-todolist',
17 |
18 | data: {
19 | todoItems: testData,
20 | newTodoText: ""
21 | },
22 |
23 | methods: {
24 |
25 | addTodo: function() {
26 |
27 | if (this.newTodoText.trim() === "")
28 | return;
29 |
30 | this.todoItems.push({ Id: GetFreeItemIndex(), Text: this.newTodoText, IsDone: false});
31 | this.newTodoText = "";
32 |
33 | },
34 |
35 | removeTodo: function(todo) {
36 | this.todoItems.splice(this.todoItems.indexOf(todo), 1);
37 | }
38 | }
39 | });
40 |
--------------------------------------------------------------------------------
/Todo list application/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Vue.js in action
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
23 |
24 |
28 |
29 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/Todo list application/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | input:focus,
7 | select:focus,
8 | textarea:focus,
9 | button:focus {
10 | outline: none;
11 | }
12 |
13 | body {
14 | display: grid;
15 | grid-template-rows: 150px 1fr;
16 | background-color: #202124;
17 | font-family: 'Ubuntu Mono', monospace;
18 | }
19 |
20 | header {
21 | display: grid;
22 | border-bottom: 1px solid #5f6368;
23 | color: white;
24 | }
25 |
26 | header h1 {
27 | place-self: center;
28 | }
29 |
30 | #app-todolist {
31 | place-self: center;
32 | }
33 |
34 | #commands {
35 | place-self: center;
36 | display: grid;
37 | grid-template-columns: 1fr auto;
38 | padding: 10px;
39 | margin-top: 30px;
40 | box-shadow: 0 1px 2px 0 rgba(0,0,0,0.6), 0 2px 6px 2px rgba(0,0,0,0.302);
41 | }
42 |
43 | #commands input {
44 | border: none;
45 | background: #2d2e30;
46 | color: white;
47 | padding-left: 5px;
48 | font-size: 18px;
49 | }
50 |
51 | a {
52 | color: #5f6368;
53 | text-decoration: none;
54 | padding: 2px;
55 | margin-left: 5px;
56 | font-weight: bold;
57 | font-size: 22px;
58 | transition: color 0.5s ease;
59 | }
60 |
61 | a:active {
62 | color: #5f6368;
63 | }
64 |
65 | a:hover {
66 | color: white;
67 | }
68 |
69 | #main-content {
70 | place-self: center;
71 | margin-top: 30px;
72 | }
73 |
74 | .todo-item, #commands {
75 | background: #2d2e30;
76 | width: 450px;
77 | border-radius: 8px;
78 | border: 1px solid #5f6368;
79 | align-items: center;
80 | }
81 |
82 | .todo-item {
83 | list-style: none;
84 | color: white;
85 | padding: 10px 10px;
86 | margin-bottom: 10px;
87 | display: grid;
88 | grid-template-columns: auto 1fr auto;
89 | }
90 |
91 | .todo-text span {
92 | overflow-wrap: break-word;
93 | }
94 |
95 | .completed {
96 | text-decoration: line-through;
97 | color: #5f6368;
98 | transition: color 0.4s ease;
99 | }
100 |
101 | .todo-check {
102 | margin-right: 10px;
103 | place-self: center;
104 | display: block;
105 | user-select: none;
106 | -webkit-user-select: none;
107 | -moz-user-select: none;
108 | -ms-user-select: none;
109 | cursor: pointer;
110 | }
111 |
112 | .todo-check input {
113 | position: absolute;
114 | opacity: 0;
115 | cursor: pointer;
116 | height: 0;
117 | width: 0;
118 | }
119 |
120 | .checkmark {
121 | display: block;
122 | height: 18px;
123 | width: 18px;
124 | background-color: transparent;
125 | border: 2px solid #5f6368;
126 | border-radius: 3px;
127 | transition: all 0.5s ease;
128 | }
129 |
130 | .todo-check:hover, .checkmark:hover, .checkmark:hover:after {
131 | color: white;
132 | border-color: white !important;
133 | transition: all 0.5s ease;
134 | }
135 |
136 | .checkmark:after {
137 | content: "";
138 | position: relative;
139 | display: none;
140 | }
141 |
142 | .todo-check input:checked ~ .checkmark:after {
143 | display: block;
144 | }
145 |
146 | .todo-check .checkmark:after {
147 | left: 5px;
148 | top: 1px;
149 | width: 5px;
150 | height: 10px;
151 | border: solid #5f6368;
152 | border-width: 0 3px 3px 0;
153 | -webkit-transform: rotate(45deg);
154 | -ms-transform: rotate(45deg);
155 | transform: rotate(45deg);
156 | transition: all 0.5s ease;
157 | }
158 |
159 | .todo-item-animated {
160 | transition: all 0.5s;
161 | }
162 |
163 | .list-animation-enter, .list-animation-leave-to {
164 | opacity: 0;
165 | transform: translateY(30px);
166 | }
167 |
168 | .list-animation-leave-active {
169 | position: absolute;
170 | }
--------------------------------------------------------------------------------