Блоґ одного кібера

Історія хвороби контуженого інформаційним вибухом

Archive for the ‘Павутина’ Category

Як написати свій букмарклет?

with 22 comments

Букмарклет (bookmark) – це слово створене поєднанням слів bookmark (закладка) і applet (application (застосунок) + зменшувальний суфікс -let). Таким чином правильним перекладом bookmarklet було б “закластуночок” (чи “застокладочка”), але ви цього краще не кажіть Юрку Зеленому. Але я відхиляюсь. Отож, букмарклет, це маленька програма що міститься в закладці.

Як її туди помістили? Ну, виявляється браузери крім протоколів http, ftp, ітп, розуміють такий протокол як javascript. І коли отримують посилання з цим протоколом, при кліку по ньому не змінюють сторінку, а виконують його href як код JavaScript. Щоб побачити приклад простого букмарклету, створіть документ bookmarklet.htm, і помістіть в нього такий код:

<html>
<head><meta charset="utf-8" /></head>
<body>
<a href="javascript:
    alert('Привіт!')
">Мій букмарклет</a>
</body>
</html>

Прочитати решту цього запису »

Advertisements

Written by bunyk

Березень 10, 2016 at 14:31

Логуючий фільтр для Angular expression

with one comment

Вирази в Angular (те що в фігурних дужках і ngBind) – не зовсім те що Javascript. Так каже документація.

Context: JavaScript expressions are evaluated against the global window. In Angular, expressions are evaluated against a scope object.

А тому ми не можемо там використати console.log. Але можемо написати наприклад такі фільтри:

    angular
        .module('starter')
        .filter('log', function() {
            // do not change value, but log it in console
            return function(input) {
                console.log(input);
                return input;
            };
        })
        .filter('justlog', function() {
            // do not render value but log it in console
            return function(input) {
                console.log(input);
                return '';
            };
        });

Хоча напевне існує якийсь правильніший, вже вбудований спосіб зневадження в Angular. 🙂

Written by bunyk

Лютий 25, 2016 at 15:52

Оприлюднено в Кодерство, Павутина

Tagged with ,

Вступ в AngularJS (1)

with 3 comments

Я почав писати цей конспект від початку 2015-го, за цей час вийшов AngularJS 2, напевне варто переписати. Хоча другий Angular написаний на TypeScript, тому він напевне вже не JS. Або вивчити React і написати конспект для нього. Вибір безмежний. 🙂

Написано на основі шикарного курсу від Code School. Просто щоб не передивлятись кожного разу перед тим як знову засвербить щось написати для фронт-енду.

Angular.js дозволяє писати шаблони прямо в HTML, розширюючи його своїми директивами, а потім автоматично заповнюючи даними.

Директива – це маркер (атрибут тегу) чи тег HTML що каже Angular-у запустити якийсь JavaScript код.

Єдиний файл що потрібен для початку роботи – angular.js.

Модулі

Код в Angular.js поміщається в модулі. Модулі містять код і описують залежності.

Щоб створити модуль пишемо:

var app = angular.module('store', []);

Перший аргумент – назва модуля, другий – список залежностей (якщо без залежностей – то порожній).

Тоді в html пишемо:

<html ng-app="store">

І це запустить наш модуль коли документ завантажиться.

І хоча наш модуль нічого не робить, але його включення вже допомагає розглядати код html який ми пишемо як директиви Angular.

Після чого можна писати на сторінці вирази. Як от

<p>2 + 2 = {{2 + 2}}</p>

Контролери

Щоб передати дані з JS в HTML, потрібно використати контролер:

var gem = {
    name: 'Dodecahedron',
    price: 10,
};

app.controller('StoreController', function() {
    this.product = gem;
});

Важливо щоб контролери називались КемелКейсом і останнім словом завжди було Controller.

Далі, в html, пишемо

<div ng-controller="StoreController as store">
<h1>{{store.product.name}}</h1>
<h2>{{store.product.price}}</h2>
</div>

store – аліас який ми описали і що використовується всередині виразів. Доступний лише всередині елементу для якого описаний контролер.

Директиви

ng-show – покаже елемент лише коли значення виразу істинне.

<div ng-controller="StoreController as store">
<button ng-show="store.product.canPurchase">Add to Cart</button>
</div>

ng-hide – навпаки, сховає елемент коли значення істинне.

ng-repeat – повторить елемент ітеруючи по якомусь списку.

ng-click – виконає код написаний всередині значення директиви при кліку по ньому.
ng-init – виконає код написаний всередині значення директиви при відображенні сторінки. Не користуйтесь ним, покладіть код який хочете покласти туди, всередину контролера.

<div ng-controller="StoreController as store">
<div ng-repeat="product in store.products">
<button ng-show="product.canPurchase">Add to Cart</button>
</div>
</div>

ng-src – директива що встановлює значення атрибуту src в тегу на зразок img. Тому що встановлення його значення через <img src="{{value}}">, призведе, перед тим як спрацює Angular, до спроби браузера завантажити файл “{{value}}“, і помилки 404. А цього ми не хочемо.

ng-class="{ 'class1': condition1, class2: condition2 }" – дозволяє додавати і забирати класи з елемента залежно від значення виразів умов.

Фільтри

При виводі даних в шаблонах, їх можна пропускати через фільтри. Загальний синтаксис:

<p>2 + 2 = {{вираз|фільтр:опції}}</p>

<!-- або так: -->
<li ng-repeat="product in store.products | limitTo:3 | orderBy:'-price'">

Форми

Директива ng-model прив’язує значення елемента форми до моделі (атрибута контролера). Вони оновлюються автоматично.

Щоб якийсь код виконувався коли форма відправляється, ми додаємо цей код в значення директиви ng-submit. І дописуємо директиву novalidate, щоб вимкнути стандартну валідацію HTML.

<form name="reviewForm"
      ng-controller="ReviewController as reviewCtrl"
      ng-submit="reviewForm.$valid && reviewCtrl.addReview(product)" 
      novalidate
>

Angular автоматично додає до полів класи – ng-pristine – до поля до якого ще не додавали код, ng-dirty – до зміненого поля, і ng-invalid – до поля що не проходить валідацію, та ng-valid – до того що проходить.

Поля валідуються по атрибуту type. Може бути наприклад email, url, number (додатково є атрибути min, max).

Далі в курсі (ось слайди) ще йдеться про те як

  • включати розмітку з інших файлів
  • писати власні директиви і власні html елементи
  • завантажувати дані через XHR

Щоправда, цього не треба щоб написати застосунок який я хочу написати. Але Про нього пізніше, бо github лежить, і вже трохи пізно. 🙂

Written by bunyk

Лютий 18, 2016 at 00:02

Оприлюднено в Кодерство, Павутина

Tagged with

D3: фіксація вузла в графі

with 4 comments

Knowledge is power – it’s measured in WAT?!s (Rose Ames)

Я все мрію написати детективну історію на зразок “Шерлок Холмс і Бага Баскервілів”, але ніяк не підберу багу аби сюжет був достатньо гостросюжетним. Ось наприклад поділюсь знанням цікавої особливості D3.js при малюванні графів за допомогою фізичної симуляції. Наприклад ми хочемо деякі вузли графа розміщувати вручну.

Документація пише:

Each node has the following attributes: …
fixed – a boolean indicating whether node position is locked.

Ок, тоді давайте при кліку по вузлі, показувати меню, в якому є галочка “фіксувати ноду”. В коді що показує меню пишемо:

pin_down.setChecked(data.fixed);

І чомусь, не залежно від того фіксований вузол, чи ні, галочка завжди стоїть:

pin

Я почав логувати data.fixed, виявилось що вона отримує значення то 6, то 7, то 3… Зовсім не булевські. Я думав вже що десь якийсь код думає що fixed на вузлі графа означає щось інше.

Документація бреше. Виявилось що fixed – не булева змінна.

Internally, the force layout uses three bits to control whether a node is fixed. The first bit can be set externally, as in this example. The second and third bits are set on mouseover and mousedown, respectively, so that nodes are fixed temporarily during dragging. Although the second and third bits are automatically cleared when dragging ends, the first bit stays true in this example, and thus nodes remain fixed after dragging. (Sticky Force Layout).

Ну що ж, давайте по масці виділяти перший біт:

pin_down.setChecked(data.fixed && 1);

Все одно завжди поставлена? Ааа, ну так, && – це логічна кон’юнкція, а не побітова. 6 && 1 – true. Нам треба побітову.

pin_down.setChecked(data.fixed & 1);

Resolve issue -> Fixed.

Тепер залишилось придумати як в такий детектив додати персонажів і саспенсу. 😀

Written by bunyk

Червень 3, 2015 at 16:51

Оприлюднено в Графіка, Кодерство, Павутина

Tagged with

Ethernet на хлопський розум

with 11 comments

I’m a web crawling spider; you an Internet mosquito;
You thought the 7-layer model referred to a burrito.
You’re a dialup connection; I’m a gigabit LAN.
I last a mythical man-month; you a one-minute man.

Monzy – “kill -9

Іноді аби щось зрозуміти, іноді мало читати, треба писати. Сьогодні ми розберемось чим комутатор та міст відрізняються від концентратора. 🙂 Я хотів добре розібратись як працює маршрутизатор, але це ще рівнем вище, і ця вся справа затягнулась.

Рівні мережевої моделі

Почнемо з рівнів. Комп’ютерні мережі такі складні, що зрозуміти їх цілком дуже важко, тому вирішили розділити їх на рівні абстракції. Цих рівнів можна нарахувати від п’яти до семи, але ми почнемо з перших двох.
Прочитати решту цього запису »

Written by bunyk

Квітень 19, 2015 at 21:23

Оприлюднено в Конспекти, Павутина

Tagged with

Генштаб для грамнацистів

with 4 comments

Щойно з’явилась ідея супер-пупер сервісу для всіх хто пише і вичитує.

Сценарії використання

  1. Користувач бачить помилку на якомусь сайті. (Ідея націлена на вікіпедію, але має працювати на будь-яких інших сайтах, наприклад тут.) Нехай він зареєстрований на нашому порталі грамнацистів, і встановив букмарклет. Користувач виділяє ту помилку, натискає на букмарклет, той букмарклет показує попап з формою, де вписаний рядок з помилкою, полем куди можна ввести правильний варіант, пояснення помилки і посилання на словники та правопис.
  2. Користувач пише статтю. Він хоче написати її грамотно. Він вводить її текст, натискає інший букмарклет, і той використовуючи алгоритм Ахо-Корасік чи щось легше, підкреслює всі помилки і в попапах показує коментарі користувачів що їх виправили, та варіанти виправлень.
  3. Користувач вважає що помилка – не помилка, і попередній користувач помилився додавши її до словника. В попапі він клацає кнопочку “обговорення” і переходить на наш портал, де може обговорити.
  4. Адміністратори/редактори (вікіпедії) вирішують хто правий, а хто ні. Помилка яка насправді такою не була, позначається, і при наступних спробах її ввести, йому будуть повідомляти що це не помилка, і якщо він не згоден – посилати в обговорення.
  5. Найпопулярніші помилки, які вже точно помилки експортуються в файл що читається роботом який лазить по вікіпедії і виправляє всі статті та перевіряє всі нові правки. Якщо користувач вніс правку з помилкою – йому приходить повідомлення з поясненням суті помилки, проханням так не робити і порадою поставити букмарклет. 🙂 На зразок такого:
    https://www.facebook.com/mova.ukr/posts/723929884309871
  6. Треба врахувати те, що помилок існує більше ніж правильних слів (наприклад в слові “пиво” можна помилитися 32^4 = 2^{20} \approx 10^6 мільйоном різних способів, і то якщо не враховувати що також існують пропуск, дефіс, апостроф та інші символи. Тому варто намагатись вводити лише часті помилки, а решту залишати на hunspell. Словник для hunspell теж дозволити редагувати спільно, через букмарклети.

P.S. Я ще можу змиритись з тим що Firefox мені підкреслює hunspell, latex, букмарклет, попап і подібне. Але “блозі”, “кнопочку” “P.S.” і т.п. міг би вже вивчити.

Written by bunyk

Березень 19, 2015 at 21:22

Зберегти всю стіну групи VK в таблицю

with one comment

Якось під час чергового наближення економічної кризи захотілось проаналізувати ціну нерухомості в Львові. А ще, в той же час я наткнувся на документацію API Вконтакті. А так як своє житло я шукав в тому числі і в тій соціальній мережі, то вирішив проаналізувати наприклад спільноту vk.com/nomakler.

Ну, проаналізувати це легко сказати – важче зробити. Як витягти з повідомлення ціну, і як відрізнити попит від пропозиції? Га?

Але є половинний результат – ФСБ мусило поділитись частиною своєї бази даних розміром в 40450 оголошень. Тут можна її завантажити як tsv, xls чи інший зручний для вас формат. Може комусь, хто захоче збільшити конкуренцію серед львівськи маклерів/ріелторів знадобиться.

А якщо кому потрібна інформація з інших груп – ось скрипт. Викликаєте функцію save2tsv з назвою групи і назвою файлу в який писати – і чекаєте поки завантажиться.

import requests
import json
from pprint import pprint
from itertools import islice
from datetime import datetime

from butils.csv_wrapper import UnicodeWriter

class APIError(Exception):
    pass

def vk(method, **kwargs):
    '''
        https://vk.com/dev/methods
    '''
    r = requests.get(
        'https://api.vk.com/method/%s' % method,
        params=kwargs
    )
    js = json.loads(r.text)
    if js.get('error'):
        raise APIError(js['error']['error_msg'])

    return js['response']


def get_users(ids, known_users={}):
    request_ids = [i for i in ids if i not in known_users]
    if request_ids:
        user_ids=','.join(str(i) for i in request_ids if i > 0)
        if user_ids:
            users = vk('users.get', user_ids=user_ids)
        else:
            users = []
        group_ids=','.join(str(-i) for i in request_ids if i < 0)
        if group_ids:
            groups = vk('groups.getById', group_ids=group_ids)
        else:
            groups = []
        for user in users:
            known_users[int(user['uid'])] = dict(
                first_name = user['first_name'],
                last_name = user['last_name'],
            )
        for group in groups:
            known_users[-int(group['gid'])] = dict(
                first_name = group['name'],
                last_name = group['gid']
            )
    return known_users


def get_wall(domain):
    count = 50
    offset = 0
    def get_with_offset(offset):
        nonlocal count
        print('get_with_offset(%s)' % offset)
        total = vk('wall.get',
            domain=domain,
            count=1,
        )[0]
        off = total - offset - count
        if off < 0:
            count = count + off
            off = 0
        return vk('wall.get',
            domain=domain,
            count=count,
            offset=off,
        )[1:][::-1] # remove first and reverse

    while True:
        posts = get_with_offset(offset)
        offset += count
        users = get_users(p['from_id'] for p in posts)
        for p in posts:
            yield p, users[p['from_id']]
        if count < 50:
            return


def save2tsv(domain, dst):
    with UnicodeWriter(dst, encoding='utf-8', delimiter='\t') as writer:
        writer.writerow((
            'ID',
            'Datetime',
            'First name',
            'Last name',
            'Text',
            'Type',
            'Comments',
            'Reposts',
            'Likes',
        ))
        for p, user in get_wall(domain):
            writer.writerow(list(map(str, (
                p['id'], # ID
                datetime.fromtimestamp(p['date']), # Datetime
                user['first_name'], # First name
                user['last_name'], # Last name
                p['text'], # Text
                p['post_type'], # Type
                p['comments']['count'], # Comments
                p['reposts']['count'], # Reposts
                p['likes']['count'], # Likes
            ))))

# save2tsv('nomakler', 'nomakler.tsv')

Written by bunyk

Березень 8, 2015 at 17:38

Оприлюднено в Кодерство, Павутина

Tagged with