Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
081d3cd15b | ||
|
|
8d7faddfc0 | ||
|
|
25f46ee198 | ||
|
|
2b44a449ed | ||
|
|
41a03cf63d | ||
|
|
e5eeb5ce6f | ||
|
|
d11cd3058f | ||
|
|
56af723e4f | ||
|
|
f0cbf9248e | ||
|
|
8b8f785e5a | ||
|
|
5a2b0c70cf | ||
|
|
dbf43a65f5 | ||
|
|
5ba6c431f7 | ||
|
|
ac026f32c2 | ||
|
|
d491d4f5af | ||
|
|
4c93a5598b | ||
|
|
e748934c8a | ||
|
|
f6dcbaef87 | ||
|
|
7b6f54d35e | ||
|
|
32091fce2a | ||
|
|
a46c1f2c82 | ||
|
|
fc18464f2a | ||
|
|
dc57804bab | ||
|
|
6025b017c8 | ||
|
|
6239ea262a |
@@ -23,4 +23,6 @@ module.exports = function(config) {
|
||||
//.forServerPage()
|
||||
.configureNode(nodeConfig);
|
||||
});
|
||||
|
||||
bevisHelper.configureUnitTests('test/client');
|
||||
};
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,3 +3,5 @@ node_modules
|
||||
build/index/*
|
||||
!build/index/i
|
||||
!build/index/index.btjson.js
|
||||
test/client/*
|
||||
!test/client/test.html
|
||||
|
||||
4
.travis.yml
Normal file
4
.travis.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.12"
|
||||
|
||||
10
Makefile
10
Makefile
@@ -27,11 +27,17 @@ npm:
|
||||
# Build project
|
||||
build:
|
||||
$(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
|
||||
|
||||
# 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:
|
||||
$(ENB) make clean
|
||||
|
||||
.PHONY: all install build clean
|
||||
.PHONY: all install build clean test
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
[](https://travis-ci.org/chitalka/reader)
|
||||
|
||||
# chitalka
|
||||
Welcome to chitalka.js repository. It is a JavaScript-library to read fb2 books.
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ module.exports = function (bt) {
|
||||
|
||||
bt.match('chitalka-fb2*', function (ctx) {
|
||||
ctx.setInitOption('keyboard', true);
|
||||
ctx.setInitOption('touch', true);
|
||||
ctx.setInitOption('url', ctx.getParam('url'));
|
||||
ctx.enableAutoInit();
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
- hammer
|
||||
- chitalka
|
||||
- unzip
|
||||
- storage
|
||||
|
||||
@@ -116,7 +116,6 @@ modules.define(
|
||||
* 'appendix' – в конце
|
||||
*/
|
||||
_setFootnotesMode: function (mode) {
|
||||
this._subscribeToLinksEvents();
|
||||
if (mode === 'inline') {
|
||||
this._footnotesMode = mode;
|
||||
this._setState('footnotes', 'inline');
|
||||
@@ -178,12 +177,13 @@ modules.define(
|
||||
this._fontSize = parseInt(this._bookPlaceholder.css('font-size'), 10);
|
||||
this._settings.save('font-size', this._fontSize);
|
||||
}
|
||||
this._lineHeight = parseInt(this._bookPlaceholder.css('line-height'), 10);
|
||||
this._annotations = this.getDomNode().find('.annotation');
|
||||
|
||||
this._subscribeToWindowEvents();
|
||||
this._subscribeToLinksEvents();
|
||||
|
||||
this._setFootnotesMode(this._settings.get('footnotes') || this._getState('footnotes') || 'appendix');
|
||||
|
||||
this._setPageViewMode(this._settings.get('pages') || this._getState('pages') || 'auto');
|
||||
|
||||
this._storage = new Storage(this.getBookId());
|
||||
@@ -194,14 +194,12 @@ modules.define(
|
||||
// связанный баг https://st.yandex-team.ru/CHITALKA-65
|
||||
nextTick(function () {
|
||||
this._buildCFIs();
|
||||
this._countSymbols();
|
||||
this._calcDimensions();
|
||||
|
||||
this._restoreSavedPosition();
|
||||
|
||||
this._firstElementOnPage = this._getKeeper();
|
||||
|
||||
this.emit('ready');
|
||||
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
@@ -301,8 +299,7 @@ modules.define(
|
||||
this._pageCount = this._getBookPages();
|
||||
|
||||
// Среднее число символов на странице, speedCoeff - эмпирически вычисленный коэффцицент
|
||||
var speedCoeff = (this._pageWidth / (11 * this._fontSize / 16));
|
||||
this._avgSymbolsOnPage = Math.round(Math.floor(this._bookCanvasHeight / this._lineHeight) * speedCoeff);
|
||||
this._avgSymbolsOnPage = Math.round(this._totalBookSymbols / this._pageCount)
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -490,40 +487,33 @@ modules.define(
|
||||
parent = parent || this._bookPlaceholder;
|
||||
var counter = 1;
|
||||
id = id || '/';
|
||||
var totalSymbols = 0;
|
||||
|
||||
$(parent).contents().map(function (i, el) {
|
||||
var genID = id + counter;
|
||||
var symbols;
|
||||
|
||||
if (el.nodeType === TEXT_NODE) {
|
||||
symbols = $.trim(el.textContent).length;
|
||||
totalSymbols += symbols;
|
||||
|
||||
// оборачиваем только если не пустая нода и не единственная
|
||||
if ($.trim(el.textContent) !== '' && $(parent).size() > 1) {
|
||||
var wrap = $('<span></span>');
|
||||
wrap.attr('data-4cfi', genID);
|
||||
if (symbols) {
|
||||
wrap.attr('data-symbols', symbols);
|
||||
}
|
||||
|
||||
$(el).wrap(wrap);
|
||||
counter++;
|
||||
}
|
||||
} else {
|
||||
$(el).attr('data-4cfi', genID);
|
||||
|
||||
symbols = this._buildCFIs(el, genID + '/');
|
||||
totalSymbols += symbols;
|
||||
if (symbols) {
|
||||
$(el).attr('data-symbols', symbols);
|
||||
}
|
||||
this._buildCFIs(el, genID + '/');
|
||||
|
||||
counter++;
|
||||
}
|
||||
}.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) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $domElem = $(domElem);
|
||||
|
||||
// Элементы, которые не видимы или имеют position отличный
|
||||
// от static возвращают неверные координаты, включаем их
|
||||
// в boolean флаг preconditions
|
||||
var preconditions = $(domElem).is(':visible') &&
|
||||
['fixed', 'absolute'].indexOf($(domElem).css('position')) === -1 &&
|
||||
var preconditions = $domElem.is(':visible') &&
|
||||
['fixed', 'absolute'].indexOf($domElem.css('position')) === -1 &&
|
||||
// Мега костыль, т.к 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
|
||||
return preconditions ?
|
||||
|
||||
@@ -6,6 +6,7 @@ modules.define(
|
||||
'inherit',
|
||||
'y-extend',
|
||||
'chitalka-ui',
|
||||
'hammer',
|
||||
'storage'
|
||||
],
|
||||
function (
|
||||
@@ -15,6 +16,7 @@ modules.define(
|
||||
inherit,
|
||||
extend,
|
||||
ChitalkaUI,
|
||||
Hammer,
|
||||
Storage
|
||||
) {
|
||||
|
||||
@@ -24,6 +26,15 @@ modules.define(
|
||||
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 для вычисления медианы массива
|
||||
*
|
||||
@@ -117,7 +128,7 @@ modules.define(
|
||||
}
|
||||
|
||||
if (params.touch) {
|
||||
this._initTouchEvents();
|
||||
isTouch() && this._initTouchEvents();
|
||||
}
|
||||
|
||||
this._fontSizeLimits = params.fontSize;
|
||||
@@ -158,6 +169,22 @@ modules.define(
|
||||
* в функции выполняется навешивание соответствующих событий
|
||||
*/
|
||||
_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) {
|
||||
@@ -261,7 +288,7 @@ modules.define(
|
||||
*/
|
||||
_checkSpeed: function () {
|
||||
var speedEntries = this._speedAccumulator.length;
|
||||
if (speedEntries > 10) {
|
||||
if (speedEntries >= 10) {
|
||||
this._speedAccumulator = this._speedAccumulator.sort(numSort);
|
||||
|
||||
var median = Math.median(this._speedAccumulator);
|
||||
|
||||
@@ -76,9 +76,11 @@ module.exports = function (bt) {
|
||||
items += 2;
|
||||
|
||||
content.push({
|
||||
elem: 'plus'
|
||||
elem: 'plus',
|
||||
alt: 'Увеличить размер шрифта'
|
||||
}, {
|
||||
elem: 'minus'
|
||||
elem: 'minus',
|
||||
alt: 'Уменьшить размер шрифта'
|
||||
});
|
||||
}
|
||||
if (ctx.getParam('footnotes')) {
|
||||
@@ -106,6 +108,7 @@ module.exports = function (bt) {
|
||||
|
||||
bt.match('controls*__footnotes', function (ctx) {
|
||||
ctx.setState('mode', ctx.getParam('footnotes') || 'appendix');
|
||||
ctx.setAttr('title', 'Изменить режим отображения сносок');
|
||||
ctx.setContent([{
|
||||
elem: 'footnotes-anchor'
|
||||
}, {
|
||||
@@ -124,6 +127,7 @@ module.exports = function (bt) {
|
||||
|
||||
bt.match('controls*__pages', function (ctx) {
|
||||
ctx.setState('mode', ctx.getParam('pages') || 'auto');
|
||||
ctx.setAttr('title', 'Изменить режим отображения страниц');
|
||||
ctx.setContent([{
|
||||
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
2464
client/core/hammer/hammer.js
Normal file
File diff suppressed because it is too large
Load Diff
57
client/core/spin/spin.test.js
Normal file
57
client/core/spin/spin.test.js
Normal 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();
|
||||
}
|
||||
);
|
||||
@@ -63,7 +63,6 @@ modules.define('test', ['y-extend'], function (provide, extend) {
|
||||
extend(true, target, obj);
|
||||
target.date.should.eq(obj.date);
|
||||
target.div.should.eq(obj.div);
|
||||
target.window.should.eq(obj.window);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
</section>
|
||||
</xsl:for-each>
|
||||
|
||||
<navMap style="display: none;">
|
||||
<xsl:apply-templates select="fb:body" mode="toc"/>
|
||||
</navMap>
|
||||
<!--<navMap style="display: none;">-->
|
||||
<!--<xsl:apply-templates select="fb:body" mode="toc"/>-->
|
||||
<!--</navMap>-->
|
||||
|
||||
|
||||
<xsl:for-each select="fb:body">
|
||||
|
||||
16
package.json
16
package.json
@@ -1,15 +1,23 @@
|
||||
{
|
||||
"name": "chitalka",
|
||||
"description": "",
|
||||
"version": "1.0.0",
|
||||
"author": "Yandex Maps <mapsui-dev-team.ru>",
|
||||
"description": "JavaScript library to read fb2 books",
|
||||
"version": "0.0.1",
|
||||
"author": "Oleg Mokhov <o.mokhov@ya.ru>",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"inherit": "2.2.2",
|
||||
"vow-fs": "0.3.2",
|
||||
"vow": "0.4.4",
|
||||
"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": {
|
||||
"dependencies": [
|
||||
|
||||
51
test/client/test.html
Normal file
51
test/client/test.html
Normal 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>
|
||||
|
||||
Reference in New Issue
Block a user