Stworzenie sitemapy w node.js

Ma艂y przyjemny kod 馃槈
Na pocz膮tku pobieramy wszystkie pliki z foldera build za pomoc膮 readdir, nast臋pnie p臋telka po tych plikach. Robimy split po kropce aby dobra膰 si臋 do rozszerzenia a interesuje nas oczywi艣cie html
Je偶eli rozszerzeniem oka偶e si臋 html to wszystko pakujemy do tablicy urlPart.
Na ko艅cu budujemy xml sitemap i zapisujemy to przez writeFile i to tyle.

const fs = require("fs");

const htmlPlace = "build";
const ulrPart = [];

fs.readdir(`${htmlPlace}`, function (err, files) {
    if (err)
        throw err;
    for (let index in files) {
        let rest = files[index].split('.')[1];
        if (rest === 'html') {
            let path = `
                <url>
                    <loc>http://blog.grzegorztomicki.pl/${files[index]}</loc>
                    <changefreq>monthly</changefreq>
                </url>
            `;
            ulrPart.push(path);
        }

    }

    const template = `
        <?xml version="1.0" encoding="UTF-8"?>
        <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
            ${ulrPart.join('')}</urlset>`;

    fs.writeFile(`./sitemap.xml`, template, function (err) {});
});

艁adowanie CSS i CSS modules w tym samym czasie Webpack

W react mo偶emy importowa膰 css jak i css jako modu艂y.
Ale co je艣li chcemy zrobi膰 do w tym samym czasie powiedzmy doda膰 globalny styl np. normalize.css?

Importowanie jako modu艂:

import React from 'react'
import styles from './moj-komponent.css';

const MyComponent => <div className={styles.jakasKlasa}></div>

No ale jak u偶y膰 css powiedzmy jakie艣 zewn臋trznej biblioteki:

import React from 'react'
import './moj-komponent-zewnetrzny.css';

const MyComponent => <div className="jakasKlasa"></div>

Aby tego dokona膰 nale偶y zmodyfikowa膰 webpack. Ja korzystam z create-react-app i modyfikuj臋 zar贸wno wersj臋 dev jak i prod webpacka.

module: {
    rules: [
        {
            // wcze艣niej by艂o /\.css$/
            test: /^(?!.*?\.module).*\.css$/,
           
            // dalej zostawiamy jak by艂o czyli
            use: [
              require.resolve('style-loader'),
              {
                loader: require.resolve('css-loader'),
                options: {
                  importLoaders: 1,
                  modules: true,
                  localIdentName: '[name]__[local]__[hash:base64:5]'
                },
                ...
        },
        // dodajemy nast臋pn膮 regu艂臋 dla zewn臋trznych css
        {
            test: /\.module\.css$/,
            use: [
                require.resolve('style-loader'),
                require.resolve('css-loader')
            ],
        },
    ]
}

Teraz mo偶emy u偶y膰 w jednym komponencie zar贸wno css modu艂贸w jak i zewn臋trznych bibliotek.
Nale偶y pami臋ta膰 偶e zewn臋trzny komponent musi mie膰 w nazwie *.module.css

import React from 'react'
import styles from './moj-komponent.css';
import './jakis-zewnetrzny.module.css'

const MyComponent => <div className={`${styles.jakasKlasa} jakas-klasa-z-zewnatrz`}></div>

W wersji produkcyjnej webpack kopiuj臋 ca艂膮 regu艂臋 css i wstawiam poni偶ej,
zmieniam test: /\.css$/, na test: /\.module\.css$/,
Ustawiam modules: false i tyle.

Importowanie absolutne w Create React App

Jak pozby膰 si臋 zagnie偶d偶onych 艣cie偶ek w pejekcie.
Np. taka nie艂adna 艣cie偶ka jak poni偶ej.

import TopImage from '../../../components/TopImage/TopImage';

Chcemy mie膰 co艣 takiego, czy do foldera components czy do containers czy innych folder贸w w src.

import TopImage from 'components/TopImage/TopImage';

Najpro艣ciej jak mo偶na to tworzymy plik w folderze src o nazwie .env tak z kropk膮 na pocz膮tku.
W nim wpisujemy NODE_PATH=src/ robimy save i uruchamiamy project jak zwykle przez npm run start

Od tej chili zamiast podawa膰 ca艂膮 艣cie偶k臋 podajemy components, containers, hoc czy inne foldery jakie mamy w projekcie.

Innym sposobem jest modyfikacja package.json

"scripts": {
  "start": "react-scripts start",
  "build": "react-scripts build"
}

Dodajemy NODE_PATH=src/

"scripts": {
   "start": "NODE_PATH=src/ react-scripts start",
   "build": "NODE_PATH=src/ react-scripts build"
}

Jest jeden problem z u偶ytkownikami windowsa jak zwykle 馃槈 NODE_PATH=src/ w package.json nie zadzia艂a.
Nale偶y zainstalowa膰 modu艂 cross-env czyli npm install –save-dev cross-env i zmodyfikowa膰 package.json, oczywi艣cie to tylko w wypadku windowsa.

"scripts": {
   "start": "cross-env NODE_PATH=src/ react-scripts start",
   "build": "cross-env NODE_PATH=src/ react-scripts build"
}

I to tyle chyba ten pierwszy spos贸b jest mniej inwazyjny i powinien zadzia艂a膰 na wszystkich platformach.

Wys艂anie formularza w React

Proste wys艂anie formularza w React do tego axios czyli biblioteka oparta na obiektach HTTP dla przegl膮darek i Node.js wi臋cej mo偶na przeczyta膰 tutaj – axios

import React, { Component } from 'react';
import axios from 'axios';

class UserForm extends Component {
    state = {
        imie: '',
        nazwisko: '',
        email: '',
    };

    onChange = (event) => {
        const state = this.state
        state[event.target.name] = event.target.value;
        this.setState(state);
    }

    onSubmit = (event) => {
        event.preventDefault();
        const { imie, nazwisko, email } = this.state;

        axios.post('/', { imie, nazwisko, email })
            .then((result) => {
                // a tuj co艣 robimy z danymi
            });
    }

    render() {
        const { imie, nazwisko, email } = this.state;
        return (
            <form onSubmit={this.onSubmit}>
                <input type="text" name="imie" value={imie} onChange={this.onChange} />
                <input type="text" name="nazwisko" value={nazwisko} onChange={this.onChange} />
                <input type="text" name="email" value={email} onChange={this.onChange} />
                <button type="submit">Wy艣lij</button>
            </form>
        );
    }
}

export default UserForm;

ES6, var vs let

Przyk艂ad u偶ycia let oraz var

for (var i = 0; i < 5; ++i) {
  setTimeout(function () {
    console.log(i); // Wynik 5 razy 5 :)
  }, 100);  
}
for (let i = 0; i < 5; ++i) {
  setTimeout(function () {
    console.log(i); // Wynik 0, 1, 2, 3, 4
  }, 100);  
}

呕eby to wykona膰 bez let mo偶na by zrobi膰 tak jak poni偶ej.

for (var i = 0; i < 5; ++i) {
    (function(n) {
        setTimeout(function(){
            console.log(n); // Wynik 0, 1, 2, 3, 4
        }, 100);
    }(i));
}

Object.keys, values, entries

Poni偶ej kilka przyk艂ad贸w jak dobra膰 si臋 do obiekt贸w 馃檪

var codes = {
  reset: [0, 0],
  bold: [1, 22]
};

Object.keys(codes).forEach(function (key) {
  console.log(key); // "reset", "bold"
});

Object.values(codes).forEach(function (key) {
  console.log(key); // [0,0] [1,22]
});

Object.entries(codes).forEach(function (key) {
  console.log(key); // ["reset", [0, 0]] ["bold", [1, 22]]
});

U偶ycie operator spread syntax czyli […]

W ES6 pojawi艂a si臋 nowa funkcjonalno艣膰 nazywana „Spread syntax” operacje na tablicach czy obiektach. Poni偶ej kilka przyk艂ad贸w u偶ycia. W ES5 jest to concat.

W ES6

const boys = ["Ja艣", "Grze艣", "Ada艣"];
const girls = ["Ma艂gosia", "Ania", "Czesia"];

let people = [...boys, ...girls];

console.log(people); // ["Ja艣", "Grze艣", "Ada艣", "Ma艂gosia", "Ania", "Czesia"]

W ES5

const boys = ["Ja艣", "Grze艣", "Ada艣"];
const girls = ["Ma艂gosia", "Ania", "Czesia"];

let people = boys.concat(girls);

console.log(people); // ["Ja艣", "Grze艣", "Ada艣", "Ma艂gosia", "Ania", "Czesia"]

Inny przyk艂ad:

const divs = document.querySelector('div');

// u偶ycie call
[].foreach.call(divs, function(div) {
   console.log(div);
});

// u偶ycie spread
[...divs].foreach(div => {
    console.log(div)
}

show/hide scroll React

Ukrywanie buttona scroll-top je偶eli wysoko艣膰 przekroczy 200 oraz dodanie obs艂ugi zdarzenia na onClick i wywo艂anie funkcji scrollToTop i metody scrollIntoView.

export default BackToTop extends Component {
    state = {
        scrolling: false,
        scrollPosHeight: 200
    }

    componentDidMount() {
        console.log('componentDidMount()');
        window.addEventListener('scroll', this.hideShowButtonTop);
    };

    componentWillUnmount() {
        console.log('componentWillUnmount()');
        window.removeEventListener('scroll', this.hideShowButtonTop);
    };

    hideShowButtonTop = () => {
        const scrollPos = window.pageYOffset || document.documentElement.scrollTop;
        const myDiv = document.querySelector('.back-to-top');
        (scrollPos > this.state.scrollPosHeight && scrollPos !== 0) ? myDiv.style.display = 'block' : myDiv.style.display = 'none';
    }

    scrollToTop() {
        const logoView = document.getElementById('logo');
        logoView.scrollIntoView({
            behavior: 'smooth'
        })
    }

    render() {
        return (
            <div onClick={this.scrollToTop} className="back-to-top"></div>
        )
    };
};

forEach, filter, map, sort, reduce

Troch臋 operacji na tablicach 馃檪

const employments = [
  { name: 'Andrzej', category: 'Finanse', start: 1982, end: 2017 },
  { name: 'Agnieszka', category: 'Sprzeda偶', start: 1992, end: 2008 },
  { name: 'Mariola', category: 'Samochody', start: 1991, end: 2007 }
];

const digits = [23, 22, 10, 1, 5, 54, 25, 24, 21];

Chcemy pobra膰 imi臋 pracownika.
Najpierw w starym stylu.

for (let i = 0; i < employments.length; i++) {
  console.log(employments[i].name); // Andrzej, Agnieszka, Mariola
}

forEach – teraz pobierzemy przez forEach

employments.forEach(function(employment) {
  console.log(employment.name);
});

Mo偶emy to zrobi膰 jeszcze szybciej prze ES6

employments.forEach(employment => {
  console.log(employment.name);
});

filter – u偶yjemy teraz filter aby pobra膰 liczb臋 21 lub wi臋ksz膮

Najpierw w starym stylu.

let digitNumber = [];
for(let i = 0; i < digits.length; i++) {
  if(digits[i] >= 21) {
    digitNumber.push(digits[i]);
  }
}

console.log(digitNumber); // 23, 22, 54, 25, 24, 21

Teraz kr贸cej 馃檪

const digitNumber = digits.filter(function(digit) {
  if(digit >= 21) {
    return true;
  }
});

console.log(digitNumber);

I jeszcze kr贸cej.

const digitNumbers = digits.filter(digit => digit >= 21);

console.log(digitNumbers);

A mo偶e by tak wyszuka膰 osoby po kategorii np. Technologie

const retailEmployments = employments.filter(function(employment) {
  if(employment.category === 'Samochody') {
    return true;
  }
});

console.log(retailEmployments); // { category: "Samochody", end: 2007, name: "Mariola", start: 1991 }

A mo偶e da si臋 jeszcze szybciej

const retailEmployments = employments.filter(employment => employment.category === 'Samochody');

console.log(retailEmployments);
const eightiesEmployments = employments.filter(employment => (employment.start >= 1980 && employment.start < 1990));

console.log(eightiesEmployments); // { category: "Finanse", end: 2017, name: "Andrzej", start: 1982 }

map – u偶yjmy map
Utworzymy tablice imion.

const employmentsNames = employments.map(function(employment) {
  return employment.name;
});

console.log(employmentsNames); // Andrzej, Agnieszka, Mariola

Mo偶emy po艂膮czy膰 to z template.

const testEmployments = employments.map(function(employment) {
  return `${employment.name} [${employment.start} - ${employment.end}]`;
});

console.log(testEmployments); // ["Andrzej [1982 - 2017]", "Agnieszka [1992 - 2008]", "Mariola [1991 - 2007]"]

Lub nawet kr贸cej.

const testEmployments = employments.map(
  employment => `${employment.name} [${employment.start} - ${employment.end}]`
);

console.log(testEmployments);

Mo偶emy wielokrotnie u偶y膰 map.

const testDigits = digits
  .map(digit => Math.sqrt(digit))
  .map(digit => digit * 3);

console.log(testDigits); // [14.387494569938157, 14.071247279470288, 9.486832980505138, 3, 6.708203932499369, 22.045407685048602, 15, 14.696938456699067, 13.74772708486752]

sort – teraz przechodzimy do sort

const sortEmployments = employments.sort(function(ec1, ec2) {
  if(ec1.start > ec2.start) {
    return 1;
  } else {
    return -1;
  }
});

console.log(sortEmployments);
/*
{
  category: "Finanse",
  end: 2017,
  name: "Andrzej",
  start: 1982
}, [object Object] {
  category: "Samochody",
  end: 2007,
  name: "Mariola",
  start: 1991
}, [object Object] {
  category: "Sprzeda偶",
  end: 2008,
  name: "Agnieszka",
  start: 1992
}
*/

Wersja skr贸cona.

const sortEmployments = employments.sort((a, b) => (a.start > b.start ? 1 : -1));

console.log(sortEmployments);

reduce – u偶yjmy reduce

let digitSum = 0;
for(let i = 0; i < digits.length; i++) {
  digitSum += digits[i];
}

console.log(digitSum); // 185

Inna wersja reduce.

const digitSum = digits.reduce(function(total, digit) {
  return total + digit;
}, 0);

console.log(digitSum); // 185
const digitSum = digits.reduce((total, age) => total + age, 0);

console.log(digitSum); // 185

I na koniec 艂膮czenie wszystkich metod.

const combined = digits
 .map(digit => digit * 2)
 .filter(digit => digit >= 40)
 .sort((a, b) => a - b)
 .reduce((a, b) => a + b, 0);

console.log(combined); // 338

Odczyt atrybut贸w elementu w obs艂udze zdarzena w javascript

<select name="banner_url" onchange="var idx=this.selectedIndex;
var value=this.options[idx].getAttribute('banner_url');
var element = document.getElementById('img_banner_url');
element.setAttribute('src', value); element.style.display='block'">


!{section name=ii loop=$data}!
    !{capture assign=banner_url}!http://kody.wig.pl/!{/capture}!
    <option value="!{$banner_url}!" banner_url="!{$banner_url}!">
    !{$data[ii].name}! ---> !{$banner_url}!</option>
!{/section}!

</select>
<br><br>

<img src="" id="img_banner_url" style="display:none">