RxDB is a tool for setting up a reactive database which in turn uses PouchDB, which in turn offers a variety of adapters that can build different types of databases with solutions like indexeddb and websql. It wasn’t altogether clear to me whether it would work nicely in an Electron app, and a nuxt.js driven one at that. Installation was a right nightmare.
To get setup you probably want to use sqlite / the websql adapter in pouchdb/RxDB. This involves configuring node-gyp and a bunch of dependencies. It won’t run properly out of the box until you tailor it to the version of electron you are running. To get sqlite3 running you will need a bunch of other dependencies installed as well, such as python 2.7. On Windows the most convenient way to do is to install windows-build-tools.
Here are some helpful tips if you have trouble installing windows build tools
If you get errors like “electron-v1.3-win32-x64\node_sqlite3.node module missing” you can try performing the manual steps outlined here and here. The important bit is that you need to tie your sqlite3 package to the specific version of electron that you have running in your project.
I also was getting webpack errors (unexpected character # at 1:0) relating to js files that open with a # hash/shebang directive. To fix that you can install the shebang loader and run it on the js files (like this) in question as a loader in your webpack configuration. In a nuxt project you configure your webpack config modifications in the nuxt.config.js file!
If you fail to get things running like I did for 3 days (until I got it working), there are alternatives like lowdb, nedb or realm but it really depends on what kind of setup you need in your project.
Update
So it turns out the hardest part of setting up RxDB with sqlite3 is due to webpack not working well with native add-ons. There are a whole slew of build/parsing errors you will encounter by the dependencies that are introduced via node-gyp, node-pre-gyp and sqlite3. The errors are very similar to ones mentioned in this webpack related thread. Some examples:
SyntaxError: Unexpected character '#' (1:0)
the request of a dependency is an expression
Module not found: Error: Cannot resolve module 'node-gyp'
node-pre-gyp/~/tar/tar.js
Module build failed: SyntaxError: Invalid number (108:10)
Workaround
Because nuxt.js uses a SSR approach you’re kind of stuck with webpack for all your components. However, RxDB can work just fine with sqlite3 (via the pouchdb-node-websql-adapter) on the client. This offers one way of working around webpack: just load up RxDB as a script asset on the client and access it inside a Vue instance. You can configure a header script in your nuxt.config.js file. You may want to set webSecurity to false to be able to load the script as a local file.
Mastering Javascript is something I’ve set out to do. Truth be told, it’s a weird language. When I encounter a resource that elucidates in an exemplary fashion, I feel great gratitude. I’m compiling a list of articles and resources here that do an extraordinary job at explaining Javascript programming topics.
Understanding scope
This is the clearest tutorial on scope, contexts and the this variable that I have read.
Binding Scope in Javascript
Learning Regex
Regular expressions are used in many languages and mastering it is incredibly useful. When I first started, it was very confusing to me. This site is fantastic at helping one understand regex.
Regex 101
Javascript/jQuery Design Patterns
Learning Javascript Design Patterns is a book by Addy Osmani, who produces outstanding learning materials. The unbelievable part is that the book can be had free.
Learning Javascript Design Patterns
Javascript Video Resources
A fantastic curated list of the best video presentations on Javascript
There are a number of ways to bind event handlers to elements with jQuery, a popular one called live() is deprecated since version 1.7 so people are advised to replace this in their code. The live() method was great for committing event handlers to elements that were dynamically inserted after page load. Now the right method to use is on() which is relatively new and its benefits have been discussed at length. Just like live(), on() is able to attach event handlers to newly inserted elements, perfect right? But there’s a bit of a gotcha.
Converting instances of live() to on() is going to be straightforward most of the time (see how), but you still may run into trouble. A potential issue has to do with how event delegation is dealt with. Event delegation is important to take advantage of because it replaces the need to add a multitude event handlers attached to separate elements by applying one event handler to a single parent element. When assigning event handlers in this way – say, because you want to add some click hanlders to buttons inside the rows of a table – you usually pick the most efficient parent element. The broader the parent element, the less efficient and less robust things become, so it is important to make the parent element as near as possible.
If you are adding event handlers inside a table, the obvious choice might be the table element.
$('table').on("click", "a.addrow", function(){ // do stuff });
That will work fine if this table element was present on page load. But what if the table was added dynamically? And this is where you might get confused (I certainly did). The thing is, it won’t work if your parent element was dynamically added. It has to be an element that was present on page load.
The problem:
When setting the parent element with the on() method, this element must be present on the page, elements added later are ignored.
Solutions
Applying event delegation to a broader parent element
One easy solution is to set a broader parent element that you know for sure exists after page load has finished. There can be some drawbacks to this which are mostly relevant in situations where you do not control all the elements on the page to start with. In these case you might be tempted to append the event handler to something like the body element, because you can be certain this element will be on the page. But the broader the element, the more likely it is that something else could prevent your event handler firing. If the environment has a lot of other scripts running, the chances increase that a conflict might occur. This is especially true if you are coding something like a WordPress plugin and have to contend with dozens of other scripts you can’t control.
In the best case scenario, you pick an element with a specific ID that is one level higher up the dom. This is going to be more efficient than say, a class name or something higher up the DOM.
// table would later be inserted here
$('#tablewrap').on("click", "table a.addrow", function(){ // do stuff });
Attaching event handlers when elements are inserted
The second solution involves setting the event handlers when the relevant elements are inserted. There are a couple of possible scenarios that may apply and a few ways to implement this. I’ll cover one or two to illustrate the general idea.
So let’s say groups of elements are being inserted into the page with jQuery’s .clone() method and you want the new clone to have the same event handlers. If this is your own code doing so, you can easily opt to do a deep clone and copy all of the event handlers. This way all the event handlers that apply to the element that is being cloned will apply to the clone. This is as easy as setting a few parameters:
instead of using .clone() without parameters set, use .clone(true, true) and all your event handlers will apply to the new clone!
When you can’t edit the code of the script that is inserting elements
Maybe you can’t change the code (for example, to add the parameters to the clone method) because it belongs to a script you can’t edit. In this case you will have to figure out another way to bind the event handlers on insertion. The best thing is to inspect what the code looks like and see where you can hook in. Often a custom event is triggered when elements are being inserted. If this is the case, you can piggy back on that custom event.
// the addTable event triggers when a new table is inserted into the DOM $('#interface').on("addTable", function(){ // now we can add our event handler $("table").on("click", "a.delete-table", function(){ // do stuff $(this).closest('table').remove(); } });
An even better variation of this is when the triggered event passes the element as an argument. That way you can target that element and append your event handlers without the extra legwork.
// demo link here http://codepen.io/PeterKnight/pen/oknre $("#interface").on("click", ".add-table", function(){ var $el = $('
‘); $el.insertAfter(‘button’) .append(‘New table!DELETE THIS TABLE, DO IT NOW!’) .trigger(“addTable”, $el); }); $(“#interface”).on(“addTable”, function(e, el){ $(el).on(“click”, “a.delete-table”, function(){ // do stuff e.preventDefault(); $(this).closest(‘table’).remove(); }); });
Execute a function or method that binds the event handler after the element has been inserted
This solution is really simple a straightforward. Basically you write a function or method that appends the event handlers to the desired element and you execute this function or method after the element has been inserted into the page. A very rudimentary example (not copy paste worthy!):
// function or code that inserts element someFunctionThatInsertsAnElement(); // function that appends event handlers someFunctionThatAppendsEventHandlers(element); // above function could look a bit like this function someFunctionThatAppendsEventHandlers(element){ jQuery(element).on("click", "a.addRow", function(){ // add a row etc. }); }
A Ninja CSS Trick
There is a very clever and effective way of detecting a newly inserted element with the help of CSS animations. This technique doesn’t require jquery but it only works in browsers that support keyframe, which all modern browsers do…of course IE6-9 aren’t party to that. The neat thing about this method is that it is great in situations where you don’t how your script is going to be used, while you can still reliably and efficiently can set a suitable parent element to use with on().
I have created a blunt demo that demonstrates the technique on codepen, be sure to read the original article linked above though!
While building an add-on for a WordPress plugin, I ran into a little javascript puzzle. I needed to perform an action straight after a table row was removed by a user. At first I tried binding an event handler to the button that deletes the row using the click event. This would normally work just fine, except the plugin was calling a confirmation dialog. When the javascript functions alert or confirm are called, it brings up a dialog box. At this point a user can choose to cancel the action. If you attach an event handler to the click event of the delete button, it will fire, but it won’t know if the user confirmed or not. In other words, this method was not going to work.
As the plugin was using jQuery’s remove() function to remove the table row, it’s possible to watch for the ‘remove’ event. This event handler isn’t widely documented yet at the time of writing. It should trigger when the selected element is removed from the DOM using jQuery’s remove() method. At first I tried to apply the event handler to table row using On() method with the ‘remove’ event. For some reason this wasn’t triggering after deleting a table row. So, the next method I tried was to bind a ‘remove’ event handler using the bind() method whenever the delete button for the row gets pressed. This does work, but you’ll need to use a recent jQuery version with jQuery UI 1.9+, specifically the jQuery UI widgets component.
And here’s an example:
DEMO @ codepen.io