Skip to content

Commit

Permalink
handle gallery, and blog
Browse files Browse the repository at this point in the history
  • Loading branch information
zeyadetman committed Sep 25, 2021
1 parent a5c392e commit a3cd45d
Show file tree
Hide file tree
Showing 21 changed files with 2,696 additions and 203 deletions.
128 changes: 128 additions & 0 deletions blogs/another-way-to-write-your-javascript.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
title: Another way to write your JavaScript
date: "2019-09-09"
author: zeyadetman
tags:
- programming
- javascript
- frontend
comments: true
---

Hi all, in this post I'll share with you some frontend code, that we can write it in another way,
And everything is working well, doesn't break the rules or putting smells in code, is cool.

##1. Generate an array of sequential numbers `[1, 2, 3, ...., n]`

If we want to generate an array like this `[1, 2, 3, 4, 5, 6, ...., n]`, We can write code using `new Array()` with
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill">`Array.fill()`</a> so it'll be

```js
const N = 10;
new Array(N).fill().map((_, indx) => indx + 1); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```

<a href="https://docs.google.com/document/d/1FBxDuUJmUt_udO9ofJGXF4GAM2ZoiWI-PTEeq9Gbf1w/edit#heading=h.yf7gjfvrq7gx">_**Why `new Array(N).map()` doesn't work?**_</a>

Cool, But if we're working on a large array of sequential numbers, Is this method will be the best?
Mmmm, No! because `new Array()` creates <a href="https://v8.dev/blog/elements-kinds">a holey array</a>
which is slow compared to <a href="https://v8.dev/blog/elements-kinds">packed arrays</a>. So we can avoid this and re-write this method
using <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from">`Array.from()`</a>
So the code will be

```js
const N = 10;
Array.from({ length: N }, (_, indx) => indx + 1); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```

<figure style="margin: 15px">
<img src="https://i.imgur.com/UWkajiz.png" width="700px" alt="new array()" />
<i><figcaption>source: <a href="https://slidr.io/mathiasbynens/v8-internals-for-javascript-developers#102">
https://slidrio-decks.global.ssl.fastly.net/1259/original.pdf?1521622174</a> <br />slide: 102</figcaption></i>
</figure>

you can check the holey array in your Chrome Console, so if we write this `new Array(10)` your console will display
`[empty × 10]` which is an array of empty values.

More Resources:

1. https://v8.dev/blog/elements-kinds
2. https://stackoverflow.com/questions/3746725/how-to-create-an-array-containing-1-n

##2. Number formatting

Sometimes you want to write a money with specific currency `EGP 1000` or a size of something `50 kB` one of the ways to write it,
simply `const money = '1000 EGP'`. But there's a nicer way to write formatted numbers using <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat">`Intl.NumberFormat`</a>. So this strings will be

```js
const money = new Intl.NumberFormat("en", {
style: "currency",
currency: "EGP",
useGrouping: false,
maximumSignificantDigits: 1
}).format(1000);
// "EGP 1000"

const storage = new Intl.NumberFormat("en", {
style: "unit",
unit: "kilobyte"
}).format(50);
// "50 kB"
```

_Note: style `units` works on chrome 77+, so you can use babel to compile it._ <br />
This is so cool, if you're working on multiple locale and want to switch between them in a better and fully customized way.
More info from <a href="https://v8.dev/features/intl-numberformat">V8 Blog: Intl.NumberFormat</a>

##3. Styling NonInteracitve elements on focus
You can't do this using css/html without `tabindex` and according to [MDN][1]:

> Avoid using the `tabindex` attribute in conjunction with non-interactive content to make something intended to be interactive focusable by keyboard input. An example of this would be using an `<div>` element to describe a button, instead of the `<button>` element.
[and w3 says:][2]

> The content should be semantically described using interactive elements (`<a>`, `<button>`, `<details>`, `<input>`, `<select>`, `<textarea>`, etc.) instead.
So the best practice for this is using `addEventListener()` in `JavaScript`, But if you want to use `tabindex` don't forget to add `tabindex` to inner html content.

### Another solution

You don't have to use `tabindex` if you just want to change the `div` border.
you can use `:focus-within` and just change the border.

```css
.search-box {
margin-left: 1%;
outline: red;
border: 1px solid #fc3;
}

.search-input {
border: none;
}

.search-input:focus {
outline: none;
}

.search-box:focus-within {
border: 2px solid #53c9fc;
}
```

```html
<div class="search-box">
<Row>
<div class="search-box-icon"></div>
<input class="search-input" placeholder="search in listbox" />
</Row>
</div>
```

<a href="https://stackoverflow.com/a/55087153/5721245">_I published this as an answer on stackoverflow_</a>

Finally, I believe that everyone of us has a style writing code, his favorite practices that they don't break the rules,
or putting smells in code.

[1]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex#Accessibility_concerns
[2]: https://www.w3.org/TR/html401/interact/forms.html#adef-tabindex
22 changes: 22 additions & 0 deletions blogs/how-dropbox-knows-when-youre-sharing-copyrighted-stuff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: How Dropbox Knows When You’re Sharing Copyrighted Stuff?
date: "2017-06-30"
tags:
- technical
layout: post
author: zeyadetman
comments: true
---

<div dir="ltr"><strong>Hashing.</strong>
Before i dive in:

‘A’ is a criminal, he wants to rob a bank so he asked his friends ‘B’ and ‘C’ for help. They robbed the bank successfully but unfortunately ‘B’ had forgotten his gloves at home before the crime. The police officer got his fingerprint and after a few days from fingerprint matching, the police catch’em all.
Same thing for files, every tiny file has its unique fingerprint from characters and numbers like “ah4213jn234bmn53b” and even if you change the location or name or things like that the fingerprint not change at all - if you wanna see install this <a href="https://support.microsoft.com/en-us/help/841290/availability-and-description-of-the-file-checksum-integrity-verifier-utility" target="_blank" rel="noopener noreferrer">https://support.microsoft.com/en-us/help/841290/availability-and-description-of-the-file-checksum-integrity-verifier-utility</a> and have little fun - The dropbox has a big table with the fingerprints of the origin files and when you upload a file, a hash is generated and if its fingerprint exist the site blocked the uploaded one.

<img class="alignnone size-full wp-image-1763 img-fluid" src="https://zeyadetman.files.wordpress.com/2017/05/702px-fingerprint-svg.png" alt="702px-fingerprint-svg" width="702" height="600" /> <a href="https://upload.wikimedia.org/wikipedia/commons/thumb/0/09/Fingerprint.svg/702px-Fingerprint.svg.png" target="_blank" rel="noopener noreferrer">source</a><br>

It’s the same idea to store your password and username.
<a href="https://www.quora.com/profile/Zeyad-Etman" target="_blank" rel="noopener noreferrer">Follow me on quora</a>

</div>
102 changes: 102 additions & 0 deletions blogs/how-ive-been-using-google-sheets-as-personal-assistant.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
title: How I've been using Google Sheets as a personal assistant
author: zeyadetman
tags:
- technical
comments: true
layout: post
date: '2020-05-30'
---

Hello, In this post I’ll share with you How I've been using Google Sheets to track some of important things, Replacing almost all other productivity apps. In the beginning I want to note that not all things will be interesting to you, but I think you’ll find inspiration to do your own, and this is the goal of this post btw.
Not all following sheets created by me, and I’ll mention this in their sections.

## Money (Savings and Expenses)

<img src="https://i.imgur.com/DdZzm6n.png" width="700px" alt="Money sample" />

There’s a bunch of mobile apps to track your savings and expenses, I tried most of them, but any was customized as i want, so I found a great Money Tracking sheet that you have to give it a [try from here.](https://docs.google.com/spreadsheets/d/1l9l5JH4b9g7zqKTlylqWIhHnfWlBJzP2vqj9ET9K_Ok)

## Exchange Rate and Metals Tracking

You may need to be updated about currency conversion to your local currency, or you may be interested in following metal prices like silver or gold, So instead of searching and memorize the prices, or getting another app, I created a 'cronjob' or a trigger to get the data I want, then update the target sheet. To do this, Google sheets Allows us to write scripts into sheets or any G-suite app, you’re writing basically javascript with some additional helpers to access G-suite things in easy direct way, like access sheets with name, edit them, things like that, to know more about App Script [click here](https://developers.google.com/apps-script).
Okay, what I’ve done is adding a daily `USDtoEGP` exchange rate to a sheet — Thanks to [GOOGLEFINANCE](https://support.google.com/docs/answer/3093281) — , and in another sheet page getting the price of gold daily — I’ve not found a free api to do this so I scraped a website to work around this — in the next few lines I’ll explain how to do this in a super easy few lines of `gs` code.

A sample for this sheet

<img src="https://i.imgur.com/8jVQ9gU.png" width="700px" alt="usd to egp sample" />

1. You have to create a google sheet to populate the data into it.
2. Open your sheet then select tools > script editor. You’ll end up with something like this.

<img src="https://i.imgur.com/dketxDK.png" width="700px" alt="code editor" />

3. Here's my code to get the `USD to EGP` Exchange Rate from Google Finance

```javascript
function getUsdToEgpRate() {
const spreedSheet = SpreadsheetApp.openById(<sheetID>).getSheetByName('usdtoegp');
const today = new Date();
const todayFormatted = `${today.getFullYear()}, ${today.getMonth() + 1}, ${today.getDate()}`;
const row = [
today.toUTCString(),
1,
'USD',
'Equals',
`=REGEXREPLACE(TO_TEXT(index(GOOGLEFINANCE("CURRENCY:USDEGP", "price", date(${todayFormatted})), 2, 2)), "٫", ".")`,
'EGP'
];
spreedSheet.appendRow(row);
}
```

I want to say two things here:
first, To get `sheetID`, if your sheet url is `https://docs.google.com/spreadsheets/d/blabla/edit` then `blabla` is your `sheetID`. second, Why I used `REGEXREPLACE` to convert comma to dot to easily do calculations on its value.

4. Try to run this code, It should work!
5. To create a trigger to run this script as a cronjob, you'll see a timer icon called `triggers` click on it then do whatever you want.
Super Easy, Ha?

### Metal tracker

<img src="https://i.imgur.com/SpZrXfR.png" width="700px" alt="gold price sample" />

For the Metal tracker, As I told you before I didn't find a free solution to get an instant price for gold, So I created a little script using [`puppeteer`](https://github.com/puppeteer/puppeteer) to scrape a website to get the data through api, then calling it in the script, and here's my final `gs` script:

```javascript
function goldPrice() {
const spreedSheet = SpreadsheetApp.openById('<sheetID>').getSheetByName(
'goldprice',
);
const today = new Date();

const response = UrlFetchApp.fetch('<API_ENDPOINT>');
const price = JSON.parse(response.getContentText())['price'];

const row = [today.toUTCString(), 1, 'Gram', 'Equals', price];
spreedSheet.appendRow(row);
}
```

You may notice that in the code above i didn't write the scraping code, the reason that I've a repository to just handle like stuff in an external place, you can write it in your own way, BTW I used [`Heroku`](http://heroku.com/) to deploy the scraping code that written in NodeJS.

Whatever you want to do, You'll find a way in google sheets.

## Jobs

<img src="https://i.imgur.com/QeEiBDI.png" width="700px" alt="Job tracking" />

Job tracking is another thing you may want to track in your life, you got the job or not, what was the offer, when you started, when you left, things like this will be cool to know what's your situation in your career, what're the campanies you know, ...etc. for this I found a [nice sheet to track this.](https://docs.google.com/spreadsheets/d/1eyJVRfGc5kGz5cfBYZpANosd4JRfWHc98BlD95Vsiog)
Also there's a tricks to do more, you can connect this sheet with your gmail, and add a new column to the emails recieved from the company, or what you want, But I'm using Gmail labels for kinda stuff.

## Twitter Archive

<img src="https://i.imgur.com/I6K8wTi.png" width="700px" alt="twitter archive sheet" />

If you're using Twitter to learn or getting updates/tricks/important tweets of specific field/topic to retrieve them again, you will need to search in your tweets, re-tweets, or likes one day, So I'm using `IFTTT` to fill a sheet from whatever i do on twitter. Here's what can you do. [Google sheet](https://ifttt.com/google_sheets) and [Twitter](https://ifttt.com/twitter).

## IFTTT Things

If you don't know `IFTTT` then you have to give it a try, it works in this way > if this then that, in more details words (whenever this happens, then do that), I'm using it to keep tracking of new phone contacts in a sheet, and a little other things as well.

I didn't mention everything in this post, I want to inspire you how can you track most of your daily/occasionally stuff. And my sheet templates recommendations as well. I'll update the post whenever I found a good thing to say.
65 changes: 65 additions & 0 deletions blogs/javascript-and-object-keys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
title: JavaScript and Object Keys
date: "2020-01-06"
author: zeyadetman
tags:
- programming
- javascript
- frontend
comments: true
layout: post
---

Hello 👋 In this post we will try to use objects in a different wrong way 😃 by implement a frequency array in javascript.
But before we dive into this, We will discover what's the frequency array?

## Frequency Array on a sorted array
For example, If you have an array like this `const arr = [1,2,2,3,3,4];` and you want to count occurrences of each element, then you can iterate over the values and store them as keys of object and its value increasing according to the number of occurrences in the remainig array. And this is called a frequency array. The code below go through what I'm saying (Please Don't do this again):

```js
const arr = [1,2,2,3,3,4];
const result = {};
for(let i=0; i<arr.length; i++){
if(arr[i] in result) result[arr[i]]++;
else result[arr[i]] = 1;
}

console.log(result); // {1: 1, 2: 2, 3: 2, 4: 1}
```

Wow! that's cool and Right! But No. That's wrong! Why??
You're write this code and seems that works well, but try to add `-1` to the first of your array, then you'll discover that the final result is `{1: 1, 2: 2, 3: 2, 4: 1, -1: 1}`, Wait... But Why? You're wondering why the `-1` is in the end of the result object and you know the object in javascript sorting the keys by default. (Ummm not exactly!)
Objects' Keys in Javascript are `strings` and `symbols` only, you can't use any primitive values as keys except `strings` and `symbols` So the keys in your result aren't `numbers`, they're parsed to `strings` before storing as keys in object, but `"-1" < "1" === true` so still why `-1` moved to the end?!

*Note: `Symbol` Can be a key for objects, but it doesn't work like `strings`. [Read more...](https://2ality.com/2014/12/es6-symbols.html)*

## How Javascript objects order their keys?
Keys in Javascript objects are three types, +integer-like (0,1,2,3), strings, and symbols. And the order goes:
1. +Integer-like in ascending order. `-1` like our previous example or negatives in general aren't valid as an index, there's no `-1` index, So they're ordered as `strings`.
2. Strings in order of created, without any sort or comparison.
3. Symbols in order of created, without any sort or comparison.

Okay, So in our previous example, we figured out what happens while getting the result, Right?
But what if we want to get the right order?

## new Map()
To achieve our frequency array respecting keys insertion order we can use `new Map()` which allows keys to be anytype, so the code for this will be like this:

```js
const arr = [-1,1,2,3,4,3,2];
var result = new Map();
for(let i=0; i<arr.length; i++){
if(result.has(arr[i])) {
result.set(arr[i], result.get(arr[i])+1);
}
else result.set(arr[i], 1);
}

console.log(result); //Map(5) {-1 => 1, 1 => 1, 2 => 2, 3 => 2, 4 => 1}
```
Then we can iterate over it using `forEach` method.

## Resources
- [Symbols in ECMAScript 6](https://2ality.com/2014/12/es6-symbols.html)
- [14.4.2 Traversal order of properties](https://exploringjs.com/es6/ch_oop-besides-classes.html#_traversal-order-of-properties)
- [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)
16 changes: 12 additions & 4 deletions components/CareerStack/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
import { HStack, Stack, Text } from '@chakra-ui/layout';
import { HStack, Stack, Text, Badge } from '@chakra-ui/layout';
import React from 'react';

interface Props {}

function CareerStack(props: { career: { company: string; date: string } }) {
const { company, date } = props.career;
function CareerStack(props: {
career: { company: string; date: string; techStack: [string] };
}) {
const { company, date, techStack } = props.career;
const renderJobStack = () => {
return techStack.map((tech) => <Badge size="xs">{tech}</Badge>);
};

return (
<Stack key={company}>
<HStack justify="space-between">
<Text>{company}</Text>
<Text fontWeight="bold" fontSize="lg">
{company}
</Text>
<Text color="gray.500" fontSize="sm">
{date}
</Text>
</HStack>
<HStack>{renderJobStack()}</HStack>
</Stack>
);
}
Expand Down
15 changes: 13 additions & 2 deletions components/Layout/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Box, Container } from '@chakra-ui/layout';
import { useSession } from 'next-auth/client';
import React from 'react';
import { useRouter } from 'next/router';
import React, { useState } from 'react';
import Footer from '../Footer';
import Navbar from '../Navbar';

Expand All @@ -10,11 +11,21 @@ interface Props {

function Layout(props: Props) {
const [session, loading] = useSession();
const [disable, setEnabled] = useState(true);
const { children } = props;
const router = useRouter();

//remove this
if (loading) return null;
if (localStorage.getItem('zoz') === 'hacker') {
setEnabled(false);
} else {
if (router.asPath !== '/') {
router.push('/');
}
}

return (
return disable ? null : (
<Container maxW={'80ch'} px={4} py={6}>
<Navbar user={session?.user} />
<Box px={10} py={10}>
Expand Down
Loading

0 comments on commit a3cd45d

Please sign in to comment.