85 posts tagged

по-русски

/core.php, line 2
Error 2: Use of undefined constant k - assumed 'k' (this will throw an Error in a future version of PHP)

/core.php, line 2
Error 2: Use of undefined constant k - assumed 'k' (this will throw an Error in a future version of PHP)

/core.php, line 2
Error 2: Use of undefined constant k - assumed 'k' (this will throw an Error in a future version of PHP)

/core.php, line 2
Error 2: Use of undefined constant k - assumed 'k' (this will throw an Error in a future version of PHP)

/core.php, line 2
Error 2: Use of undefined constant k - assumed 'k' (this will throw an Error in a future version of PHP)

/core.php, line 2
Error 2: Use of undefined constant k - assumed 'k' (this will throw an Error in a future version of PHP)

/core.php, line 2
Error 2: Use of undefined constant k - assumed 'k' (this will throw an Error in a future version of PHP)

Later Ctrl + ↑

Скринкаст. Как создать сайт на github pages

Сперва регистрируемся на гитхабе. Учтите, что итоговый сайт будет иметь адрес типа ИМЯ_АККАУНТА.github.com. Програмку под винду скачать тут. При установке не забудьте залогиниться со своим гитхабовским аккаунтом, а также заполнить имя и ящик.

Сам скринкаст: http://yadi.sk/d/4pUWCoLn2i7Gi.
Качество далеко от совершенства. Будем считать первым блином.

UPD Выложил запись

Создание страниц на github pages from Dmitry Podgorniy on Vimeo.

2013   видео   по-русски   разработка

Javascript сниппеты с google closure

Интересная возможность closure-compiler (это такой сервис для обфускации и оптимизации кода). Возможность складывается из двух факторов:

  • компилятор в advanced режиме пережимает код до неузнаваемости, попутно совершая оптимизации. Оптимизаций вагон: значения, которые можно вычислить, вычисляются, инлайновые функции “растворяются” в коде. Функции, которые не вызываются, выбрасываются.
  • компилятор работает с библиотекой гугла для javascript, позволяя совершать импорты модулей из библиотеки в тело скрипта.

Комбинируя эти знания, включаем библиотеку, и запрашиваем версию флеша, например:

// ==ClosureCompiler==
// @output_file_name default.js
// @compilation_level ADVANCED_OPTIMIZATIONS
// @use_closure_library true
// ==/ClosureCompiler==

goog.require('goog.userAgent.flash');
window.a = goog.userAgent.flash.VERSION

На выходе получаем слабоподдерживаемую, но работающую абракадабру, которую после легкого шлифования использует в своем мегапроекте.

2013   по-русски   разработка

Ограничений не существует

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

«Нельзя курить» — это ограничение.
«При курении, вероятность рака увеличивается» — это условие. Статус и возможность чиркнуть спичкой я ценю больше, чем шанс заболеть раком.

«По газонам нельзя ходить» — ограничение.
«Если будешь ходить по газонам, милиция попробует тебя оштрафовать» — условие. Спасаясь от шпаны, я готов бежать через газон.

«Нельзя использовать eval» – это ограничение.
«Если использовать eval, код отработает медленнее и может нарушиться область видимости» — условие. В этом проекте я готов использовать eval, потому что он решает больше задач, чем создает проблем.

Примеры принятия ограничений на веру, без оценки:

  • Тест в первых людях в черном (ограничение — далеко стоящий стол).
  • свеча Карла Дункена (ограничение — кнопки, лежащие в коробке).
  • Как из 6 спичек сложить 4 треугольника (ограничение — работа в одной плоскости).
  • Тест. 2 группы, одинаковый список задач на выполнение. Одной сказали, что существуют люди, генетически предрасположенные к решению этих задач. Второй ничего не сказали. Испытуемые из первой справились в среднем хуже. (ограничение — не предрасположенность к решению задач).

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

Менее критичное мышление.
Если ограничение принимать на веру, при этом не давая ему оценки, ограничение превращается в непреодолимое препятствие. При этом вырабатывается привычка не давать количественную оценку условиям.
Следовательно — отсутствие иерархии ограничений. Следовательно — неумение действовать в ситуации, сложность которой колеблется относительно нормы.

Будьте честные с собой, живите без ограничений.

2013   по-русски

Рендер динамического markdown в jade

Jade среди прочих, имеет классную фичу — фильтры. Вот только они не завелись у меня с динамическим markdown. Как это часто бывает с javascript-ом, очевидное решение не срабатывает.

template.jade

markdown: #{md}

router.coffee

app.get "/" (request, response, next) ->
    response.render "template", 
         indexMarkdown : indexMarkdown

В браузер приходит сырой markdown без намека на конвертацию. Решением оказалось передача функции , которая умеет парсить markdown, параметром в шаблон, и запуск ее из самого шаблона:

template.jade

div= mdToHTML(indexMarkdown)

router.coffee


md = require("marked").parse

#...
app.get "/" (request, response, next) ->
    response.render "template", 
        indexMarkdown : indexMarkdown
        mdToHTML : md

2013   по-русски   разработка

Максимальная частота срабатывания события mousemove

В голову пришла мысль, что выстреливать событие движения мыши чаще 60 раз в секунду бесмысленно. После ручных тестов браузеры (O12, FF20.02a, S6.02, C24) показали полную солидарность в моих взглядах. Каждый из них запускал обработчик движения мыши не более 60 раз в секунду. Код для проверки в домашних условиях:

var start;
var totalCalls;


start = 0
totalCalls = 0

function onmove () {
	var now = Date.now()

	// начнем считать время с момента
	// первого срабатывания события mousemove
	if (!start) {
		start = now
	}

	if (now - start < 1000) {
		totalCalls += 1
	} else {
		console.log(totalCalls)
	}
}

window.onmousemove = onmove

После запуска кода веди мышку с одной скоростью по телу страницы.

2013   по-русски   разработка

Как запустить nodemon под forever

Примеры из документации устарели, да и в явном виде решения не нашел. В двух словах:

  • forever инструмент для запуска скриптов (не только nodejs) в фоновым процессом.
  • nodemon перезапускает скрипт после изменений файлов (в моем случае coffee).
forever start -c nodemon app.coffee

Связка нужна для того чтобы постоянно работающий сервер автоматически перезапускался после обновлений.

2013   по-русски   разработка

Базопасный placeholder-болванка javascript ответа

На сервере динамически генерируется javascript ответ (допустим script.js). При этом какая-то часть файла — статическая и одинаковая для всех клиентов, а какая-то должна быть заменена для каждого клиента отдельно. При этом заменой занимается некий серверный язык. Задача: предоставить файл-шаблон, в определенное место в котором будут подставляться данные. Первое, что приходит на ум выглядит как-то так:

(function () {
	var data = #DATA_PLACEHOLDER#;
	var errors = #ERRORS_PLACEHOLDER#;
	var all = {};
		
	all.data = data;
	all.errors = errors;
	window.provide = processData(all);
}());

Файл получается невалидным, что влечет ряд последствий:

  • Его валидацию надо исключить из общей валидации проекта, или реализовывать отдельную.
  • При исключении файла из валидации велик шанс синтаксической ошибки при последующей его правке (сборка проекта пройдет успешно, но клиентская часть не отработает)
  • В случае отказа бекэнда инициализация не произойдет, и код, зависящий от кода в файле, что мы генерируем, завалится, обращаясь к необъявленной переменной (provide).

Явно напрашивается, что плейсхолдером должен быть особой формы комментарий, при это должна быть альтернатива, в случае, если комментарий не заменится на значение. Вот-же ж оно: использем самовызывающиеся анонимные функции:

(function () {
	var data = (function () {return /*!DATA_PLACEHOLDER*/})() || {};
	var errors = (function () {return /*!ERRORS_PLACEHOLDER*/})() || [];
	var all = {};
	
	all.data = data;
	all.errors = errors;
	window.provide = processData(all);
}());

Уже намного лучше. Файл валиден, теперь его можно не исключать из процесса проверки всего проекта. А так-же в случае с проблемами на бекэнде, клиентская часть продолжает инициализироваться. Тут она сможет сама решить, как поступать в случае падения серверов.

Однако не все так безрадостно.

var data = (function() {return
	{
		importantValue: true
	}
})() || {};
console.log(data.importantValue); // undefined

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

И вот оно, финальное решение: передадим данные аргументом, и вернем их-же.

(function () {
	var data = (function (data) {return data})(/*!DATA_PLACEHOLDER*/) || {};
	var errors = (function (errors) {return errors})(/*!ERRORS_PLACEHOLDER*/) || [];
	var all = {};
		
	all.data = data;
	all.errors = errors;
	window.provide = processData(all);
}());

На выходе — пуленепробиваемая, валидная конструкция для последующего наполнения данными.

2013   по-русски   разработка
Earlier Ctrl + ↓