Внезапно оказался перед фактом ― закончилось место на VPS. Оказалось, что node-forever съел своими логами 21 GiB места на винте. Приложение упрямо не хотело подниматься, падало, forever это писал в логи и снова пытался его поднять. Забавно…
Внезапно оказался перед фактом ― закончилось место на VPS. Оказалось, что node-forever съел своими логами 21 GiB места на винте. Приложение упрямо не хотело подниматься, падало, forever это писал в логи и снова пытался его поднять. Забавно…
Возникла задача ― в скролируемом контейнере найти первый видимый domElement. Я подумал, что, наверняка, это довольно частая задача, и должно быть множество разных готовых решений. Порыскав по сети я нашёл лишь множество вариаций одного и того же: рекурсивный обход всего древа domElement-ов, с рассчётом их границ. В голову полезли варианты с бинарным поиском по тому же принципу, но уж больно не хотелось с этим всем связываться. Как то уж слишком сурово, для такой мелочной задачи. Должен быть “нативный” инструмент.
Увы, совсем уж нативного инструмента я не нашёл. Но нашёл, гхм, альтернативный путь. Возможно, кому-нибудь ещё пригодится.
domElement-ы вызываем getBoundingClientRect. Получаем его расположение на экранеviewPort-а, где должен находится искомый domElementdocument.elementFromPoint, указав нужные координаты экранаРешение сгодится не для любого случая. Но мне вполне подошло.
Для нужд разработки возникла необходимость в proxy-овании некоторых запросов, в обход CORS-а. Погуглив и слегка причесав код, получилось следующее:
"use strict"; /** * run: iojs --harmony_arrow_functions proxy.js * * nginx: * location ~ ^/api.*$ { * proxy_pass http://127.0.0.1:3001; * proxy_set_header X-Real-IP $remote_addr; * proxy_set_header Host $host; * proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; * } */ let hostname = '%hostname%'; let port = 3001; let auth = '%user%:%pass%'; let http = require('http'); http.createServer((clientReq, clientRes) => { let opts = { hostname: hostname, port: 80, path: clientReq.url, auth: auth, headers: clientReq.headers, method: clientReq.method }; opts.headers.host = hostname; console.info('serve: %s %s', clientReq.method, clientReq.url); let proxy = http.request(opts, (proxyRes) => { proxyRes.addListener('data', (chunk) => clientRes.write(chunk, 'binary')); proxyRes.addListener('end', () => clientRes.end()); clientRes.writeHead(proxyRes.statusCode, proxyRes.headers); }); clientReq.addListener('data', (chunk) => proxy.write(chunk, 'binary')); clientReq.addListener('end', () => proxy.end()); }).listen(port);
Запускается путём выполнения iojs --harmony_arrow_functions proxy.js, логирует все запросы в консоль. Точно умеет POST, GET, отдавать статику… Для простых нужд вполне сгодится. Жаль браузеры пока толком не умеют arrow functions :(
Knockout, безусловно, весьма мощная библиотека, которая позволяет сэкономить море времени, но некоторые моменты в её работе, мне показались неудобными. Про один из них эта заметка. Binding «click» просит указать метод, но особенности JavaScript-а, не позволяют удобным способом указать метод и объект this, для его вызова. В итоге мы имеем вот такие вот уродливые конструкции
<span data-bind="click: $root.save.bind($root)"></span> <span data-bind="click: $root.edit.bind($root, 'someParameter')"></span>
У меня возникло желание как это дело упростить. Я решил остановиться на таком варианте:
<span data-bind="click: @save"></span> <span data-bind="click: [@edit, 'someParameter']"></span>
Возможно, не очень очевидный синтаксис, но никто не мешает придумать свой :) Итак, задача состоит в том, чтобы заставить knockout эти конструкции принимать за нужный метод. Для этого воспользуемся хаком preprocess для binding-а click. У меня получилось примерно так:
ko.bindingHandlers.click.preprocess = function( val ) { val = $.trim( val ); if( val[ 0 ] === '@' ) { var method = val.substr( 1 ); return 'function(){ return $root["' + method + '"].apply( $root, arguments ); }'; } if( val[ 0 ] === '[' && val[ val.length - 1 ] === ']' ) { val = $.trim( val.substr( 1, val.length - 2 ) ); var params = val.split( /\s*,\s*/ ); if( params[ 0 ] && params[ 0 ][ 0 ] === '@' ) { var method = params.shift().substr( 1 ); var args = params.join(', '); var js = 'function()\n' + '{\n' + '\tvar args = [ ' + params + ' ].concat( _.toArray( arguments ) );\n' + '\treturn $root["' + method + '"].apply( $root, args );\n' + '}'; return js; } } return val; }
Решение пока черновое и не обкатанное. К тому же на click-е мир клином не сошёлся и нужно что-то более универсальное.
CKEditor - это WYSIWYG редактор HTML-кода для браузеров. Всякий раз, сталкиваясь с его документацией или же с его исходным кодом, с исходным кодом его плагинов я терялся. И это не мудрено, ведь CKEditor это очень большой продукт, имеющий довольно сложную инфраструктуру. Но, зачастую, стандартных возможностей не хватает и требуется добавить свою. В этой статье я хотел бы остановиться на плагине, который позволяет встраивать и оперировать в редакторе Yandex-картами. Вот так это будет выглядеть по окончанию редактирования:
