Для получения полного доступа
зарегистрируйтесь


В некоторых случаях требуется выдеруть из URL параметры или текущюю локализацию и еще что-нибудь, для этого и существует данный скрипт. Применяем очень просто

parseUrl('https://gostash.it/ru/stashes/create?type=snippet')

В ответ получаем следующее:

{
    "protocol":"https:",
    "host":"gostash.it",
    "hostname":"gostash.it",
    "pathname":"/ru/stashes/create",
    "search":"?type=snippet",
    "hash":""
}

Сам скрипт:

  function parseUrl(href) {
    const match = href.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/);

    return {
      protocol: match[1],
      host: match[2],
      hostname: match[3],
      port: match[4],
      pathname: match[5],
      search: match[6],
      hash: match[7],
    };
  }

Простая в использовании библиотека, позволяет строить красивые графики использую <canvas>.

Фичи

— Библиотека содержит 8 типов графиков
— Графики адаптивны — будут выглядеть везде хорошо, как на десктопах, так и на мобильных устройствах
— Можно совмещать разные типы графиков
— Отличная документация
— Простое API

Теперь покажу пример подключения и использования библиотеки, и перейдём к типам видов графиков (картинки).

Продолжение

Плюсом данного фреймворка является то, что написав код для бота, он будет работать для множества платформ:

  1. Slack
  2. Telegram
  3. Microsoft Bot Framework
  4. Nexmo
  5. HipChat
  6. Facebook Messenger

Кроме того, вы можете определять как будет вести себя команда для определённого мессенджера. Например, так:

// Restrict to Slack and Telegram driver
$botman->hears('keyword', function(BotMan $bot) {
    // do something to respond to message
    $bot->reply('You used a keyword!');
})->driver([SlackDriver::DRIVER_NAME, TelegramDriver::DRIVER_NAME]);
SELECT * ,
    DATE_ADD(
        birthday, 
        INTERVAL IF(DAYOFYEAR(birthday) >= DAYOFYEAR(CURDATE()),
            YEAR(CURDATE())-YEAR(birthday),
            YEAR(CURDATE())-YEAR(birthday)+1
        ) YEAR
    ) AS `next_birthday`  
FROM `users` 
WHERE 
    `birthday` IS NOT NULL
ORDER BY DATEDIFF(CURDATE(), `next_birthday`) DESC

Как написали в комментариях к моему сниппету, 58kb довольно много для инпута от которого нужен только поиск.Правда этот вариант требует jQuery, но, нет проблем переписать на Vanila JS.

Покажу сразу результат того, что у нас получится:

А теперь, к делу. Для начала добавим общий скелет:

Продолжение

<?php
/**
* Разбивает массив на чанки размером [n,2n-1]
*/
function array_chunk_min($list, $minSize){
	$listCount = count($list);
	$chunks = array_chunk($list, $minSize);
	$chunksCount = count($chunks);
	if ($listCount > $minSize && count($chunks[$chunksCount - 1]) % $minSize > 0) {
		$chunks[$chunksCount - 2] = array_merge($chunks[$chunksCount - 2], $chunks[$chunksCount - 1]);
		array_pop($chunks);
	}
	return $chunks;
}
print_r(array_chunk_min(range(1,45),20)); // [[1...20],[21...45]]
print_r(array_chunk_min(range(1,19),20)); // [[1...19]]

На сайте Designmodo предоставлена большая подборка плагинов, без дополнительных библиотек типа jQuery.

В подборке есть плагин для модальных окон, сладер, проигрыватель видео, кастомный скроллбар и много другое. Вот список некоторых, интересных плагинов на мой взгляд.

Plyr (Github)
Красивый плеер для воспроизведения видео с таких сервисов как Youtube, Vimeo

Продолжение

<!-- Позволяет избежать дублирование индексации контента -->
<!-- http://www.searchengines.ru/kak_pravilno_is_rel_canonical.html -->
<link rel="canonical" href="https://example.com/2010/06/9-things-to-do-before-entering-social-media.html">

<!-- Короткая ссылка на документ. Не рекомендуется к использованию, т. к. может порождать дубли страниц при индексации -->
<link rel="shortlink" href="https://example.com/?p=42">

<!-- Ссылка на AMP-версию -->
<!-- https://support.google.com/webmasters/answer/6340290?hl=ru -->
<link rel="amphtml" href="https://example.com/path/to/amp-version.html">

<!-- Ссылка на CSS-файл -->
<link rel="stylesheet" href="https://example.com/styles.css">

<!-- Ссылка на JSON-файл, который описывает установку веб-приложения -->
<link rel="manifest" href="manifest.json">

<!-- Ссылка на автора документа -->
<link rel="author" href="humans.txt">

<!-- Cсылка на страницу с авторскими правами, согласно которым предоставляется текущий документ -->
<link rel="copyright" href="copyright.html">

<!-- Ссылка на другую языковую версию документа -->
<link rel="alternate" href="https://es.example.com/" hreflang="es">

<!-- Информация об авторе -->
<link rel="me" href="https://google.com/profiles/thenextweb" type="text/html">
<link rel="me" href="mailto:name@example.com">
<link rel="me" href="sms:+15035550125">

<!-- Ссылка на документ, который содержит архивную ссылку на текущий документ -->
<link rel="archives" href="https://example.com/2003/05/" title="May 2003">

<!-- Ссылка на документ выше (относительно иерархии сайта) -->
<link rel="index" href="https://example.com/" title="Cassius Clay">

<!-- Ссылка на начало текущего документа (например, на первую страницу статьи) -->
<link rel="start" href="https://example.com/books/winnie_the_pooh/part1/" title="Pattern Recognition 1">

<!-- Ссылка на предыдущую страницу текущего документа -->
<link rel="prev" href="https://example.com/opensearch/opensearch-and-openid-a-sure-way-to-get-my-attention/" title="OpenSearch and OpenID? A sure way to get my attention.">

<!-- Ссылка на сам ресурс (ссылка "на себя"). Данная ссылка может, например, понадобиться для обращения к документу, если его описание было получено в составе коллекции -->
<link rel="self" type="application/atom+xml" href="https://example.com/atomFeed.php?page=3">

<!-- Ссылка на первую, следующую, предыдущую и последнюю страницы документа -->
<link rel="first" href="https://example.com/atomFeed.php">
<link rel="next" href="https://example.com/atomFeed.php?page=4">
<link rel="previous" href="https://example.com/atomFeed.php?page=2">
<link rel="last" href="https://example.com/atomFeed.php?page=147">

<!-- Используется когда используется сторонний сервис для редактирования блога -->
<link rel="EditURI" href="https://example.com/xmlrpc.php?rsd" type="application/rsd+xml" title="RSD">

<!-- Указывает адрес пингбэк-сервера -->
<!-- Как поясняется в спецификации, «пингбэк» это способ для блога автоматически оповещать сайты, ссылающиеся на него. Это создает обратную связь — способ пройти назад по цепочке ссылок вместо «прямого прохода». В блогах, частности WordPress, пингбэк-механизм используется для уведомления авторов, что вы ссылаетесь на кого-то при создании новой записи -->
<link rel="pingback" href="https://example.com/xmlrpc.php">

<!-- Уведомляет URL, когда вы ссылаетесь на него на вашем сайте -->
<link rel="webmention" href="https://example.com/webmention">

<!-- Загружает внешний HTML-файл в текущий файл -->
<link rel="import" href="component.html">

<!-- Open Search -->
<link rel="search" href="/open-search.xml" type="application/opensearchdescription+xml" title="Поисковый запрос">

<!-- Фиды -->
<link rel="alternate" href="https://feeds.feedburner.com/example" type="application/rss+xml" title="RSS">
<link rel="alternate" href="https://example.com/feed.atom" type="application/atom+xml" title="Atom 0.3">

<!-- Prefetching, preloading, prebrowsing -->
<link rel="dns-prefetch" href="//example.com/">
<link rel="preconnect" href="https://www.example.com/">
<link rel="prefetch" href="https://www.example.com/">
<link rel="prerender" href="https://example.com/">
<link rel="subresource" href="styles.css">
<link rel="preload" href="image.png">

В стандартной библиотеке есть функция str_getcsv для разбора CSV-строки в массив, но нет для нее пары, которая бы собирала массив в CSV-строку. Зато есть парные функции для сбора-разбора в файл - fputcsv / fgetcsv.

<?php
if (!function_exists('str_putcsv')) {
    /**
     * Format line as CSV string
     *
     * @param array  $fields      An array of values.
     * @param string $delimiter   [optional] The optional delimiter parameter sets the field delimiter (one character only).
     * @param string $enclosure   [optional] The optional enclosure parameter sets the field enclosure (one character only).
     * @param string $escape_char The optional escape_char parameter sets the escape character (one character only).
     * 
     * @return int the length of the written string or false on failure.
     */
    function str_putcsv(array $fields, $delimiter = ",", $enclosure = '"', $escape_char = "\\") {
        $fileHandler = fopen('php://temp', 'r+b');
        fputcsv($fileHandler, $handle, $fields, $delimiter, $enclosure, $escape_char);
        rewind($fileHandler);
        $csvString = rtrim(stream_get_contents($fileHandler), "\n");
        fclose($fileHandler);

        return $csvString;
    }
}
/**
 * Вычисляет расстояние между двумя точками по gps-координатам
 *
 * @param float $lat1
 * @param float $lng1
 * @param float $lat2
 * @param float $lng2
 * @return int расстояние в метрах
 */
function distance($lat1, $lng1, $lat2, $lng2)
{
    $cosLat1 = cos($lat1 * M_PI / 180);
    $cosLat2 = cos($lat2 * M_PI / 180);
    $sinLat1 = sin($lat1 * M_PI / 180);
    $sinLat2 = sin($lat2 * M_PI / 180);
    $cosDelta = cos(($lng2 - $lng1) * M_PI / 180);
    $sinDelta = sin(($lng2 - $lng1) * M_PI / 180);

    $dist = atan2(
        sqrt(
            pow($cosLat2 * $sinDelta, 2) +
            pow($cosLat1 * $sinLat2 - $sinLat1 * $cosLat2 * $cosDelta, 2)
        ),
        $sinLat1 * $sinLat2 + $cosLat1 * $cosLat2 * $cosDelta
    ) * 6372795;

    return round($dist);
}

assert(distance(77.1539, -139.398, -77.1804, -139.55) == 17166029);
assert(distance(77.1539, 120.398, 77.1804, 129.55) == 225883);
assert(distance(77.1539, -120.398, 77.1804, 129.55) == 2332669);