FEATURE: Starting the search cards and service port

This commit is contained in:
walljm 2016-12-27 17:23:20 -05:00
parent 64fb22afb4
commit 96ab452280
24 changed files with 641 additions and 32 deletions

View File

@ -28,4 +28,10 @@
<feature name="StatusBar">
<param name="ios-package" onload="true" value="CDVStatusBar"/>
</feature>
<plugin name="ionic-plugin-keyboard" spec="~2.2.1"/>
<plugin name="cordova-plugin-whitelist" spec="1.3.1"/>
<plugin name="cordova-plugin-console" spec="1.0.5"/>
<plugin name="cordova-plugin-statusbar" spec="2.2.1"/>
<plugin name="cordova-plugin-device" spec="1.1.4"/>
<plugin name="cordova-plugin-splashscreen" spec="~4.0.1"/>
</widget>

View File

@ -8,37 +8,39 @@
"ionic_source_map": "source-map"
},
"scripts": {
"clean": "ionic-app-scripts clean",
"build": "ionic-app-scripts build",
"ionic:build": "ionic-app-scripts build",
"ionic:serve": "ionic-app-scripts serve"
},
"dependencies": {
"@angular/common": "2.1.1",
"@angular/compiler": "2.1.1",
"@angular/compiler-cli": "2.1.1",
"@angular/core": "2.1.1",
"@angular/forms": "2.1.1",
"@angular/http": "2.1.1",
"@angular/platform-browser": "2.1.1",
"@angular/platform-browser-dynamic": "2.1.1",
"@angular/platform-server": "2.1.1",
"@ionic/storage": "1.1.6",
"ionic-angular": "2.0.0-rc.3",
"ionic-native": "2.2.3",
"@angular/common": "2.2.1",
"@angular/compiler": "2.2.1",
"@angular/compiler-cli": "2.2.1",
"@angular/core": "2.2.1",
"@angular/forms": "2.2.1",
"@angular/http": "2.2.1",
"@angular/platform-browser": "2.2.1",
"@angular/platform-browser-dynamic": "2.2.1",
"@angular/platform-server": "2.2.1",
"@ionic/storage": "1.1.7",
"ionic-angular": "2.0.0-rc.4",
"ionic-native": "2.2.11",
"ionicons": "3.0.0",
"rxjs": "5.0.0-beta.12",
"zone.js": "0.6.26"
},
"devDependencies": {
"@ionic/app-scripts": "0.0.45",
"typescript": "2.0.6"
"@ionic/app-scripts": "0.0.47",
"typescript": "2.0.9"
},
"cordovaPlugins": [
"cordova-plugin-whitelist",
"cordova-plugin-console",
"cordova-plugin-statusbar",
"cordova-plugin-console",
"cordova-plugin-device",
"ionic-plugin-keyboard",
"cordova-plugin-splashscreen"
"cordova-plugin-splashscreen",
"ionic-plugin-keyboard"
],
"cordovaPlatforms": [],
"description": "Dynamic Bible: A bible made for studying scripture"

View File

@ -1,5 +0,0 @@
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);

View File

@ -14,7 +14,7 @@ export class BibleService
{
}
getPassage(section: Section): BiblePassageResult
getResult(section: Section): BiblePassageResult
{
try
{

View File

@ -0,0 +1,11 @@
<ion-item class="title" padding>
{{item.prefix}}{{item.sn}}
<button ion-button icon-only item-right large clear (click)="close()">
<ion-icon name="close-circle"></ion-icon>
</button>
</ion-item>
<ion-card-content>
<p>
<b>{{item.def.tr}} ({{item.def.sn}})</b> - {{item.def.p}} - {{item.def.lemma}} - <span [innerHTML]="item.def.de"></span><br />
</p>
</ion-card-content>

View File

@ -0,0 +1,23 @@
import {EventEmitter, Component, Input, Output} from "@angular/core";
@Component({
selector: "search",
templateUrl: "search.html"
})
export class Search {
@Output()
onClose = new EventEmitter<CardItem>();
@Input()
item: SearchResult;
@Input()
cardItem: CardItem;
constructor() {
}
close() {
this.onClose.emit(this.cardItem);
}
}

View File

@ -102,7 +102,7 @@ export class SearchPage {
dict = "grk";
}
q = q.substring(1, q.length);
let result = this.strongsService.getStrongs(parseInt(q), dict);
let result = this.strongsService.getResult(parseInt(q), dict);
if (this.user.strongs_modal)
this.presentStrongsModal(result);
else
@ -111,7 +111,7 @@ export class SearchPage {
// its a verse reference.
if (q.trim() !== "") {
let myref = new Reference(q.trim());
let r = this.bibleService.getPassage(myref.Section);
let r = this.bibleService.getResult(myref.Section);
r.ref = myref.toString();
this.items.unshift({ id: this.last++, data: r, type: Passage, dict: r.testament == 'new' ? "G" : "H" });
}

View File

@ -0,0 +1,459 @@
/// <reference path="../typings/browser/ambient/jquery/index.d.ts" />
/// <reference path="types.ts" />
import { Injectable } from "@angular/core";
import { Http } from "@angular/http";
@Injectable()
export class SearchService
{
result: SearchResult;
count = 0;
constructor(private http: Http)
{
}
getResult(qry)
{
qry = qry.toLowerCase();
let qs = qry.split(" ");
let words = this.buildIndexArray().sort();
let results = new Array();
// Loop through each query term.
for (let i = 0; i < qs.length; i++)
{
let q = qs[i].replace("'", ""); // we don't included ticks in our words.
// For each query term, figure out which xml file it is in, and get it.
// getSearchRefs returns an array of references.
for (let w = 0; w < words.length; w++)
{
// If we are at the end of the array, we want to use a different test.
if (w == 0)
{
if (q <= words[w])
{
results.unshift(this.getSearchReferences("data/index/" + words[w] + "idx.json", q));
break;
}
} else
{
if (q <= words[w] && q > words[w - 1])
{
results.unshift(this.getSearchReferences("data/index/" + words[w] + "idx.json", q));
break;
}
}
}
} // End of loop through query terms
// Now we need to test results. If there is more than one item in the array, we need to find the set
// that is shared by all of them. IF not, we can just return those refs.
if (results.length == 0)
{
this.result = { word: qry, refs: null, status: Status.Failure, msg: ":)" };
}
else if (results.length == 1)
{
this.result = { word: qry, refs: results[0].refs, status: Status.Success, msg: ":)" };
}
else
{
let shared = this.findSharedSet(results);
if (shared == null)
{
this.result = { word: qry, refs: null, status: Status.Failure, msg: "No passages found." };
}
this.result = { word: qry, refs: shared[0].refs, status: Status.Success, msg: ":)" };
}
}
/**
* Gets the references a given word is found in.
* Returns a string[].
* @param {string} url - The url of the word index
* @param {string} query - The word to lookup.
*/
private getSearchReferences(url, query): string[]
{
// getSearchRefs takes a url and uses ajax to retrieve the references and returns an array of references.
let r: IndexResult[];
$.ajax({
async: false,
type: "GET",
url: url,
dataType: "json",
success: function (d: IndexResult[], t, x)
{
r = d;
},
error: function (request, status, error)
{
//Util.HandleError(error);
}
});
// find the right word
let refs = $.grep(r, function (o, i)
{
return o.word == query;
});
if (refs.length > 0)
{
return refs[0].refs;
} else
{
return [];
}
}
private buildIndexArray()
{
let words = new Array();
words.unshift('abiram');
words.unshift('accepteth');
words.unshift('acquit');
words.unshift('adna');
words.unshift('affecteth');
words.unshift('aharhel');
words.unshift('aijeleth');
words.unshift('almug');
words.unshift('amiable');
words.unshift('ancients');
words.unshift('anything');
words.unshift('appointeth');
words.unshift('areopagus');
words.unshift('art');
words.unshift('ashteroth');
words.unshift('astaroth');
words.unshift('availeth');
words.unshift('azotus');
words.unshift('badness');
words.unshift('baptizing');
words.unshift('bat');
words.unshift('bechorath');
words.unshift('beguile');
words.unshift('bemoaning');
words.unshift('beside');
words.unshift('bezek');
words.unshift('bitterly');
words.unshift('bloodthirsty');
words.unshift('bolted');
words.unshift('bountifulness');
words.unshift('breastplates');
words.unshift('broth');
words.unshift('bunni');
words.unshift('cain');
words.unshift('cankered');
words.unshift('carry');
words.unshift('celebrate');
words.unshift('chapel');
words.unshift('cheese');
words.unshift('chilmad');
words.unshift('circumcision');
words.unshift('closer');
words.unshift('come');
words.unshift('communication');
words.unshift('concerning');
words.unshift('confusion');
words.unshift('consummation');
words.unshift('convince');
words.unshift('couch');
words.unshift('covers');
words.unshift('crisping');
words.unshift('curse');
words.unshift('damnable');
words.unshift('deacons');
words.unshift('decision');
words.unshift('defileth');
words.unshift('depart');
words.unshift('despisest');
words.unshift('diblathaim');
words.unshift('directly');
words.unshift('dishonesty');
words.unshift('distracted');
words.unshift('dominion');
words.unshift('dreamer');
words.unshift('dulcimer');
words.unshift('eastward');
words.unshift('eighteenth');
words.unshift('elihoreph');
words.unshift('embrace');
words.unshift('endeavored');
words.unshift('ensign');
words.unshift('ephraim');
words.unshift('eshtemoa');
words.unshift('evening');
words.unshift('excellest');
words.unshift('extended');
words.unshift('fairer');
words.unshift('fastings');
words.unshift('feign');
words.unshift('fight');
words.unshift('fishermen');
words.unshift('flint');
words.unshift('foolishness');
words.unshift('forever');
words.unshift('forts');
words.unshift('fresh');
words.unshift('furnish');
words.unshift('gallio');
words.unshift('gebal');
words.unshift('gezrites');
words.unshift('girt');
words.unshift('goath');
words.unshift('government');
words.unshift('greeteth');
words.unshift('guiltless');
words.unshift('haggai');
words.unshift('hamstrung');
words.unshift('happy');
words.unshift('harum');
words.unshift('hattush');
words.unshift('heard');
words.unshift('heir');
words.unshift('herbs');
words.unshift('hezronites');
words.unshift('hivite');
words.unshift('honored');
words.unshift('hostages');
words.unshift('huntest');
words.unshift('idalah');
words.unshift('impenitent');
words.unshift('inferior');
words.unshift('insomuch');
words.unshift('ira');
words.unshift('isuah');
words.unshift('jabneh');
words.unshift('japhia');
words.unshift('jeduthun');
words.unshift('jerahmeelites');
words.unshift('jew');
words.unshift('joined');
words.unshift('joy');
words.unshift('kadmonites');
words.unshift('kid');
words.unshift('kneaded');
words.unshift('lack');
words.unshift('languish');
words.unshift('lazarus');
words.unshift('legions');
words.unshift('libnath');
words.unshift('likhi');
words.unshift('lock');
words.unshift('louder');
words.unshift('lysias');
words.unshift('magpiash');
words.unshift('malchus');
words.unshift('marble');
words.unshift('mastery');
words.unshift('meddle');
words.unshift('members');
words.unshift('mesech');
words.unshift('midian');
words.unshift('ministered');
words.unshift('mithnite');
words.unshift('morasthite');
words.unshift('mower');
words.unshift('myrtle');
words.unshift('naphish');
words.unshift('necks');
words.unshift('net');
words.unshift('noadiah');
words.unshift('nursed');
words.unshift('occurrent');
words.unshift('omnipotent');
words.unshift('orchard');
words.unshift('outside');
words.unshift('owed');
words.unshift('palti');
words.unshift('partition');
words.unshift('paulus');
words.unshift('peoples');
words.unshift('persecute');
words.unshift('phares');
words.unshift('pilate');
words.unshift('plagues');
words.unshift('plentiful');
words.unshift('poorer');
words.unshift('powerful');
words.unshift('presented');
words.unshift('prison');
words.unshift('promoted');
words.unshift('provision');
words.unshift('purely');
words.unshift('quarter');
words.unshift('rahab');
words.unshift('ravening');
words.unshift('rebuking');
words.unshift('refined');
words.unshift('release');
words.unshift('rent');
words.unshift('requirest');
words.unshift('return');
words.unshift('rezon');
words.unshift('riseth');
words.unshift('roof');
words.unshift('rump');
words.unshift('sail');
words.unshift('sanctuaries');
words.unshift('savors');
words.unshift('scorpions');
words.unshift('second');
words.unshift('sellers');
words.unshift('served');
words.unshift('shaft');
words.unshift('sharaim');
words.unshift('shedder');
words.unshift('shepho');
words.unshift('shimshai');
words.unshift('shophan');
words.unshift('shuppim');
words.unshift('sihor');
words.unshift('sippai');
words.unshift('slandereth');
words.unshift('smelling');
words.unshift('softer');
words.unshift('sores');
words.unshift('sparrows');
words.unshift('spoil');
words.unshift('staff');
words.unshift('steel');
words.unshift('stool');
words.unshift('stretched');
words.unshift('stumblingblocks');
words.unshift('suffice');
words.unshift('surnamed');
words.unshift('swore');
words.unshift('take');
words.unshift('task');
words.unshift('temani');
words.unshift('testator');
words.unshift('thessalonica');
words.unshift('threatening');
words.unshift('tie');
words.unshift('titus');
words.unshift('torments');
words.unshift('translation');
words.unshift('tributaries');
words.unshift('tubal');
words.unshift('unchangeable');
words.unshift('unlawful');
words.unshift('upbraideth');
words.unshift('uzza');
words.unshift('verily');
words.unshift('visage');
words.unshift('walk');
words.unshift('washing');
words.unshift('wayside');
words.unshift('wellspring');
words.unshift('whisperer');
words.unshift('win');
words.unshift('withereth');
words.unshift('work');
words.unshift('wrest');
words.unshift('yours');
words.unshift('zealously');
words.unshift('zetham');
words.unshift('zophim');
words.unshift('zuzims');
return words;
}
/*
* Returns a list of references in string form as a string[] that are shared given a list of lists of references in string form.
*/
private findSharedSet(results)
{
// FindSharedSet takes an array of reference arrays, and figures out which references are shared
// by all arrays/sets, then returns a single array of references.
for (let j in results)
{
let refs = results[j];
if (refs != null)
{
for (let i = 0; i < refs.length; i++)
{
let r = refs[i].split(":");
// convert references to single integers.
// Book * 100000, Chapter * 1000, Verse remains same, add all together.
let ref = r[0] * 100000000;
ref = ref + (r[1] * 10000);
ref = ref + r[2] * 1;
results[j][i] = ref;
}
} else
{
return null;
}
}
// get the first result
let result = results[0];
// for each additional result, get the shared set
for (let i = 1; i < results.length; i++)
{
result = this.returnSharedSet(results[i], result);
}
// convert the references back into book, chapter and verse.
for (let i = 0; i < result.length; i++)
{
let ref = result[i];
result[i] = Math.floor(ref / 100000000) + ":" + Math.floor((ref % 100000000) / 10000) + ":" + Math.floor((ref % 100000000) % 10000);
}
return result;
}
private returnSharedSet(x, y)
{
/// <summary>
/// Takes two javascript arrays and returns an array
/// containing a set of values shared by arrays.
/// </summary>
// declare iterator
let i = 0;
// declare terminator
let t = (x.length < y.length) ? x.length : y.length;
// sort the arrays
x.sort((x, y) => x - y);
y.sort((x, y) => x - y);
// in this loop, we remove from the arrays, the
// values that aren't shared between them.
while (i < t)
{
if (x[i] == y[i])
{
i++;
}
if (x[i] < y[i])
{
x.splice(i, 1);
}
if (x[i] > y[i])
{
y.splice(i, 1);
}
t = (x.length < y.length) ? x.length : y.length;
// we have to make sure to remove any extra values
// at the end of an array when we reach the end of
// the other.
if (t == i && t < x.length)
{
x.splice(i, x.length - i);
}
if (t == i && t < y.length)
{
y.splice(i, x.length - i);
}
}
// we could return y, because at this time, both arrays
// are identical.
return x;
}
}

View File

@ -12,7 +12,7 @@ export class StrongsService
constructor(private http: Http)
{
}
getStrongs(sn: number, dict: string): StrongsResult
getResult(sn: number, dict: string): StrongsResult
{
try
{
@ -120,5 +120,4 @@ export class StrongsService
}
return null;
}
}

View File

@ -1,8 +1,19 @@

type CardItem = { id: number, data: any, type: any, dict: string}
type User = {
strongs_modal: boolean
type SearchResult = {
refs: string[],
word: string,
status: Status,
msg: string
}
enum Status {Success, Failure};
type IndexResult = {
refs: string[];
word: string;
}
type CardItem = { id: number, data: any, type: any, dict: string}
type User = {
strongs_modal: boolean
}
type BiblePassage = {

View File

@ -0,0 +1,35 @@
// Ionicons Icon Font CSS
// --------------------------
// Ionicons CSS for Ionic's <ion-icon> element
// ionicons-icons.scss has the icons and their unicode characters
$ionicons-font-path: $font-path !default;
@import "ionicons-icons";
@import "ionicons-variables";
@font-face {
font-family: "Ionicons";
src: url("#{$ionicons-font-path}/ionicons.woff2?v=#{$ionicons-version}") format("woff2"),
url("#{$ionicons-font-path}/ionicons.woff?v=#{$ionicons-version}") format("woff"),
url("#{$ionicons-font-path}/ionicons.ttf?v=#{$ionicons-version}") format("truetype");
font-weight: normal;
font-style: normal;
}
ion-icon {
display: inline-block;
font-family: "Ionicons";
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
font-style: normal;
font-variant: normal;
font-weight: normal;
line-height: 1;
text-rendering: auto;
text-transform: none;
speak: none;
}

Binary file not shown.

View File

@ -0,0 +1,34 @@
// Noto Sans Font
// Google
// Apache License, version 2.0
// http://www.apache.org/licenses/LICENSE-2.0.html
$noto-sans-font-path: $font-path !default;
@font-face {
font-family: "Noto Sans";
font-style: normal;
font-weight: 300;
src: local("Noto Sans"), local("Noto-Sans-Regular"), url("#{$noto-sans-font-path}/noto-sans-regular.ttf") format("truetype");
}
@font-face {
font-family: "Noto Sans";
font-style: normal;
font-weight: 400;
src: local("Noto Sans"), local("Noto-Sans-Regular"), url("#{$noto-sans-font-path}/noto-sans-regular.ttf") format("truetype");
}
@font-face {
font-family: "Noto Sans";
font-style: normal;
font-weight: 500;
src: local("Noto Sans Bold"), local("Noto-Sans-Bold"), url("#{$noto-sans-font-path}/noto-sans-bold.ttf") format("truetype");
}
@font-face {
font-family: "Noto Sans";
font-style: normal;
font-weight: 700;
src: local("Noto Sans Bold"), local("Noto-Sans-Bold"), url("#{$noto-sans-font-path}/noto-sans-bold.ttf") format("truetype");
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,34 @@
// Roboto Font
// Google
// Apache License, version 2.0
// http://www.apache.org/licenses/LICENSE-2.0.html
$roboto-font-path: $font-path !default;
@font-face {
font-family: "Roboto";
font-style: normal;
font-weight: 300;
src: local("Roboto Light"), local("Roboto-Light"), url("#{$roboto-font-path}/roboto-light.ttf") format("truetype"), url("#{$roboto-font-path}/roboto-light.woff") format("woff");
}
@font-face {
font-family: "Roboto";
font-style: normal;
font-weight: 400;
src: local("Roboto"), local("Roboto-Regular"), url("#{$roboto-font-path}/roboto-regular.ttf") format("truetype"), url("#{$roboto-font-path}/roboto-regular.woff") format("woff");
}
@font-face {
font-family: "Roboto";
font-style: normal;
font-weight: 500;
src: local("Roboto Medium"), local("Roboto-Medium"), url("#{$roboto-font-path}/roboto-medium.ttf") format("truetype"), url("#{$roboto-font-path}/roboto-medium.woff") format("woff");
}
@font-face {
font-family: "Roboto";
font-style: normal;
font-weight: 700;
src: local("Roboto Bold"), local("Roboto-Bold"), url("#{$roboto-font-path}/roboto-bold.ttf") format("truetype"), url("#{$roboto-font-path}/roboto-bold.woff") format("woff");
}