RecyclerView initial demonstration

This commit is contained in:
Bradlee Speice 2014-11-25 22:32:16 -05:00
parent 147c6a5248
commit d6c5662fa5
11 changed files with 71 additions and 22918 deletions

View File

@ -8,12 +8,12 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
android { android {
compileSdkVersion 20 compileSdkVersion 21
buildToolsVersion '20.0.0' buildToolsVersion '21.1.1'
defaultConfig { defaultConfig {
applicationId 'org.bspeice.minimalbible' applicationId 'org.bspeice.minimalbible'
minSdkVersion 8 minSdkVersion 8
targetSdkVersion 20 targetSdkVersion 21
versionCode 1 versionCode 1
versionName '1.0' versionName '1.0'
} }
@ -47,7 +47,8 @@ dependencies {
compile 'com.jakewharton:butterknife:+' compile 'com.jakewharton:butterknife:+'
compile 'com.readystatesoftware.systembartint:systembartint:+' compile 'com.readystatesoftware.systembartint:systembartint:+'
compile 'com.netflix.rxjava:rxjava-android:+' 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 'org.apache.commons:commons-lang3:+'
compile 'com.google.code.gson:gson:+' compile 'com.google.code.gson:gson:+'
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

View File

@ -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>

File diff suppressed because it is too large Load Diff

View File

@ -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
*/

View File

@ -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
*/

View File

@ -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();
});

View File

@ -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>
###

View File

@ -4,11 +4,12 @@ import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.webkit.WebView; import android.support.v7.widget.RecyclerView;
import org.bspeice.minimalbible.Injector; import org.bspeice.minimalbible.Injector;
import org.bspeice.minimalbible.R; import org.bspeice.minimalbible.R;
@ -40,7 +41,8 @@ public class BookFragment extends BaseFragment {
VerseLookup verseLookup; VerseLookup verseLookup;
@InjectView(R.id.book_content) @InjectView(R.id.book_content)
WebView mainContent; RecyclerView bookContent;
PublishSubject<String> titleReceiver = PublishSubject.create(); PublishSubject<String> titleReceiver = PublishSubject.create();
@ -69,7 +71,6 @@ public class BookFragment extends BaseFragment {
this.i = (Injector) getActivity(); this.i = (Injector) getActivity();
i.inject(this); i.inject(this);
ButterKnife.inject(this, rootView); ButterKnife.inject(this, rootView);
mainContent.getSettings().setJavaScriptEnabled(true);
// TODO: Load initial text from SharedPreferences, rather than getting the actual book. // TODO: Load initial text from SharedPreferences, rather than getting the actual book.
displayBook(mBook); displayBook(mBook);
@ -93,29 +94,11 @@ public class BookFragment extends BaseFragment {
* *
* @param b The book we want to display * @param b The book we want to display
*/ */
@SuppressLint("AddJavascriptInterface")
private void displayBook(Book b) { private void displayBook(Book b) {
Log.d("BookFragment", b.getName()); Log.d("BookFragment", b.getName());
((BibleViewer)getActivity()).setActionBarTitle(b.getInitials()); ((BibleViewer)getActivity()).setActionBarTitle(b.getInitials());
mainContent.loadUrl(getString(R.string.book_html));
BibleViewClient client = new BibleViewClient(b, verseLookup, titleReceiver); bookContent.setLayoutManager(new LinearLayoutManager(getActivity()));
titleReceiver bookContent.setAdapter(new BookAdapter(b));
.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);
}
} }
} }

View File

@ -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
}

View File

@ -2,11 +2,12 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="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:id="@+id/book_content"
android:layout_width="fill_parent" android:scrollbars="none"
android:layout_height="fill_parent" /> android:layout_height="match_parent"
android:layout_width="match_parent" />
</RelativeLayout> </RelativeLayout>

View 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" />