mirror of
https://github.com/MinimalBible/MinimalBible
synced 2024-11-24 17:08:18 -05:00
RecyclerView initial demonstration
This commit is contained in:
parent
147c6a5248
commit
d6c5662fa5
@ -8,12 +8,12 @@ apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
compileSdkVersion 20
|
||||
buildToolsVersion '20.0.0'
|
||||
compileSdkVersion 21
|
||||
buildToolsVersion '21.1.1'
|
||||
defaultConfig {
|
||||
applicationId 'org.bspeice.minimalbible'
|
||||
minSdkVersion 8
|
||||
targetSdkVersion 20
|
||||
targetSdkVersion 21
|
||||
versionCode 1
|
||||
versionName '1.0'
|
||||
}
|
||||
@ -47,7 +47,8 @@ dependencies {
|
||||
compile 'com.jakewharton:butterknife:+'
|
||||
compile 'com.readystatesoftware.systembartint:systembartint:+'
|
||||
compile 'com.netflix.rxjava:rxjava-android:+'
|
||||
compile 'com.android.support:appcompat-v7:20.+'
|
||||
compile 'com.android.support:appcompat-v7:21.+'
|
||||
compile 'com.android.support:recyclerview-v7:21.+'
|
||||
compile 'org.apache.commons:commons-lang3:+'
|
||||
compile 'com.google.code.gson:gson:+'
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
|
@ -1,18 +0,0 @@
|
||||
<html lang="en" ng-app="bookApp">
|
||||
<head>
|
||||
<script type="text/javascript" src="file:///android_asset/dist/book-bundle.js"></script>
|
||||
<script type="text/javascript" src="file:///android_asset/dist/scroll.js"></script>
|
||||
<script type="text/javascript" src="file:///android_asset/dist/scroll-jqlite.js"></script>
|
||||
</head>
|
||||
<body ng-controller="BookCtrl" id="bookController">
|
||||
<div u-scroll-viewport style="height:200px;">
|
||||
<div ui-scroll="verse in verseSource" style="display: inline;">
|
||||
<h3 style="display: inline;" ng-show="verse.verseNum === 1">
|
||||
{{ verse.chapter }}
|
||||
</h3>
|
||||
<sup ng-show="verse.verseNum !== 1 && verse.verseNum !== 0">{{ verse.verseNum }}</sup>
|
||||
{{ verse.content }}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
21999
app/src/main/assets/dist/book-bundle.js
vendored
21999
app/src/main/assets/dist/book-bundle.js
vendored
File diff suppressed because it is too large
Load Diff
229
app/src/main/assets/dist/scroll-jqlite.js
vendored
229
app/src/main/assets/dist/scroll-jqlite.js
vendored
@ -1,229 +0,0 @@
|
||||
'use strict';
|
||||
angular.module('ui.scroll.jqlite', ['ui.scroll']).service('jqLiteExtras', [
|
||||
'$log', '$window', function(console, window) {
|
||||
return {
|
||||
registerFor: function(element) {
|
||||
var convertToPx, css, getMeasurements, getStyle, getWidthHeight, isWindow, scrollTo;
|
||||
css = angular.element.prototype.css;
|
||||
element.prototype.css = function(name, value) {
|
||||
var elem, self;
|
||||
self = this;
|
||||
elem = self[0];
|
||||
if (!(!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style)) {
|
||||
return css.call(self, name, value);
|
||||
}
|
||||
};
|
||||
isWindow = function(obj) {
|
||||
return obj && obj.document && obj.location && obj.alert && obj.setInterval;
|
||||
};
|
||||
scrollTo = function(self, direction, value) {
|
||||
var elem, method, preserve, prop, _ref;
|
||||
elem = self[0];
|
||||
_ref = {
|
||||
top: ['scrollTop', 'pageYOffset', 'scrollLeft'],
|
||||
left: ['scrollLeft', 'pageXOffset', 'scrollTop']
|
||||
}[direction], method = _ref[0], prop = _ref[1], preserve = _ref[2];
|
||||
if (isWindow(elem)) {
|
||||
if (angular.isDefined(value)) {
|
||||
return elem.scrollTo(self[preserve].call(self), value);
|
||||
} else {
|
||||
if (prop in elem) {
|
||||
return elem[prop];
|
||||
} else {
|
||||
return elem.document.documentElement[method];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (angular.isDefined(value)) {
|
||||
return elem[method] = value;
|
||||
} else {
|
||||
return elem[method];
|
||||
}
|
||||
}
|
||||
};
|
||||
if (window.getComputedStyle) {
|
||||
getStyle = function(elem) {
|
||||
return window.getComputedStyle(elem, null);
|
||||
};
|
||||
convertToPx = function(elem, value) {
|
||||
return parseFloat(value);
|
||||
};
|
||||
} else {
|
||||
getStyle = function(elem) {
|
||||
return elem.currentStyle;
|
||||
};
|
||||
convertToPx = function(elem, value) {
|
||||
var core_pnum, left, result, rnumnonpx, rs, rsLeft, style;
|
||||
core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source;
|
||||
rnumnonpx = new RegExp('^(' + core_pnum + ')(?!px)[a-z%]+$', 'i');
|
||||
if (!rnumnonpx.test(value)) {
|
||||
return parseFloat(value);
|
||||
} else {
|
||||
style = elem.style;
|
||||
left = style.left;
|
||||
rs = elem.runtimeStyle;
|
||||
rsLeft = rs && rs.left;
|
||||
if (rs) {
|
||||
rs.left = style.left;
|
||||
}
|
||||
style.left = value;
|
||||
result = style.pixelLeft;
|
||||
style.left = left;
|
||||
if (rsLeft) {
|
||||
rs.left = rsLeft;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
getMeasurements = function(elem, measure) {
|
||||
var base, borderA, borderB, computedMarginA, computedMarginB, computedStyle, dirA, dirB, marginA, marginB, paddingA, paddingB, _ref;
|
||||
if (isWindow(elem)) {
|
||||
base = document.documentElement[{
|
||||
height: 'clientHeight',
|
||||
width: 'clientWidth'
|
||||
}[measure]];
|
||||
return {
|
||||
base: base,
|
||||
padding: 0,
|
||||
border: 0,
|
||||
margin: 0
|
||||
};
|
||||
}
|
||||
_ref = {
|
||||
width: [elem.offsetWidth, 'Left', 'Right'],
|
||||
height: [elem.offsetHeight, 'Top', 'Bottom']
|
||||
}[measure], base = _ref[0], dirA = _ref[1], dirB = _ref[2];
|
||||
computedStyle = getStyle(elem);
|
||||
paddingA = convertToPx(elem, computedStyle['padding' + dirA]) || 0;
|
||||
paddingB = convertToPx(elem, computedStyle['padding' + dirB]) || 0;
|
||||
borderA = convertToPx(elem, computedStyle['border' + dirA + 'Width']) || 0;
|
||||
borderB = convertToPx(elem, computedStyle['border' + dirB + 'Width']) || 0;
|
||||
computedMarginA = computedStyle['margin' + dirA];
|
||||
computedMarginB = computedStyle['margin' + dirB];
|
||||
marginA = convertToPx(elem, computedMarginA) || 0;
|
||||
marginB = convertToPx(elem, computedMarginB) || 0;
|
||||
return {
|
||||
base: base,
|
||||
padding: paddingA + paddingB,
|
||||
border: borderA + borderB,
|
||||
margin: marginA + marginB
|
||||
};
|
||||
};
|
||||
getWidthHeight = function(elem, direction, measure) {
|
||||
var computedStyle, measurements, result;
|
||||
measurements = getMeasurements(elem, direction);
|
||||
if (measurements.base > 0) {
|
||||
return {
|
||||
base: measurements.base - measurements.padding - measurements.border,
|
||||
outer: measurements.base,
|
||||
outerfull: measurements.base + measurements.margin
|
||||
}[measure];
|
||||
} else {
|
||||
computedStyle = getStyle(elem);
|
||||
result = computedStyle[direction];
|
||||
if (result < 0 || result === null) {
|
||||
result = elem.style[direction] || 0;
|
||||
}
|
||||
result = parseFloat(result) || 0;
|
||||
return {
|
||||
base: result - measurements.padding - measurements.border,
|
||||
outer: result,
|
||||
outerfull: result + measurements.padding + measurements.border + measurements.margin
|
||||
}[measure];
|
||||
}
|
||||
};
|
||||
return angular.forEach({
|
||||
before: function(newElem) {
|
||||
var children, elem, i, parent, self, _i, _ref;
|
||||
self = this;
|
||||
elem = self[0];
|
||||
parent = self.parent();
|
||||
children = parent.contents();
|
||||
if (children[0] === elem) {
|
||||
return parent.prepend(newElem);
|
||||
} else {
|
||||
for (i = _i = 1, _ref = children.length - 1; 1 <= _ref ? _i <= _ref : _i >= _ref; i = 1 <= _ref ? ++_i : --_i) {
|
||||
if (children[i] === elem) {
|
||||
angular.element(children[i - 1]).after(newElem);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new Error('invalid DOM structure ' + elem.outerHTML);
|
||||
}
|
||||
},
|
||||
height: function(value) {
|
||||
var self;
|
||||
self = this;
|
||||
if (angular.isDefined(value)) {
|
||||
if (angular.isNumber(value)) {
|
||||
value = value + 'px';
|
||||
}
|
||||
return css.call(self, 'height', value);
|
||||
} else {
|
||||
return getWidthHeight(this[0], 'height', 'base');
|
||||
}
|
||||
},
|
||||
outerHeight: function(option) {
|
||||
return getWidthHeight(this[0], 'height', option ? 'outerfull' : 'outer');
|
||||
},
|
||||
/*
|
||||
UIScroller no longer relies on jQuery method offset. The jQLite implementation of the method
|
||||
is kept here just for the reference. Also the offset setter method was never implemented
|
||||
*/
|
||||
|
||||
offset: function(value) {
|
||||
var box, doc, docElem, elem, self, win;
|
||||
self = this;
|
||||
if (arguments.length) {
|
||||
if (value === void 0) {
|
||||
return self;
|
||||
} else {
|
||||
throw new Error('offset setter method is not implemented');
|
||||
}
|
||||
}
|
||||
box = {
|
||||
top: 0,
|
||||
left: 0
|
||||
};
|
||||
elem = self[0];
|
||||
doc = elem && elem.ownerDocument;
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
docElem = doc.documentElement;
|
||||
if (elem.getBoundingClientRect != null) {
|
||||
box = elem.getBoundingClientRect();
|
||||
}
|
||||
win = doc.defaultView || doc.parentWindow;
|
||||
return {
|
||||
top: box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0),
|
||||
left: box.left + (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)
|
||||
};
|
||||
},
|
||||
scrollTop: function(value) {
|
||||
return scrollTo(this, 'top', value);
|
||||
},
|
||||
scrollLeft: function(value) {
|
||||
return scrollTo(this, 'left', value);
|
||||
}
|
||||
}, function(value, key) {
|
||||
if (!element.prototype[key]) {
|
||||
return element.prototype[key] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
]).run([
|
||||
'$log', '$window', 'jqLiteExtras', function(console, window, jqLiteExtras) {
|
||||
if (!window.jQuery) {
|
||||
return jqLiteExtras.registerFor(angular.element);
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
/*
|
||||
//# sourceURL=src/scripts/ui-scroll-jqlite.js
|
||||
*/
|
||||
|
576
app/src/main/assets/dist/scroll.js
vendored
576
app/src/main/assets/dist/scroll.js
vendored
@ -1,576 +0,0 @@
|
||||
'use strict';
|
||||
/*
|
||||
globals: angular, window
|
||||
|
||||
List of used element methods available in JQuery but not in JQuery Lite
|
||||
|
||||
element.before(elem)
|
||||
element.height()
|
||||
element.outerHeight(true)
|
||||
element.height(value) = only for Top/Bottom padding elements
|
||||
element.scrollTop()
|
||||
element.scrollTop(value)
|
||||
*/
|
||||
|
||||
angular.module('ui.scroll', []).directive('uiScrollViewport', [
|
||||
'$log', function() {
|
||||
return {
|
||||
controller: [
|
||||
'$scope', '$element', function(scope, element) {
|
||||
return element;
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
]).directive('uiScroll', [
|
||||
'$log', '$injector', '$rootScope', '$timeout', function(console, $injector, $rootScope, $timeout) {
|
||||
return {
|
||||
require: ['?^uiScrollViewport'],
|
||||
transclude: 'element',
|
||||
priority: 1000,
|
||||
terminal: true,
|
||||
compile: function(elementTemplate, attr, linker) {
|
||||
return function($scope, element, $attr, controllers) {
|
||||
var adapter, adjustBuffer, adjustRowHeight, bof, bottomVisiblePos, buffer, bufferPadding, bufferSize, clipBottom, clipTop, datasource, datasourceName, doAdjustment, enqueueFetch, eof, eventListener, fetch, finalize, first, hideElementBeforeAppend, insert, isDatasource, isLoading, itemName, loading, log, match, next, pending, reload, removeFromBuffer, resizeHandler, ridActual, scrollHandler, scrollHeight, shouldLoadBottom, shouldLoadTop, showElementAfterRender, tempScope, topVisible, topVisibleElement, topVisibleItem, topVisiblePos, topVisibleScope, viewport, viewportScope, wheelHandler;
|
||||
log = console.debug || console.log;
|
||||
match = $attr.uiScroll.match(/^\s*(\w+)\s+in\s+(\w+)\s*$/);
|
||||
if (!match) {
|
||||
throw new Error('Expected uiScroll in form of \'_item_ in _datasource_\' but got \'' + $attr.uiScroll + '\'');
|
||||
}
|
||||
itemName = match[1];
|
||||
datasourceName = match[2];
|
||||
isDatasource = function(datasource) {
|
||||
return angular.isObject(datasource) && datasource.get && angular.isFunction(datasource.get);
|
||||
};
|
||||
datasource = $scope[datasourceName];
|
||||
if (!isDatasource(datasource)) {
|
||||
datasource = $injector.get(datasourceName);
|
||||
if (!isDatasource(datasource)) {
|
||||
throw new Error('' + datasourceName + ' is not a valid datasource');
|
||||
}
|
||||
}
|
||||
bufferSize = Math.max(3, +$attr.bufferSize || 10);
|
||||
bufferPadding = function() {
|
||||
return viewport.outerHeight() * Math.max(0.1, +$attr.padding || 0.1);
|
||||
};
|
||||
scrollHeight = function(elem) {
|
||||
var _ref;
|
||||
return (_ref = elem[0].scrollHeight) != null ? _ref : elem[0].document.documentElement.scrollHeight;
|
||||
};
|
||||
adapter = null;
|
||||
linker(tempScope = $scope.$new(), function(template) {
|
||||
var bottomPadding, createPadding, padding, repeaterType, topPadding, viewport;
|
||||
repeaterType = template[0].localName;
|
||||
if (repeaterType === 'dl') {
|
||||
throw new Error('ui-scroll directive does not support <' + template[0].localName + '> as a repeating tag: ' + template[0].outerHTML);
|
||||
}
|
||||
if (repeaterType !== 'li' && repeaterType !== 'tr') {
|
||||
repeaterType = 'div';
|
||||
}
|
||||
viewport = controllers[0] || angular.element(window);
|
||||
viewport.css({
|
||||
'overflow-y': 'auto',
|
||||
'display': 'block'
|
||||
});
|
||||
padding = function(repeaterType) {
|
||||
var div, result, table;
|
||||
switch (repeaterType) {
|
||||
case 'tr':
|
||||
table = angular.element('<table><tr><td><div></div></td></tr></table>');
|
||||
div = table.find('div');
|
||||
result = table.find('tr');
|
||||
result.paddingHeight = function() {
|
||||
return div.height.apply(div, arguments);
|
||||
};
|
||||
return result;
|
||||
default:
|
||||
result = angular.element('<' + repeaterType + '></' + repeaterType + '>');
|
||||
result.paddingHeight = result.height;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
createPadding = function(padding, element, direction) {
|
||||
element[{
|
||||
top: 'before',
|
||||
bottom: 'after'
|
||||
}[direction]](padding);
|
||||
return {
|
||||
paddingHeight: function() {
|
||||
return padding.paddingHeight.apply(padding, arguments);
|
||||
},
|
||||
insert: function(element) {
|
||||
return padding[{
|
||||
top: 'after',
|
||||
bottom: 'before'
|
||||
}[direction]](element);
|
||||
}
|
||||
};
|
||||
};
|
||||
topPadding = createPadding(padding(repeaterType), element, 'top');
|
||||
bottomPadding = createPadding(padding(repeaterType), element, 'bottom');
|
||||
tempScope.$destroy();
|
||||
return adapter = {
|
||||
viewport: viewport,
|
||||
topPadding: topPadding.paddingHeight,
|
||||
bottomPadding: bottomPadding.paddingHeight,
|
||||
append: bottomPadding.insert,
|
||||
prepend: topPadding.insert,
|
||||
bottomDataPos: function() {
|
||||
return scrollHeight(viewport) - bottomPadding.paddingHeight();
|
||||
},
|
||||
topDataPos: function() {
|
||||
return topPadding.paddingHeight();
|
||||
}
|
||||
};
|
||||
});
|
||||
viewport = adapter.viewport;
|
||||
viewportScope = viewport.scope() || $rootScope;
|
||||
if (angular.isDefined($attr.topVisible)) {
|
||||
topVisibleItem = function(item) {
|
||||
return viewportScope[$attr.topVisible] = item;
|
||||
};
|
||||
}
|
||||
if (angular.isDefined($attr.topVisibleElement)) {
|
||||
topVisibleElement = function(element) {
|
||||
return viewportScope[$attr.topVisibleElement] = element;
|
||||
};
|
||||
}
|
||||
if (angular.isDefined($attr.topVisibleScope)) {
|
||||
topVisibleScope = function(scope) {
|
||||
return viewportScope[$attr.topVisibleScope] = scope;
|
||||
};
|
||||
}
|
||||
topVisible = function(item) {
|
||||
if (topVisibleItem) {
|
||||
topVisibleItem(item.scope[itemName]);
|
||||
}
|
||||
if (topVisibleElement) {
|
||||
topVisibleElement(item.element);
|
||||
}
|
||||
if (topVisibleScope) {
|
||||
topVisibleScope(item.scope);
|
||||
}
|
||||
if (datasource.topVisible) {
|
||||
return datasource.topVisible(item);
|
||||
}
|
||||
};
|
||||
if (angular.isDefined($attr.isLoading)) {
|
||||
loading = function(value) {
|
||||
viewportScope[$attr.isLoading] = value;
|
||||
if (datasource.loading) {
|
||||
return datasource.loading(value);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
loading = function(value) {
|
||||
if (datasource.loading) {
|
||||
return datasource.loading(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
ridActual = 0;
|
||||
first = 1;
|
||||
next = 1;
|
||||
buffer = [];
|
||||
pending = [];
|
||||
eof = false;
|
||||
bof = false;
|
||||
isLoading = false;
|
||||
removeFromBuffer = function(start, stop) {
|
||||
var i, _i;
|
||||
for (i = _i = start; start <= stop ? _i < stop : _i > stop; i = start <= stop ? ++_i : --_i) {
|
||||
buffer[i].scope.$destroy();
|
||||
buffer[i].element.remove();
|
||||
}
|
||||
return buffer.splice(start, stop - start);
|
||||
};
|
||||
reload = function() {
|
||||
ridActual++;
|
||||
first = 1;
|
||||
next = 1;
|
||||
removeFromBuffer(0, buffer.length);
|
||||
adapter.topPadding(0);
|
||||
adapter.bottomPadding(0);
|
||||
pending = [];
|
||||
eof = false;
|
||||
bof = false;
|
||||
return adjustBuffer(ridActual, false);
|
||||
};
|
||||
bottomVisiblePos = function() {
|
||||
return viewport.scrollTop() + viewport.outerHeight();
|
||||
};
|
||||
topVisiblePos = function() {
|
||||
return viewport.scrollTop();
|
||||
};
|
||||
shouldLoadBottom = function() {
|
||||
return !eof && adapter.bottomDataPos() < bottomVisiblePos() + bufferPadding();
|
||||
};
|
||||
clipBottom = function() {
|
||||
var bottomHeight, i, item, itemHeight, itemTop, newRow, overage, rowTop, _i, _ref;
|
||||
bottomHeight = 0;
|
||||
overage = 0;
|
||||
for (i = _i = _ref = buffer.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) {
|
||||
item = buffer[i];
|
||||
itemTop = item.element.offset().top;
|
||||
newRow = rowTop !== itemTop;
|
||||
rowTop = itemTop;
|
||||
if (newRow) {
|
||||
itemHeight = item.element.outerHeight(true);
|
||||
}
|
||||
if (adapter.bottomDataPos() - bottomHeight - itemHeight > bottomVisiblePos() + bufferPadding()) {
|
||||
if (newRow) {
|
||||
bottomHeight += itemHeight;
|
||||
}
|
||||
overage++;
|
||||
eof = false;
|
||||
} else {
|
||||
if (newRow) {
|
||||
break;
|
||||
}
|
||||
overage++;
|
||||
}
|
||||
}
|
||||
if (overage > 0) {
|
||||
adapter.bottomPadding(adapter.bottomPadding() + bottomHeight);
|
||||
removeFromBuffer(buffer.length - overage, buffer.length);
|
||||
next -= overage;
|
||||
return log('clipped off bottom ' + overage + ' bottom padding ' + (adapter.bottomPadding()));
|
||||
}
|
||||
};
|
||||
shouldLoadTop = function() {
|
||||
return !bof && (adapter.topDataPos() > topVisiblePos() - bufferPadding());
|
||||
};
|
||||
clipTop = function() {
|
||||
var item, itemHeight, itemTop, newRow, overage, rowTop, topHeight, _i, _len;
|
||||
topHeight = 0;
|
||||
overage = 0;
|
||||
for (_i = 0, _len = buffer.length; _i < _len; _i++) {
|
||||
item = buffer[_i];
|
||||
itemTop = item.element.offset().top;
|
||||
newRow = rowTop !== itemTop;
|
||||
rowTop = itemTop;
|
||||
if (newRow) {
|
||||
itemHeight = item.element.outerHeight(true);
|
||||
}
|
||||
if (adapter.topDataPos() + topHeight + itemHeight < topVisiblePos() - bufferPadding()) {
|
||||
if (newRow) {
|
||||
topHeight += itemHeight;
|
||||
}
|
||||
overage++;
|
||||
bof = false;
|
||||
} else {
|
||||
if (newRow) {
|
||||
break;
|
||||
}
|
||||
overage++;
|
||||
}
|
||||
}
|
||||
if (overage > 0) {
|
||||
adapter.topPadding(adapter.topPadding() + topHeight);
|
||||
removeFromBuffer(0, overage);
|
||||
first += overage;
|
||||
return log('clipped off top ' + overage + ' top padding ' + (adapter.topPadding()));
|
||||
}
|
||||
};
|
||||
enqueueFetch = function(rid, direction, scrolling) {
|
||||
if (!isLoading) {
|
||||
isLoading = true;
|
||||
loading(true);
|
||||
}
|
||||
if (pending.push(direction) === 1) {
|
||||
return fetch(rid, scrolling);
|
||||
}
|
||||
};
|
||||
hideElementBeforeAppend = function(element) {
|
||||
element.displayTemp = element.css('display');
|
||||
return element.css('display', 'none');
|
||||
};
|
||||
showElementAfterRender = function(element) {
|
||||
if (element.hasOwnProperty('displayTemp')) {
|
||||
return element.css('display', element.displayTemp);
|
||||
}
|
||||
};
|
||||
insert = function(index, item) {
|
||||
var itemScope, toBeAppended, wrapper;
|
||||
itemScope = $scope.$new();
|
||||
itemScope[itemName] = item;
|
||||
toBeAppended = index > first;
|
||||
itemScope.$index = index;
|
||||
if (toBeAppended) {
|
||||
itemScope.$index--;
|
||||
}
|
||||
wrapper = {
|
||||
scope: itemScope
|
||||
};
|
||||
linker(itemScope, function(clone) {
|
||||
wrapper.element = clone;
|
||||
if (toBeAppended) {
|
||||
if (index === next) {
|
||||
hideElementBeforeAppend(clone);
|
||||
adapter.append(clone);
|
||||
return buffer.push(wrapper);
|
||||
} else {
|
||||
buffer[index - first].element.after(clone);
|
||||
return buffer.splice(index - first + 1, 0, wrapper);
|
||||
}
|
||||
} else {
|
||||
hideElementBeforeAppend(clone);
|
||||
adapter.prepend(clone);
|
||||
return buffer.unshift(wrapper);
|
||||
}
|
||||
});
|
||||
return {
|
||||
appended: toBeAppended,
|
||||
wrapper: wrapper
|
||||
};
|
||||
};
|
||||
adjustRowHeight = function(appended, wrapper) {
|
||||
var newHeight;
|
||||
if (appended) {
|
||||
return adapter.bottomPadding(Math.max(0, adapter.bottomPadding() - wrapper.element.outerHeight(true)));
|
||||
} else {
|
||||
newHeight = adapter.topPadding() - wrapper.element.outerHeight(true);
|
||||
if (newHeight >= 0) {
|
||||
return adapter.topPadding(newHeight);
|
||||
} else {
|
||||
return viewport.scrollTop(viewport.scrollTop() + wrapper.element.outerHeight(true));
|
||||
}
|
||||
}
|
||||
};
|
||||
doAdjustment = function(rid, scrolling, finalize) {
|
||||
var item, itemHeight, itemTop, newRow, rowTop, topHeight, _i, _len, _results;
|
||||
log('top {actual=' + (adapter.topDataPos()) + ' visible from=' + (topVisiblePos()) + ' bottom {visible through=' + (bottomVisiblePos()) + ' actual=' + (adapter.bottomDataPos()) + '}');
|
||||
if (shouldLoadBottom()) {
|
||||
enqueueFetch(rid, true, scrolling);
|
||||
} else {
|
||||
if (shouldLoadTop()) {
|
||||
enqueueFetch(rid, false, scrolling);
|
||||
}
|
||||
}
|
||||
if (finalize) {
|
||||
finalize(rid);
|
||||
}
|
||||
if (pending.length === 0) {
|
||||
topHeight = 0;
|
||||
_results = [];
|
||||
for (_i = 0, _len = buffer.length; _i < _len; _i++) {
|
||||
item = buffer[_i];
|
||||
itemTop = item.element.offset().top;
|
||||
newRow = rowTop !== itemTop;
|
||||
rowTop = itemTop;
|
||||
if (newRow) {
|
||||
itemHeight = item.element.outerHeight(true);
|
||||
}
|
||||
if (newRow && (adapter.topDataPos() + topHeight + itemHeight < topVisiblePos())) {
|
||||
_results.push(topHeight += itemHeight);
|
||||
} else {
|
||||
if (newRow) {
|
||||
topVisible(item);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
}
|
||||
};
|
||||
adjustBuffer = function(rid, scrolling, newItems, finalize) {
|
||||
if (newItems && newItems.length) {
|
||||
return $timeout(function() {
|
||||
var itemTop, row, rowTop, rows, _i, _j, _len, _len1;
|
||||
rows = [];
|
||||
for (_i = 0, _len = newItems.length; _i < _len; _i++) {
|
||||
row = newItems[_i];
|
||||
element = row.wrapper.element;
|
||||
showElementAfterRender(element);
|
||||
itemTop = element.offset().top;
|
||||
if (rowTop !== itemTop) {
|
||||
rows.push(row);
|
||||
rowTop = itemTop;
|
||||
}
|
||||
}
|
||||
for (_j = 0, _len1 = rows.length; _j < _len1; _j++) {
|
||||
row = rows[_j];
|
||||
adjustRowHeight(row.appended, row.wrapper);
|
||||
}
|
||||
return doAdjustment(rid, scrolling, finalize);
|
||||
});
|
||||
} else {
|
||||
return doAdjustment(rid, scrolling, finalize);
|
||||
}
|
||||
};
|
||||
finalize = function(rid, scrolling, newItems) {
|
||||
return adjustBuffer(rid, scrolling, newItems, function() {
|
||||
pending.shift();
|
||||
if (pending.length === 0) {
|
||||
isLoading = false;
|
||||
return loading(false);
|
||||
} else {
|
||||
return fetch(rid, scrolling);
|
||||
}
|
||||
});
|
||||
};
|
||||
fetch = function(rid, scrolling) {
|
||||
var direction;
|
||||
direction = pending[0];
|
||||
if (direction) {
|
||||
if (buffer.length && !shouldLoadBottom()) {
|
||||
return finalize(rid, scrolling);
|
||||
} else {
|
||||
return datasource.get(next, bufferSize, function(result) {
|
||||
var item, newItems, _i, _len;
|
||||
if (rid && rid !== ridActual) {
|
||||
return;
|
||||
}
|
||||
newItems = [];
|
||||
if (result.length < bufferSize) {
|
||||
eof = true;
|
||||
adapter.bottomPadding(0);
|
||||
}
|
||||
if (result.length > 0) {
|
||||
clipTop();
|
||||
for (_i = 0, _len = result.length; _i < _len; _i++) {
|
||||
item = result[_i];
|
||||
newItems.push(insert(++next, item));
|
||||
}
|
||||
}
|
||||
return finalize(rid, scrolling, newItems);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (buffer.length && !shouldLoadTop()) {
|
||||
return finalize(rid, scrolling);
|
||||
} else {
|
||||
return datasource.get(first - bufferSize, bufferSize, function(result) {
|
||||
var i, newItems, _i, _ref;
|
||||
if (rid && rid !== ridActual) {
|
||||
return;
|
||||
}
|
||||
newItems = [];
|
||||
if (result.length < bufferSize) {
|
||||
bof = true;
|
||||
adapter.topPadding(0);
|
||||
}
|
||||
if (result.length > 0) {
|
||||
if (buffer.length) {
|
||||
clipBottom();
|
||||
}
|
||||
for (i = _i = _ref = result.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) {
|
||||
newItems.unshift(insert(--first, result[i]));
|
||||
}
|
||||
}
|
||||
return finalize(rid, scrolling, newItems);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
resizeHandler = function() {
|
||||
if (!$rootScope.$$phase && !isLoading) {
|
||||
adjustBuffer(null, false);
|
||||
return $scope.$apply();
|
||||
}
|
||||
};
|
||||
viewport.bind('resize', resizeHandler);
|
||||
scrollHandler = function() {
|
||||
if (!$rootScope.$$phase && !isLoading) {
|
||||
adjustBuffer(null, true);
|
||||
return $scope.$apply();
|
||||
}
|
||||
};
|
||||
viewport.bind('scroll', scrollHandler);
|
||||
wheelHandler = function(event) {
|
||||
var scrollTop, yMax;
|
||||
scrollTop = viewport[0].scrollTop;
|
||||
yMax = viewport[0].scrollHeight - viewport[0].clientHeight;
|
||||
if ((scrollTop === 0 && !bof) || (scrollTop === yMax && !eof)) {
|
||||
return event.preventDefault();
|
||||
}
|
||||
};
|
||||
viewport.bind('mousewheel', wheelHandler);
|
||||
$scope.$watch(datasource.revision, function() {
|
||||
return reload();
|
||||
});
|
||||
if (datasource.scope) {
|
||||
eventListener = datasource.scope.$new();
|
||||
} else {
|
||||
eventListener = $scope.$new();
|
||||
}
|
||||
$scope.$on('$destroy', function() {
|
||||
eventListener.$destroy();
|
||||
viewport.unbind('resize', resizeHandler);
|
||||
viewport.unbind('scroll', scrollHandler);
|
||||
return viewport.unbind('mousewheel', wheelHandler);
|
||||
});
|
||||
eventListener.$on('update.items', function(event, locator, newItem) {
|
||||
var wrapper, _fn, _i, _len, _ref;
|
||||
if (angular.isFunction(locator)) {
|
||||
_fn = function(wrapper) {
|
||||
return locator(wrapper.scope);
|
||||
};
|
||||
for (_i = 0, _len = buffer.length; _i < _len; _i++) {
|
||||
wrapper = buffer[_i];
|
||||
_fn(wrapper);
|
||||
}
|
||||
} else {
|
||||
if ((0 <= (_ref = locator - first - 1) && _ref < buffer.length)) {
|
||||
buffer[locator - first - 1].scope[itemName] = newItem;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
eventListener.$on('delete.items', function(event, locator) {
|
||||
var i, item, temp, wrapper, _fn, _i, _j, _k, _len, _len1, _len2, _ref;
|
||||
if (angular.isFunction(locator)) {
|
||||
temp = [];
|
||||
for (_i = 0, _len = buffer.length; _i < _len; _i++) {
|
||||
item = buffer[_i];
|
||||
temp.unshift(item);
|
||||
}
|
||||
_fn = function(wrapper) {
|
||||
if (locator(wrapper.scope)) {
|
||||
removeFromBuffer(temp.length - 1 - i, temp.length - i);
|
||||
return next--;
|
||||
}
|
||||
};
|
||||
for (i = _j = 0, _len1 = temp.length; _j < _len1; i = ++_j) {
|
||||
wrapper = temp[i];
|
||||
_fn(wrapper);
|
||||
}
|
||||
} else {
|
||||
if ((0 <= (_ref = locator - first - 1) && _ref < buffer.length)) {
|
||||
removeFromBuffer(locator - first - 1, locator - first);
|
||||
next--;
|
||||
}
|
||||
}
|
||||
for (i = _k = 0, _len2 = buffer.length; _k < _len2; i = ++_k) {
|
||||
item = buffer[i];
|
||||
item.scope.$index = first + i;
|
||||
}
|
||||
return adjustBuffer(null, false);
|
||||
});
|
||||
return eventListener.$on('insert.item', function(event, locator, item) {
|
||||
var i, inserted, _i, _len, _ref;
|
||||
inserted = [];
|
||||
if (angular.isFunction(locator)) {
|
||||
throw new Error('not implemented - Insert with locator function');
|
||||
} else {
|
||||
if ((0 <= (_ref = locator - first - 1) && _ref < buffer.length)) {
|
||||
inserted.push(insert(locator, item));
|
||||
next++;
|
||||
}
|
||||
}
|
||||
for (i = _i = 0, _len = buffer.length; _i < _len; i = ++_i) {
|
||||
item = buffer[i];
|
||||
item.scope.$index = first + i;
|
||||
}
|
||||
return adjustBuffer(null, false, inserted);
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
]);
|
||||
|
||||
/*
|
||||
//# sourceURL=src/scripts/ui-scroll.js
|
||||
*/
|
||||
|
@ -1,29 +0,0 @@
|
||||
var gulp = require('gulp');
|
||||
var gutil = require('gulp-util');
|
||||
var source = require('vinyl-source-stream');
|
||||
var watchify = require('watchify');
|
||||
var browserify = require('browserify');
|
||||
var buffer = require('gulp-buffer');
|
||||
|
||||
gulp.task('watch', function() {
|
||||
var bundler = watchify(browserify('./src/book.coffee', watchify.args));
|
||||
|
||||
// Optionally, you can apply transforms
|
||||
// and other configuration options on the
|
||||
// bundler just as you would with browserify
|
||||
bundler.transform('coffeeify');
|
||||
|
||||
bundler.on('update', rebundle);
|
||||
|
||||
function rebundle() {
|
||||
return bundler.bundle()
|
||||
// log errors if they happen
|
||||
.on('error', gutil.log.bind(gutil, 'Browserify Error'))
|
||||
.pipe(source('book-bundle.js'))
|
||||
.pipe(buffer())
|
||||
//.pipe(uglify()) // Since Android needs to call in, can't minify
|
||||
.pipe(gulp.dest('./dist'));
|
||||
}
|
||||
|
||||
return rebundle();
|
||||
});
|
@ -1,36 +0,0 @@
|
||||
require 'angular'
|
||||
|
||||
app = angular.module('bookApp', ['ui.scroll', 'ui.scroll.jqlite'])
|
||||
|
||||
app.controller 'BookCtrl', ['$scope', '$filter', ($scope, $filter) ->
|
||||
$scope.verseSource =
|
||||
get: (index, count, success) ->
|
||||
console.log "Calling me with " + index
|
||||
success angular.fromJson Android.getVerses(index, count)
|
||||
|
||||
$scope.order_verses = ->
|
||||
$scope.verses = $filter('orderBy')($scope.verses, 'id', false)
|
||||
|
||||
$scope.appendVerse = (jsonVerseString) ->
|
||||
$scope.verses.push angular.fromJson jsonVerseString
|
||||
$scope.order_verses()
|
||||
]
|
||||
|
||||
# Due to page initialization, we can only store the controller string.
|
||||
# The actual element changes, so there's nothing we can do with JQuery
|
||||
# etc. to grab the scope ahead of time and re-use it.
|
||||
controller = "#bookController"
|
||||
|
||||
#window.appendVerse = (jsonVerseString) ->
|
||||
#scope = angular.element($("#bookController")).scope()
|
||||
#scope.appendVerse jsonVerseString
|
||||
## Since we're calling outside of angular, we need to manually apply
|
||||
#scope.$apply()
|
||||
|
||||
###
|
||||
Future reference: Get the controller scope like so:
|
||||
angular.element($("<controller-element>")).scope().<function>
|
||||
|
||||
For example:
|
||||
angular.element($("#bookController")).scope().<function>
|
||||
###
|
@ -4,11 +4,12 @@ import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebView;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
||||
import org.bspeice.minimalbible.Injector;
|
||||
import org.bspeice.minimalbible.R;
|
||||
@ -40,7 +41,8 @@ public class BookFragment extends BaseFragment {
|
||||
VerseLookup verseLookup;
|
||||
|
||||
@InjectView(R.id.book_content)
|
||||
WebView mainContent;
|
||||
RecyclerView bookContent;
|
||||
|
||||
|
||||
PublishSubject<String> titleReceiver = PublishSubject.create();
|
||||
|
||||
@ -69,7 +71,6 @@ public class BookFragment extends BaseFragment {
|
||||
this.i = (Injector) getActivity();
|
||||
i.inject(this);
|
||||
ButterKnife.inject(this, rootView);
|
||||
mainContent.getSettings().setJavaScriptEnabled(true);
|
||||
|
||||
// TODO: Load initial text from SharedPreferences, rather than getting the actual book.
|
||||
displayBook(mBook);
|
||||
@ -93,29 +94,11 @@ public class BookFragment extends BaseFragment {
|
||||
*
|
||||
* @param b The book we want to display
|
||||
*/
|
||||
@SuppressLint("AddJavascriptInterface")
|
||||
private void displayBook(Book b) {
|
||||
Log.d("BookFragment", b.getName());
|
||||
((BibleViewer)getActivity()).setActionBarTitle(b.getInitials());
|
||||
mainContent.loadUrl(getString(R.string.book_html));
|
||||
|
||||
BibleViewClient client = new BibleViewClient(b, verseLookup, titleReceiver);
|
||||
titleReceiver
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Action1<String>() {
|
||||
@Override
|
||||
public void call(String s) {
|
||||
// TODO: Handle activity potentially null
|
||||
((BibleViewer) getActivity()).setActionBarTitle(s);
|
||||
Log.d("BibleViewClient", s);
|
||||
}
|
||||
});
|
||||
mainContent.setWebViewClient(client);
|
||||
mainContent.addJavascriptInterface(client, "Android");
|
||||
|
||||
// Enable remote debug
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
WebView.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
bookContent.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||
bookContent.setAdapter(new BookAdapter(b));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
package org.bspeice.minimalbible.activity.viewer
|
||||
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.ViewGroup
|
||||
import org.crosswire.jsword.book.Book
|
||||
import org.crosswire.jsword.passage.Verse
|
||||
import android.view.View
|
||||
import android.view.LayoutInflater
|
||||
import org.bspeice.minimalbible.R
|
||||
import android.widget.TextView
|
||||
|
||||
/**
|
||||
* Adapter used for displaying a book
|
||||
* Displays one chapter at a time,
|
||||
* as each TextView widget is it's own line break
|
||||
*/
|
||||
class BookAdapter(val b: Book) : RecyclerView.Adapter<PassageView>() {
|
||||
|
||||
/**
|
||||
* Create a new view
|
||||
*/
|
||||
override fun onCreateViewHolder(parent: ViewGroup?,
|
||||
position: Int): PassageView? {
|
||||
val emptyView = LayoutInflater.from(parent?.getContext())
|
||||
.inflate(R.layout.viewer_passage_view, parent, false)
|
||||
|
||||
val passage = PassageView(emptyView)
|
||||
passage.v setText "1"
|
||||
return passage
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind an existing view
|
||||
*/
|
||||
override fun onBindViewHolder(view: PassageView, position: Int) {
|
||||
view.v setText "${Integer.parseInt(view.v.getText() as String) + 1}"
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of chapters in the book
|
||||
*/
|
||||
override fun getItemCount(): Int = 800
|
||||
}
|
||||
|
||||
class PassageView(val _v: View) : RecyclerView.ViewHolder(_v) {
|
||||
|
||||
val v = _v as TextView
|
||||
|
||||
}
|
@ -2,11 +2,12 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="org.bspeice.minimalbible.MainActivity$PlaceholderFragment" >
|
||||
tools:context="org.bspeice.minimalbible.activity.viewer.BookFragment" >
|
||||
|
||||
<WebView
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/book_content"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" />
|
||||
android:scrollbars="none"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
6
app/src/main/res/layout/viewer_passage_view.xml
Normal file
6
app/src/main/res/layout/viewer_passage_view.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/passage" />
|
Loading…
Reference in New Issue
Block a user