Tuesday, March 24, 2015

Three more packages we needed to install. They were required for describe() functions in our test code, and also allowed our different testing frameworks to talk to each other. I decided to install them all globally, just to make it all easier to access. In addition, you need to have a config file for Karma, in the directory you're working in. Ours is available on GitHub right here. Once you've navigated to the directory, you open two terminal windows: one in which you type "karma start", and another one you type "karma run" to run all tests you have created. You can double-check that karma is running by going to localhost:9876 in your browser. From here, you can edit and add to tests! Our test files are available here for an example. We'll continue to add to them, so I decided not to link to today's commit, rather to our files, as they will grow a lot over time, and provide a perfect example of how to write unit tests.

I also started working on some unit test code myself. I wrote a full test for Book objects, most of which is still in development. However, everything is already defined as to what the function is supposed to do, so we just need to put assert methods under each it() statement to complete the test! Tomorrow I hope to have full testing of both Book() and Chapter() objects.

Monday, March 23, 2015

Installing Mocha, Karma, and setting up Unit Tests

Today we worked a lot on setting up unit testing. While it could be done in Javascript, there's a lot of tools available that allow the process to be done more quickly and efficiently. We decided to use Mocha and Karma. The setup was simple, however I ran into a lot of issues, so I decided to make a shell script that will automate the process for anyone on a Mac with Homebrew. Comments are included so that anyone knows what it is doing.


After some research, we got Mocha working. We created a /tests/ directory on our GitHub repo, which we use to create and test working code. Our first test function, stripHTMLTags, isn't working yet, because we are still working with issues related to Mocha detecting our window variable from Firefox OS. A fix will hopefully come tomorrow.

The function so far looks like this.

It can be tested by using the following code:

mocha . -r "js/app"

Mocha . runs all tests in the directory you're in, so you have to be in the tests/ directory. -r is equivalent to "require", which is a function that tells the test what Javascript file you're testing. For some reason, using require("js/app") as a function in our test isn't working. It's likely due to a directory structure issue.

We also are awaiting an email response as to what we can use Karma for. Hopefully a response will come tomorrow, but otherwise we can always do some more research. Tests will start tomorrow, since our setup is done.

Sunday, March 22, 2015

A LibriFox Website, Starting Unit Testing (3/22)

So today I made some progress! One of the major things I did today was using GitHub Pages to create a basic website for LibriFox. A Jekyll installation will come later this week when I go on vacation. From what I've learned, Jekyll is great, and works amazingly with blogging. I was thinking of somehow linking our Blogger posts to the website sometime later on. Anyways, with some DNS changes, I was able to route the site to the GitHub pages branch, which actually is in the LibriFox project but on a different branch [can be changed later if needed]. The best thing is, it's completely free, and we can modify the code of the website whenever we want. I plan to change it to a custom website, instead of its current template, sometime later on. The main reason I got the website done today was because I didn't want to jump ahead with unit testing without discussing everything first tomorrow, and also due to the fact that librifox.com was available and I just had to go for it :)

But for now, we need to focus on unit testing. I actually just did some minor testing today, and I've already found a few issues! One of the main ones was with our stripHTMLTags method. It's very, very specific, but who knows, it might pop up in a few of the books' descriptions, causing some issues.

Basically, the name of stripHTMLTags is what we use it for. LibriVox's API and RSS feeds provide descriptions of each book. In our search results, I have previously coded it such that short bits of the description are displayed below each book. This is fine, until you notice that all descriptions have HTML tags in them - bold, italics, links, etc. and this ruins JQueryMobile's list. As such, we need a way to remove the HTML tags so that the list displays nicely, and for the most part, this method performs that well. However, under very specific circumstances, the method will result in large blocks of text being accidentally excluded from the description.

Imagine you had text like this for your description:

"<b>The left angle bracket, also known as <, is often used as a less than sign. On the other hand, the right angle bracket, known as >, is often used as a greater than sign.</b>"

You'd expect something like:
"The left angle bracket, also known as <, is often used as a less than sign. On the other hand, the right angle bracket, known as >, is often used as a greater than sign."

to be your output. However, our method is outputting:
"The left angle bracket, also known as , is often used as a greater than sign."

And this can easily be seen why, we're using this code for our stripHTMLTags method:

It's quick, easy, and for the most part does well. However, if any of these characters are used in a way similar to that shown above, it could cause issues for displaying descriptions.

Anyways, that's it for today; I hope to find more bugs tomorrow!

Friday, March 20, 2015

Working with Trello and GitHub Integration (3/20)

Today we setup our new Trello board, you can access it here! I also integrated it with GitHub so that our feature request and issue creation processes are easily controlled. I'll explain how I did that below.

I found a website called Zapier, which served as a middleman between hundreds of websites that have public APIs. Luckily, it had events usable with both Trello and GitHub, so that they could be linked extremely easily.

I setup one link that fired an event when issues were posted on GitHub. On that event, it will post a card to our Trello board under the "Requested Features" section.

I also setup another link that fired an event when Trello cards were created in the "Approved Features" section. On this event, it will post the same thing to an issue on our GitHub repo. This will be useful for user stories - if we approve for a feature to be created, it'll be posted as an issue to be handled and then we can easily see what we have to add into the app.

These two links will make user stories and feature requests much easier to handle, and the entire process will be automated.

EDIT: I also added a link to the Trello board on the top right!

Thursday, March 19, 2015

More Refactoring (3/19)

Today we continued to work on refactoring. Originally I had found that our download function wasn't working, so we made some changes to that so that it's no longer using localStorage - it's now using objects like the rest of the code. Here's an example of that:
It still needs a lot of fixing, mainly with individual parts of chapters. Also something that will need fixing is our file manager. We plan to store books in folders named by IDs, then have a user access downloads with a listView that converts the book IDs into titles, therefore allowing them to access their books without modifying the file system. Other than that, we didn't make any significant changes today, it was mainly refactoring and experimenting with code to check for errors.

Wednesday, March 18, 2015

More Refactoring, Fixing Bugs (3/18)

Today we have made more improvements to refactoring. It's funny, we made so many code changes, but no real feature was changed. However, we did fix some bugs.

The first bug we fixed was audio not saving after load. We completely removed our timeupdate event function, which allowed us to recode it into a simple 4-line function which saves our audio data. We then added a .position variable to the Chapter class, and allowed the app to save to this variable when the timeupdate event was fired. You can see Alex's explanation of this here.
Another bug that was fixed today was the descriptions in search not being formatted properly. This bug was also a simple fix, I had run into it earlier and I showed Alex the code from previously. We determined that it was not parsing the HTML properly. [See line "this.description"]

All that was required was JQuery's parseHTML method, followed by a text() method. This allowed for the app to remove all HTML formatting from the description, which had resulted in weird, random spaces, and bolded/hyperlinked text that we didn't want.

That was about it for today! Refactoring can be time consuming, but in the end it's making it a lot easier to add things on.

EDIT: After further testing, it seems as if we're no longer getting "not well formed" errors, and the page change bug [you had to restart the app to search for a different book] is no longer there!

Tuesday, March 17, 2015

Looking Into the LibriVox App (3/17)

*Long post warning*

Today I got back late to school, so I decided to work not on refactoring but to check into the LibriVox apps for Android. After all, not only will they provide a good example of how our app should work, but it will also give us insight into what features we should add. I took some notes on it below.

How it works

  • Starts with an asking for rating screen. While I don't think we should do this immediately, I think that we should ask the user to eventually rate our app, as an app with more ratings is better for us and users. We can improve on certain features, while new users finding the app for the first time can see what people think about it.
  • Immediately, it starts you off at a home screen that displays Top Free, Top Paid, and New apps. I like this feature - it reminds me of some other apps I have used. All of the top books' covers are shown, which is also possible to do via RSS or the API. It adds a clean UI interface to this with a nice color scheme.
  • I had to look over this a few times, but I realized there was a "Top Paid" category. I thought LibriVox's goal was free and public domain audiobooks...?
  • There is a search icon as well, at the top, just like our app.
  • You can go into more books on the top sections, and also view them, with their covers shown.
  • Clicking on the app gives it some time to load, instead of immediately going to the next screen. The player has a clean interface, and also allows you to look at the description, similar books, and go to chapter selection. There's a share icon, favorite icon, and sleep icon.
  • All search results are conducted without a loading screen, and all books are shown with their covers.
My Opinion

The LibriVox app is full of features, and as an Android app it's very well put together. I am in no way saying that we should have all these features, or none of them, but I'd like to go over a few and say how I liked and disliked them. That way, we can adapt certain features, maybe with better methods. As a result, we can help towards making a better app!

  • I loved the cover-based UI for books on the home screen. The "Top Free", etc. categories were very nice as well. However, once we got to search results, I found that covers just got in the way. I much prefer our search results with simple title and description. I'm thinking, however, that some people will like the cover in search results. As a result, I have proposed a few solutions. One is that we allow for different types of results, similar to how in Windows and OSX (Linux too, possibly?) you can switch the way you look at your search results - IE if you're looking at images, and you just want to see the filename, or want to see the image, or both, you can choose either. I'd also like to propose having a ListView with Thumbnails via JQuery Mobile. That way, we could have a small icon of the book's cover, along with a name and description, so the user can have more information on the novel if needed.
  • I like the idea of share and favorite buttons. After all, if you really like a book, I'm sure anyone would want to recommend it to friends, especially if it's completely free to listen to. Not only is this a helpful feature for users, but it also allows your app to be shared more if both users are on FirefoxOS. We should look into different methods of sharing, and include linking to the LibriFox App/LibriVox when the book is shared. Favoriting is also great, and we could make a feature such that a user can access their favorited books with ease [possibly a folder]. A "download favorites" button would be an interesting feature to look into as well.
  • I also appreciated the "Similar" category when you were listening to a book. I'm not exactly sure how this would be done, however we should look into it.
  • I think we need to look into more UI coding as well (with CSS). Using a non-default JQuery Mobile theme would be nicer in my opinion.
  • The loading screen was nice, but I'm not really sure if it was needed. I hate seeing loading screens on my phone when I'm using apps, so maybe it would be best to just not have one. A splash screen, however, would be nice.
  • Bookmarks were really nice. These would be an easy feature to add.
  • Reviews were also nice, I'm not sure how they would be implemented without some sort of hosting (possibly a database?), but they would be nice as well.
  • One thing it seemed that this app lacked was a full file manager and a download file option. Maybe I didn't do enough exploring. Sure, the LibriVox Downloader app does this, but why split it into two? I feel as if it's easy enough to implement, so we might as well have one and keep it all in one app.
That's all the notes I have for now, I think they will be very helpful after we refactor a bit more! I will be taking more notes on the LibriVox Downloader app soon, possibly tomorrow. I was also very surprised to see that the Android app has 1-5 million installs, 60 thousand reviews, and offers in-app purchases. While I don't think in-app purchases in a LibriVox app makes sense, I would like to do some experimentation with Kumar's library!

The downloader, on the other hand, only had 50 thousand to 100 thousand installs. Regardless, this is still a very large amount of people, and shows that a feature should be added to the main LibriVox app to implement the feature! I hope that our app will include it, as I've now realized how important it is to have one.

Monday, March 16, 2015

Refactoring, and Exploration Into the LibriFox Android App

Today I worked with Alex a bit on refactoring, which I had eventually planned on doing - essentially, the code we currently have works, but it's a mess, and it's starting to get to the point where it's much harder than it should be to write code, simply because of how scrambled our code is.

As a result, today we worked on some minor refactoring. Even in an hour or so, only a few lines were changed, and a lot of code was broken - but the result was amazing. We must have removed over 30 lines of useless code (and keep in mind, our app is only around 300 lines of JavaScript and a few hundred lines of HTML) from our app.js. A few minor methods, notably these Chapter and Book methods below, have changed the entire way our app works for the better.


Eliminating localStorage overuse was one of the first things we came to. Alex has changed all basic localStorage access into Objects, which I had never thought of doing [since I'm still very new to JavaScript]. These Objects not only save lots of space in the code, but also make access of variables much easier.

Instead of having something like this:
We have something like this:
You can already see the incredible amount of time and space saved by using these methods, not to mention how much easier it is to add, modify, or remove code!

We will also start refactoring repeated code in our audio handlers, and create a multiclass implementation soon.

Later on this week, after some refactoring, I might look at the LibriVox app for Android. I want to make sure our app is refactored more before we start looking into adding new features!

EDIT: I also did some research about the Firefox Marketplace. Our app should be reviewed soon! In my research, I found that they allow something called "App Preloading". You can read about it here. Basically, it allows developers to submit an app to be included with the phone by default. I think later on in development, this app would be great for that, as it would allow all Firefox OS users to have access to our app immediately, and it's something they could use daily!

Wednesday, March 11, 2015

App Submission and IRC (3/11)

Today I checked the #openwebapps channel on IRC. Turns out I got assistance on my question fairly quickly: JQuery's demos folder was in our app, and it was accessing external scripts very frequently.  This isn't allowed in privileged apps, so it was preventing us from uploading our app to the marketplace! 66 errors were removed after fixing this, and then there were a few more in the manifest that I easily fixed.

After fixing all these issues, I spent the day uploading the app to the marketplace. It took awhile, but I got it rated and it's pending submission. We'll see where it goes from there!

Tuesday, March 10, 2015

Not Well Formed errors and the Defer option (3/10)

Today we did some experimenting with our "not well formed" errors we've been getting. They've become a big issue, because they refer to code errors in our app.js, but don't tell us exactly where.

I experimented a bit with the defer option. According to Mozilla, it means that it will continue loading the app without loading the app.js every single time. While it's good in some cases, in our case we thought it might be causing these errors, so I removed it temporarily to test.

What I found was a bit interesting - it now pointed out specific errors in our HTML code. I quickly fixed all those errors, only to find later that our search didn't work anymore. I turned defer on again, and it worked again. I'm not exactly sure why, so I guess we need to look into this a bit more.

The rest of the day today we had our meeting, so hopefully more progress will be made tomorrow!

Monday, March 9, 2015

Saving Books and a File Manager! (3/9/15)

Today I got the books to fully save, and double checked the file manager I had made earlier to see if it was showing files properly.

Alex helped me by writing more code onto our XMLHttpResponse method such that we can now grab Blobs [or large amounts of bits]. Essentially, these are our files. We then add them to the sdcard with the DeviceStorage.addNamed function, and from there they are saved to the SD card for later access. My file manager [so far] displays all files on the SD card.

At first, we had some issues with the buttons, but Alex put them below the onLoad of our page, and now they work perfectly!

Here's a screenshot of an average page you'd see for a book chapter. You can choose to download the full book [~50MB-2GB] or the individual part [~1MB-50MB]. They both seem to be working perfectly!


Wednesday, March 4, 2015

A Huge Success! (3/4)

Another duplicate post, but I think it's needed.

Today, I got home and realized how close we were to getting the app to fully load the URLs and books, so I decided to start working. I guess I got into the coding zone, because in just an hour or so, I created 100 lines of code which essentially will be the basis for loading all books and all titles.

The way it works is pretty simple. We had already been saving the IDs when a user chooses a book, so I thought, why not save the title and chapter as well? I made localStorage saves for both of these when a user selects a book and chapter, and saved the title as well. I then created a chapter selection page (and I'll create loading methods so the user doesn't have to re-select a chapter soon). From here, all the chapter titles are loaded to a list, which the user may press and it will then provide the app with the book URL to load in an audio tag.

I highlighted the way I did all this on GitHub here. The app.js changes that made the most difference are here, and the chapter index HTML file is here.

I have to say, it was pretty great when I got this message in my console:


I'll start working on audio loading soon, as well as downloads and a file manager! Those three shouldn't be too hard to make.

NEW EDIT: It's now fully working! I did it using an audio tag (via HTML5), and in Javascript I used JQuery to handle the loading and audio functions.

NEW EDIT 2: I made full persistency of audio data. It's not perfect, but it's a great working version. If you have opened a book, and gone to a certain point, the app will automatically bring you to the book page, load all resources, and then bring your audio to your past point (where you last left it). It'll also change this time for later if you seek through the audio.


Starting RSS Work + Finding Audiobook URLs (3/4)

Luckily, we've found a way to get audiobook URLs to load! Unfortunately, we have to use RSS, which (so far) is a LOT tougher to parse through than JSON.


This function will go through the RSS feed, and we can then figure out certain attributes of the code with these lines here.

From there, we've found that there's tags in the RSS feed that will allows us to determine title, URL, etc. with certain indicies. It's pretty much like JSON in that instance, it's just that parsing it can get a bit more complex with the different types of objects.

So far, I've gotten titles to load. I'll start working on audiobook URLs once I have that working perfectly.

Tuesday, March 3, 2015

Audio! ... And some problems (3/3)

This is my second post today, but it's completely different from the last, so I thought it was worth it.

I finally got audio working. Well, at least close. Here's the complete code. As you can see, it references our book.html, and then sets the audio source to a URL. While I haven't fully tested it with the CSP, it should work, or at least be close to working.

But finishing this resulted in a large problem, and that's that LibriVox API doesn't give a direct MP3 link. That means that we can't stream the file. Even worse, it's likely that we'll have to either download each book individually (most books are 1+ GB from my testing), or download ALL the books and host them somewhere as MP3 files. A third option would be to get URLs from LibriVox's site, but they're not constant - they're hosted in random URLs such as this link and this link (notice the large difference in the beginning of the URL). As a result, it's going to be really tough to get each book to load easily.

So, it's going to take a ton of work to finish this last part. We'll have to figure out which option is best! It's going to be massive if we go the MP3 route, according to here there's 8,533 items in the collection, and things are being added constantly. Given that the average filesize is 1GB each, that's over 8.5 terabytes of data.

Getting Books to Load! (3/3)

Today we made a lot of progress! In addition to search bugfixes, we also finally got the variable to pass between pages. It's done via an onClick event.

Basically, when the user clicks on an individual search result, we save the variable of that book to localStorage. Then, I figured out an onPageLoad event via JavaScript. It looks like the following:

$( document ).on( "pagecreate", "#homeSettings", function( event ) {
  console.log("Settings.html loaded");
});

Where #homeSettings is the name of the div that has the data-role of page in the html file.

We then have a method such that when book.html is loaded, it loads the ID, and can therefore then get JSON and other information about the book. From there, it should be extremely easy to load the audiobook, and the user can later go back and choose a new one!

I also setup some basic sliders for the book time, as well as play, pause, volume, and stop buttons. I'll add functionality to them hopefully tomorrow.

Monday, March 2, 2015

Yay! Search and More! (3/2)

So today Alex managed to get search working! Props to him for that; it was a 'return false;' statement right below our loop. Turns out the form we were using was messing up our page - it was a result of refreshing, which was removing all the list items we were adding.

So, here's some fancy pictures of the new search functionality we now have. I also added descriptions and links to our search results, so now they'll take you to book.html, which will [soon] play your audio book and have controls as well. I made it pass a variable to the book.html, called ID, which is handling the book ID via JSON. This book ID is used in their API, and should give us enough information to be able to get the audiobook itself!

Side note: Descriptions will contain more information soon, it'll just take some slight modifications!




Sunday, March 1, 2015

Finding the Search Issue (3/1)

So I worked a bit more today on the whole search issue, and the listview that goes along with it. I put some code in JSFiddle here to isolate it, and the list works. Then, I put it back in the loop, and it didn't work. I put it out of the loop (without getting JSON), and it worked perfectly again. So, I've determined that our JSON function is actually refreshing the page, and it's ruining the list, since it's resetting it every single time.

While I'm not sure of exactly how to fix this, hopefully Alex can find the line of code that's causing it. Once we can stop it from refreshing our page, our search results should work perfectly.