Compare commits

25 Commits

Author SHA1 Message Date
Oleg Mokhov
081d3cd15b Merge pull request #34 from mokhov/upnode
up node.js version
2015-10-05 12:57:26 +03:00
mokhov
8d7faddfc0 up node.js version 2015-10-05 12:56:04 +03:00
Oleg Mokhov
25f46ee198 Merge pull request #31 from mokhov/checkSpeedBug
Checking speed bug
2015-10-03 16:10:03 +03:00
mokhov
2b44a449ed Checking speed bug 2015-10-03 16:09:39 +03:00
Oleg Mokhov
41a03cf63d Merge pull request #30 from mokhov/issue-29
CFI builder broken
2015-10-03 16:09:27 +03:00
mokhov
e5eeb5ce6f CFI builder broken 2015-10-03 13:16:07 +03:00
Oleg Mokhov
d11cd3058f Merge pull request #28 from mokhov/issue-27
fixed issue-27
2015-09-25 13:17:08 +05:00
mokhov
56af723e4f fixed issue-27 2015-09-25 11:15:20 +03:00
Oleg Mokhov
f0cbf9248e Merge pull request #26 from mokhov/issue-24
issue-24: Speed loading time
2015-07-26 15:19:31 +05:00
mokhov
8b8f785e5a issue-24: Speed loading time 2015-07-26 11:45:33 +03:00
Oleg Mokhov
5a2b0c70cf Merge pull request #23 from mokhov/titles
Added titles to menu
2015-07-20 00:40:16 +05:00
mokhov
dbf43a65f5 Added titles to menu 2015-07-19 22:39:22 +03:00
Oleg Mokhov
5ba6c431f7 Merge pull request #21 from mokhov/new-package
update package.json
2015-07-11 23:54:58 +05:00
mokhov
ac026f32c2 update package.json 2015-07-11 21:54:26 +03:00
Oleg Mokhov
d491d4f5af Merge pull request #20 from mokhov/touch
Add reaction to the swipe events on touch devices
2015-07-10 22:38:36 +05:00
mokhov
4c93a5598b Add reaction to the swipe events on touch devices 2015-07-10 20:33:36 +03:00
Oleg Mokhov
e748934c8a Merge pull request #19 from mokhov/spin-tests
Тесты для спиннера
2015-07-10 21:59:10 +05:00
mokhov
f6dcbaef87 spin tests 2015-07-10 19:56:57 +03:00
Oleg Mokhov
7b6f54d35e Merge pull request #18 from mokhov/master
Show travis status
2015-07-10 00:17:24 +05:00
mokhov
32091fce2a Show travis status 2015-07-09 22:16:52 +03:00
Oleg Mokhov
a46c1f2c82 Merge pull request #17 from mokhov/tests
Travis
2015-07-10 00:14:28 +05:00
mokhov
fc18464f2a Travis 2015-07-09 22:13:13 +03:00
Oleg Mokhov
dc57804bab Merge pull request #13 from mokhov/avg-algo
simple average symbols per page algorithm
2015-06-22 23:52:59 +05:00
mokhov
6025b017c8 simple average symbols per page algorithm 2015-06-22 21:51:38 +03:00
Oleg Mokhov
6239ea262a Merge pull request #11 from chitalka/arrows
fix arrow size
2015-06-22 22:24:24 +05:00
16 changed files with 2664 additions and 40 deletions

View File

@@ -23,4 +23,6 @@ module.exports = function(config) {
//.forServerPage() //.forServerPage()
.configureNode(nodeConfig); .configureNode(nodeConfig);
}); });
bevisHelper.configureUnitTests('test/client');
}; };

2
.gitignore vendored
View File

@@ -3,3 +3,5 @@ node_modules
build/index/* build/index/*
!build/index/i !build/index/i
!build/index/index.btjson.js !build/index/index.btjson.js
test/client/*
!test/client/test.html

4
.travis.yml Normal file
View File

@@ -0,0 +1,4 @@
language: node_js
node_js:
- "0.12"

View File

@@ -27,11 +27,17 @@ npm:
# Build project # Build project
build: build:
$(ENB) make $(ENB_FLAGS) $(ENB) make $(ENB_FLAGS)
@cp -r lib build/index/lib @rm -rf build/index/lib
@cp -rf lib build/index/lib
@mv build/index/index.ru.html build/index/index.html @mv build/index/index.ru.html build/index/index.html
# Build and run client tests
test:
$(ENB) make test -n
$(NODE_MODULES_BIN)/mocha-phantomjs $(MOCHA_FLAGS) test/client/test.html
# Clean build results # Clean build results
clean: clean:
$(ENB) make clean $(ENB) make clean
.PHONY: all install build clean .PHONY: all install build clean test

View File

@@ -1,3 +1,5 @@
[![Build Status](https://travis-ci.org/chitalka/reader.svg?branch=master)](https://travis-ci.org/chitalka/reader)
# chitalka # chitalka
Welcome to chitalka.js repository. It is a JavaScript-library to read fb2 books. Welcome to chitalka.js repository. It is a JavaScript-library to read fb2 books.

View File

@@ -3,6 +3,7 @@ module.exports = function (bt) {
bt.match('chitalka-fb2*', function (ctx) { bt.match('chitalka-fb2*', function (ctx) {
ctx.setInitOption('keyboard', true); ctx.setInitOption('keyboard', true);
ctx.setInitOption('touch', true);
ctx.setInitOption('url', ctx.getParam('url')); ctx.setInitOption('url', ctx.getParam('url'));
ctx.enableAutoInit(); ctx.enableAutoInit();

View File

@@ -1,3 +1,4 @@
- hammer
- chitalka - chitalka
- unzip - unzip
- storage - storage

View File

@@ -116,7 +116,6 @@ modules.define(
* 'appendix' в конце * 'appendix' в конце
*/ */
_setFootnotesMode: function (mode) { _setFootnotesMode: function (mode) {
this._subscribeToLinksEvents();
if (mode === 'inline') { if (mode === 'inline') {
this._footnotesMode = mode; this._footnotesMode = mode;
this._setState('footnotes', 'inline'); this._setState('footnotes', 'inline');
@@ -178,12 +177,13 @@ modules.define(
this._fontSize = parseInt(this._bookPlaceholder.css('font-size'), 10); this._fontSize = parseInt(this._bookPlaceholder.css('font-size'), 10);
this._settings.save('font-size', this._fontSize); this._settings.save('font-size', this._fontSize);
} }
this._lineHeight = parseInt(this._bookPlaceholder.css('line-height'), 10);
this._annotations = this.getDomNode().find('.annotation'); this._annotations = this.getDomNode().find('.annotation');
this._subscribeToWindowEvents(); this._subscribeToWindowEvents();
this._subscribeToLinksEvents();
this._setFootnotesMode(this._settings.get('footnotes') || this._getState('footnotes') || 'appendix'); this._setFootnotesMode(this._settings.get('footnotes') || this._getState('footnotes') || 'appendix');
this._setPageViewMode(this._settings.get('pages') || this._getState('pages') || 'auto'); this._setPageViewMode(this._settings.get('pages') || this._getState('pages') || 'auto');
this._storage = new Storage(this.getBookId()); this._storage = new Storage(this.getBookId());
@@ -194,14 +194,12 @@ modules.define(
// связанный баг https://st.yandex-team.ru/CHITALKA-65 // связанный баг https://st.yandex-team.ru/CHITALKA-65
nextTick(function () { nextTick(function () {
this._buildCFIs(); this._buildCFIs();
this._countSymbols();
this._calcDimensions(); this._calcDimensions();
this._restoreSavedPosition(); this._restoreSavedPosition();
this._firstElementOnPage = this._getKeeper();
this.emit('ready'); this.emit('ready');
}.bind(this)); }.bind(this));
}, },
@@ -301,8 +299,7 @@ modules.define(
this._pageCount = this._getBookPages(); this._pageCount = this._getBookPages();
// Среднее число символов на странице, speedCoeff - эмпирически вычисленный коэффцицент // Среднее число символов на странице, speedCoeff - эмпирически вычисленный коэффцицент
var speedCoeff = (this._pageWidth / (11 * this._fontSize / 16)); this._avgSymbolsOnPage = Math.round(this._totalBookSymbols / this._pageCount)
this._avgSymbolsOnPage = Math.round(Math.floor(this._bookCanvasHeight / this._lineHeight) * speedCoeff);
}, },
/** /**
@@ -490,40 +487,33 @@ modules.define(
parent = parent || this._bookPlaceholder; parent = parent || this._bookPlaceholder;
var counter = 1; var counter = 1;
id = id || '/'; id = id || '/';
var totalSymbols = 0;
$(parent).contents().map(function (i, el) { $(parent).contents().map(function (i, el) {
var genID = id + counter; var genID = id + counter;
var symbols;
if (el.nodeType === TEXT_NODE) { if (el.nodeType === TEXT_NODE) {
symbols = $.trim(el.textContent).length;
totalSymbols += symbols;
// оборачиваем только если не пустая нода и не единственная // оборачиваем только если не пустая нода и не единственная
if ($.trim(el.textContent) !== '' && $(parent).size() > 1) { if ($.trim(el.textContent) !== '' && $(parent).size() > 1) {
var wrap = $('<span></span>'); var wrap = $('<span></span>');
wrap.attr('data-4cfi', genID); wrap.attr('data-4cfi', genID);
if (symbols) {
wrap.attr('data-symbols', symbols);
}
$(el).wrap(wrap); $(el).wrap(wrap);
counter++; counter++;
} }
} else { } else {
$(el).attr('data-4cfi', genID); $(el).attr('data-4cfi', genID);
symbols = this._buildCFIs(el, genID + '/'); this._buildCFIs(el, genID + '/');
totalSymbols += symbols;
if (symbols) {
$(el).attr('data-symbols', symbols);
}
counter++; counter++;
} }
}.bind(this)); }.bind(this));
},
return totalSymbols; /**
* Вычисляет число символов в книге
*/
_countSymbols: function () {
this._totalBookSymbols = $.trim(this._bookPlaceholder.get(0).textContent).replace(/\s{2,}/g, ' ').length;
}, },
/** /**
@@ -570,16 +560,19 @@ modules.define(
if (!domElem) { if (!domElem) {
return; return;
} }
var $domElem = $(domElem);
// Элементы, которые не видимы или имеют position отличный // Элементы, которые не видимы или имеют position отличный
// от static возвращают неверные координаты, включаем их // от static возвращают неверные координаты, включаем их
// в boolean флаг preconditions // в boolean флаг preconditions
var preconditions = $(domElem).is(':visible') && var preconditions = $domElem.is(':visible') &&
['fixed', 'absolute'].indexOf($(domElem).css('position')) === -1 && ['fixed', 'absolute'].indexOf($domElem.css('position')) === -1 &&
// Мега костыль, т.к image__wrapper внутри содержить position: absolute элемент, // Мега костыль, т.к image__wrapper внутри содержить position: absolute элемент,
// то это сносит крышу счетоводу // то это сносит крышу счетоводу
!$(domElem).is('.image__wrapper'); !$domElem.is('.image__wrapper');
var pageDelta = Number($(domElem).position().left) / (this._pageWidth + this._gapWidth); var pageDelta = Number($domElem.position().left) / (this._pageWidth + this._gapWidth);
// И если текущий элемент именно такой, то возвращаем 0 // И если текущий элемент именно такой, то возвращаем 0
return preconditions ? return preconditions ?

View File

@@ -6,6 +6,7 @@ modules.define(
'inherit', 'inherit',
'y-extend', 'y-extend',
'chitalka-ui', 'chitalka-ui',
'hammer',
'storage' 'storage'
], ],
function ( function (
@@ -15,6 +16,7 @@ modules.define(
inherit, inherit,
extend, extend,
ChitalkaUI, ChitalkaUI,
Hammer,
Storage Storage
) { ) {
@@ -24,6 +26,15 @@ modules.define(
throw new Error('UNIMPLEMENTED METHOD: ' + method); throw new Error('UNIMPLEMENTED METHOD: ' + method);
}; };
/**
* Detect if device is touch
* @see http://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript
*/
var isTouch = function () {
return 'ontouchstart' in window // works on most browsers
|| 'onmsgesturechange' in window; // works on ie10
};
/** /**
* Расширение объекта Math для вычисления медианы массива * Расширение объекта Math для вычисления медианы массива
* *
@@ -117,7 +128,7 @@ modules.define(
} }
if (params.touch) { if (params.touch) {
this._initTouchEvents(); isTouch() && this._initTouchEvents();
} }
this._fontSizeLimits = params.fontSize; this._fontSizeLimits = params.fontSize;
@@ -158,6 +169,22 @@ modules.define(
* в функции выполняется навешивание соответствующих событий * в функции выполняется навешивание соответствующих событий
*/ */
_initTouchEvents: function () { _initTouchEvents: function () {
this._swiper = new Hammer(this.getDomNode()[0]);
this._swiper.on('swipe', function(e) {
var direction = (e.direction === 2)? 'left' : 'right';
switch (direction) {
case 'left':
this.nextPage();
break;
case 'right':
this.previousPage();
break;
}
}.bind(this));
}, },
_onKeyDown: function (e) { _onKeyDown: function (e) {
@@ -261,7 +288,7 @@ modules.define(
*/ */
_checkSpeed: function () { _checkSpeed: function () {
var speedEntries = this._speedAccumulator.length; var speedEntries = this._speedAccumulator.length;
if (speedEntries > 10) { if (speedEntries >= 10) {
this._speedAccumulator = this._speedAccumulator.sort(numSort); this._speedAccumulator = this._speedAccumulator.sort(numSort);
var median = Math.median(this._speedAccumulator); var median = Math.median(this._speedAccumulator);

View File

@@ -76,9 +76,11 @@ module.exports = function (bt) {
items += 2; items += 2;
content.push({ content.push({
elem: 'plus' elem: 'plus',
alt: 'Увеличить размер шрифта'
}, { }, {
elem: 'minus' elem: 'minus',
alt: 'Уменьшить размер шрифта'
}); });
} }
if (ctx.getParam('footnotes')) { if (ctx.getParam('footnotes')) {
@@ -106,6 +108,7 @@ module.exports = function (bt) {
bt.match('controls*__footnotes', function (ctx) { bt.match('controls*__footnotes', function (ctx) {
ctx.setState('mode', ctx.getParam('footnotes') || 'appendix'); ctx.setState('mode', ctx.getParam('footnotes') || 'appendix');
ctx.setAttr('title', 'Изменить режим отображения сносок');
ctx.setContent([{ ctx.setContent([{
elem: 'footnotes-anchor' elem: 'footnotes-anchor'
}, { }, {
@@ -124,6 +127,7 @@ module.exports = function (bt) {
bt.match('controls*__pages', function (ctx) { bt.match('controls*__pages', function (ctx) {
ctx.setState('mode', ctx.getParam('pages') || 'auto'); ctx.setState('mode', ctx.getParam('pages') || 'auto');
ctx.setAttr('title', 'Изменить режим отображения страниц');
ctx.setContent([{ ctx.setContent([{
elem: 'pages-one' elem: 'pages-one'
}, { }, {
@@ -131,4 +135,7 @@ module.exports = function (bt) {
} }
]); ]);
}); });
bt.match(['controls*__plus', 'controls*__minus'], function (ctx) {
ctx.setAttr('title', ctx.getParam('alt'));
});
}; };

2464
client/core/hammer/hammer.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
modules.define(
'test',
[
'spin',
'y-dom',
'jquery',
'inherit'
],
function (
provide,
Spin,
dom,
$,
inherit
) {
describe('Spin', function () {
var spin;
var expect = chai.expect;
var SpinStub = inherit(Spin, {
_classes: function() {
return [].slice.call(this.getDomNode()[0].classList)
}
});
beforeEach(function(){
spin = new SpinStub();
spin.getDomNode().appendTo(document.body);
});
afterEach(function(){
spin.destruct();
});
it('should have class _progressed after creation', function (){
expect(spin._classes()).to.contain('_progressed');
});
it('should remove class _progressed, on spin stop', function () {
spin.stop();
expect(spin._classes()).to.not.contain('_progressed');
});
it('should add class _progressed, on spin start', function () {
spin.stop();
spin.start();
expect(spin._classes()).to.contain('_progressed');
});
});
provide();
}
);

View File

@@ -63,7 +63,6 @@ modules.define('test', ['y-extend'], function (provide, extend) {
extend(true, target, obj); extend(true, target, obj);
target.date.should.eq(obj.date); target.date.should.eq(obj.date);
target.div.should.eq(obj.div); target.div.should.eq(obj.div);
target.window.should.eq(obj.window);
}); });
}); });
}); });

View File

@@ -26,9 +26,9 @@
</section> </section>
</xsl:for-each> </xsl:for-each>
<navMap style="display: none;"> <!--<navMap style="display: none;">-->
<xsl:apply-templates select="fb:body" mode="toc"/> <!--<xsl:apply-templates select="fb:body" mode="toc"/>-->
</navMap> <!--</navMap>-->
<xsl:for-each select="fb:body"> <xsl:for-each select="fb:body">

View File

@@ -1,15 +1,23 @@
{ {
"name": "chitalka", "name": "chitalka",
"description": "", "description": "JavaScript library to read fb2 books",
"version": "1.0.0", "version": "0.0.1",
"author": "Yandex Maps <mapsui-dev-team.ru>", "author": "Oleg Mokhov <o.mokhov@ya.ru>",
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"inherit": "2.2.2", "inherit": "2.2.2",
"vow-fs": "0.3.2", "vow-fs": "0.3.2",
"vow": "0.4.4", "vow": "0.4.4",
"enb-bevis-helper": "1.1.0", "enb-bevis-helper": "1.1.0",
"stylus": "0.47.1" "stylus": "0.47.1",
"mocha": "1.20.1",
"mocha-phantomjs": "3.5.0",
"phantomjs": "1.9.8",
"sinon": "1.10.2",
"chai": "1.9.1"
},
"scripts": {
"test": "make test"
}, },
"enb": { "enb": {
"dependencies": [ "dependencies": [

51
test/client/test.html Normal file
View File

@@ -0,0 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../../node_modules/mocha/mocha.css" />
<script src="../../node_modules/mocha/mocha.js"></script>
<script src="../../node_modules/chai/chai.js"></script>
<script src="../../node_modules/sinon/pkg/sinon.js"></script>
<script src="sources.js"></script>
<script src="tests.js"></script>
<script>
// default config
// @see configs/current/config for more information.
modules.define('config', function (provide) {
provide({
urls: {
jquery: 'http://yandex.st/jquery/1.10.1/jquery.min.js'
}
});
});
mocha.setup('bdd');
mocha.checkLeaks();
mocha.globals([]);
chai.config.includeStack = true;
// Resolve test dependency if `test` module is not found.
modules.define('test', function (provide) {
provide();
});
var should = chai.should();
modules.require(['test'], function () {
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
} else {
mocha.run();
}
});
</script>
</head>
<body>
<div id="mocha"></div>
</body>
</html>