mirror of
https://github.com/Brandon-Rozek/website.git
synced 2025-06-01 02:44:41 +00:00
Added old URL paths as aliases and cleaned up some code sections of old posts
This commit is contained in:
parent
8e175e60e4
commit
b86c103ade
27 changed files with 1023 additions and 966 deletions
|
@ -1,89 +1,79 @@
|
||||||
---
|
---
|
||||||
id: 57
|
id: 57
|
||||||
title: Responsive Layout and Animation
|
title: Responsive Layout and Animation
|
||||||
date: 2015-04-16T22:19:36+00:00
|
date: 2015-04-16T22:19:36+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: http://brandonrozek.com/?p=57
|
guid: http://brandonrozek.com/?p=57
|
||||||
permalink: /2015/04/responsive-layout-and-animation/
|
aliases:
|
||||||
medium_post:
|
- /2015/04/responsive-layout-and-animation/
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
permalink: /2015/04/responsive-layout-and-animation/
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
dsq_thread_id:
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
- "3688354609"
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
- "3688354609"
|
dsq_thread_id:
|
||||||
mf2_cite:
|
- "3688354609"
|
||||||
- 'a:1:{s:6:"author";a:0:{}}'
|
- "3688354609"
|
||||||
- 'a:1:{s:6:"author";a:0:{}}'
|
mf2_cite:
|
||||||
tumblr_post_id:
|
- 'a:1:{s:6:"author";a:0:{}}'
|
||||||
- "135656876494"
|
- 'a:1:{s:6:"author";a:0:{}}'
|
||||||
- "135656876494"
|
tumblr_post_id:
|
||||||
kind:
|
- "135656876494"
|
||||||
- article
|
- "135656876494"
|
||||||
---
|
kind:
|
||||||
I saw [Mike Riethmuller’s](http://madebymike.com.au/) precision typography [pen](http://codepen.io/MadeByMike/pen/YPJJYv){.broken_link}, and was highly impressed. I think the equation used has other purposes as well
|
- article
|
||||||
|
---
|
||||||
<!--more-->
|
I saw [Mike Riethmuller’s](http://madebymike.com.au/) precision typography [pen](http://codepen.io/MadeByMike/pen/YPJJYv){.broken_link}, and was highly impressed. I think the equation used has other purposes as well
|
||||||
|
|
||||||
Side Note: I changed the form of the equation to something similar to y = mx + b so that I can more easily recognize how it functions
|
<!--more-->
|
||||||
|
|
||||||
#### Responsive Layout
|
Side Note: I changed the form of the equation to something similar to y = mx + b so that I can more easily recognize how it functions
|
||||||
|
|
||||||
There are many occasions where I want an element on the page to move between two points. The navigation in the header of my site (at the time of writing) is a great example of this. So knowing the two points I want it to lie between and having the screen width as the variable, I can plug in… [<img class="aligncenter size-full wp-image-58" src="https://brandonrozek.com/wp-content/uploads/2015/04/responsivelayoutequation.gif" alt="f(x) = (100 * (b - a)/(d - c))X + (ad - bc) / (d - c)" width="219" height="36" />](https://brandonrozek.com/wp-content/uploads/2015/04/responsivelayoutequation.gif){.broken_link} where a is the start pixel b is the end pixel c is the start media query d is the end media query and X is the screen width out of 100 otherwise known as 1vw \*\*Don’t forget to keep track of your units!! Whether it’s px/rem/em/etc.\*\* Say I want to push a box towards the right a minimum of 5px, a maximum of 20px and for the push to vary between the widths 400-800px. Then I would write…
|
#### Responsive Layout
|
||||||
|
|
||||||
<pre><code class="language-css">
|
There are many occasions where I want an element on the page to move between two points. The navigation in the header of my site (at the time of writing) is a great example of this. So knowing the two points I want it to lie between and having the screen width as the variable, I can plug in… [<img class="aligncenter size-full wp-image-58" src="https://brandonrozek.com/wp-content/uploads/2015/04/responsivelayoutequation.gif" alt="f(x) = (100 * (b - a)/(d - c))X + (ad - bc) / (d - c)" width="219" height="36" />](https://brandonrozek.com/wp-content/uploads/2015/04/responsivelayoutequation.gif){.broken_link} where a is the start pixel b is the end pixel c is the start media query d is the end media query and X is the screen width out of 100 otherwise known as 1vw \*\*Don’t forget to keep track of your units!! Whether it’s px/rem/em/etc.\*\* Say I want to push a box towards the right a minimum of 5px, a maximum of 20px and for the push to vary between the widths 400-800px. Then I would write…
|
||||||
|
|
||||||
|
```css
|
||||||
@media (min-width: 400px) and (max-width: 800px) {
|
@media (min-width: 400px) and (max-width: 800px) {
|
||||||
|
.box {
|
||||||
.box {
|
position: relative;
|
||||||
|
left: calc(3.75vw - 10px) /*After simplifying the equation*/
|
||||||
position: relative;
|
}
|
||||||
|
|
||||||
left: calc(3.75vw - 10px) /*After simplifying the equation*/ }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
That would only make it vary between 400-800px. Now we need to include what happens under 400px and over 800px.
|
That would only make it vary between 400-800px. Now we need to include what happens under 400px and over 800px.
|
||||||
|
|
||||||
<pre><code class="language-css">
|
```css
|
||||||
@media (max-width: 400px) {
|
@media (max-width: 400px) {
|
||||||
|
.box {
|
||||||
.box {
|
position: relative;
|
||||||
|
left: 5px;
|
||||||
position: relative;
|
}
|
||||||
|
|
||||||
left: 5px; }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 400px) and (max-width: 800px) {
|
@media (min-width: 400px) and (max-width: 800px) {
|
||||||
|
.box {
|
||||||
.box {
|
position: relative;
|
||||||
|
left: calc(3.75vw - 10px);
|
||||||
position: relative;
|
}
|
||||||
|
|
||||||
left: calc(3.75vw - 10px); }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 800px) {
|
@media (min-width: 800px) {
|
||||||
|
.box {
|
||||||
.box {
|
position: relative;
|
||||||
|
left: 20px;
|
||||||
position: relative;
|
}
|
||||||
|
|
||||||
left: 20px; }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
This is exactly like Mike’s pen, but instead he uses the equation to adjust the font-size between an upper and lower bound. You can apply this method to anything that accepts calc() and viewport units. Here is my [pen](http://codepen.io/brandonrozek/pen/JoQVEb){.broken_link} showing some use cases. To make your life easier, I made a quick little tool where you can input the variables and it will provide you with a simpler form of the equation to put into your calc() function [here](http://codepen.io/brandonrozek/pen/KpPwGL){.broken_link}.
|
This is exactly like Mike’s pen, but instead he uses the equation to adjust the font-size between an upper and lower bound. You can apply this method to anything that accepts calc() and viewport units. Here is my [pen](http://codepen.io/brandonrozek/pen/JoQVEb){.broken_link} showing some use cases. To make your life easier, I made a quick little tool where you can input the variables and it will provide you with a simpler form of the equation to put into your calc() function [here](http://codepen.io/brandonrozek/pen/KpPwGL){.broken_link}.
|
||||||
|
|
||||||
#### Animation
|
#### Animation
|
||||||
|
|
||||||
This is where the majority of my research went towards. It’s not as practical as say positioning an element is but I find it interesting. Like, what if I can manipulate the acceleration of the function? [<img class="aligncenter size-full wp-image-62" src="https://brandonrozek.com/wp-content/uploads/2015/04/accelerationequation.gif" alt="f(x) = ((b - a) / (d^n - c^n))X^n + (ad^n - bc^n) / (d^n - c^n) " width="202" height="36" />](https://brandonrozek.com/wp-content/uploads/2015/04/accelerationequation.gif){.broken_link} Where a is the start unit b is the end unit c is the start time d is the end time n is the acceleration modifier and X is time The interesting part of the function here is the n. If I keep n at 1, then the acceleration is constant. If it’s less than one, then it’s fast in the beginning and slows down at the end. If it’s greater than one, then it’s the opposite. I also made a little pen [here](http://codepen.io/brandonrozek/pen/RNzdOV){.broken_link} to demo this for you.
|
This is where the majority of my research went towards. It’s not as practical as say positioning an element is but I find it interesting. Like, what if I can manipulate the acceleration of the function? [<img class="aligncenter size-full wp-image-62" src="https://brandonrozek.com/wp-content/uploads/2015/04/accelerationequation.gif" alt="f(x) = ((b - a) / (d^n - c^n))X^n + (ad^n - bc^n) / (d^n - c^n) " width="202" height="36" />](https://brandonrozek.com/wp-content/uploads/2015/04/accelerationequation.gif){.broken_link} Where a is the start unit b is the end unit c is the start time d is the end time n is the acceleration modifier and X is time The interesting part of the function here is the n. If I keep n at 1, then the acceleration is constant. If it’s less than one, then it’s fast in the beginning and slows down at the end. If it’s greater than one, then it’s the opposite. I also made a little pen [here](http://codepen.io/brandonrozek/pen/RNzdOV){.broken_link} to demo this for you.
|
||||||
|
|
||||||
#### Conclusion
|
#### Conclusion
|
||||||
|
|
||||||
Having a function that goes between two points is incredibly handy. Now when it comes to positioning, I don’t have to guess which values match the design. If i cant something to be between here and there fluidly, I can do it. What about animation? Chaining them together should have an interesting affect… P.S For those of you crazy people who like to see the theory behind the math, (like myself) I have my scanned work [here](https://brandonrozek.com/2015/04/function-two-points-theory/).
|
Having a function that goes between two points is incredibly handy. Now when it comes to positioning, I don’t have to guess which values match the design. If i cant something to be between here and there fluidly, I can do it. What about animation? Chaining them together should have an interesting affect… P.S For those of you crazy people who like to see the theory behind the math, (like myself) I have my scanned work [here](https://brandonrozek.com/2015/04/function-two-points-theory/).
|
|
@ -5,6 +5,8 @@ date: 2015-05-23T19:59:25+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: http://brandonrozek.com/?p=85
|
guid: http://brandonrozek.com/?p=85
|
||||||
|
aliases:
|
||||||
|
- /2015/05/animatable-border/
|
||||||
permalink: /2015/05/animatable-border/
|
permalink: /2015/05/animatable-border/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
@ -34,21 +36,16 @@ This post follows well along with my Codepen [demo](http://codepen.io/brandonroz
|
||||||
|
|
||||||
Border-color animates by splitting the colors to their red, green and blue components and raises/lowers them to it’s new value. ([Demo](http://codepen.io/brandonrozek/pen/PqzPMe){.broken_link}) ([Spec](http://www.w3.org/TR/css3-transitions/#animtype-color)) Example of animation corresponds to #1 in the pen, but I will rewrite the relevant code here.
|
Border-color animates by splitting the colors to their red, green and blue components and raises/lowers them to it’s new value. ([Demo](http://codepen.io/brandonrozek/pen/PqzPMe){.broken_link}) ([Spec](http://www.w3.org/TR/css3-transitions/#animtype-color)) Example of animation corresponds to #1 in the pen, but I will rewrite the relevant code here.
|
||||||
|
|
||||||
<pre><code class="language-css">
|
```css
|
||||||
@keyframes color {
|
@keyframes color {
|
||||||
|
to { border-color: purple red green blue; }
|
||||||
to { border-color: purple red green blue; }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.border-color {
|
.border-color {
|
||||||
|
border-color: white;
|
||||||
border-color: white;
|
animation: color .4s ease-in .1s infinite alternate;
|
||||||
|
|
||||||
animation: color .4s ease-in .1s infinite alternate;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,44 +55,31 @@ animation: color .4s ease-in .1s infinite alternate;
|
||||||
* Each value corresponds to a corner starting from the top left and going clockwise
|
* Each value corresponds to a corner starting from the top left and going clockwise
|
||||||
* Initial Value: 0
|
* Initial Value: 0
|
||||||
|
|
||||||
<pre><code class="language-css">
|
```css
|
||||||
.border-radius {
|
.border-radius {
|
||||||
|
border-radius: 40% 30% 60% 50% / 20% 40% 60% 80%;
|
||||||
border-radius: 40% 30% 60% 50% / 20% 40% 60% 80%;
|
/** is the same as **/
|
||||||
|
border-top-left-radius: 40% 20%;
|
||||||
/** is the same as **/
|
border-top-right-radius: 30% 40%;
|
||||||
|
border-bottom-right-radius: 60% 60%;
|
||||||
border-top-left-radius: 40% 20%;
|
border-bottom-left-radius: 50% 80%;
|
||||||
|
/** where the first value is the horizontal
|
||||||
border-top-right-radius: 30% 40%;
|
radius and the second value the vertical radius **/
|
||||||
|
|
||||||
border-bottom-right-radius: 60% 60%;
|
|
||||||
|
|
||||||
border-bottom-left-radius: 50% 80%;
|
|
||||||
|
|
||||||
/** where the first value is the horizontal radius and the second value the vertical radius**/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
For animation, this corresponds to #2 in the pen I made at the top. I’ll repeat the relevant code here.
|
For animation, this corresponds to #2 in the pen I made at the top. I’ll repeat the relevant code here.
|
||||||
|
|
||||||
<pre><code class="language-css">
|
```css
|
||||||
|
|
||||||
@keyframes radius {
|
@keyframes radius {
|
||||||
|
to { border-radius: 20%; }
|
||||||
to { border-radius: 20%; }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.border-radius {
|
.border-radius {
|
||||||
|
border-radius: 0;
|
||||||
border-radius: 0;
|
animation: radius .5s ease-in .1s infinite alternate;
|
||||||
|
|
||||||
animation: radius .5s ease-in .1s infinite alternate;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,24 +91,27 @@ animation: radius .5s ease-in .1s infinite alternate;
|
||||||
|
|
||||||
For animation, this corresponds to #3 in the pen I made at the top. I’ll repeat the relevant code here.
|
For animation, this corresponds to #3 in the pen I made at the top. I’ll repeat the relevant code here.
|
||||||
|
|
||||||
<pre><code class="language-css">
|
```css
|
||||||
@keyframes width {
|
@keyframes width {
|
||||||
|
to { border-width: .15rem .25rem .15rem .25rem; }
|
||||||
to { border-width: .15rem .25rem .15rem .25rem; }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.border-width {
|
.border-width {
|
||||||
|
border-width: .7rem;
|
||||||
border-width: .7rem;
|
animation: width .5s ease-in .1s infinite alternate;
|
||||||
|
|
||||||
animation: width .5s ease-in .1s infinite alternate;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Conclusion
|
### Conclusion
|
||||||
|
|
||||||
Animations are quite enjoyable. The last box in my Codepen demo tries combining all three of those animations. (Super Wacky!) You don’t need to use keyframe animations to achieve this, you can also use the transition property. I used keyframes so you can better visualize what’s going on. There are plenty of other animatable properties to go through, so I’ll get started on those. In the meantime, if you want to look at some of the sites I used for research I’ll include the links below. <https://developer.mozilla.org/en-US/docs/Web/CSS/animation> <http://www.w3.org/TR/css3-transitions/#animatable-css> <https://developer.mozilla.org/en-US/docs/Web/CSS/border-color> <https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius> <https://developer.mozilla.org/en-US/docs/Web/CSS/border-width> <https://docs.webplatform.org/wiki/css/properties/border-color>{.broken_link} <https://docs.webplatform.org/wiki/css/properties/border-radius>{.broken_link} <https://docs.webplatform.org/wiki/css/properties/border-width>{.broken_link}
|
Animations are quite enjoyable. The last box in my Codepen demo tries combining all three of those animations. (Super Wacky!) You don’t need to use keyframe animations to achieve this, you can also use the transition property. I used keyframes so you can better visualize what’s going on. There are plenty of other animatable properties to go through, so I’ll get started on those. In the meantime, if you want to look at some of the sites I used for research I’ll include the links below.
|
||||||
|
- <https://developer.mozilla.org/en-US/docs/Web/CSS/animation>
|
||||||
|
- <http://www.w3.org/TR/css3-transitions/#animatable-css>
|
||||||
|
- <https://developer.mozilla.org/en-US/docs/Web/CSS/border-color>
|
||||||
|
- <https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius>
|
||||||
|
- <https://developer.mozilla.org/en-US/docs/Web/CSS/border-width>
|
||||||
|
- <https://docs.webplatform.org/wiki/css/properties/border-color>{.broken_link}
|
||||||
|
- <https://docs.webplatform.org/wiki/css/properties/border-radius>{.broken_link}
|
||||||
|
- <https://docs.webplatform.org/wiki/css/properties/border-width>{.broken_link}
|
||||||
|
|
|
@ -5,6 +5,8 @@ date: 2015-09-14T12:07:52+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=155
|
guid: https://brandonrozek.com/?p=155
|
||||||
|
aliases:
|
||||||
|
- /2015/09/animatable-box-model/
|
||||||
permalink: /2015/09/animatable-box-model/
|
permalink: /2015/09/animatable-box-model/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
|
|
@ -5,6 +5,8 @@ date: 2015-10-03T09:34:08+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=190
|
guid: https://brandonrozek.com/?p=190
|
||||||
|
aliases:
|
||||||
|
- /2015/10/animatable-location/
|
||||||
permalink: /2015/10/animatable-location/
|
permalink: /2015/10/animatable-location/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
@ -44,7 +46,7 @@ Background-position sets where the background is relative to it’s backgrou
|
||||||
|
|
||||||
<pre><code class="language-css">
|
<pre><code class="language-css">
|
||||||
@keyframes background-position {
|
@keyframes background-position {
|
||||||
|
|
||||||
to { background-position: 100% 0%; }
|
to { background-position: 100% 0%; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -78,7 +80,7 @@ The left, right, top, and bottom properties require the position to be set to so
|
||||||
25% {
|
25% {
|
||||||
|
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
||||||
left: 3rem;
|
left: 3rem;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -86,7 +88,7 @@ The left, right, top, and bottom properties require the position to be set to so
|
||||||
50% {
|
50% {
|
||||||
|
|
||||||
top: 3rem;
|
top: 3rem;
|
||||||
|
|
||||||
left: 3rem;
|
left: 3rem;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -94,7 +96,7 @@ The left, right, top, and bottom properties require the position to be set to so
|
||||||
75% {
|
75% {
|
||||||
|
|
||||||
top: 3rem;
|
top: 3rem;
|
||||||
|
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ date: 2015-10-03T08:44:51+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=148
|
guid: https://brandonrozek.com/?p=148
|
||||||
|
aliases:
|
||||||
|
- /2015/10/animatable-text/
|
||||||
permalink: /2015/10/animatable-text/
|
permalink: /2015/10/animatable-text/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
@ -38,7 +40,7 @@ Line-height is the space between each line in a text block. It is commonly recom
|
||||||
to {
|
to {
|
||||||
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -120,9 +122,9 @@ Text-shadow applies a shadow to both the text and it’s text-decoration. Mu
|
||||||
.text-shadow {
|
.text-shadow {
|
||||||
|
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
|
|
||||||
text-shadow: -10px 5px 3.5px rgba(0, 0, 0, .3);
|
text-shadow: -10px 5px 3.5px rgba(0, 0, 0, .3);
|
||||||
|
|
||||||
animation: text-shadow 1s ease 0s infinite;
|
animation: text-shadow 1s ease 0s infinite;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ date: 2015-10-04T17:50:50+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=210
|
guid: https://brandonrozek.com/?p=210
|
||||||
|
aliases:
|
||||||
|
- /2015/10/html-css-javascript-link-together/
|
||||||
permalink: /2015/10/html-css-javascript-link-together/
|
permalink: /2015/10/html-css-javascript-link-together/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
|
|
@ -5,6 +5,8 @@ date: 2015-10-10T20:01:20+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=238
|
guid: https://brandonrozek.com/?p=238
|
||||||
|
aliases:
|
||||||
|
- /2015/10/javascript-data-types/
|
||||||
permalink: /2015/10/javascript-data-types/
|
permalink: /2015/10/javascript-data-types/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
@ -41,7 +43,7 @@ You can access a character inside of a string by using [] notation. Inside the [
|
||||||
<td>
|
<td>
|
||||||
B
|
B
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
r
|
r
|
||||||
</td>
|
</td>
|
||||||
|
@ -66,7 +68,7 @@ You can access a character inside of a string by using [] notation. Inside the [
|
||||||
n
|
n
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -5,6 +5,8 @@ date: 2015-10-11T16:52:36+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=297
|
guid: https://brandonrozek.com/?p=297
|
||||||
|
aliases:
|
||||||
|
- /2015/10/animatable-visual/
|
||||||
permalink: /2015/10/animatable-visual/
|
permalink: /2015/10/animatable-visual/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
|
|
@ -5,6 +5,8 @@ date: 2015-10-18T16:32:37+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=337
|
guid: https://brandonrozek.com/?p=337
|
||||||
|
aliases:
|
||||||
|
- /2015/10/animatable-transform/
|
||||||
permalink: /2015/10/animatable-transform/
|
permalink: /2015/10/animatable-transform/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
|
|
@ -5,6 +5,8 @@ date: 2015-10-18T18:30:21+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=344
|
guid: https://brandonrozek.com/?p=344
|
||||||
|
aliases:
|
||||||
|
- /2015/10/javascript-conditional-statements/
|
||||||
permalink: /2015/10/javascript-conditional-statements/
|
permalink: /2015/10/javascript-conditional-statements/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
@ -32,25 +34,28 @@ This post is part of my lecture series for Math I/O. There is no pre-reading for
|
||||||
|
|
||||||
To run a block of code when a condition is true, use an <code class="language-javascript">if</code> statement.
|
To run a block of code when a condition is true, use an <code class="language-javascript">if</code> statement.
|
||||||
|
|
||||||
<pre><code class="language-javascript"> if (condition) {
|
```javascript
|
||||||
|
if (condition) {
|
||||||
doSomething();
|
doSomething();
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
You can also run a block of code when a condition is false using the <code class="language-javascript">else</code> statement.
|
You can also run a block of code when a condition is false using the <code class="language-javascript">else</code> statement.
|
||||||
|
|
||||||
<pre><code class="language-javascript"> if (condition) {
|
```javascript
|
||||||
doSomething();
|
if (condition) {
|
||||||
} else {
|
doSomething();
|
||||||
doSomethingElse();
|
} else {
|
||||||
}
|
doSomethingElse();
|
||||||
</code></pre>
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <a href="#switch-statement" name="switch-statement"></a>Switch statement {#switch-statement}
|
### <a href="#switch-statement" name="switch-statement"></a>Switch statement {#switch-statement}
|
||||||
|
|
||||||
If you want to check a variable for **equality** against multiple different cases, use a <code class="language-javascript">switch</code> statement.
|
If you want to check a variable for **equality** against multiple different cases, use a <code class="language-javascript">switch</code> statement.
|
||||||
|
|
||||||
<pre><code class="language-javascript"> switch (variable) {
|
```javascript
|
||||||
|
switch (variable) {
|
||||||
case condition1:
|
case condition1:
|
||||||
doSomething();
|
doSomething();
|
||||||
break;
|
break;
|
||||||
|
@ -60,8 +65,8 @@ If you want to check a variable for **equality** against multiple different case
|
||||||
default:
|
default:
|
||||||
doSomethingCompletelyDifferent();
|
doSomethingCompletelyDifferent();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
The default statement runs when the variable doesn’t equal any of the cases.
|
The default statement runs when the variable doesn’t equal any of the cases.
|
||||||
|
|
||||||
|
@ -69,10 +74,11 @@ The default statement runs when the variable doesn’t equal any of the cases.
|
||||||
|
|
||||||
To run a block of code over and over again until a condition is false, use a <code class="language-javascript">while</code> loop.
|
To run a block of code over and over again until a condition is false, use a <code class="language-javascript">while</code> loop.
|
||||||
|
|
||||||
<pre><code class="language-javascript"> while (condition) {
|
```javascript
|
||||||
doSomething();
|
while (condition) {
|
||||||
}
|
doSomething();
|
||||||
</code></pre>
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Don’t forget to include something in the loop that will eventually make the condition <code class="language-javascript">false</code>, otherwise you run into an infinite loop. (Which is a loop that never stops repeating itself; most likely crashing your browser)
|
Don’t forget to include something in the loop that will eventually make the condition <code class="language-javascript">false</code>, otherwise you run into an infinite loop. (Which is a loop that never stops repeating itself; most likely crashing your browser)
|
||||||
|
|
||||||
|
@ -80,10 +86,11 @@ Don’t forget to include something in the loop that will eventually make the co
|
||||||
|
|
||||||
If you want to run something a certain amount of times, use a “<code class="language-javascript">for"</code> loop. For loops can be broken down into three components: an initiating statement, a condition, and a statement that runs after every loop.
|
If you want to run something a certain amount of times, use a “<code class="language-javascript">for"</code> loop. For loops can be broken down into three components: an initiating statement, a condition, and a statement that runs after every loop.
|
||||||
|
|
||||||
<pre><code class="language-javascript"> for (var i = 0; i < 5; i++) {
|
```javascript
|
||||||
|
for (var i = 0; i < 5; i++) {
|
||||||
doSomething();
|
doSomething();
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
Here you have the initiating statement of <code class="language-javascript">var i = 0</code>. From there you check, is <code class="language-javascript">i</code> less than 5? Yes, so then we <code class="language-javascript">doSomething();</code>. After we <code class="language-javascript">doSomething();</code>, we add 1 to <code class="language-javascript">i</code>. Now <code class="language-javascript">i</code> equals 2. Is <code class="language-javascript">i</code> still less than 5? Yes, so we <code class="language-javascript">doSomething();</code>. Then we add 1 to <code class="language-javascript">i</code> again. This loop will keep happening until <code class="language-javascript">i</code> is not less than 5.
|
Here you have the initiating statement of <code class="language-javascript">var i = 0</code>. From there you check, is <code class="language-javascript">i</code> less than 5? Yes, so then we <code class="language-javascript">doSomething();</code>. After we <code class="language-javascript">doSomething();</code>, we add 1 to <code class="language-javascript">i</code>. Now <code class="language-javascript">i</code> equals 2. Is <code class="language-javascript">i</code> still less than 5? Yes, so we <code class="language-javascript">doSomething();</code>. Then we add 1 to <code class="language-javascript">i</code> again. This loop will keep happening until <code class="language-javascript">i</code> is not less than 5.
|
||||||
|
|
||||||
|
@ -91,11 +98,12 @@ Here you have the initiating statement of <code class="language-javascript">var
|
||||||
|
|
||||||
Having different control/conditional statements helps keep the state of any application you’re making. Did the user say not to notify them? Then don’t, otherwise (else) notify them. That’s all I have to say for this week. Hope this post helps you get a little more used to this big world called programming.
|
Having different control/conditional statements helps keep the state of any application you’re making. Did the user say not to notify them? Then don’t, otherwise (else) notify them. That’s all I have to say for this week. Hope this post helps you get a little more used to this big world called programming.
|
||||||
|
|
||||||
<pre><code class="language-javascript"> if (youLikeThisPost) {
|
```javascript
|
||||||
|
if (youLikeThisPost) {
|
||||||
console.log("Come back next week! :)");
|
console.log("Come back next week! :)");
|
||||||
} else {
|
} else {
|
||||||
console.log("Aww that's okay, you should give me another chance next week :)");
|
console.log("Aww that's okay, you should give me another chance next week :)");
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
I recommend that you look at different perspectives of the same concepts. WebCheatSheet.com has a similar post to mine, check out what they had to say [here](http://webcheatsheet.com/javascript/if_else_switch.php).
|
I recommend that you look at different perspectives of the same concepts. WebCheatSheet.com has a similar post to mine, check out what they had to say [here](http://webcheatsheet.com/javascript/if_else_switch.php).
|
|
@ -5,6 +5,8 @@ date: 2015-10-25T13:48:41+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=350
|
guid: https://brandonrozek.com/?p=350
|
||||||
|
aliases:
|
||||||
|
- /2015/10/functions/
|
||||||
permalink: /2015/10/functions/
|
permalink: /2015/10/functions/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
@ -27,33 +29,33 @@ Ever had a snippet of code that appears multiple times in different places in yo
|
||||||
|
|
||||||
To make a function
|
To make a function
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var doSomething = function() {
|
var doSomething = function() {
|
||||||
doStuff;
|
doStuff;
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
To call the above function to execute
|
To call the above function to execute
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
doSomething();
|
doSomething();
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
### <a href="#arguments" name="arguments"></a>Arguments {#arguments}
|
### <a href="#arguments" name="arguments"></a>Arguments {#arguments}
|
||||||
|
|
||||||
You can also add in arguments (parameters that go inside the paraenthesis next to the word function) for the functions to use.
|
You can also add in arguments (parameters that go inside the paraenthesis next to the word function) for the functions to use.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var add = function(number1, number2) {
|
var add = function(number1, number2) {
|
||||||
return number1 + number2;
|
return number1 + number2;
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
And when you use the `return` keyword, like the function above. You can store the value in a variable for future use.
|
And when you use the `return` keyword, like the function above. You can store the value in a variable for future use.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var total = add(1, 3);
|
var total = add(1, 3);
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
<code class="language-javascript">total</code> here will equal `4`
|
<code class="language-javascript">total</code> here will equal `4`
|
||||||
|
|
||||||
|
@ -63,16 +65,16 @@ Functions create their own scope, which means that variables created inside the
|
||||||
|
|
||||||
The snippet below will output an error like <code class="language-javascript">total is not defined</code>
|
The snippet below will output an error like <code class="language-javascript">total is not defined</code>
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var add = function(number1, number2) {
|
var add = function(number1, number2) {
|
||||||
var total = number1 + number2;
|
var total = number1 + number2;
|
||||||
}
|
}
|
||||||
console.log(total);
|
console.log(total);
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
Below is a correct example of the concept
|
Below is a correct example of the concept
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
//Function below converts km/hr to m/s
|
//Function below converts km/hr to m/s
|
||||||
var convert = function(speed) {
|
var convert = function(speed) {
|
||||||
var metersPerHour = speed * 1000;
|
var metersPerHour = speed * 1000;
|
||||||
|
@ -80,13 +82,13 @@ Below is a correct example of the concept
|
||||||
return metersPerSecond;
|
return metersPerSecond;
|
||||||
}
|
}
|
||||||
var currentSpeed = convert(5);
|
var currentSpeed = convert(5);
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
It’s also important to note that functions can use variables outside of it; granted it resides in the same scope.
|
It’s also important to note that functions can use variables outside of it; granted it resides in the same scope.
|
||||||
|
|
||||||
Here is an example of a variable that doesn’t reside in the same scope as the function. (The below code will fail)
|
Here is an example of a variable that doesn’t reside in the same scope as the function. (The below code will fail)
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var something = function() {
|
var something = function() {
|
||||||
var x = 5;
|
var x = 5;
|
||||||
var y = 2;
|
var y = 2;
|
||||||
|
@ -96,17 +98,17 @@ Here is an example of a variable that doesn’t reside in the same scope as
|
||||||
console.log(x + y);
|
console.log(x + y);
|
||||||
}
|
}
|
||||||
addXandY();
|
addXandY();
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
Below, is an example of where the variable does reside in the same scope as the function. Which allows this snippet to execute properly.
|
Below, is an example of where the variable does reside in the same scope as the function. Which allows this snippet to execute properly.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var x = 5;
|
var x = 5;
|
||||||
var addX = function(a) {
|
var addX = function(a) {
|
||||||
return a + x;
|
return a + x;
|
||||||
}
|
}
|
||||||
var sum = addX(6);
|
var sum = addX(6);
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
<code class="language-javascript">sum</code> here will equal <code class="language-javascript">11</code>
|
<code class="language-javascript">sum</code> here will equal <code class="language-javascript">11</code>
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@ date: 2015-11-14T15:47:06+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=400
|
guid: https://brandonrozek.com/?p=400
|
||||||
|
aliases:
|
||||||
|
- /2015/11/service-workers/
|
||||||
permalink: /2015/11/service-workers/
|
permalink: /2015/11/service-workers/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
@ -33,34 +35,37 @@ You need HTTPS to be able to use service workers on your site. This is mainly fo
|
||||||
|
|
||||||
Place `service-worker.js` on the root of your site. This is so the service worker can access all the files in the site. Then in your main javascript file, register the service worker.
|
Place `service-worker.js` on the root of your site. This is so the service worker can access all the files in the site. Then in your main javascript file, register the service worker.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
if (navigator.serviceWorker) {
|
if (navigator.serviceWorker) {
|
||||||
navigator.serviceWorker.register('/serviceworker.js', {
|
navigator.serviceWorker.register('/serviceworker.js', {
|
||||||
scope: '/'
|
scope: '/'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
## <a href="#install-the-service-worker" name="install-the-service-worker"></a>Install the service worker {#install-the-service-worker}
|
## <a href="#install-the-service-worker" name="install-the-service-worker"></a>Install the service worker {#install-the-service-worker}
|
||||||
|
|
||||||
The first time the service worker runs, it emits the `install` event. At this time, we can load the visitor’s cache with some resources for when they’re offline. Every so often, I like to change up the theme of the site. So I have version numbers attached to my files. I would also like to invalidate my cache with this version number. So at the top of the file I added
|
The first time the service worker runs, it emits the `install` event. At this time, we can load the visitor’s cache with some resources for when they’re offline. Every so often, I like to change up the theme of the site. So I have version numbers attached to my files. I would also like to invalidate my cache with this version number. So at the top of the file I added
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var version = 'v2.0.24:';
|
var version = 'v2.0.24:';
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
Now, to specify which files I want the service worker to cache for offline use. I thought my home page and my offline page would be good enough.
|
Now, to specify which files I want the service worker to cache for offline use. I thought my home page and my offline page would be good enough.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var offlineFundamentals = [
|
var offlineFundamentals = [
|
||||||
'/',
|
'/',
|
||||||
'/offline/'
|
'/offline/'
|
||||||
];
|
];
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
Since <code class="language-javascript">cache.addAll()</code> hasn’t been implemented yet in any of the browsers, and the polyfill implementation didn’t work for my needs. I pieced together my own.
|
Since <code class="language-javascript">cache.addAll()</code> hasn’t been implemented yet in any of the browsers, and the polyfill implementation didn’t work for my needs. I pieced together my own.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var updateStaticCache = function() {
|
var updateStaticCache = function() {
|
||||||
return caches.open(version + 'fundamentals').then(function(cache) {
|
return caches.open(version + 'fundamentals').then(function(cache) {
|
||||||
return Promise.all(offlineFundamentals.map(function(value) {
|
return Promise.all(offlineFundamentals.map(function(value) {
|
||||||
|
@ -76,7 +81,8 @@ var updateStaticCache = function() {
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
Let’s go through this chunk of code.
|
Let’s go through this chunk of code.
|
||||||
|
|
||||||
|
@ -88,11 +94,12 @@ Let’s go through this chunk of code.
|
||||||
|
|
||||||
Now we call it when the `install` event is fired.
|
Now we call it when the `install` event is fired.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
self.addEventListener("install", function(event) {
|
self.addEventListener("install", function(event) {
|
||||||
event.waitUntil(updateStaticCache())
|
event.waitUntil(updateStaticCache())
|
||||||
})
|
})
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
With this we now cached all the files in the offlineFundamentals array during the install step.
|
With this we now cached all the files in the offlineFundamentals array during the install step.
|
||||||
|
|
||||||
|
@ -100,7 +107,7 @@ With this we now cached all the files in the offlineFundamentals array during th
|
||||||
|
|
||||||
Since we’re caching everything. If you change one of the files, your visitor wouldn’t get the changed file. Wouldn’t it be nice to remove old files from the visitor’s cache? Every time the service worker finishes the install step, it releases an `activate` event. We can use this to look and see if there are any old cache containers on the visitor’s computer. From [Nicolas’ code](https://ponyfoo.com/articles/serviceworker-revolution). Thanks for sharing 🙂
|
Since we’re caching everything. If you change one of the files, your visitor wouldn’t get the changed file. Wouldn’t it be nice to remove old files from the visitor’s cache? Every time the service worker finishes the install step, it releases an `activate` event. We can use this to look and see if there are any old cache containers on the visitor’s computer. From [Nicolas’ code](https://ponyfoo.com/articles/serviceworker-revolution). Thanks for sharing 🙂
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var clearOldCaches = function() {
|
var clearOldCaches = function() {
|
||||||
return caches.keys().then(function(keys) {
|
return caches.keys().then(function(keys) {
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
|
@ -114,7 +121,8 @@ var clearOldCaches = function() {
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
1. Check the names of each of the cache containers
|
1. Check the names of each of the cache containers
|
||||||
2. If they don’t start with the correct version number
|
2. If they don’t start with the correct version number
|
||||||
|
@ -122,11 +130,12 @@ var clearOldCaches = function() {
|
||||||
|
|
||||||
Call the function when the `activate` event fires.
|
Call the function when the `activate` event fires.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
self.addEventListener("activate", function(event) {
|
self.addEventListener("activate", function(event) {
|
||||||
event.waitUntil(clearOldCaches())
|
event.waitUntil(clearOldCaches())
|
||||||
});
|
});
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
## <a href="#intercepting-fetch-requests" name="intercepting-fetch-requests"></a>Intercepting fetch requests {#intercepting-fetch-requests}
|
## <a href="#intercepting-fetch-requests" name="intercepting-fetch-requests"></a>Intercepting fetch requests {#intercepting-fetch-requests}
|
||||||
|
|
||||||
|
@ -136,7 +145,7 @@ The cool thing about service worker’s is that it can handle file requests. We
|
||||||
|
|
||||||
If the visitor started browsing all of the pages on my site, his or her cache would start to get bloated with files. To not burden my visitors, I decided to only keep the latest 25 pages and latest 10 images in the cache.
|
If the visitor started browsing all of the pages on my site, his or her cache would start to get bloated with files. To not burden my visitors, I decided to only keep the latest 25 pages and latest 10 images in the cache.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var limitCache = function(cache, maxItems) {
|
var limitCache = function(cache, maxItems) {
|
||||||
cache.keys().then(function(items) {
|
cache.keys().then(function(items) {
|
||||||
if (items.length > maxItems) {
|
if (items.length > maxItems) {
|
||||||
|
@ -144,7 +153,8 @@ var limitCache = function(cache, maxItems) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
We’ll call it later in the code.
|
We’ll call it later in the code.
|
||||||
|
|
||||||
|
@ -152,7 +162,7 @@ We’ll call it later in the code.
|
||||||
|
|
||||||
Every time I fetch a file from the network I throw it into a specific cache container. <code class="language-javascript">'pages'</code> for HTML files, <code class="language-javascript">'images'</code> for CSS files, and <code class="language-javascript">'assets'</code> for any other file. This is so I can handle the cache limiting above easier. Defined within the `fetch` event.
|
Every time I fetch a file from the network I throw it into a specific cache container. <code class="language-javascript">'pages'</code> for HTML files, <code class="language-javascript">'images'</code> for CSS files, and <code class="language-javascript">'assets'</code> for any other file. This is so I can handle the cache limiting above easier. Defined within the `fetch` event.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var fetchFromNetwork = function(response) {
|
var fetchFromNetwork = function(response) {
|
||||||
var cacheCopy = response.clone();
|
var cacheCopy = response.clone();
|
||||||
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
|
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
|
||||||
|
@ -172,16 +182,15 @@ var fetchFromNetwork = function(response) {
|
||||||
cache.put(event.request, cacheCopy);
|
cache.put(event.request, cacheCopy);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
### <a href="#when-the-network-fails" name="when-the-network-fails"></a>When the network fails {#when-the-network-fails}
|
### <a href="#when-the-network-fails" name="when-the-network-fails"></a>When the network fails {#when-the-network-fails}
|
||||||
|
|
||||||
There are going to be times where the visitor cannot access the website. Maybe they went in a tunnel while they were riding a train? Or maybe your site went down. I thought it would be nice for my reader’s to be able to look over my blog posts again regardless of an internet connection. So I provide a fall-back. Defined within the `fetch` event.
|
There are going to be times where the visitor cannot access the website. Maybe they went in a tunnel while they were riding a train? Or maybe your site went down. I thought it would be nice for my reader’s to be able to look over my blog posts again regardless of an internet connection. So I provide a fall-back. Defined within the `fetch` event.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var fallback = function() {
|
var fallback = function() {
|
||||||
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
|
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
|
||||||
return caches.match(event.request).then(function (response) {
|
return caches.match(event.request).then(function (response) {
|
||||||
|
@ -191,7 +200,8 @@ var fallback = function() {
|
||||||
return new Response('<svg width="400" height="300" role="img" aria-labelledby="offline-title" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg"><title id="offline-title">Offline</title><g fill="none" fill-rule="evenodd"><path fill="#D8D8D8" d="M0 0h400v300H0z"/><text fill="#9B9B9B" font-family="Helvetica Neue,Arial,Helvetica,sans-serif" font-size="72" font-weight="bold"><tspan x="93" y="172">offline</tspan></text></g></svg>', { headers: { 'Content-Type': 'image/svg+xml' }});
|
return new Response('<svg width="400" height="300" role="img" aria-labelledby="offline-title" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg"><title id="offline-title">Offline</title><g fill="none" fill-rule="evenodd"><path fill="#D8D8D8" d="M0 0h400v300H0z"/><text fill="#9B9B9B" font-family="Helvetica Neue,Arial,Helvetica,sans-serif" font-size="72" font-weight="bold"><tspan x="93" y="172">offline</tspan></text></g></svg>', { headers: { 'Content-Type': 'image/svg+xml' }});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
1. Is the request for a HTML file?
|
1. Is the request for a HTML file?
|
||||||
* Show the [offline](https://brandonrozek.com/offline/) page.
|
* Show the [offline](https://brandonrozek.com/offline/) page.
|
||||||
|
@ -202,20 +212,22 @@ var fallback = function() {
|
||||||
|
|
||||||
First off, I’m only handling GET requests.
|
First off, I’m only handling GET requests.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
if (event.request.method != 'GET') {
|
if (event.request.method != 'GET') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
For HTML files, grab the file from the network. If that fails, then look for it in the cache. _Network then cache strategy_
|
For HTML files, grab the file from the network. If that fails, then look for it in the cache. _Network then cache strategy_
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
|
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
|
||||||
event.respondWith(fetch(event.request).then(fetchFromNetwork, fallback));
|
event.respondWith(fetch(event.request).then(fetchFromNetwork, fallback));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
For non-HTML files, follow this series of steps
|
For non-HTML files, follow this series of steps
|
||||||
|
|
||||||
|
@ -226,13 +238,14 @@ For non-HTML files, follow this series of steps
|
||||||
|
|
||||||
_Cache then network strategy_
|
_Cache then network strategy_
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
event.respondWith(
|
event.respondWith(
|
||||||
caches.match(event.request).then(function(cached) {
|
caches.match(event.request).then(function(cached) {
|
||||||
return cached || fetch(event.request).then(fetchFromNetwork, fallback);
|
return cached || fetch(event.request).then(fetchFromNetwork, fallback);
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
|
|
||||||
For different stategy’s, take a look at Jake Archibald’s [offline cookbook](https://jakearchibald.com/2014/offline-cookbook/).
|
For different stategy’s, take a look at Jake Archibald’s [offline cookbook](https://jakearchibald.com/2014/offline-cookbook/).
|
||||||
|
|
||||||
|
@ -240,7 +253,7 @@ For different stategy’s, take a look at Jake Archibald’s [offline cookbook](
|
||||||
|
|
||||||
With all of that, we now have a fully functioning offline-capable website! I wouldn’t be able to implement this myself if it wasn’t for some of the awesome people I mentioned earlier sharing their experience. So share, share, share! With that sentiment, I’ll now share the full code for `service-worker.js` **Update:** There is a new version of this code over at this [blog post](https://brandonrozek.com/2015/11/limiting-cache-service-workers-revisited/).
|
With all of that, we now have a fully functioning offline-capable website! I wouldn’t be able to implement this myself if it wasn’t for some of the awesome people I mentioned earlier sharing their experience. So share, share, share! With that sentiment, I’ll now share the full code for `service-worker.js` **Update:** There is a new version of this code over at this [blog post](https://brandonrozek.com/2015/11/limiting-cache-service-workers-revisited/).
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var version = 'v2.0.24:';
|
var version = 'v2.0.24:';
|
||||||
|
|
||||||
var offlineFundamentals = [
|
var offlineFundamentals = [
|
||||||
|
@ -321,10 +334,10 @@ self.addEventListener("fetch", function(event) {
|
||||||
cache.put(event.request, cacheCopy);
|
cache.put(event.request, cacheCopy);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Fetch from network failed
|
//Fetch from network failed
|
||||||
var fallback = function() {
|
var fallback = function() {
|
||||||
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
|
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
|
||||||
|
@ -335,18 +348,18 @@ self.addEventListener("fetch", function(event) {
|
||||||
return new Response('<svg width="400" height="300" role="img" aria-labelledby="offline-title" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg"><title id="offline-title">Offline</title><g fill="none" fill-rule="evenodd"><path fill="#D8D8D8" d="M0 0h400v300H0z"/><text fill="#9B9B9B" font-family="Helvetica Neue,Arial,Helvetica,sans-serif" font-size="72" font-weight="bold"><tspan x="93" y="172">offline</tspan></text></g></svg>', { headers: { 'Content-Type': 'image/svg+xml' }});
|
return new Response('<svg width="400" height="300" role="img" aria-labelledby="offline-title" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg"><title id="offline-title">Offline</title><g fill="none" fill-rule="evenodd"><path fill="#D8D8D8" d="M0 0h400v300H0z"/><text fill="#9B9B9B" font-family="Helvetica Neue,Arial,Helvetica,sans-serif" font-size="72" font-weight="bold"><tspan x="93" y="172">offline</tspan></text></g></svg>', { headers: { 'Content-Type': 'image/svg+xml' }});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//This service worker won't touch non-get requests
|
//This service worker won't touch non-get requests
|
||||||
if (event.request.method != 'GET') {
|
if (event.request.method != 'GET') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//For HTML requests, look for file in network, then cache if network fails.
|
//For HTML requests, look for file in network, then cache if network fails.
|
||||||
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
|
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
|
||||||
event.respondWith(fetch(event.request).then(fetchFromNetwork, fallback));
|
event.respondWith(fetch(event.request).then(fetchFromNetwork, fallback));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//For non-HTML requests, look for file in cache, then network if no cache exists.
|
//For non-HTML requests, look for file in cache, then network if no cache exists.
|
||||||
event.respondWith(
|
event.respondWith(
|
||||||
caches.match(event.request).then(function(cached) {
|
caches.match(event.request).then(function(cached) {
|
||||||
|
@ -359,4 +372,4 @@ self.addEventListener("fetch", function(event) {
|
||||||
self.addEventListener("activate", function(event) {
|
self.addEventListener("activate", function(event) {
|
||||||
event.waitUntil(clearOldCaches())
|
event.waitUntil(clearOldCaches())
|
||||||
});
|
});
|
||||||
</code></pre>
|
```
|
|
@ -5,6 +5,8 @@ date: 2015-11-15T12:46:14+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=398
|
guid: https://brandonrozek.com/?p=398
|
||||||
|
aliases:
|
||||||
|
- /2015/11/fractions-js/
|
||||||
permalink: /2015/11/fractions-js/
|
permalink: /2015/11/fractions-js/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
@ -36,12 +38,12 @@ I broke up each fraction into two things, a numerator and a denominator. With th
|
||||||
For addition, if two fractions have the same denominator, then you just need to add the numerators.
|
For addition, if two fractions have the same denominator, then you just need to add the numerators.
|
||||||
|
|
||||||
1/3 + 1/3 = 2/3
|
1/3 + 1/3 = 2/3
|
||||||
|
|
||||||
|
|
||||||
If not, then you need to change it to have a common denominator. We can do this by multiply each fractions numerator and denominator by the other fractions denominator.
|
If not, then you need to change it to have a common denominator. We can do this by multiply each fractions numerator and denominator by the other fractions denominator.
|
||||||
|
|
||||||
1/2 + 1/3 = (1 * 3)/ (2 * 3) + (1 * 2)/ (2 * 3) = 3/6 + 2/6 = 5/6
|
1/2 + 1/3 = (1 * 3)/ (2 * 3) + (1 * 2)/ (2 * 3) = 3/6 + 2/6 = 5/6
|
||||||
|
|
||||||
|
|
||||||
### <a href="#subtraction" name="subtraction"></a>Subtraction {#subtraction}
|
### <a href="#subtraction" name="subtraction"></a>Subtraction {#subtraction}
|
||||||
|
|
||||||
|
@ -52,27 +54,27 @@ Works the same as addition, except the second fraction is subtracted (taken away
|
||||||
To multiply two fractions, just multiply the numerators by each other, and the denominators by each other.
|
To multiply two fractions, just multiply the numerators by each other, and the denominators by each other.
|
||||||
|
|
||||||
2/3 * 1/2 = 2/6
|
2/3 * 1/2 = 2/6
|
||||||
|
|
||||||
|
|
||||||
### <a href="#division" name="division"></a>Division {#division}
|
### <a href="#division" name="division"></a>Division {#division}
|
||||||
|
|
||||||
Treated similar to multiplication since dividing a number is the same thing as multiplying by it’s [reciprocal](https://www.mathsisfun.com/reciprocal.html).
|
Treated similar to multiplication since dividing a number is the same thing as multiplying by it’s [reciprocal](https://www.mathsisfun.com/reciprocal.html).
|
||||||
|
|
||||||
1 / (1 / 2) = 1 * 2 = 2
|
1 / (1 / 2) = 1 * 2 = 2
|
||||||
|
|
||||||
|
|
||||||
### <a href="#simplification" name="simplification"></a>Simplification {#simplification}
|
### <a href="#simplification" name="simplification"></a>Simplification {#simplification}
|
||||||
|
|
||||||
Sometimes with the operations above, it’ll produce fractions in an unsimplified form. To avoid any confusion, I created a simplify function. It was challanging trying to figure out a way to code this. While I was browsing around for an implementation, I knocked into Euclider’s algorithm for finding the greatest common factor. Straight from the [Wikipedia article](https://en.wikipedia.org/wiki/Euclidean_algorithm) (where a is greater than b):
|
Sometimes with the operations above, it’ll produce fractions in an unsimplified form. To avoid any confusion, I created a simplify function. It was challanging trying to figure out a way to code this. While I was browsing around for an implementation, I knocked into Euclider’s algorithm for finding the greatest common factor. Straight from the [Wikipedia article](https://en.wikipedia.org/wiki/Euclidean_algorithm) (where a is greater than b):
|
||||||
|
|
||||||
|
|
||||||
function gcd(a, b)
|
function gcd(a, b)
|
||||||
while b ≠ 0
|
while b ≠ 0
|
||||||
t := b;
|
t := b;
|
||||||
b := a mod b;
|
b := a mod b;
|
||||||
a := t;
|
a := t;
|
||||||
return a;
|
return a;
|
||||||
|
|
||||||
|
|
||||||
I can then simplify the fraction by dividing the numerator and denominator by the greatest common factor.
|
I can then simplify the fraction by dividing the numerator and denominator by the greatest common factor.
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,11 @@ date: 2015-11-30T00:34:15+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=449
|
guid: https://brandonrozek.com/?p=449
|
||||||
|
aliases:
|
||||||
|
- /2015/11/limiting-cache-service-workers-revisited/
|
||||||
|
- /2015/11/limiting-cache-service-workers-revisited1/
|
||||||
|
- /2015/11/limiting-cache-service-workers-revisited2/
|
||||||
|
- /2015/11/limiting-cache-service-workers-revisited3/
|
||||||
permalink: /2015/11/limiting-cache-service-workers-revisited3/
|
permalink: /2015/11/limiting-cache-service-workers-revisited3/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
@ -27,7 +32,7 @@ Summary: I rewrote how cache limiting works to address a few problems listed lat
|
||||||
|
|
||||||
I wrote a function in my [previous service worker post](https://brandonrozek.com/2015/11/service-workers/) to help limit the cache. Here’s a reminder of what it looked like.
|
I wrote a function in my [previous service worker post](https://brandonrozek.com/2015/11/service-workers/) to help limit the cache. Here’s a reminder of what it looked like.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var limitCache = function(cache, maxItems) {
|
var limitCache = function(cache, maxItems) {
|
||||||
cache.keys().then(function(items) {
|
cache.keys().then(function(items) {
|
||||||
if (items.length > maxItems) {
|
if (items.length > maxItems) {
|
||||||
|
@ -35,7 +40,7 @@ var limitCache = function(cache, maxItems) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
### The Problem
|
### The Problem
|
||||||
|
|
||||||
|
@ -45,7 +50,7 @@ Jeremy Keith updated the service worker on his site and noticed that the images
|
||||||
|
|
||||||
Jeremy wrote a function to help trim the cache and asked when it would be appropriate to apply it.
|
Jeremy wrote a function to help trim the cache and asked when it would be appropriate to apply it.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var trimCache = function (cacheName, maxItems) {
|
var trimCache = function (cacheName, maxItems) {
|
||||||
caches.open(cacheName)
|
caches.open(cacheName)
|
||||||
.then(function (cache) {
|
.then(function (cache) {
|
||||||
|
@ -58,11 +63,11 @@ var trimCache = function (cacheName, maxItems) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
And that got me thinking. In what situations is this problem more likely to occur? This particular problem happens when a lot of files are being called asynchronously. This problem doesn’t occur when only one file is being loaded. So when do we load a bunch of files? During page load. During page load, the browser might request css, javascript, images, etc. Which for most [websites](http://royal.pingdom.com/2011/11/21/web-pages-getting-bloated-here-is-why/), is a lot of files. Let’s now move our focus back to the humble script.js. Before, the only role it played with service workers was registering the script. However, if we can get the script to notify the service worker when the page is done loading, then the service worker will know when to trim the cache.
|
And that got me thinking. In what situations is this problem more likely to occur? This particular problem happens when a lot of files are being called asynchronously. This problem doesn’t occur when only one file is being loaded. So when do we load a bunch of files? During page load. During page load, the browser might request css, javascript, images, etc. Which for most [websites](http://royal.pingdom.com/2011/11/21/web-pages-getting-bloated-here-is-why/), is a lot of files. Let’s now move our focus back to the humble script.js. Before, the only role it played with service workers was registering the script. However, if we can get the script to notify the service worker when the page is done loading, then the service worker will know when to trim the cache.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
if ('serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
navigator.serviceWorker.register('https://yourwebsite.com/serviceworker.js', {scope: '/'});
|
navigator.serviceWorker.register('https://yourwebsite.com/serviceworker.js', {scope: '/'});
|
||||||
}
|
}
|
||||||
|
@ -71,21 +76,21 @@ window.addEventListener("load", function() {
|
||||||
navigator.serviceWorker.controller.postMessage({"command":"trimCache"});
|
navigator.serviceWorker.controller.postMessage({"command":"trimCache"});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
Why <code class="language-javascript">if (navigator.serviceWorker.controller != null)</code>? Service Workers don’t take control of the page immediately but on subsequent page loads, Jake Archibald [explains](https://jakearchibald.com/2014/using-serviceworker-today/). When the service worker does have control of the page however, we can use the [postMessage api](https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage) to send a message to the service worker. Inside, I provided a json with a “command” to “trimCache”. Since we send the json to the service worker, we need to make sure that it can receive it.
|
Why `if (navigator.serviceWorker.controller != null)` Service Workers don’t take control of the page immediately but on subsequent page loads, Jake Archibald [explains](https://jakearchibald.com/2014/using-serviceworker-today/). When the service worker does have control of the page however, we can use the [postMessage api](https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage) to send a message to the service worker. Inside, I provided a json with a “command” to “trimCache”. Since we send the json to the service worker, we need to make sure that it can receive it.
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
self.addEventListener("message", function(event) {
|
self.addEventListener("message", function(event) {
|
||||||
var data = event.data;
|
var data = event.data;
|
||||||
|
|
||||||
if (data.command == "trimCache") {
|
if (data.command == "trimCache") {
|
||||||
trimCache(version + "pages", 25);
|
trimCache(version + "pages", 25);
|
||||||
trimCache(version + "images", 10);
|
trimCache(version + "images", 10);
|
||||||
trimCache(version + "assets", 30);
|
trimCache(version + "assets", 30);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
Once it receives the command, it goes on to trim all of the caches.
|
Once it receives the command, it goes on to trim all of the caches.
|
||||||
|
|
||||||
|
@ -93,7 +98,7 @@ Once it receives the command, it goes on to trim all of the caches.
|
||||||
|
|
||||||
So whenever you download a bunch of files, make sure to run <code class="language-javascript">navigator.serviceWorker.controller.postMessage({"command":"trimCache"});</code> on the main javascript file to trim the cache. A downside to this method is that since Service Workers don’t take control during the first page load, the cache isn’t trimmed until the second page load. If you can find a way to make it so that this event happens in the first page load [tell me](mailto:hello@brandonrozek.com) about it/write a blog post. 🙂 **Update:** To get the service worker to take control of the page immediately call [self.skipWaiting()](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/skipWaiting) after the install event and [self.clients.claim()](https://developer.mozilla.org/en-US/docs/Web/API/Clients/claim) after the activate event. Current code for our humble service worker:
|
So whenever you download a bunch of files, make sure to run <code class="language-javascript">navigator.serviceWorker.controller.postMessage({"command":"trimCache"});</code> on the main javascript file to trim the cache. A downside to this method is that since Service Workers don’t take control during the first page load, the cache isn’t trimmed until the second page load. If you can find a way to make it so that this event happens in the first page load [tell me](mailto:hello@brandonrozek.com) about it/write a blog post. 🙂 **Update:** To get the service worker to take control of the page immediately call [self.skipWaiting()](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/skipWaiting) after the install event and [self.clients.claim()](https://developer.mozilla.org/en-US/docs/Web/API/Clients/claim) after the activate event. Current code for our humble service worker:
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
var version = 'v2.0.24:';
|
var version = 'v2.0.24:';
|
||||||
|
|
||||||
var offlineFundamentals = [
|
var offlineFundamentals = [
|
||||||
|
@ -191,10 +196,10 @@ self.addEventListener("fetch", function(event) {
|
||||||
cache.put(event.request, cacheCopy);
|
cache.put(event.request, cacheCopy);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Fetch from network failed
|
//Fetch from network failed
|
||||||
var fallback = function() {
|
var fallback = function() {
|
||||||
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
|
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
|
||||||
|
@ -213,10 +218,10 @@ self.addEventListener("fetch", function(event) {
|
||||||
|
|
||||||
//For HTML requests, look for file in network, then cache if network fails.
|
//For HTML requests, look for file in network, then cache if network fails.
|
||||||
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
|
if (event.request.headers.get('Accept').indexOf('text/html') != -1) {
|
||||||
event.respondWith(fetch(event.request).then(fetchFromNetwork, fallback));
|
event.respondWith(fetch(event.request).then(fetchFromNetwork, fallback));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//For non-HTML requests, look for file in cache, then network if no cache exists.
|
//For non-HTML requests, look for file in cache, then network if no cache exists.
|
||||||
event.respondWith(
|
event.respondWith(
|
||||||
caches.match(event.request).then(function(cached) {
|
caches.match(event.request).then(function(cached) {
|
||||||
|
@ -233,9 +238,9 @@ self.addEventListener("activate", function(event) {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
<pre><code class="language-javascript">
|
```javascript
|
||||||
if ('serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
navigator.serviceWorker.register('https://brandonrozek.com/serviceworker.js', {scope: '/'});
|
navigator.serviceWorker.register('https://brandonrozek.com/serviceworker.js', {scope: '/'});
|
||||||
}
|
}
|
||||||
|
@ -244,4 +249,4 @@ window.addEventListener("load", function() {
|
||||||
navigator.serviceWorker.controller.postMessage({"command":"trimCache"});
|
navigator.serviceWorker.controller.postMessage({"command":"trimCache"});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</code></pre>
|
```
|
|
@ -5,6 +5,8 @@ date: 2015-12-22T15:13:44+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=572
|
guid: https://brandonrozek.com/?p=572
|
||||||
|
aliases:
|
||||||
|
- /2015/12/playing-with-qr-codes/
|
||||||
permalink: /2015/12/playing-with-qr-codes/
|
permalink: /2015/12/playing-with-qr-codes/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
@ -35,7 +37,7 @@ QR Codes aren’t prevalent in the United States of America. In fact, they&#
|
||||||
|
|
||||||
<div id="attachment_573" style="width: 235px" class="wp-caption aligncenter">
|
<div id="attachment_573" style="width: 235px" class="wp-caption aligncenter">
|
||||||
<img aria-describedby="caption-attachment-573" class="size-medium wp-image-573" src="https://brandonrozek.com/wp-content/uploads/2016/10/heinz-2-768x1024.jpg" alt="Picture of Heinz ketchup bottle with QR Code." width="225" height="300" />
|
<img aria-describedby="caption-attachment-573" class="size-medium wp-image-573" src="https://brandonrozek.com/wp-content/uploads/2016/10/heinz-2-768x1024.jpg" alt="Picture of Heinz ketchup bottle with QR Code." width="225" height="300" />
|
||||||
|
|
||||||
<p id="caption-attachment-573" class="wp-caption-text">
|
<p id="caption-attachment-573" class="wp-caption-text">
|
||||||
Picture by <a href="http://azadzahoory.com/2014/07/03/when-the-product-becomes-an-ad/">Azad Zahoory</a>
|
Picture by <a href="http://azadzahoory.com/2014/07/03/when-the-product-becomes-an-ad/">Azad Zahoory</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -5,6 +5,8 @@ date: 2015-12-27T15:17:12+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=599
|
guid: https://brandonrozek.com/?p=599
|
||||||
|
aliases:
|
||||||
|
- /2015/12/creating-vcards-from-h-cards/
|
||||||
permalink: /2015/12/creating-vcards-from-h-cards/
|
permalink: /2015/12/creating-vcards-from-h-cards/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
@ -143,7 +145,7 @@ var makeVCard = function(hCard) {
|
||||||
vCard += "FN: " + name[i] + "n";
|
vCard += "FN: " + name[i] + "n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add photo
|
//Add photo
|
||||||
var photo = hCard.items[0].properties.photo;
|
var photo = hCard.items[0].properties.photo;
|
||||||
if (typeof(photo) == "object") {
|
if (typeof(photo) == "object") {
|
||||||
|
@ -152,7 +154,7 @@ var makeVCard = function(hCard) {
|
||||||
vCard += "PHOTO: " + photo[i] + "n";
|
vCard += "PHOTO: " + photo[i] + "n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add phone number
|
//Add phone number
|
||||||
var tel = hCard.items[0].properties.tel;
|
var tel = hCard.items[0].properties.tel;
|
||||||
if (typeof(tel) == "object") {
|
if (typeof(tel) == "object") {
|
||||||
|
@ -169,7 +171,7 @@ var makeVCard = function(hCard) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add URLs
|
//Add URLs
|
||||||
var url = hCard.items[0].properties.url;
|
var url = hCard.items[0].properties.url;
|
||||||
if (typeof(url) == "object") {
|
if (typeof(url) == "object") {
|
||||||
|
@ -178,7 +180,7 @@ var makeVCard = function(hCard) {
|
||||||
vCard += "URL: " + url[i] + "n";
|
vCard += "URL: " + url[i] + "n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var impp = hCard.items[0].properties.impp;
|
var impp = hCard.items[0].properties.impp;
|
||||||
//Add IMPP (Instant Messaging and Presence Protocol)
|
//Add IMPP (Instant Messaging and Presence Protocol)
|
||||||
if (typeof(impp) == "object") {
|
if (typeof(impp) == "object") {
|
||||||
|
@ -187,7 +189,7 @@ var makeVCard = function(hCard) {
|
||||||
vCard += "IMPP;PREF=" + (i + 1) + ": " + impp[i] + "n";
|
vCard += "IMPP;PREF=" + (i + 1) + ": " + impp[i] + "n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add emails
|
//Add emails
|
||||||
var email = hCard.items[0].properties.email;
|
var email = hCard.items[0].properties.email;
|
||||||
if (typeof(email) == "object") {
|
if (typeof(email) == "object") {
|
||||||
|
@ -200,7 +202,7 @@ var makeVCard = function(hCard) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add roles
|
//Add roles
|
||||||
var role = hCard.items[0].properties.role;
|
var role = hCard.items[0].properties.role;
|
||||||
if (typeof(role) == "object") {
|
if (typeof(role) == "object") {
|
||||||
|
@ -209,7 +211,7 @@ var makeVCard = function(hCard) {
|
||||||
vCard += "ROLE: " + role[i] + "n";
|
vCard += "ROLE: " + role[i] + "n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add Organizations
|
//Add Organizations
|
||||||
var org = hCard.items[0].properties.org;
|
var org = hCard.items[0].properties.org;
|
||||||
if (typeof(org) == "object") {
|
if (typeof(org) == "object") {
|
||||||
|
@ -218,13 +220,13 @@ var makeVCard = function(hCard) {
|
||||||
vCard += "ORG: " + org[i] + "n";
|
vCard += "ORG: " + org[i] + "n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add Categories
|
//Add Categories
|
||||||
var category = hCard.items[0].properties.category;
|
var category = hCard.items[0].properties.category;
|
||||||
if (typeof(category) == "object") {
|
if (typeof(category) == "object") {
|
||||||
vCard += "CATEGORIES: " + category.removeEmptyStrings().join(",") + "n";
|
vCard += "CATEGORIES: " + category.removeEmptyStrings().join(",") + "n";
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add notes
|
//Add notes
|
||||||
var note = hCard.items[0].properties.note;
|
var note = hCard.items[0].properties.note;
|
||||||
if (typeof(note) == "object") {
|
if (typeof(note) == "object") {
|
||||||
|
@ -233,9 +235,9 @@ var makeVCard = function(hCard) {
|
||||||
vCard += "NOTE: " + note[i] + "n";
|
vCard += "NOTE: " + note[i] + "n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return vCard + "END:VCARD";
|
|
||||||
|
|
||||||
|
return vCard + "END:VCARD";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Array.prototype.removeEmptyStrings = function() {
|
Array.prototype.removeEmptyStrings = function() {
|
||||||
|
@ -302,7 +304,7 @@ var render = function() {
|
||||||
border: medium none;
|
border: medium none;
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
|
|
||||||
node.innerHTML = link + style;
|
node.innerHTML = link + style;
|
||||||
document.body.appendChild(node);
|
document.body.appendChild(node);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ date: 2016-08-16T23:37:09+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: http://brandonrozek.com/?p=919
|
guid: http://brandonrozek.com/?p=919
|
||||||
|
aliases:
|
||||||
|
- /2016/08/pass-password-manager/
|
||||||
permalink: /2016/08/pass-password-manager/
|
permalink: /2016/08/pass-password-manager/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";s:2:"no";s:2:"id";N;s:21:"follower_notification";s:3:"yes";s:7:"license";s:19:"all-rights-reserved";s:14:"publication_id";s:2:"-1";s:6:"status";s:4:"none";s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";s:2:"no";s:2:"id";N;s:21:"follower_notification";s:3:"yes";s:7:"license";s:19:"all-rights-reserved";s:14:"publication_id";s:2:"-1";s:6:"status";s:4:"none";s:3:"url";N;}'
|
||||||
|
|
|
@ -5,6 +5,8 @@ date: 2017-03-07T04:29:50+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=2090
|
guid: https://brandonrozek.com/?p=2090
|
||||||
|
aliases:
|
||||||
|
- /2017/03/knit-document-rstudio/
|
||||||
permalink: /2017/03/knit-document-rstudio/
|
permalink: /2017/03/knit-document-rstudio/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
|
|
@ -1,132 +1,142 @@
|
||||||
---
|
---
|
||||||
id: 2095
|
id: 2095
|
||||||
title: Uniformity of Math.random()
|
title: Uniformity of Math.random()
|
||||||
date: 2017-03-07T21:50:52+00:00
|
date: 2017-03-07T21:50:52+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=2095
|
guid: https://brandonrozek.com/?p=2095
|
||||||
permalink: /2017/03/uniformity-math-random/
|
aliases:
|
||||||
medium_post:
|
- /2017/03/uniformity-math-random/
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
permalink: /2017/03/uniformity-math-random/
|
||||||
mf2_syndicate-to:
|
medium_post:
|
||||||
- 'a:1:{i:0;s:4:"none";}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
mf2_cite:
|
mf2_syndicate-to:
|
||||||
- 'a:4:{s:9:"published";s:25:"0000-01-01T00:00:00+00:00";s:7:"updated";s:25:"0000-01-01T00:00:00+00:00";s:8:"category";a:1:{i:0;s:0:"";}s:6:"author";a:0:{}}'
|
- 'a:1:{i:0;s:4:"none";}'
|
||||||
tumblr_post_id:
|
mf2_cite:
|
||||||
- "158123669889"
|
- 'a:4:{s:9:"published";s:25:"0000-01-01T00:00:00+00:00";s:7:"updated";s:25:"0000-01-01T00:00:00+00:00";s:8:"category";a:1:{i:0;s:0:"";}s:6:"author";a:0:{}}'
|
||||||
format: aside
|
tumblr_post_id:
|
||||||
kind:
|
- "158123669889"
|
||||||
- note
|
format: aside
|
||||||
---
|
kind:
|
||||||
There are many cases where websites use random number generators to influence some sort of page behavior. One test to ensure the quality of a random number generator is to see if after many cases, the numbers produced follow a uniform distribution.
|
- note
|
||||||
|
---
|
||||||
<!--more-->
|
There are many cases where websites use random number generators to influence some sort of page behavior. One test to ensure the quality of a random number generator is to see if after many cases, the numbers produced follow a uniform distribution.
|
||||||
|
|
||||||
Today, I will compare Internet Explorer 11, Chrome, and Firefox on a Windows 7 machine and report my results.
|
<!--more-->
|
||||||
|
|
||||||
## Hypothesis
|
Today, I will compare Internet Explorer 11, Chrome, and Firefox on a Windows 7 machine and report my results.
|
||||||
|
|
||||||
H0: The random numbers outputted follow the uniform distribution
|
## Hypothesis
|
||||||
|
|
||||||
HA: The random numbers outputted do not follow the uniform distribution
|
H0: The random numbers outputted follow the uniform distribution
|
||||||
|
|
||||||
## Gathering Data
|
HA: The random numbers outputted do not follow the uniform distribution
|
||||||
|
|
||||||
I wrote a small [website](http://share.zeropointshift.com/files/2017/03/random.html) and obtained my data by getting the CSV outputted when I use IE11, Firefox, and Chrome.
|
## Gathering Data
|
||||||
|
|
||||||
The website works by producing a random number using <code class='language-javascript'>Math.random()</code> between 1 and 1000 inclusive and calls the function 1,000,000 times. Storing it’s results in a file
|
I wrote a small [website](http://share.zeropointshift.com/files/2017/03/random.html) and obtained my data by getting the CSV outputted when I use IE11, Firefox, and Chrome.
|
||||||
|
|
||||||
This website produces a file with all the numbers separated by a comma. We want these commas to be replaced by newlines. To do so, we can run a simple command in the terminal
|
The website works by producing a random number using <code class='language-javascript'>Math.random()</code> between 1 and 1000 inclusive and calls the function 1,000,000 times. Storing it’s results in a file
|
||||||
|
|
||||||
<pre class='language-bash'><code class='language-bash'>
|
This website produces a file with all the numbers separated by a comma. We want these commas to be replaced by newlines. To do so, we can run a simple command in the terminal
|
||||||
|
|
||||||
|
```bash
|
||||||
grep -oE '[0-9]+' Random.csv > Random_corrected.csv
|
grep -oE '[0-9]+' Random.csv > Random_corrected.csv
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
Do this with all three files and make sure to keep track of which is which.
|
Do this with all three files and make sure to keep track of which is which.
|
||||||
|
|
||||||
Here are a copy of my files for [Firefox](https://brandonrozek.com/wp-content/uploads/2017/03/Firefox_corrected.csv), [Chrome](https://brandonrozek.com/wp-content/uploads/2017/03/Chrome_corrected-1.csv), and [IE11](https://brandonrozek.com/wp-content/uploads/2017/03/IE11_corrected.csv)
|
Here are a copy of my files for [Firefox](https://brandonrozek.com/wp-content/uploads/2017/03/Firefox_corrected.csv), [Chrome](https://brandonrozek.com/wp-content/uploads/2017/03/Chrome_corrected-1.csv), and [IE11](https://brandonrozek.com/wp-content/uploads/2017/03/IE11_corrected.csv)
|
||||||
|
|
||||||
## Check Conditions
|
## Check Conditions
|
||||||
|
|
||||||
Since we’re interested in if the random values occur uniformly, we need to perform a Chi-Square test for Goodness of Fit. With every test comes some assumptions
|
Since we’re interested in if the random values occur uniformly, we need to perform a Chi-Square test for Goodness of Fit. With every test comes some assumptions
|
||||||
|
|
||||||
<u>Counted Data Condition:</u> The data can be converted from quantatative to count data.
|
<u>Counted Data Condition:</u> The data can be converted from quantatative to count data.
|
||||||
|
|
||||||
<u>Independence Assumption:</u> One random value does not affect another.
|
<u>Independence Assumption:</u> One random value does not affect another.
|
||||||
|
|
||||||
<u>Expected Cell Frequency Condition:</u> The expected counts are going to be 10000
|
<u>Expected Cell Frequency Condition:</u> The expected counts are going to be 10000
|
||||||
|
|
||||||
Since all of the conditions are met, we can use the Chi-square test of Goodness of Fit
|
Since all of the conditions are met, we can use the Chi-square test of Goodness of Fit
|
||||||
|
|
||||||
## Descriptive Statistics
|
## Descriptive Statistics
|
||||||
|
|
||||||
For the rest of the article, we will use R for analysis. Looking at the histograms for the three browsers below. The random numbers all appear to occur uniformly
|
For the rest of the article, we will use R for analysis. Looking at the histograms for the three browsers below. The random numbers all appear to occur uniformly
|
||||||
|
|
||||||
<pre class="language-R"><code class='language-R'>rm(list=ls())
|
```R
|
||||||
|
rm(list=ls())
|
||||||
chrome = read.csv("~/Chrome_corrected.csv", header = F)
|
chrome = read.csv("~/Chrome_corrected.csv", header = F)
|
||||||
firefox = read.csv("~/Firefox_corrected.csv", header = F)
|
firefox = read.csv("~/Firefox_corrected.csv", header = F)
|
||||||
ie11 = read.csv("~/IE11_corrected.csv", header = F)
|
ie11 = read.csv("~/IE11_corrected.csv", header = F)
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
<pre class="language-R"><code class='language-R'>
|
```R
|
||||||
hist(ie11$V1, main = "Distribution of Random Values for IE11", xlab = "Random Value")</code></pre>
|
hist(ie11$V1, main = "Distribution of Random Values for IE11", xlab = "Random Value")
|
||||||
|
```
|
||||||

|
|
||||||
|

|
||||||
<pre class="language-R"><code class='language-R'>hist(firefox$V1, main = "Distribution of Random Values for Firefox", xlab = "Random Value")</code></pre>
|
|
||||||
|
```R
|
||||||

|
hist(firefox$V1, main = "Distribution of Random Values for Firefox", xlab = "Random Value")
|
||||||
|
```
|
||||||
<pre class="language-R"><code class='language-R'>hist(chrome$V1, main = "Distribution of Random Values for Chrome", xlab = "Random Value")</code></pre>
|
|
||||||
|

|
||||||

|
|
||||||
|
```R
|
||||||
## Chi-Square Test
|
hist(chrome$V1, main = "Distribution of Random Values for Chrome", xlab = "Random Value")
|
||||||
|
```
|
||||||
Before we run our test, we need to convert the quantatative data to count data by using the plyr package
|
|
||||||
|

|
||||||
<pre class="language-R"><code class='language-R'>#Transform to count data
|
|
||||||
|
## Chi-Square Test
|
||||||
|
|
||||||
|
Before we run our test, we need to convert the quantatative data to count data by using the plyr package
|
||||||
|
|
||||||
|
```R
|
||||||
|
#Transform to count data
|
||||||
library(plyr)
|
library(plyr)
|
||||||
chrome_count = count(chrome)
|
chrome_count = count(chrome)
|
||||||
firefox_count = count(firefox)
|
firefox_count = count(firefox)
|
||||||
ie11_count = count(ie11)
|
ie11_count = count(ie11)
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
Run the tests
|
Run the tests
|
||||||
|
|
||||||
<pre class='language-R'><code class='language-R'>
|
```R
|
||||||
# Chi-Square Test for Goodness-of-Fit
|
# Chi-Square Test for Goodness-of-Fit
|
||||||
chrome_test = chisq.test(chrome_count$freq)
|
chrome_test = chisq.test(chrome_count$freq)
|
||||||
firefox_test = chisq.test(firefox_count$freq)
|
firefox_test = chisq.test(firefox_count$freq)
|
||||||
ie11_test = chisq.test(ie11_count$freq)
|
ie11_test = chisq.test(ie11_count$freq)
|
||||||
|
|
||||||
# Test results
|
# Test results
|
||||||
chrome_test</code></pre>
|
chrome_test
|
||||||
|
```
|
||||||
As you can see in the test results below, we fail to reject the null hypothesis at a 5% significance level because all of the p-values are above 0.05.
|
|
||||||
|
As you can see in the test results below, we fail to reject the null hypothesis at a 5% significance level because all of the p-values are above 0.05.
|
||||||
|
|
||||||
##
|
##
|
||||||
## Chi-squared test for given probabilities
|
## Chi-squared test for given probabilities
|
||||||
##
|
##
|
||||||
## data: chrome_count$freq
|
## data: chrome_count$freq
|
||||||
## X-squared = 101.67, df = 99, p-value = 0.4069
|
## X-squared = 101.67, df = 99, p-value = 0.4069
|
||||||
|
|
||||||
<pre class="r"><code>firefox_test</code></pre>
|
`firefox_test`
|
||||||
|
|
||||||
##
|
##
|
||||||
## Chi-squared test for given probabilities
|
## Chi-squared test for given probabilities
|
||||||
##
|
##
|
||||||
## data: firefox_count$freq
|
## data: firefox_count$freq
|
||||||
## X-squared = 105.15, df = 99, p-value = 0.3172
|
## X-squared = 105.15, df = 99, p-value = 0.3172
|
||||||
|
|
||||||
<pre class="r"><code>ie11_test</code></pre>
|
`ie11_test`
|
||||||
|
|
||||||
##
|
##
|
||||||
## Chi-squared test for given probabilities
|
## Chi-squared test for given probabilities
|
||||||
##
|
##
|
||||||
## data: ie11_count$freq
|
## data: ie11_count$freq
|
||||||
## X-squared = 78.285, df = 99, p-value = 0.9384
|
## X-squared = 78.285, df = 99, p-value = 0.9384
|
||||||
|
|
||||||
## Conclusion
|
## Conclusion
|
||||||
|
|
||||||
At a 5% significance level, we fail to obtain enough evidence to suggest that the distribution of random number is not uniform. This is a good thing since it shows us that our random number generators give all numbers an equal chance of being represented. We can use <code class='language-javascript'>Math.random()</code> with ease of mind.
|
At a 5% significance level, we fail to obtain enough evidence to suggest that the distribution of random number is not uniform. This is a good thing since it shows us that our random number generators give all numbers an equal chance of being represented. We can use `Math.random()` with ease of mind.
|
|
@ -1,66 +1,68 @@
|
||||||
---
|
---
|
||||||
id: 2115
|
id: 2115
|
||||||
title: Simplifying Expressions with Octave
|
title: Simplifying Expressions with Octave
|
||||||
date: 2017-03-09T02:09:58+00:00
|
date: 2017-03-09T02:09:58+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=2115
|
guid: https://brandonrozek.com/?p=2115
|
||||||
permalink: /2017/03/simplifying-expressions-octave/
|
aliases:
|
||||||
medium_post:
|
- /2017/03/simplifying-expressions-octave/
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
permalink: /2017/03/simplifying-expressions-octave/
|
||||||
mf2_syndicate-to:
|
medium_post:
|
||||||
- 'a:1:{i:0;s:22:"bridgy-publish_twitter";}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
mf2_cite:
|
mf2_syndicate-to:
|
||||||
- 'a:4:{s:9:"published";s:25:"0000-01-01T00:00:00+00:00";s:7:"updated";s:25:"0000-01-01T00:00:00+00:00";s:8:"category";a:1:{i:0;s:0:"";}s:6:"author";a:0:{}}'
|
- 'a:1:{i:0;s:22:"bridgy-publish_twitter";}'
|
||||||
tumblr_post_id:
|
mf2_cite:
|
||||||
- "158172999969"
|
- 'a:4:{s:9:"published";s:25:"0000-01-01T00:00:00+00:00";s:7:"updated";s:25:"0000-01-01T00:00:00+00:00";s:8:"category";a:1:{i:0;s:0:"";}s:6:"author";a:0:{}}'
|
||||||
mf2_syndication:
|
tumblr_post_id:
|
||||||
- 'a:1:{i:0;s:60:"https://twitter.com/B_RozekJournal/status/839659534146801665";}'
|
- "158172999969"
|
||||||
format: aside
|
mf2_syndication:
|
||||||
kind:
|
- 'a:1:{i:0;s:60:"https://twitter.com/B_RozekJournal/status/839659534146801665";}'
|
||||||
- note
|
format: aside
|
||||||
---
|
kind:
|
||||||
Octave is a high level programming language intended for numerical computations. One of the cool features of this is that with symbolic expressions, you can then simplify mathematical expressions.
|
- note
|
||||||
|
---
|
||||||
<!--more-->
|
Octave is a high level programming language intended for numerical computations. One of the cool features of this is that with symbolic expressions, you can then simplify mathematical expressions.
|
||||||
|
|
||||||
## Setup
|
<!--more-->
|
||||||
|
|
||||||
First install [Octave](https://www.gnu.org/software/octave/) and the [symbolic package](https://octave.sourceforge.io/symbolic/) using the website or your package manager of choice.
|
## Setup
|
||||||
|
|
||||||
Then in octave type in the following code
|
First install [Octave](https://www.gnu.org/software/octave/) and the [symbolic package](https://octave.sourceforge.io/symbolic/) using the website or your package manager of choice.
|
||||||
|
|
||||||
```MATLAB
|
Then in octave type in the following code
|
||||||
pkg load symbolic
|
|
||||||
```
|
```MATLAB
|
||||||
|
pkg load symbolic
|
||||||
|
```
|
||||||
## Usage
|
|
||||||
|
|
||||||
For every variable not defined earlier in your expression, make sure to declare it as a symbolic data type
|
## Usage
|
||||||
|
|
||||||
```MATLAB
|
For every variable not defined earlier in your expression, make sure to declare it as a symbolic data type
|
||||||
syms x y
|
|
||||||
```
|
```MATLAB
|
||||||
|
syms x y
|
||||||
Then make an expression
|
```
|
||||||
|
|
||||||
```MATLAB
|
Then make an expression
|
||||||
expr = y + sin(x)^2 + cos(x)^2
|
|
||||||
```
|
```MATLAB
|
||||||
|
expr = y + sin(x)^2 + cos(x)^2
|
||||||
You can then ask Octave to simplify the expression for you
|
```
|
||||||
|
|
||||||
```MATLAB
|
You can then ask Octave to simplify the expression for you
|
||||||
|
|
||||||
|
```MATLAB
|
||||||
simp_expr = simplify(expr)
|
simp_expr = simplify(expr)
|
||||||
```
|
```
|
||||||
|
|
||||||
Displaying it shows it as
|
Displaying it shows it as
|
||||||
|
|
||||||
```MATLAB
|
```MATLAB
|
||||||
(sym) y + 1
|
(sym) y + 1
|
||||||
```
|
```
|
||||||
|
|
||||||
Which is indeed a simplification using a trig identity 🙂
|
Which is indeed a simplification using a trig identity 🙂
|
||||||
|
|
||||||
Update: Octave's symbolic is based on [SymPy](https://www.sympy.org/en/index.html). If you're confortable with Python, I recommend checking it out.
|
Update: Octave's symbolic is based on [SymPy](https://www.sympy.org/en/index.html). If you're confortable with Python, I recommend checking it out.
|
||||||
|
|
|
@ -1,80 +1,83 @@
|
||||||
---
|
---
|
||||||
id: 2089
|
id: 2089
|
||||||
title: Monte Carlo Pi
|
title: Monte Carlo Pi
|
||||||
date: 2017-03-14T05:31:21+00:00
|
date: 2017-03-14T05:31:21+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=2089
|
guid: https://brandonrozek.com/?p=2089
|
||||||
permalink: /2017/03/monte-carlo-pi/
|
aliases:
|
||||||
medium_post:
|
- /2017/03/monte-carlo-pi/
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
permalink: /2017/03/monte-carlo-pi/
|
||||||
tumblr_post_id:
|
medium_post:
|
||||||
- "158383170019"
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
mf2_syndicate-to:
|
tumblr_post_id:
|
||||||
- 'a:1:{i:0;s:22:"bridgy-publish_twitter";}'
|
- "158383170019"
|
||||||
mf2_cite:
|
mf2_syndicate-to:
|
||||||
- 'a:4:{s:9:"published";s:25:"0000-01-01T00:00:00+00:00";s:7:"updated";s:25:"0000-01-01T00:00:00+00:00";s:8:"category";a:1:{i:0;s:0:"";}s:6:"author";a:0:{}}'
|
- 'a:1:{i:0;s:22:"bridgy-publish_twitter";}'
|
||||||
mf2_syndication:
|
mf2_cite:
|
||||||
- 'a:1:{i:0;s:60:"https://twitter.com/B_RozekJournal/status/841522141346570244";}'
|
- 'a:4:{s:9:"published";s:25:"0000-01-01T00:00:00+00:00";s:7:"updated";s:25:"0000-01-01T00:00:00+00:00";s:8:"category";a:1:{i:0;s:0:"";}s:6:"author";a:0:{}}'
|
||||||
format: aside
|
mf2_syndication:
|
||||||
kind:
|
- 'a:1:{i:0;s:60:"https://twitter.com/B_RozekJournal/status/841522141346570244";}'
|
||||||
- note
|
format: aside
|
||||||
---
|
kind:
|
||||||
Using Monte Carlo methods, we can create a simulation that approximates pi. In this post, we will go over the math behind the approximation and the code.
|
- note
|
||||||
|
---
|
||||||
<!--more-->
|
Using Monte Carlo methods, we can create a simulation that approximates pi. In this post, we will go over the math behind the approximation and the code.
|
||||||
|
|
||||||
## The Math
|
<!--more-->
|
||||||
|
|
||||||
Pi is a mathematical constant consisting of the ratio between the circumfrence of a circle and it’s diameter.
|
## The Math
|
||||||
|
|
||||||
The circumfrence of the circle is defined to be $$ C = 2\pi r$$ while the diameter of the circle is $$d = 2r$$
|
Pi is a mathematical constant consisting of the ratio between the circumfrence of a circle and it’s diameter.
|
||||||
|
|
||||||
Take the ratio between the two and you get $$\frac{2\pi r}{2r} = \pi$$
|
The circumfrence of the circle is defined to be $$ C = 2\pi r$$ while the diameter of the circle is $$d = 2r$$
|
||||||
|
|
||||||
Now let us consider the area of a circle. One can derive the area of a circle by taking the integral of the circumfrence with respect to it’s radius $$ A_{circle} = \int{(2\pi r) dr} = \pi r^2 $$
|
Take the ratio between the two and you get $$\frac{2\pi r}{2r} = \pi$$
|
||||||
|
|
||||||
Let us simplify the formula more by setting the radius equal to one. $$A_{circle} = \pi$$
|
Now let us consider the area of a circle. One can derive the area of a circle by taking the integral of the circumfrence with respect to it’s radius $$ A_{circle} = \int{(2\pi r) dr} = \pi r^2 $$
|
||||||
|
|
||||||
Now consider only the first quadrant of the circle. Since our circle is centered at the origin and all the points on the circumfrence is equidistant from the center, our area is now $$A_{circle} = \frac{1}{4} \pi$$
|
Let us simplify the formula more by setting the radius equal to one. $$A_{circle} = \pi$$
|
||||||
|
|
||||||
And bound the quarter-circle in a 1×1 box with an area of $$A_{square} = 1^2 = 1$$
|
Now consider only the first quadrant of the circle. Since our circle is centered at the origin and all the points on the circumfrence is equidistant from the center, our area is now $$A_{circle} = \frac{1}{4} \pi$$
|
||||||
|
|
||||||
Notice that the ratio between the circle and the square is a quarter of pi $$\frac{A\_{circle}}{A\_{square}} = \frac{\frac{1}{4} \pi}{1} = \frac{1}{4} \pi$$
|
And bound the quarter-circle in a 1×1 box with an area of $$A_{square} = 1^2 = 1$$
|
||||||
|
|
||||||
## Simulation and Statisitcs
|
Notice that the ratio between the circle and the square is a quarter of pi $$\frac{A\_{circle}}{A\_{square}} = \frac{\frac{1}{4} \pi}{1} = \frac{1}{4} \pi$$
|
||||||
|
|
||||||
The formula for a circle centered at the origin with radius one is $$x^2 + y^2 = 1$$
|
## Simulation and Statisitcs
|
||||||
|
|
||||||
Let us focus again on the first quadrent, and do a Monte Carlo simulation to find the area of the quarter-circle
|
The formula for a circle centered at the origin with radius one is $$x^2 + y^2 = 1$$
|
||||||
|
|
||||||

|
Let us focus again on the first quadrent, and do a Monte Carlo simulation to find the area of the quarter-circle
|
||||||
|
|
||||||
We can do this by what is called the dart board method. We generate a random x and y between 0 and 1. If it satisfies the inequality $$x^2 + y^2 \leq 1$$ then it counts as being inside the circle, if not then it lies outside the circle.
|

|
||||||
|
|
||||||
That point will count as an really small area. The point will always be inside the square but may sometimes be inside the circle. Running the simulations a large number of times allows us to add up all the tiny little areas that make up the circle and the square.
|
We can do this by what is called the dart board method. We generate a random x and y between 0 and 1. If it satisfies the inequality $$x^2 + y^2 \leq 1$$ then it counts as being inside the circle, if not then it lies outside the circle.
|
||||||
|
|
||||||
To add up these small areas we need to make an assumption. The assumption is that the variance of all the little Monte Carlo trials are the same. Since we are using a psuedo-random number generator, it is safe to assume it is met.
|
That point will count as an really small area. The point will always be inside the square but may sometimes be inside the circle. Running the simulations a large number of times allows us to add up all the tiny little areas that make up the circle and the square.
|
||||||
|
|
||||||
This will allow us to perform a pooled empiricle probability on the simulations to sum up the areas.
|
To add up these small areas we need to make an assumption. The assumption is that the variance of all the little Monte Carlo trials are the same. Since we are using a psuedo-random number generator, it is safe to assume it is met.
|
||||||
|
|
||||||
Meaning the area of the circle will be the number of times that the inequality was satisfied $$A_{circle} = \# Successes$$
|
This will allow us to perform a pooled empiricle probability on the simulations to sum up the areas.
|
||||||
|
|
||||||
And the area of the square will be the number of times the simulation was run, since the random numbers generated will always be between 0 and 1 $$A_{square} = \# Trials$$
|
Meaning the area of the circle will be the number of times that the inequality was satisfied $$A_{circle} = \# Successes$$
|
||||||
|
|
||||||
Recall that taking the ratio of the area of the circle and the area of the square is a fourth of pi. $$\frac{\frac{1}{4} \pi}{1} = \frac{1}{4} \pi$$
|
And the area of the square will be the number of times the simulation was run, since the random numbers generated will always be between 0 and 1 $A_{square} = \# Trials$
|
||||||
|
|
||||||
Multiply this number by 4 and you get the value for pi.
|
Recall that taking the ratio of the area of the circle and the area of the square is a fourth of pi. $$\frac{\frac{1}{4} \pi}{1} = \frac{1}{4} \pi$$
|
||||||
|
|
||||||
This tells us that four times the probability that the randomly generated point is in the circle is equal to pi.
|
Multiply this number by 4 and you get the value for pi.
|
||||||
|
|
||||||
$$\pi = 4 \* (Probability\ of\ being\ inside\ circle) = 4 \* \frac{\# Success}{\# Trials} = 4 * \frac{A\_{circle}}{A\_{square}}$$
|
This tells us that four times the probability that the randomly generated point is in the circle is equal to pi.
|
||||||
|
|
||||||
## Implementation
|
$$\pi = 4 * (Probability\ of\ being\ inside\ circle) = 4 * \frac{\# Success}{\# Trials} = 4 * \frac{A\_{circle}}{A\_{square}}$$
|
||||||
|
|
||||||
For the Monte Carlo simulation I used Java. The BigDecimal implementation was used so that there wouldn’t be any issue with integer size limits
|
## Implementation
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>/** Calculates Pi
|
For the Monte Carlo simulation I used Java. The BigDecimal implementation was used so that there wouldn’t be any issue with integer size limits
|
||||||
|
|
||||||
|
```java
|
||||||
|
/** Calculates Pi
|
||||||
* @author Brandon Rozek
|
* @author Brandon Rozek
|
||||||
*/
|
*/
|
||||||
// Big Integers are used so we don't run into the integer size limit
|
// Big Integers are used so we don't run into the integer size limit
|
||||||
|
@ -85,10 +88,10 @@ class MonteCarloPi {
|
||||||
|
|
||||||
BigInteger successes = BigInteger.ZERO;
|
BigInteger successes = BigInteger.ZERO;
|
||||||
BigInteger trials = BigInteger.ZERO;
|
BigInteger trials = BigInteger.ZERO;
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
For this simulation, we will run 1,000,000,000 trials
|
For this simulation, we will run 1,000,000,000 trials
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'> BigInteger numTrials = new BigInteger("1000000000");
|
<pre class='language-java'><code class='language-java'> BigInteger numTrials = new BigInteger("1000000000");
|
||||||
/*
|
/*
|
||||||
Monte Carlo Simulation
|
Monte Carlo Simulation
|
||||||
|
@ -104,22 +107,23 @@ for (; trials.compareTo(numTrials) < 0; trials = trials.add(BigInteger.ONE))
|
||||||
successes = successes.add(BigInteger.ONE);
|
successes = successes.add(BigInteger.ONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
And then we finalize it with a quick calculation of pi
|
And then we finalize it with a quick calculation of pi
|
||||||
|
|
||||||
<pre class='language=java'><code class='language-java'>// (Number of successes) / (Number of trials) * 4 gives the approximation for pi
|
```java
|
||||||
|
// (Number of successes) / (Number of trials) * 4 gives the approximation for pi
|
||||||
BigDecimal pi = new BigDecimal(successes)
|
BigDecimal pi = new BigDecimal(successes)
|
||||||
.divide(new BigDecimal(trials))
|
.divide(new BigDecimal(trials))
|
||||||
.multiply(new BigDecimal("4"));
|
.multiply(new BigDecimal("4"));
|
||||||
System.out.println("The calculated value of pi is: " + pi);
|
System.out.println("The calculated value of pi is: " + pi);
|
||||||
}}
|
}}
|
||||||
</code></pre>
|
```
|
||||||
|
|
||||||
## Conclusion
|
## Conclusion
|
||||||
|
|
||||||
We found an approximation of pi using the Monte Carlo methods! I find that really awesome, however, there are some concerns I have with this approach.
|
We found an approximation of pi using the Monte Carlo methods! I find that really awesome, however, there are some concerns I have with this approach.
|
||||||
|
|
||||||
1) We don’t keep track of double counting. One possible solution for this is increasing the radius and bounding box appropriately so that the probability of double counting is low.
|
1) We don’t keep track of double counting. One possible solution for this is increasing the radius and bounding box appropriately so that the probability of double counting is low.
|
||||||
|
|
||||||
2) Speed. The more trials you ask it to run, the longer it takes to perform all of the simulations. One possible way around this is to write a parrallel version of this code. That’s possible because of the equal variance that we spoke of earlier. Pooling the successses and trials will still result in a good approximation.
|
2) Speed. The more trials you ask it to run, the longer it takes to perform all of the simulations. One possible way around this is to write a parrallel version of this code. That’s possible because of the equal variance that we spoke of earlier. Pooling the successses and trials will still result in a good approximation.
|
|
@ -1,40 +1,42 @@
|
||||||
---
|
---
|
||||||
id: 2174
|
id: 2174
|
||||||
title: Viewing Java Applets
|
title: Viewing Java Applets
|
||||||
date: 2017-05-24T15:59:45+00:00
|
date: 2017-05-24T15:59:45+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=2174
|
guid: https://brandonrozek.com/?p=2174
|
||||||
permalink: /2017/05/viewing-java-applets/
|
aliases:
|
||||||
medium_post:
|
- /2017/05/viewing-java-applets/
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
permalink: /2017/05/viewing-java-applets/
|
||||||
mf2_syndicate-to:
|
medium_post:
|
||||||
- 'a:1:{i:0;s:22:"bridgy-publish_twitter";}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
mf2_cite:
|
mf2_syndicate-to:
|
||||||
- 'a:4:{s:9:"published";s:25:"0000-01-01T00:00:00+00:00";s:7:"updated";s:25:"0000-01-01T00:00:00+00:00";s:8:"category";a:1:{i:0;s:0:"";}s:6:"author";a:0:{}}'
|
- 'a:1:{i:0;s:22:"bridgy-publish_twitter";}'
|
||||||
tumblr_post_id:
|
mf2_cite:
|
||||||
- "161024360884"
|
- 'a:4:{s:9:"published";s:25:"0000-01-01T00:00:00+00:00";s:7:"updated";s:25:"0000-01-01T00:00:00+00:00";s:8:"category";a:1:{i:0;s:0:"";}s:6:"author";a:0:{}}'
|
||||||
mf2_syndication:
|
tumblr_post_id:
|
||||||
- 'a:1:{i:0;s:60:"https://twitter.com/B_RozekJournal/status/867409810932760576";}'
|
- "161024360884"
|
||||||
kind:
|
mf2_syndication:
|
||||||
- article
|
- 'a:1:{i:0;s:60:"https://twitter.com/B_RozekJournal/status/867409810932760576";}'
|
||||||
---
|
kind:
|
||||||
When you use an IDE there are many things you can take for granted. A section of an intro level computer science course at my university uses [JGrasp](http://www.jgrasp.org/) to build Java Applets.
|
- article
|
||||||
|
---
|
||||||
Following around using a normal text editor, I found that I couldn’t just compile and run the code like I have with my java programs in the past. To be able to help around and assist in the course, I need to be able to build and run these applications. The rest of this article describes the process I underwent to be able to use my existing setup to write and build java applets. Of course you can always install JGrasp and have that all built in, but it’s always nice to not have to change your workflow.
|
When you use an IDE there are many things you can take for granted. A section of an intro level computer science course at my university uses [JGrasp](http://www.jgrasp.org/) to build Java Applets.
|
||||||
|
|
||||||
<!--more-->
|
Following around using a normal text editor, I found that I couldn’t just compile and run the code like I have with my java programs in the past. To be able to help around and assist in the course, I need to be able to build and run these applications. The rest of this article describes the process I underwent to be able to use my existing setup to write and build java applets. Of course you can always install JGrasp and have that all built in, but it’s always nice to not have to change your workflow.
|
||||||
|
|
||||||
When I tried following along, I would receive the following error
|
<!--more-->
|
||||||
|
|
||||||
Main method not found in class HelloWorld, please define main method as...
|
When I tried following along, I would receive the following error
|
||||||
|
|
||||||
Which makes sense since I have never defined a main method inside my source code. So how do I go about doing this?
|
Main method not found in class HelloWorld, please define main method as...
|
||||||
|
|
||||||
## Setup
|
Which makes sense since I have never defined a main method inside my source code. So how do I go about doing this?
|
||||||
|
|
||||||
Java Applets are meant to run on web pages, because of this one needs an html file to host the applet. The following code gives you the bare minimum for setting up the html file. I called it `HelloWorld.html`.
|
## Setup
|
||||||
|
|
||||||
|
Java Applets are meant to run on web pages, because of this one needs an html file to host the applet. The following code gives you the bare minimum for setting up the html file. I called it `HelloWorld.html`.
|
||||||
|
|
||||||
<pre class='language-html'><code class='language-html'>
|
<pre class='language-html'><code class='language-html'>
|
||||||
<html>
|
<html>
|
||||||
<head><title>Applet Container<title>
|
<head><title>Applet Container<title>
|
||||||
|
@ -42,12 +44,12 @@ Java Applets are meant to run on web pages, because of this one needs an html fi
|
||||||
<applet code='HelloWorld.class' width=400 height=400></applet>
|
<applet code='HelloWorld.class' width=400 height=400></applet>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
## Hello World Program
|
## Hello World Program
|
||||||
|
|
||||||
To get it up and running, I will show a “Hello World” like application for applets.
|
To get it up and running, I will show a “Hello World” like application for applets.
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
import javax.swing.JApplet;
|
import javax.swing.JApplet;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
|
@ -57,18 +59,18 @@ public class HelloWorld extends JApplet {
|
||||||
g.drawString("Hello World", 30, 30);
|
g.drawString("Hello World", 30, 30);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
## Running the Applet
|
## Running the Applet
|
||||||
|
|
||||||
Now we need to compile the code
|
Now we need to compile the code
|
||||||
|
|
||||||
<pre class='langauge-bash'><code class='language-bash'>javac HelloWorld.java</code></pre>
|
<pre class='langauge-bash'><code class='language-bash'>javac HelloWorld.java</code></pre>
|
||||||
|
|
||||||
Then run the appletviewer
|
Then run the appletviewer
|
||||||
|
|
||||||
<pre class='language-bash'><code class='language-bash'>appletviewer HelloWorld.html</code></pre>
|
<pre class='language-bash'><code class='language-bash'>appletviewer HelloWorld.html</code></pre>
|
||||||
|
|
||||||
## Conclusion
|
## Conclusion
|
||||||
|
|
||||||
This tutorial concludes the setup of running a simple Java applet. From here you can look at the different methods in the [Graphics library](https://docs.oracle.com/javase/7/docs/api/java/awt/Graphics.html) and play around 😀
|
This tutorial concludes the setup of running a simple Java applet. From here you can look at the different methods in the [Graphics library](https://docs.oracle.com/javase/7/docs/api/java/awt/Graphics.html) and play around 😀
|
|
@ -1,67 +1,69 @@
|
||||||
---
|
---
|
||||||
id: 2198
|
id: 2198
|
||||||
title: Java Swing Components
|
title: Java Swing Components
|
||||||
date: 2017-06-05T23:30:18+00:00
|
date: 2017-06-05T23:30:18+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=2198
|
guid: https://brandonrozek.com/?p=2198
|
||||||
permalink: /2017/06/java-swing-components/
|
aliases:
|
||||||
medium_post:
|
- /2017/06/java-swing-components/
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
permalink: /2017/06/java-swing-components/
|
||||||
mf2_syndicate-to:
|
medium_post:
|
||||||
- 'a:1:{i:0;s:4:"none";}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
mf2_cite:
|
mf2_syndicate-to:
|
||||||
- 'a:4:{s:9:"published";s:25:"0000-01-01T00:00:00+00:00";s:7:"updated";s:25:"0000-01-01T00:00:00+00:00";s:8:"category";a:1:{i:0;s:0:"";}s:6:"author";a:0:{}}'
|
- 'a:1:{i:0;s:4:"none";}'
|
||||||
tumblr_post_id:
|
mf2_cite:
|
||||||
- "161484582559"
|
- 'a:4:{s:9:"published";s:25:"0000-01-01T00:00:00+00:00";s:7:"updated";s:25:"0000-01-01T00:00:00+00:00";s:8:"category";a:1:{i:0;s:0:"";}s:6:"author";a:0:{}}'
|
||||||
kind:
|
tumblr_post_id:
|
||||||
- article
|
- "161484582559"
|
||||||
---
|
kind:
|
||||||
This post, over time, will serve as a reference to myself and others of the different UI components available in the Swing library. This post assumes a general familiarity with setting up a basic Swing application and focuses only on the individual components.
|
- article
|
||||||
|
---
|
||||||
<!--more-->
|
This post, over time, will serve as a reference to myself and others of the different UI components available in the Swing library. This post assumes a general familiarity with setting up a basic Swing application and focuses only on the individual components.
|
||||||
|
|
||||||
### Buttons
|
<!--more-->
|
||||||
|
|
||||||
Buttons are created using the JButton component. The constructor takes the text placed inside the button.
|
### Buttons
|
||||||
|
|
||||||
|
Buttons are created using the JButton component. The constructor takes the text placed inside the button.
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
JButton stopBtn = new JButton("Stop");
|
JButton stopBtn = new JButton("Stop");
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/stopbutton.png" alt="" width="67" height="25" class="alignnone size-full wp-image-2211" />
|
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/stopbutton.png" alt="" width="67" height="25" class="alignnone size-full wp-image-2211" />
|
||||||
|
|
||||||
You can also add images inside a button. To do that you need to get the image and make it into an icon. The following code grabs the image file “smallpanda.jpg” from the current working directory.
|
You can also add images inside a button. To do that you need to get the image and make it into an icon. The following code grabs the image file “smallpanda.jpg” from the current working directory.
|
||||||
|
|
||||||
<pre class='langauge-java'><code class='language-java'>
|
<pre class='langauge-java'><code class='language-java'>
|
||||||
Image img = this.getImage(this.getCodeBase(), "smallpanda.jpg");
|
Image img = this.getImage(this.getCodeBase(), "smallpanda.jpg");
|
||||||
ImageIcon imgIcon = new ImageIcon(img);
|
ImageIcon imgIcon = new ImageIcon(img);
|
||||||
JButton feedBtn = new JButton("Feed", imgIcon);
|
JButton feedBtn = new JButton("Feed", imgIcon);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
Sometimes, you want to change the location of the text in the button. Like say, we want to place the text in the center horizontally and bottom vertically.
|
Sometimes, you want to change the location of the text in the button. Like say, we want to place the text in the center horizontally and bottom vertically.
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
feedBtn.setHorizontalTextPosition(JButton.CENTER);
|
feedBtn.setHorizontalTextPosition(JButton.CENTER);
|
||||||
feedBtn.setVerticalTextPosition(JButton.BOTTOM);
|
feedBtn.setVerticalTextPosition(JButton.BOTTOM);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
Don’t forget to add your buttons to the screen!
|
Don’t forget to add your buttons to the screen!
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
this.add(stopBtn);
|
this.add(stopBtn);
|
||||||
this.add(feedBtn);
|
this.add(feedBtn);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/smallpandabutton.png" alt="" width="234" height="181" class="alignnone size-full wp-image-2210" />
|
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/smallpandabutton.png" alt="" width="234" height="181" class="alignnone size-full wp-image-2210" />
|
||||||
|
|
||||||
### Labels and Textfields
|
### Labels and Textfields
|
||||||
|
|
||||||
One of the most common forms of input is a text field, usually distinguished with a label. Those components are called JTextField and JLabel respectively. The constructor for JTextArea can take just the width of the text field, or another common use is to have already inputed text and its width.
|
One of the most common forms of input is a text field, usually distinguished with a label. Those components are called JTextField and JLabel respectively. The constructor for JTextArea can take just the width of the text field, or another common use is to have already inputed text and its width.
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
JLabel nameLabel = new JLabel("Enter in your name: ");
|
JLabel nameLabel = new JLabel("Enter in your name: ");
|
||||||
|
|
||||||
// Create an input and set the width to be 10px wide
|
// Create an input and set the width to be 10px wide
|
||||||
JTextField nameInput = new JTextField(10);
|
JTextField nameInput = new JTextField(10);
|
||||||
//Override nameInput with a field already contains the text "Brandon"
|
//Override nameInput with a field already contains the text "Brandon"
|
||||||
|
@ -70,14 +72,14 @@ One of the most common forms of input is a text field, usually distinguished wit
|
||||||
|
|
||||||
this.add(nameLabel);
|
this.add(nameLabel);
|
||||||
this.add(nameInput);
|
this.add(nameInput);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/labeltextfield.png" alt="" width="274" height="24" class="alignnone size-full wp-image-2209" />
|
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/labeltextfield.png" alt="" width="274" height="24" class="alignnone size-full wp-image-2209" />
|
||||||
|
|
||||||
### Checkboxes
|
### Checkboxes
|
||||||
|
|
||||||
Checkboxes are commonly used when giving the possibility for multiple answers. Such as, check all of the foods that you like.
|
Checkboxes are commonly used when giving the possibility for multiple answers. Such as, check all of the foods that you like.
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
JCheckBox pizza = new JCheckBox("Pizza");
|
JCheckBox pizza = new JCheckBox("Pizza");
|
||||||
JCheckBox noodles = new JCheckBox("Noodles");
|
JCheckBox noodles = new JCheckBox("Noodles");
|
||||||
|
@ -85,12 +87,12 @@ Checkboxes are commonly used when giving the possibility for multiple answers. S
|
||||||
this.add(pizza);
|
this.add(pizza);
|
||||||
this.add(noodles);
|
this.add(noodles);
|
||||||
this.add(rice);
|
this.add(rice);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/checkboxes.png" alt="" width="206" height="40" class="alignnone size-full wp-image-2207" />
|
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/checkboxes.png" alt="" width="206" height="40" class="alignnone size-full wp-image-2207" />
|
||||||
|
|
||||||
You can even replace the default look of the checkbox with an image. To do this, you need to make image icons for both when it’s checked and when it’s unchecked.
|
You can even replace the default look of the checkbox with an image. To do this, you need to make image icons for both when it’s checked and when it’s unchecked.
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
Image checkedImage = this.getImage(this.getCodeBase(), "checked.png");
|
Image checkedImage = this.getImage(this.getCodeBase(), "checked.png");
|
||||||
Image uncheckedImage = this.getImage(this.getCodeBase(), "unchecked.png");
|
Image uncheckedImage = this.getImage(this.getCodeBase(), "unchecked.png");
|
||||||
|
@ -102,31 +104,31 @@ JCheckBox checkbox = new JCheckBox("Check Me", uncheckedIcon);
|
||||||
checkbox.setSelectedIcon(checkedIcon);
|
checkbox.setSelectedIcon(checkedIcon);
|
||||||
|
|
||||||
this.add(checkbox);
|
this.add(checkbox);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/unchecked.png" alt="" width="187" height="123" class="alignnone size-full wp-image-2213" />
|
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/unchecked.png" alt="" width="187" height="123" class="alignnone size-full wp-image-2213" />
|
||||||
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/checked.png" alt="" width="186" height="102" class="alignnone size-full wp-image-2208" />
|
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/checked.png" alt="" width="186" height="102" class="alignnone size-full wp-image-2208" />
|
||||||
|
|
||||||
### Text Areas
|
### Text Areas
|
||||||
|
|
||||||
Text Areas are different from text fields in which it is made to be able to hold multiple lines of text. It’s called JTextArea and its construction takes a width and height as it’s arguments.
|
Text Areas are different from text fields in which it is made to be able to hold multiple lines of text. It’s called JTextArea and its construction takes a width and height as it’s arguments.
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
JTextArea textarea = new JTextArea(10, 10);
|
JTextArea textarea = new JTextArea(10, 10);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
By default, when the someone inputs more text than the size can hold, it will automatically grow with the text inputted. To override this behaviour and instead introuduce scroll bars. One must define a ScrollPane and put the TextArea inside of it by using it as the scroll pane’s argument for its constructor.
|
By default, when the someone inputs more text than the size can hold, it will automatically grow with the text inputted. To override this behaviour and instead introuduce scroll bars. One must define a ScrollPane and put the TextArea inside of it by using it as the scroll pane’s argument for its constructor.
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
JScrollPane scrollPane = new JScrollPane(textarea);
|
JScrollPane scrollPane = new JScrollPane(textarea);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/textarea.png" alt="" width="119" height="149" class="alignnone size-full wp-image-2212" />
|
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/textarea.png" alt="" width="119" height="149" class="alignnone size-full wp-image-2212" />
|
||||||
|
|
||||||
### Radio Buttons
|
### Radio Buttons
|
||||||
|
|
||||||
Radio buttons are used for when you only want one out of many different options to be selected. For this, one needs to define a button group that houses the radio buttons for the user to choose from. This can be achieved with ButtonGroup and JRadioButton respectively.
|
Radio buttons are used for when you only want one out of many different options to be selected. For this, one needs to define a button group that houses the radio buttons for the user to choose from. This can be achieved with ButtonGroup and JRadioButton respectively.
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
// Make the radio buttons
|
// Make the radio buttons
|
||||||
JRadioButton radio1 = new JRadioButton("Pies");
|
JRadioButton radio1 = new JRadioButton("Pies");
|
||||||
|
@ -143,54 +145,54 @@ desserts.add(radio3);
|
||||||
this.add(radio1);
|
this.add(radio1);
|
||||||
this.add(radio2);
|
this.add(radio2);
|
||||||
this.add(radio3);
|
this.add(radio3);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/radiobuttons.png" alt="" width="211" height="34" class="alignnone size-full wp-image-2218" />
|
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/radiobuttons.png" alt="" width="211" height="34" class="alignnone size-full wp-image-2218" />
|
||||||
|
|
||||||
### JList
|
### JList
|
||||||
|
|
||||||
To display a list of items that are clickable by the user, you can use a `JList`. JLists require a model that stores the list implementation, we’ll use `DefaultListModel` to achieve this purpose.
|
To display a list of items that are clickable by the user, you can use a `JList`. JLists require a model that stores the list implementation, we’ll use `DefaultListModel` to achieve this purpose.
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
DefaultListModel model = new DefaultListModel();
|
DefaultListModel model = new DefaultListModel();
|
||||||
JList list = new JList(model);
|
JList list = new JList(model);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
To add scrolling capabilities, remember to add it to a scroll pane
|
To add scrolling capabilities, remember to add it to a scroll pane
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
JScollPane sp = new JScrollPane(list);
|
JScollPane sp = new JScrollPane(list);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
You can set the number of items you wish to see in the list. The example below, allows us to see three items in the list.
|
You can set the number of items you wish to see in the list. The example below, allows us to see three items in the list.
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
list.setVisibleRowCount(3);
|
list.setVisibleRowCount(3);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
There are a variety of ways to add items to the list. If a number is specified that tells it to place it at the index specified. Starting from the top at zero, to the button.
|
There are a variety of ways to add items to the list. If a number is specified that tells it to place it at the index specified. Starting from the top at zero, to the button.
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
model.addElement("Apples")
|
model.addElement("Apples")
|
||||||
model.addElement("Cherries");
|
model.addElement("Cherries");
|
||||||
model.addElement("Bananas");
|
model.addElement("Bananas");
|
||||||
// Adds 'Oranges' to the top
|
// Adds 'Oranges' to the top
|
||||||
model.add(0, "Oranges");
|
model.add(0, "Oranges");
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
Sometimes, you want to only let the user select one item. At the end, don’t forget to add the component to the screen!
|
Sometimes, you want to only let the user select one item. At the end, don’t forget to add the component to the screen!
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
this.add(sp);
|
this.add(sp);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/JList.png" alt="" width="77" height="53" class="alignnone size-full wp-image-2224" />
|
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/JList.png" alt="" width="77" height="53" class="alignnone size-full wp-image-2224" />
|
||||||
|
|
||||||
### JComboBox
|
### JComboBox
|
||||||
|
|
||||||
To create a dropdown list of different options, consider using a JComboBox.
|
To create a dropdown list of different options, consider using a JComboBox.
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
JComboBox cb = new JComboBox();
|
JComboBox cb = new JComboBox();
|
||||||
cb.addItem("Select Food Option");
|
cb.addItem("Select Food Option");
|
||||||
|
@ -200,6 +202,6 @@ cb.addItem("Hot Dog");
|
||||||
cb.addItem("Steak");
|
cb.addItem("Steak");
|
||||||
// Add it to the screen
|
// Add it to the screen
|
||||||
this.add(cb);
|
this.add(cb);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/JComboBox.png" alt="" width="153" height="24" class="alignnone size-full wp-image-2223" srcset="https://brandonrozek.com/wp-content/uploads/2017/06/JComboBox.png 153w, https://brandonrozek.com/wp-content/uploads/2017/06/JComboBox-150x24.png 150w" sizes="(max-width: 153px) 100vw, 153px" />
|
<img src="https://brandonrozek.com/wp-content/uploads/2017/06/JComboBox.png" alt="" width="153" height="24" class="alignnone size-full wp-image-2223" srcset="https://brandonrozek.com/wp-content/uploads/2017/06/JComboBox.png 153w, https://brandonrozek.com/wp-content/uploads/2017/06/JComboBox-150x24.png 150w" sizes="(max-width: 153px) 100vw, 153px" />
|
|
@ -1,45 +1,47 @@
|
||||||
---
|
---
|
||||||
id: 2192
|
id: 2192
|
||||||
title: Using System Themes In Java Swing
|
title: Using System Themes In Java Swing
|
||||||
date: 2017-06-05T20:36:22+00:00
|
date: 2017-06-05T20:36:22+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=2192
|
guid: https://brandonrozek.com/?p=2192
|
||||||
permalink: /2017/06/using-system-themes-java-swing/
|
aliases:
|
||||||
medium_post:
|
- /2017/06/using-system-themes-java-swing/
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
permalink: /2017/06/using-system-themes-java-swing/
|
||||||
mf2_syndicate-to:
|
medium_post:
|
||||||
- 'a:1:{i:0;s:4:"none";}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
mf2_cite:
|
mf2_syndicate-to:
|
||||||
- 'a:4:{s:9:"published";s:25:"0000-01-01T00:00:00+00:00";s:7:"updated";s:25:"0000-01-01T00:00:00+00:00";s:8:"category";a:1:{i:0;s:0:"";}s:6:"author";a:0:{}}'
|
- 'a:1:{i:0;s:4:"none";}'
|
||||||
tumblr_post_id:
|
mf2_cite:
|
||||||
- "161478693279"
|
- 'a:4:{s:9:"published";s:25:"0000-01-01T00:00:00+00:00";s:7:"updated";s:25:"0000-01-01T00:00:00+00:00";s:8:"category";a:1:{i:0;s:0:"";}s:6:"author";a:0:{}}'
|
||||||
mf2_syndication:
|
tumblr_post_id:
|
||||||
- 'a:1:{i:0;s:60:"https://twitter.com/B_RozekJournal/status/871828083459936257";}'
|
- "161478693279"
|
||||||
kind:
|
mf2_syndication:
|
||||||
- article
|
- 'a:1:{i:0;s:60:"https://twitter.com/B_RozekJournal/status/871828083459936257";}'
|
||||||
---
|
kind:
|
||||||
The default theme for Java Swing components is a cross-platform theme called “Metal”. I use the Adapta theme for GTK on Linux and this theme does not match at all what my other GUI applications look like. So here, I will describe a simple way to utlize already existent system themes in Java Swing applications.
|
- article
|
||||||
|
---
|
||||||
<!--more-->
|
The default theme for Java Swing components is a cross-platform theme called “Metal”. I use the Adapta theme for GTK on Linux and this theme does not match at all what my other GUI applications look like. So here, I will describe a simple way to utlize already existent system themes in Java Swing applications.
|
||||||
|
|
||||||
### Solution
|
<!--more-->
|
||||||
|
|
||||||
In the init method of your java application, place the following code.
|
### Solution
|
||||||
|
|
||||||
|
In the init method of your java application, place the following code.
|
||||||
|
|
||||||
<pre class='language-java'><code class='language-java'>
|
<pre class='language-java'><code class='language-java'>
|
||||||
try {
|
try {
|
||||||
UIManager.setLookAndFeel(UIManager
|
UIManager.setLookAndFeel(UIManager
|
||||||
.getSystemLookAndFeelClassName());
|
.getSystemLookAndFeelClassName());
|
||||||
} catch(Exception e) {}
|
} catch(Exception e) {}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
Here the application will attempt to look up the system theme and set that as the default styles for the Swing components. If the lookup fails, then it will default back to the metal theme.
|
Here the application will attempt to look up the system theme and set that as the default styles for the Swing components. If the lookup fails, then it will default back to the metal theme.
|
||||||
|
|
||||||
For more information, check out this page from [Oracle](http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html).
|
For more information, check out this page from [Oracle](http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html).
|
||||||
|
|
||||||
### Discussion
|
### Discussion
|
||||||
|
|
||||||
If it is so easy to set up applications that look native to each desktop environment, why not have that by default? With the cross platform metal theme, you can ensure that the style of your application is the same across all the operating systems. In this fashion, you don’t need to worry about spacing between components and have full control of the “look and feel” of your application.
|
If it is so easy to set up applications that look native to each desktop environment, why not have that by default? With the cross platform metal theme, you can ensure that the style of your application is the same across all the operating systems. In this fashion, you don’t need to worry about spacing between components and have full control of the “look and feel” of your application.
|
||||||
|
|
||||||
Since I am used to development for the web, I don’t have strong motivation to have an application look the same on all platforms. I prefer the application to match the system theme and look like it was built for the platform that I am on. One loses partial control on the presentation of your application across different desktop environmnets, but with a strong layout, it is possible to make it look organized and integrated.
|
Since I am used to development for the web, I don’t have strong motivation to have an application look the same on all platforms. I prefer the application to match the system theme and look like it was built for the platform that I am on. One loses partial control on the presentation of your application across different desktop environmnets, but with a strong layout, it is possible to make it look organized and integrated.
|
|
@ -5,6 +5,8 @@ date: 2017-08-28T17:12:00+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=2236
|
guid: https://brandonrozek.com/?p=2236
|
||||||
|
aliases:
|
||||||
|
- /2017/08/escape-sequences-java/
|
||||||
permalink: /2017/08/escape-sequences-java/
|
permalink: /2017/08/escape-sequences-java/
|
||||||
medium_post:
|
medium_post:
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
|
@ -28,12 +30,12 @@ Sometimes you want to format your outputs. This is a quick cheatsheet containing
|
||||||
<th class="tg-yw4l">
|
<th class="tg-yw4l">
|
||||||
Character
|
Character
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th class="tg-yw4l">
|
<th class="tg-yw4l">
|
||||||
Escape Sequence
|
Escape Sequence
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
Newline
|
Newline
|
||||||
|
@ -43,7 +45,7 @@ Sometimes you want to format your outputs. This is a quick cheatsheet containing
|
||||||
\n
|
\n
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
Tab
|
Tab
|
||||||
|
@ -53,7 +55,7 @@ Sometimes you want to format your outputs. This is a quick cheatsheet containing
|
||||||
\t
|
\t
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
Backspace
|
Backspace
|
||||||
|
@ -63,7 +65,7 @@ Sometimes you want to format your outputs. This is a quick cheatsheet containing
|
||||||
\b
|
\b
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
Double Quote
|
Double Quote
|
||||||
|
@ -73,7 +75,7 @@ Sometimes you want to format your outputs. This is a quick cheatsheet containing
|
||||||
\”
|
\”
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
Single Quote
|
Single Quote
|
||||||
|
@ -83,7 +85,7 @@ Sometimes you want to format your outputs. This is a quick cheatsheet containing
|
||||||
\’
|
\’
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
Backslash
|
Backslash
|
||||||
|
|
|
@ -1,127 +1,129 @@
|
||||||
---
|
---
|
||||||
id: 2241
|
id: 2241
|
||||||
title: Obtaining Command Line Input in Java
|
title: Obtaining Command Line Input in Java
|
||||||
date: 2017-08-28T17:37:59+00:00
|
date: 2017-08-28T17:37:59+00:00
|
||||||
author: Brandon Rozek
|
author: Brandon Rozek
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=2241
|
guid: https://brandonrozek.com/?p=2241
|
||||||
permalink: /2017/08/obtaining-command-line-input-java/
|
aliases:
|
||||||
medium_post:
|
- /2017/08/obtaining-command-line-input-java/
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
permalink: /2017/08/obtaining-command-line-input-java/
|
||||||
mf2_syndicate-to:
|
medium_post:
|
||||||
- 'a:1:{i:0;s:4:"none";}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";N;s:10:"author_url";N;s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";N;s:2:"id";N;s:21:"follower_notification";N;s:7:"license";N;s:14:"publication_id";N;s:6:"status";N;s:3:"url";N;}'
|
||||||
mf2_cite:
|
mf2_syndicate-to:
|
||||||
- 'a:4:{s:9:"published";s:25:"0000-01-01T00:00:00+00:00";s:7:"updated";s:25:"0000-01-01T00:00:00+00:00";s:8:"category";a:1:{i:0;s:0:"";}s:6:"author";a:0:{}}'
|
- 'a:1:{i:0;s:4:"none";}'
|
||||||
tumblr_post_id:
|
mf2_cite:
|
||||||
- "164717769554"
|
- 'a:4:{s:9:"published";s:25:"0000-01-01T00:00:00+00:00";s:7:"updated";s:25:"0000-01-01T00:00:00+00:00";s:8:"category";a:1:{i:0;s:0:"";}s:6:"author";a:0:{}}'
|
||||||
mf2_mp-syndicate-to:
|
tumblr_post_id:
|
||||||
- 'a:1:{i:0;s:4:"none";}'
|
- "164717769554"
|
||||||
kind:
|
mf2_mp-syndicate-to:
|
||||||
- note
|
- 'a:1:{i:0;s:4:"none";}'
|
||||||
---
|
kind:
|
||||||
To obtain console input for your program you can use the <code class="language-java">Scanner</code> class
|
- note
|
||||||
|
---
|
||||||
First import the relevant library
|
To obtain console input for your program you can use the <code class="language-java">Scanner</code> class
|
||||||
|
|
||||||
|
First import the relevant library
|
||||||
|
|
||||||
<pre class="language-java"><code class="language-java">
|
<pre class="language-java"><code class="language-java">
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
Then create a variable to hold the <code class="language-java">Scanner</code> object
|
Then create a variable to hold the <code class="language-java">Scanner</code> object
|
||||||
|
|
||||||
<pre class="language-java"><code class="language-java">
|
<pre class="language-java"><code class="language-java">
|
||||||
Scanner input;
|
Scanner input;
|
||||||
input = new Scanner(System.in);
|
input = new Scanner(System.in);
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
Inside the parenthesis, the <code class="language-java">Scanner</code> binds to the System input which is by default the console
|
Inside the parenthesis, the <code class="language-java">Scanner</code> binds to the System input which is by default the console
|
||||||
|
|
||||||
The new varible <code class="language-java">input</code> now has the ability to obtain input from the console. To do so, use any of the following methods
|
The new varible <code class="language-java">input</code> now has the ability to obtain input from the console. To do so, use any of the following methods
|
||||||
|
|
||||||
<table class="tg">
|
<table class="tg">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="tg-yw4l">
|
<th class="tg-yw4l">
|
||||||
Method
|
Method
|
||||||
</th>
|
</th>
|
||||||
|
|
||||||
<th class="tg-yw4l">
|
<th class="tg-yw4l">
|
||||||
What it Returns
|
What it Returns
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
next()
|
next()
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
The next space seperated string from the console
|
The next space seperated string from the console
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
nextInt()
|
nextInt()
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
An integer if it exists from the console
|
An integer if it exists from the console
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
nextDouble()
|
nextDouble()
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
A double if it exists from the console
|
A double if it exists from the console
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
nextFloat()
|
nextFloat()
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
A float if it exists from the console
|
A float if it exists from the console
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
nextLine()
|
nextLine()
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
A string up to the next newline character from the console
|
A string up to the next newline character from the console
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
hasNext()
|
hasNext()
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
Returns true if there is another token
|
Returns true if there is another token
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
close()
|
close()
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="tg-yw4l">
|
<td class="tg-yw4l">
|
||||||
Unbinds the Scanner from the console
|
Unbinds the Scanner from the console
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
Here is an example program where we get the user’s first name
|
Here is an example program where we get the user’s first name
|
||||||
|
|
||||||
<pre class="language-java"><code class="language-java">
|
<pre class="language-java"><code class="language-java">
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
|
|
@ -1,69 +1,71 @@
|
||||||
---
|
---
|
||||||
id: 2250
|
id: 2250
|
||||||
title: Identifying Misspelled Words in your Dataset with Hunspell
|
title: Identifying Misspelled Words in your Dataset with Hunspell
|
||||||
date: 2018-01-22T05:17:16+00:00
|
date: 2018-01-22T05:17:16+00:00
|
||||||
author: rozek_admin
|
author: rozek_admin
|
||||||
layout: post
|
layout: post
|
||||||
guid: https://brandonrozek.com/?p=2250
|
guid: https://brandonrozek.com/?p=2250
|
||||||
permalink: /2018/01/identifying-misspelled-words-dataset-hunspell/
|
aliases:
|
||||||
medium_post:
|
- /2018/01/identifying-misspelled-words-dataset-hunspell/
|
||||||
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";s:75:"https://cdn-images-1.medium.com/fit/c/200/200/1*06lotWcLMUnKZTN6-Th3IQ.jpeg";s:10:"author_url";s:32:"https://medium.com/@brandonrozek";s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";s:2:"no";s:2:"id";s:12:"c0ccd543b7e6";s:21:"follower_notification";s:3:"yes";s:7:"license";s:19:"all-rights-reserved";s:14:"publication_id";s:2:"-1";s:6:"status";s:6:"public";s:3:"url";s:104:"https://medium.com/@brandonrozek/identifying-misspelled-words-in-your-dataset-with-hunspell-c0ccd543b7e6";}'
|
permalink: /2018/01/identifying-misspelled-words-dataset-hunspell/
|
||||||
mf2_mp-syndicate-to:
|
medium_post:
|
||||||
- 'a:1:{i:0;s:22:"bridgy-publish_twitter";}'
|
- 'O:11:"Medium_Post":11:{s:16:"author_image_url";s:75:"https://cdn-images-1.medium.com/fit/c/200/200/1*06lotWcLMUnKZTN6-Th3IQ.jpeg";s:10:"author_url";s:32:"https://medium.com/@brandonrozek";s:11:"byline_name";N;s:12:"byline_email";N;s:10:"cross_link";s:2:"no";s:2:"id";s:12:"c0ccd543b7e6";s:21:"follower_notification";s:3:"yes";s:7:"license";s:19:"all-rights-reserved";s:14:"publication_id";s:2:"-1";s:6:"status";s:6:"public";s:3:"url";s:104:"https://medium.com/@brandonrozek/identifying-misspelled-words-in-your-dataset-with-hunspell-c0ccd543b7e6";}'
|
||||||
tumblr_post_id:
|
mf2_mp-syndicate-to:
|
||||||
- "169988632939"
|
- 'a:1:{i:0;s:22:"bridgy-publish_twitter";}'
|
||||||
mf2_syndication:
|
tumblr_post_id:
|
||||||
- 'a:1:{i:0;s:60:"https://twitter.com/B_RozekJournal/status/955308388384235521";}'
|
- "169988632939"
|
||||||
kind:
|
mf2_syndication:
|
||||||
- article
|
- 'a:1:{i:0;s:60:"https://twitter.com/B_RozekJournal/status/955308388384235521";}'
|
||||||
---
|
kind:
|
||||||
This article is based on one written by [Markus Konrad](https://datascience.blog.wzb.eu/author/markus_konrad/) at this link <a href='https://datascience.blog.wzb.eu/2016/07/13/autocorrecting-misspelled-words-in-python-using-hunspell/' target='_blank' >https://datascience.blog.wzb.eu/2016/07/13/autocorrecting-misspelled-words-in-python-using-hunspell/</a>
|
- article
|
||||||
|
---
|
||||||
I assume in this article that you have hunspell and it's integration with python installed. If not, please refer to the article mention above and follow the prerequisite steps.
|
This article is based on one written by [Markus Konrad](https://datascience.blog.wzb.eu/author/markus_konrad/) at this link <a href='https://datascience.blog.wzb.eu/2016/07/13/autocorrecting-misspelled-words-in-python-using-hunspell/' target='_blank' >https://datascience.blog.wzb.eu/2016/07/13/autocorrecting-misspelled-words-in-python-using-hunspell/</a>
|
||||||
|
|
||||||
This article is inspired from the need to correct misspelled words in the [Dress Attributes Dataset](https://archive.ics.uci.edu/ml/datasets/Dresses_Attribute_Sales). I'll share with you my initial pitfall, and what I ended up doing instead.
|
I assume in this article that you have hunspell and it's integration with python installed. If not, please refer to the article mention above and follow the prerequisite steps.
|
||||||
|
|
||||||
### Background Information
|
This article is inspired from the need to correct misspelled words in the [Dress Attributes Dataset](https://archive.ics.uci.edu/ml/datasets/Dresses_Attribute_Sales). I'll share with you my initial pitfall, and what I ended up doing instead.
|
||||||
|
|
||||||
Misspelled words are common when dealing with survey data or data where humans type in the responses manually. In the Dress Attributes Dataset this is apparent when looking at the sleeve lengths of the different dresses.
|
### Background Information
|
||||||
|
|
||||||
|
Misspelled words are common when dealing with survey data or data where humans type in the responses manually. In the Dress Attributes Dataset this is apparent when looking at the sleeve lengths of the different dresses.
|
||||||
|
|
||||||
<pre><code class='language-python' lang='python'>dresses_data['SleeveLength'].value_counts()
|
<pre><code class='language-python' lang='python'>dresses_data['SleeveLength'].value_counts()
|
||||||
</code></pre><figure>
|
</code></pre><figure>
|
||||||
|
|
||||||
| Word | Frequency |
|
| Word | Frequency |
|
||||||
| -------------- | --------- |
|
| -------------- | --------- |
|
||||||
| sleevless | 223 |
|
| sleevless | 223 |
|
||||||
| full | 97 |
|
| full | 97 |
|
||||||
| short | 96 |
|
| short | 96 |
|
||||||
| halfsleeve | 35 |
|
| halfsleeve | 35 |
|
||||||
| threequarter | 17 |
|
| threequarter | 17 |
|
||||||
| thressqatar | 10 |
|
| thressqatar | 10 |
|
||||||
| sleeveless | 5 |
|
| sleeveless | 5 |
|
||||||
| sleeevless | 3 |
|
| sleeevless | 3 |
|
||||||
| capsleeves | 3 |
|
| capsleeves | 3 |
|
||||||
| cap-sleeves | 2 |
|
| cap-sleeves | 2 |
|
||||||
| half | 1 |
|
| half | 1 |
|
||||||
| Petal | 1 |
|
| Petal | 1 |
|
||||||
| urndowncollor | 1 |
|
| urndowncollor | 1 |
|
||||||
| turndowncollor | 1 |
|
| turndowncollor | 1 |
|
||||||
| sleveless | 1 |
|
| sleveless | 1 |
|
||||||
| butterfly | 1 |
|
| butterfly | 1 |
|
||||||
| threequater | 1 |</figure>
|
| threequater | 1 |</figure>
|
||||||
|
|
||||||
Ouch, so many misspelled words. This is when my brain is racking up all the ways I can automate this problem away. Hence my stumbling upon Markus' post.
|
Ouch, so many misspelled words. This is when my brain is racking up all the ways I can automate this problem away. Hence my stumbling upon Markus' post.
|
||||||
|
|
||||||
### Automagically Correcting Data
|
### Automagically Correcting Data
|
||||||
|
|
||||||
First, I decided to completely ignore what Markus warns in his post and automatically correct all the words in that column.
|
First, I decided to completely ignore what Markus warns in his post and automatically correct all the words in that column.
|
||||||
|
|
||||||
To begin the code, let's import and create an instance of the spellchecker:
|
To begin the code, let's import and create an instance of the spellchecker:
|
||||||
|
|
||||||
<pre><code class='language-python' lang='python'>from hunspell import HunSpell
|
<pre><code class='language-python' lang='python'>from hunspell import HunSpell
|
||||||
spellchecker = HunSpell('/usr/share/hunspell/en_US.dic', '/usr/share/hunspell/en_US.aff')
|
spellchecker = HunSpell('/usr/share/hunspell/en_US.dic', '/usr/share/hunspell/en_US.aff')
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
I modified his `correct_words` function so that it only corrects one word and so I can `apply` it along the `SleeveLength` column.
|
I modified his `correct_words` function so that it only corrects one word and so I can `apply` it along the `SleeveLength` column.
|
||||||
|
|
||||||
<pre><code class='language-python' lang='python'>def correct_word(checker, word, add_to_dict=[]):
|
<pre><code class='language-python' lang='python'>def correct_word(checker, word, add_to_dict=[]):
|
||||||
"Takes in a hunspell object and a word and corrects the word if needed"
|
"Takes in a hunspell object and a word and corrects the word if needed"
|
||||||
# Add custom words to the dictionary
|
# Add custom words to the dictionary
|
||||||
|
@ -92,47 +94,47 @@ I modified his `correct_words` function so that it only corrects one word and so
|
||||||
## Not a string. Return original
|
## Not a string. Return original
|
||||||
corrected = word
|
corrected = word
|
||||||
return corrected
|
return corrected
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
Now let's apply the function over the `SleeveLength` column of the dataset:
|
Now let's apply the function over the `SleeveLength` column of the dataset:
|
||||||
|
|
||||||
<pre><code class='language-python' lang='python'>dresses_data['SleeveLength'] = dresses_data['SleeveLength'].apply(
|
<pre><code class='language-python' lang='python'>dresses_data['SleeveLength'] = dresses_data['SleeveLength'].apply(
|
||||||
lambda x: correct_word(spellchecker, x))
|
lambda x: correct_word(spellchecker, x))
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
Doing so creates the following series:<figure>
|
Doing so creates the following series:<figure>
|
||||||
|
|
||||||
| Word | Frequency |
|
| Word | Frequency |
|
||||||
| -------------- | --------- |
|
| -------------- | --------- |
|
||||||
| sleeveless | 232 |
|
| sleeveless | 232 |
|
||||||
| full | 97 |
|
| full | 97 |
|
||||||
| short | 96 |
|
| short | 96 |
|
||||||
| half sleeve | 35 |
|
| half sleeve | 35 |
|
||||||
| three quarter | 17 |
|
| three quarter | 17 |
|
||||||
| throatiness | 10 |
|
| throatiness | 10 |
|
||||||
| cap sleeves | 3 |
|
| cap sleeves | 3 |
|
||||||
| cap-sleeves | 2 |
|
| cap-sleeves | 2 |
|
||||||
| Petal | 1 |
|
| Petal | 1 |
|
||||||
| butterfly | 1 |
|
| butterfly | 1 |
|
||||||
| turndowncollor | 1 |
|
| turndowncollor | 1 |
|
||||||
| half | 1 |
|
| half | 1 |
|
||||||
| landownership | 1 |
|
| landownership | 1 |
|
||||||
| forequarter | 1 |</figure>
|
| forequarter | 1 |</figure>
|
||||||
|
|
||||||
As you might be able to tell, this process didn't go as intended. `landownership` isn't even a length of a sleeve!
|
As you might be able to tell, this process didn't go as intended. `landownership` isn't even a length of a sleeve!
|
||||||
|
|
||||||
### Reporting Misspelled Items and Allowing User Intervention
|
### Reporting Misspelled Items and Allowing User Intervention
|
||||||
|
|
||||||
This is when I have to remember, technology isn't perfect. Instead we should rely on ourselves to identify what the word should be correctly spelled as.
|
This is when I have to remember, technology isn't perfect. Instead we should rely on ourselves to identify what the word should be correctly spelled as.
|
||||||
|
|
||||||
Keeping that in mind, I modified the function again to take in a list of the data, and return a dictionary that has the misspelled words as the keys and suggestions as the values represented as a list.
|
Keeping that in mind, I modified the function again to take in a list of the data, and return a dictionary that has the misspelled words as the keys and suggestions as the values represented as a list.
|
||||||
|
|
||||||
<pre><code class='language-python' lang='python'>def list_word_suggestions(checker, words, echo = True, add_to_dict=[]):
|
<pre><code class='language-python' lang='python'>def list_word_suggestions(checker, words, echo = True, add_to_dict=[]):
|
||||||
"Takes in a list of words and returns a dictionary with mispellt words as keys and suggestions as a list. Also prints it out"
|
"Takes in a list of words and returns a dictionary with mispellt words as keys and suggestions as a list. Also prints it out"
|
||||||
# add custom words to the dictionary
|
# add custom words to the dictionary
|
||||||
for w in add_to_dict:
|
for w in add_to_dict:
|
||||||
checker.add(w)
|
checker.add(w)
|
||||||
|
|
||||||
suggestions = {}
|
suggestions = {}
|
||||||
for word in words:
|
for word in words:
|
||||||
if isinstance(word, str):
|
if isinstance(word, str):
|
||||||
|
@ -144,15 +146,15 @@ Keeping that in mind, I modified the function again to take in a list of the dat
|
||||||
elif echo:
|
elif echo:
|
||||||
print(word + ": " + "[", ", ".join(repr(i) for i in suggestions[word]), "]")
|
print(word + ": " + "[", ", ".join(repr(i) for i in suggestions[word]), "]")
|
||||||
return suggestions
|
return suggestions
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
With that, I can use the function on my data. To do so, I convert the pandas values to a list and pass it to the function:
|
With that, I can use the function on my data. To do so, I convert the pandas values to a list and pass it to the function:
|
||||||
|
|
||||||
<pre><code class='language-python' lang='python'>s = list_word_suggestions(spellchecker, dresses_data['SleeveLength'].values.tolist())
|
<pre><code class='language-python' lang='python'>s = list_word_suggestions(spellchecker, dresses_data['SleeveLength'].values.tolist())
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
These are the suggestions it produces:
|
These are the suggestions it produces:
|
||||||
|
|
||||||
<pre><code class='language-python' lang='python'>sleevless: [ 'sleeveless', 'sleepless', 'sleeves', 'sleekness', 'sleeve', 'lossless' ]
|
<pre><code class='language-python' lang='python'>sleevless: [ 'sleeveless', 'sleepless', 'sleeves', 'sleekness', 'sleeve', 'lossless' ]
|
||||||
threequarter: [ 'three quarter', 'three-quarter', 'forequarter' ]
|
threequarter: [ 'three quarter', 'three-quarter', 'forequarter' ]
|
||||||
halfsleeve: ['half sleeve', 'half-sleeve', 'sleeveless' ]
|
halfsleeve: ['half sleeve', 'half-sleeve', 'sleeveless' ]
|
||||||
|
@ -163,15 +165,15 @@ sleeevless: [ 'sleeveless', 'sleepless', 'sleeves', '
|
||||||
urndowncollor: [ 'landownership' ]
|
urndowncollor: [ 'landownership' ]
|
||||||
thressqatar: [ 'throatiness' ]
|
thressqatar: [ 'throatiness' ]
|
||||||
sleveless: [ 'sleeveless', 'levelness', 'valveless', 'loveless', 'sleepless' ]
|
sleveless: [ 'sleeveless', 'levelness', 'valveless', 'loveless', 'sleepless' ]
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
From here, you can analyze the output and do the replacements yourself:
|
From here, you can analyze the output and do the replacements yourself:
|
||||||
|
|
||||||
<pre><code class='language-python' lang='python'>dresses_data['SleeveLength'].replace('sleevless', 'sleeveless', inplace = True)
|
<pre><code class='language-python' lang='python'>dresses_data['SleeveLength'].replace('sleevless', 'sleeveless', inplace = True)
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
### What's the Benefit?
|
### What's the Benefit?
|
||||||
|
|
||||||
This is where you ask "What's the difference if it doesn't automatically fix my data?"
|
This is where you ask "What's the difference if it doesn't automatically fix my data?"
|
||||||
|
|
||||||
When you have large datasets, it can be hard to individually identify which items are misspelled. Using this method will allow you to have a list of all the items that are misspelled which can let you deal with it in a systematic way.
|
When you have large datasets, it can be hard to individually identify which items are misspelled. Using this method will allow you to have a list of all the items that are misspelled which can let you deal with it in a systematic way.
|
Loading…
Add table
Reference in a new issue