Monday, October 8, 2018

Migrating from Dragula to Shopify/Draggable/Sortable

In the following code snippets the variable draggable refers to a Draggable.Sortable instance.
You can also check out the fiddle.

Add revertOnSpill functionality to Sortable

var outContainer;
draggable.on('drag:out:container', (e) => {
 outContainer = e.data.overContainer;
});
draggable.on('sortable:stop', (e) => {
 var newContainer = e.data.newContainer;
  var spill = outContainer && outContainer === newContainer;
  if (spill) {
    var oldContainer = e.data.oldContainer;
    var oldContainerChildren = draggable.getDraggableElementsForContainer(oldContainer);
    var emptyOldContainer = !oldContainerChildren.length;
    var source = e.data.dragEvent.data.source;
    if (emptyOldContainer) {
     oldContainer.appendChild(source);
    } else {
      var oldIndex = e.data.oldIndex;
     oldContainer.insertBefore(source, oldContainer.children[oldIndex]);
    }    
  }
});

Figuring out Dragula library usage

The library in use: https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.2/dragula.js
plus its CSS: https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.2/dragula.css

Default configuration

HTML body content

<ul class="container">
<li class="draggable">1</li>
<li class="draggable">2</li>
<li class="draggable">3</li>
</ul>
<ul class="container">
<li class="draggable">1</li>
<li class="draggable">2</li>
<li class="draggable">3</li>
</ul>
<ul class="container">
<li class="draggable">1</li>
<li class="draggable">2</li>
<li class="draggable">3</li>
</ul>

JavaScript content

var containers = Array.prototype.slice.call(document.querySelectorAll('.container'));
var drake = window.dragula(containers);

How it looks like

With its CSSWithout its CSS
See the fiddle for yourself!

Figuring out Shopify/Draggable/Sortable library usage

The library in use: https://cdn.jsdelivr.net/npm/@shopify/draggable@1.0.0-beta.8/lib/draggable.bundle.js

Default configuration

The following plugins come with Draggable by default:
  • Announcement - announcing draggable events for a screenreader.
  • Focusable - adds tabindex to all draggable and container elements and thus makes them focusable
  • Mirror - creates a similar element to the original that will follow the cursor
  • Scrollable - scrolls the container while dragging when container edge is reached
Sortable is built on top of Draggable, so it has also all of this.

HTML body content

<ul class="container">
<li class="draggable">1</li>
<li class="draggable">2</li>
<li class="draggable">3</li>
</ul>
<ul class="container">
<li class="draggable">1</li>
<li class="draggable">2</li>
<li class="draggable">3</li>
</ul>
<ul class="container">
<li class="draggable">1</li>
<li class="draggable">2</li>
<li class="draggable">3</li>
</ul>

JavaScript content

var containers = document.querySelectorAll('.container');
var draggable = new window.Draggable.Sortable(containers, {
  draggable: '.draggable'
});

How it looks like

See the fiddle for yourself!

Friday, August 3, 2018

Developing Gramps on Ubuntu 16.04

Gramps is an open-source genealogy research tool written in Python3.

If you want to develop it on Windows, here are the instructions to do that.

To get started you'll need to read through a lot of documentation.
As for Python3 these can help:

Dependencies needed for Gramps

...are listed in the README.md:

EDIT: I just noticed this in the Getting Started and it might work instead of all those individual installations below, but you have to enable source code sources before you can do it: apt-get build-dep gramps

Instructions for Ubuntu 16.04:
  • Python 3.2 or greater: already installed
    • install python3-pip for further usage: sudo apt-get install python3-pip
  • GTK 3.10 or greater: already installed
  • pygobject 3.12 or greater: install it by running the following command from terminal:
    sudo apt install python-gi python-gi-cairo python3-gi python3-gi-cairo gir1.2-gtk-3.0
  • GObject Introspection bindings:
    • cairo 1.13.1 or greater: already installed (libcairo2)
    • Pycairo 1.13.3 or greater: already installed (python-cairo)
    • pango: already installed (libpango-1.0-0, libpango1.0-0)
    • pangocairo: already installed (libpangocairo-1.0-0)
    • librsvg2: already installed (librsvg2-2)
    • xdg-utils: already installed (xdg-utils)
    • bsddb3:
      • install BerkeleyDB dev package: sudo apt-get install libdb5.3-dev
      • install bsddb3: pip3 install bsddb3 --user
    • sqlite3: should be already installed with python.
  • language-pack-gnome-xx: i.e.: sudo apt-get install language-pack-gnome-en
  • osmgpsmap: 
    • install osmgpsmap: sudo apt-get install libosmgpsmap-1.0-1
    • and the python bindings: sudo apt-get install gir1.2-osmgpsmap-1.0
  • Graphviz: sudo apt-get install graphviz
  • PyICU: 
    • install ICU dev package: sudo apt-get install libicu-dev
    • and PyICU: pip3 install pyicu --user
  • Ghostscript: already installed
  • GExiv2: to get rid of the error popup when running Gramps
    • sudo apt-get install libgexiv2-2
    • sudo apt-get install gir1.2-gexiv2-0.10

Try what you cooked

  • download: git clone https://github.com/gramps-project/gramps.git Gramps
  • build: python3 setup.py build
  • DON'T INSTALL IT! (that would be python3 setup.py install)
  • run: python3 Gramps.py

Tuesday, July 31, 2018

How to subtract number of years, months and day from dates before 1900 in Google Spreadsheets?

Apparently Google Spreadsheet in incapable of handling dates before 1900 in the DATE, YEAR, MONTH, DAY functions.
So while in LibreOffice you can do this:
=DATE(YEAR(A1)-B1, MONTH(A1)-C1, DAY(A1)-D1)
where A1 is a date before 1900 and B1, C1, D1 are integers for the years, months, days to subtract
in Google Spreadsheet this results in a #NUM! error.

A workaround would be:
YEAR: =DATEDIF(-693990,A1,"Y")
MONTH: =DATEDIF(-693990,A1,"YM")
but this does not work properly with days.
A different way to put it is:
YEAR: =YEAR(A1+693961)-1900
MONTH: =MONTH(A1+693961)
DAY: =DAY(A1+693961)

However this does not help with subtracting and reconstructing the date.
So my workaround was to add a new spreadsheet function, because that can be written in javascript and these limitations do not apply.

From Tools > Script editor create a new script. Paste the following function and from Run > Test as add-on... add it to the sheet you need it in.

function dateSubtract(originalDate, yearsToSubtract, monthsToSubtract, daysToSubtract) {
  var date = new Date(originalDate);  
  date.setDate(date.getDate() - daysToSubtract);
  date.setMonth(date.getMonth() - monthsToSubtract);
  date.setFullYear(date.getFullYear() - yearsToSubtract);
  return date;
}
Than in the spreadsheet you can use this function like this:
=DATESUBTRACT(A1, B1, C1, D1)

What did I need this for?
In genealogy research the death records might indicate the age of the person in a years, months, days format. I collected some of these records in a spreadsheet and wanted to calculate the supposed birth date of the deceased.

Friday, June 1, 2018

Maven dependencies basics

Source: https://maven.apache.org/pom.html

Always required in a POM:
  • groupId
  • artifactId
  • version
Dependency hierarchy:
  • All POMs inherit from Maven's Super POM.
    This is why some properties you specify but not use have effect. For example you can set the compiler version with these properties:
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  • To set up a POM hierarchy within your project, all POMs that are specified as <parent> in other POMs or that have <modules> (aggregation aka. multi-module projects) must use <packaging>pom</packaging>.
  • Note:  A POM project may be inherited from - but does not necessarily have any modules that it aggregates. Conversely, a POM project may aggregate projects that do not inherit from it.
Dependency scope:
  • compile - this is the default scope, used if none is specified. Compile dependencies are available in all classpaths. Furthermore, those dependencies are propagated to dependent projects.
  • provided - this is much like compile, but indicates you expect the JDK or a container to provide it at runtime. It is only available on the compilation and test classpath, and is not transitive.
  • runtime - this scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.
  • test - this scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases. It is not transitive.
  • system - this scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository.
Exclusion of transitive dependencies:
  • One by one: specify them one by one
  • All: use the * wildcard for both the groupId and artifactId