• Как создать приложение VK Mini Apps на хостинге без Node.js?

    sergiks
    @sergiks Куратор тега ВКонтакте
    ♬♬
    Нельзя просто взять, и ...


    «Стили ВК, анимации от ВК» и пр. пряники для VK Apps находятся в их библиотеке компонентов VKUI под React. В виде, требующем дополнительной, скажем так, обработки, прежде, чем можно отдать браузеру.
    Ответ написан
  • Как получить все элементы с определенным id и применить к ним какую либо функцию?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    id обязательно должны быть уникальными. Нельзя использовать один id для нескольких элементов.

    Зато className может присутствовать у многих элементов. Назначьте всем слайдам класс slide-item

    Upd. примерно так можно, коротко и просто:
    Ответ написан
  • Как отсортировать массив за цифрами?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Disclaimer: неоптимальный вариант для популяризации функций PHP

    Можно использовать sscanf(), чтобы вынимать число из каждой строки (если они одинаково начинаются) и сортировать массив своей функцией, переданной в usort():

    $arr = [
      'image_name_1.jpg',
      'image_name_11.jpg',
      'image_name_2.jpg',
      'image_name_100.jpg',
      'image_name_001.jpg',
    ];
    
    usort($arr, function($a, $b) {
      $format = 'image_name_%d.jpg';
      list($aVal) = sscanf($a, $format);
      list($bVal) = sscanf($b, $format);
      return $aVal - $bVal;
    });
    
    echo json_encode($arr);
    /*
    ["image_name_1.jpg","image_name_001.jpg","image_name_2.jpg","image_name_11.jpg","image_name_100.jpg"]
    */
    Ответ написан
    Комментировать
  • Как управлять запросами к API на клиенте?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Писать свой или искать готовый механизм очереди с контролем времени.

    В очередь (массив) класть запрос (метод, параметры) и callback. Либо промисы.

    Держать массив с временем ответов последних 100 (30) вызовов. Если самый древний более 10 (5) секунд назад, можно выполнить очередной.

    Как-то написал вот такую
    кривую реализацию


    Модуль очереди:
    /**
     * Hold Your Horses!
     * Promise-based dispatcher that respects frequency limits.
     * It queues requests so that no more than N are processed within 1 second.
     * Those can go in parallel.
     *
     * Instantiate the new HH with options, specifying time limit.
     * Method .add(function) adds a new job to the queue.
     * Argument function should return Promise object that starts to process only after the function is called.
     * @return Object Promise.
     */
    
    function HorsesHolder(options) {
      options         = options || {};
      this.rps        = options.rps || 3; // requests per second
      this.parallel   = options.parallel || this.rps; // max parallel running jobs
    
      this.times      = []; // -1: slot is busy, 0: slot is free, positive timestamp - time slot's job has finished
      for (let i=0; i<this.rps; i++) this.times.push(0); // [0, 0, 0] initially
    
      this.queue      = [];
      this.inprogress = [];
      this.debug      = !!options.debug;
      
      this.debug  &&  console.log("%s ms: [HH] initialized", this.ts());
    }
    
    
    HorsesHolder.prototype.add = function(promiseMaker) {
      var self = this;
      
      return new Promise(function(resolve, reject) {
        self.queue.push({
          resolve: resolve,
          reject: reject,
          promiseMaker: promiseMaker,
        });
        
        self._ping();
      });
    };
    
    
    // Decide: work or wait
    HorsesHolder.prototype._ping = function() {
    
      if (this.queue.length === 0) {
        this.debug  &&  console.log("%s ms: [ping] queue is empty", this.ts());
        return;
      }
      
      const best = this._bestTime();
      
      if (best === -1) {
        this.debug  &&  console.log("%s ms: [ping] cannot go: %s", this.ts(), JSON.stringify(this.times));
        return;
      }
      
      const index = this.times.indexOf(best);
      
      this.debug  &&  console.info("%s ms: [ping] exec now at index %d", this.ts(), index);
    
      this._execute(index);
    }
    
    
    /**
     * Out of current times[] finds the best to occupy, if possible;
     * otherwise -1
     */
    HorsesHolder.prototype._bestTime = function() {
      let best = -1;
    
      for (let i=0; i<this.rps; i++) {
        const time = this.times[i];
        if (time === 0) return 0;        // can go now - nothing better!
        if (time < 0) continue;          // previous not finished yet
        if (this.ts() < time + 1000) continue; // not yet
    
        if (best === -1) best = time;
        else best = Math.min(best, time);
      }
      
      return best;
    }
    
    
    HorsesHolder.prototype.ts = function() {
      return (new Date()).getTime();
    }
    
    
    HorsesHolder.prototype._execute = function(index) {
      this.times[index] = -1; // mark busy
      const job = this.queue.shift();
      this.inprogress.push(job);
    
      const self = this;
      
      job.promiseMaker()
      .then(function(r) {
        self.debug  &&  console.info("%s ms: [HH] Job done at index %d", self.ts(), index);
        job.resolve(r);
      })
      .catch(function(err){
        self.debug  &&  console.error("%s ms: [HH err] Error at index %d: %s", self.ts(), index, err.toString());
        job.reject(err);
      })
      .finally(function(){
        self.inprogress.splice( self.inprogress.indexOf(job), 1);
        self.times[index] = self.ts();
        setTimeout(() => self._ping(), 1000);
      });
    }
    
    export default HorsesHolder;


    Модуль работы с VK API:
    /*global VK*/
    /**
     * Function returns Promise for each VK API call.
     * Respects the 3 call per second limit.
     *
     * by Sergei Sokolov <hello@sergeisokolov.com> 2019.
     */
     
    import HorsesHolder from '@/utils/horsesholder';
    
    const debug = true;
    
    const HH = new HorsesHolder({ debug });
    
    
    export default function asyncVK(methodName, data) {
    
    	return HH.add(() => {
    
    		data = data || {};
    		if (!data.v) data.v = 5.92; // VK API version https://vk.com/dev/versions
    		
    		return new Promise((res, rej) => {
    			VK.Api.call(
    				methodName,
    				data,
    				r => {
    					if (r.error) {
    						debug && console.error("[asyncvk] VK API call error:", r.error);
    					}
    					
    					
    					if (r.response) {
    						
    						res(r.response);
    						
    					} else if (r.error) {
    						
    						rej(r.error);
    						
    					} else {
    						
    						debug && console.error("[asyncvk] VK API bad response:", r);
    						
    						rej(r);
    						
    					}
    				}
    			)
    		});
    	});
    }


    Ответ написан
    1 комментарий
  • Почему не выводятся на экран числа массива с помощью цикла for?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    первый вариант:

    var mass = [1,2,3,4,5,6,7,8,9,10];
    for(i=0;i<mass.length;i++){
        document.getElementById('root').innerHTML += mass[i];
    }


    второй вариант:

    var r = document.getElementById('root');
    var mass = [1,2,3,4,5,6,7,8,9,10];
    for(i=0;i<mass.length;i++){
        r.innerHTML += mass[i];
    }


    Но разумеется можно короче
    var mass = [1,2,3,4,5,6,7,8,9,10];
    for (document.getElementById("root").innerHTML = mass.join(","); 0;)
    Ответ написан
    Комментировать
  • Возможно ли при клике сэмулировать двойнок клик?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Ваниль:
    document.getElementById("tot-block")
      .addEventListener("click", e => e.target.dispatchEvent(
        new MouseEvent('dblclick', {
          'view': window,
          'bubbles': true,
          'cancelable': true
        })
      )
    );


    ⚠️ Любое событие, сгенерированное скриптом, отличается от «честного» действия пользователя свойством события isTrusted.
    Ответ написан
    Комментировать
  • Какие есть способы округлить число на js?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    const roundigit = digit => {
      if (1!==digit.toString().length||!Number.isFinite(digit))throw "Не цифра!";return digit;}

    spoiler
    Цифра - это 0, 1,2,3,4,5,6,7,8 или 9 - каждая их них целая. Можно не округлять. Расходимся.


    если серьёзно
    Чтобы в сторону нуля округлять, вариант:
    const floor = x => x | 0;
    Ответ написан
    2 комментария
  • VK api. Как получить json всех Олегов из города Кукуева?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вероятная причина ошибки

    Метод users.get() можно вызывать с ключом одного из трёх типов:
    • сервисный ключ (приложения)
    • ключ сообщества
    • ключ пользователя
    в то время, как users.search() можно вызывать только с ключом пользователя.

    Раз users.get() срабатывает , а на users.search() возвращается ошибка токена, вероятнее всего используется токен Сообщества или Сервисный ключ приложения.

    Что делать

    Получите ключ Пользователя. Для этого понадобится создать своё приложение ВК или использовать уже готовое. Специальных прав запрашивать не нужно, просто получить токен.

    В запросе к users.search() для поиска только в городе N, понадобится найти сначала id этого города N в Справочнике городов ВК. Для этого есть метод database.getCities() - клик по ссылке (внизу страницы) выполнит поиск и вернет несколько населенных пунктов, похожих на «Кукуево», у каждого свой id.

    Итого, в метод users.search() вы передадите следующие параметры:
    1. v=5.101 — версия API, обязательный
    2. access_token=XXXXX — токен Пользователя в любом приложении ВК
    3. count=1000 — без этого параметра вернёт только 20 результатов
    4. q=Олег — поисковая строка
    5. city=123 — id города Кукуево, полученный ранее в database.getCities()
    6. sex=2 — мужской пол (необязательно)
    7. age_from=18 — искомый Олег закончил школу
    8. age_to=24 — наверное, искомый Олег ещё не получает пенсию
    Ответ написан
    3 комментария
  • Какую программу использовать для имитации рисования маркёром на доске?

    Есть онлайн-сервисы для изготовления этих doodle videos

    Из софта предложу только Adobe After Effects, но он дорогой и потребуется некоторое обучение инструменту. Есть уроки на YouTube (тыц).

    Возможно, есть и какой-то специализированный софт попроще, но я не в курсе.
    Ответ написан
    1 комментарий
  • Как отправить POST запрос на VK API?

    sergiks
    @sergiks Куратор тега ВКонтакте
    ♬♬
    Метод markSeen() есть только у закладок: fave.markSeen()

    Получаемое сообщение об ошибке именно об этой причине и говорит:
    "error_msg":"Unknown method passed"

    «Передан неизвестный метод»

    Попробуйте вызывать существующие методы ВК API.

    Например, users.get()
    import requests
    
    payload = {
      'access_token': 'XXXXXXX',
      'v': '5.101'
    }
    
    r = requests.post('https://api.vk.com/method/users.get', data=payload)
    
    print(r.text)
    Ответ написан
    Комментировать
  • Как использовать строковые методы и выведите "tetsetesesesesteest"?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Строку собирайте по частям. Пригодятся эти семь методов объекта String:
    Примените каждый из них, чтобы получить часть результата.

    Например, так
    const x = "test";
    const result = ''
      + x.substr(0, 2) // te
      + x.split('').reverse().join('') // tset
      + x.substring(1,3).repeat(4) // eseseses
      + x.substring(0,2) // te
      + x.substring(1)   // est
    ; // tetsetesesesesteest

    Но здесь «незаконно» используется преобразование к Array для отзеркаливания строки "test" -> "tset".

    Задача творческая и довольно забавная. Проявите себя и найдите какой-то оригинальный способ.
    Ответ написан
    Комментировать
  • Как передать индекс цикла внутрь него другому массиву?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    К изучению: замыкания в JS.

    С минимальными изменениями можно примерно так сделать функцию, создающую функции, каждая запоминает переданный i:
    плохой код
    const slides = document.querySelectorAll('.reviews__item');
    var radioButtons = document.getElementsByName('review-toggle');
    var makeListener = function(i) {
      return function (evt) {
        evt.preventDefault;
        for (var j = 0; slides.length > j; j++) {
          slides[j].classList.add('slider__item--hidden');
        };
        slides[i].classList.remove('slider__item--hidden');
      };
    }
    
    for (var i = 0; i < radioButtons.length; i++) {
      radioButtons[i].addEventListener ('click', makeListener(i));
    };


    Лучше так:
    Ответ написан
    Комментировать
  • Удалить лишние знаки?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    const f = n => parseFloat(n.toFixed(5));
    
    // Tests:
    f(1) // 1
    f(1.12) // 1.12
    f(1.1234567890) // 1.12346
    f(000001) // 1
    f(100000) // 100000
    f(-1e5) // -100000


    Upd. Если обязательно именно отбросить без округления, то надо работать как со строками:
    (()=>{
      
    const f = x => {
      const n = parseFloat(+x);
      const sign = Math.sign(n);
      // отсечь экпоненциальную запись (0.0000001).toString() === "1e-7"
      if (Math.abs(n) < 1e-5) return 0; 
      return sign * parseFloat(x)
        .toString()
        .split('.')
        .map((n,i) => i ? n.substring(0,5) : parseInt(n))
        .join('.');
    }
    
    // Tests:
    ['0000001', '0.0000101', 1.000000001,  -1e-4, -1e-5, -1e-6, 1e5, Math.E, 1, -1, 0, false, ]
      .map(n => `${n} // ${f(n)}`)
      .join('\n');
    /*
    0000001 // 1
    0.0000101 // 0.00001
    1.000000001 // 1
    -0.0001 // -0.0001
    -0.00001 // -0.00001
    -0.000001 // 0
    100000 // 100000
    2.718281828459045 // 2.71828
    1 // 1
    -1 // 1
    0 // 0
    false // 0
    */
    Ответ написан
  • Как выполнить JS код после загрузки страницы?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    См. подробнее про загрузку скриптов с async и defer

    // вызовет initialize только когда догрузятся все скрипты defer:
    document.addEventListener('DOMContentLoaded', initialize);
    Ответ написан
    1 комментарий
  • Что такое коллекция в JavaScript?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Четкого определения «collection» в JavaScript не встречал. Интуитивно, коллекция это структура данных для хранения нескольких значений.

    Объект и массив, по-моему, можно отнести к коллекциям.

    В ES6 появились два новых типа данных – Map и Set, которые тоже можно отнести к «коллекциям». В переводе на Русский язык словом «Коллекция» назвали из них именно Set, предназначенный для хранения только уникальных значений. Но я бы не считал требование уникальности значений отличительным признаком «коллекций» вообще.
    Ответ написан
    2 комментария
  • Как организовать хранение лайков и решить вопрос с производительностью в реляционной БД (mysql)?

    Не хранить каждый лайк индивидуально, а держать два поля счётчиков лайков и дислайков в таблице connections. По поступлению лайка инкрементировать поле.

    Можно и так, как вы изначально описали. Всё равно скоро придёте к регистрации пользователей, и лайки станут связывать пользователя и лайкнутую связь – придётся их хранить индивидуально.

    Проблемы производительности решайте по мере их поступления или чуть заранее, но не так заранее, как сейчас )

    Можно установить правило, что лайк можно отменить только в течение, допустим, недели. Тогда нужно хранить индивидуальные записи каждого лайка только неделю, по прошествии которой заменять устаревшие лайки на посчитанную сумму лайков у записи «связи». Так таблица лайков будет держать только свежие лайки, и не разрастётся до миллиардов.
    Ответ написан
  • Что значит .chance?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    chance – новое придуманное свойство объекта request, назначаемое ему обработчиком.

    Пришёл запрос. Ему навесили новое свойство chance, записав в него случайное число от 0 до 1.
    В ответ на GET-запрос возвращают JSON, описывающий объект с единственным свойством тоже под названием "chance" (шанс), со значением взятым из ранее назначенного свойства объекта запроса.

    Свойство можно назвать как угодно. Например, toster. Тогда код выглядел бы так (замена в двух местах), но функционировал точно так же; возвращал тот же самый формат ответа:
    код
    const express = require('express')
    const app = express()
    app.use((request, response, next) => {  //Промежуточный обработчик
        console.log(request.headers)
        next()
    })
    app.use((request, response, next) => {
        request.toster = Math.random()
        next()
    })
    app.get('/', (request, response) => {
        response.json({
            chance: request.toster
        })
    })
    app.listen(3000)


    .headers — свойство объекта запроса, наследованное от нативного Node'овского объекта запроса, см. http.IncomingMessage.headers. Содержит все HTTP-заголовки принятого HTTP запроса.
    Ответ написан
    Комментировать
  • Как сделать приветственное сообщение для telegram бота?

    Никак.

    До инициирования пользователем диалога командой /start бот не может ничего отправить. Но посетителю бота видно название бота и его описание – это заполняется через BotFather – см. /setdescription
    Ответ написан
    Комментировать
  • Какой PHP-микро-фреймворк взять для простенького REST API с авторизацией, и чтобы не из "большой тройки"?

    sergiks
    @sergiks Куратор тега PHP
    ♬♬
    Может, в редакторе Swagger накидать спеки API и автоматом сгенерить по ним сервер и клиент на любом из предлагаемых языков/фреймворков?

    Например, сервер под теми же Lumen, Slim, Silex, Symfony, Node.js
    Ответ написан
    5 комментариев