diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..54a484d
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,17 @@
+language: node_js
+
+sudo: false
+
+install:
+ - "npm install mocha -g"
+
+before_script:
+ - "wget http://dl.node-webkit.org/live-build/09-06-2014/linux32_master-build-170-4beeddf-692f0ab-731b9e2-0f7c844-ae5bb86-86728d1/chromedriver-nw-v0.10.5-pre-linux-ia32.tar.gz"
+ - "wget http://dl.node-webkit.org/live-build/09-06-2014/linux32_master-build-170-4beeddf-692f0ab-731b9e2-0f7c844-ae5bb86-86728d1/node-webkit-v0.10.5-pre-linux-ia32.tar.gz"
+ - "unzip -j chromedriver-nw-v0.10.5-pre-osx-ia32.zip"
+ - "unzip -j node-webkit-v0.10.5-pre-linux-ia32.tar.gz"
+ - "sh -e /etc/init.d/xvfb start"
+ - sleep 5 # give xvfb some time to start
+
+script:
+ - "npm test"
\ No newline at end of file
diff --git a/app.js b/app.js
index 680fb3c..336b4c7 100644
--- a/app.js
+++ b/app.js
@@ -239,8 +239,10 @@ $(document).on("ready",function()
duplicateNote(current);
});
- $("#note").on("tripleclick",{ threshold: 600 }, function()
+ $("#note").on("tripleclick",{ threshold: 600 }, function(e)
{
+
+ console.log($.nearest({x: e.clientX, y: e.clientY}));
if (displayShowing())
{
//Unselect text from doubleclick.
diff --git a/index.html b/index.html
index 313224f..46b55d6 100755
--- a/index.html
+++ b/index.html
@@ -17,6 +17,7 @@
+
diff --git a/js/jquery.nearest.js b/js/jquery.nearest.js
new file mode 100644
index 0000000..724e6c8
--- /dev/null
+++ b/js/jquery.nearest.js
@@ -0,0 +1,253 @@
+/*!
+ * jQuery Nearest plugin v1.3.0
+ *
+ * Finds elements closest to a single point based on screen location and pixel dimensions
+ * http://gilmoreorless.github.io/jquery-nearest/
+ * Open source under the MIT licence: http://gilmoreorless.mit-license.org/2011/
+ *
+ * Requires jQuery 1.4 or above
+ * Also supports Ben Alman's "each2" plugin for faster looping (if available)
+ */
+
+/**
+ * Method signatures:
+ *
+ * $.nearest({x, y}, selector) - find $(selector) closest to point
+ * $(elem).nearest(selector) - find $(selector) closest to elem
+ * $(elemSet).nearest({x, y}) - filter $(elemSet) and return closest to point
+ *
+ * Also:
+ * $.furthest()
+ * $(elem).furthest()
+ *
+ * $.touching()
+ * $(elem).touching()
+ */
+;(function ($, undefined) {
+
+ /**
+ * Internal method that does the grunt work
+ *
+ * @param mixed selector Any valid jQuery selector providing elements to filter
+ * @param hash options Key/value list of options for matching elements
+ * @param mixed thisObj (optional) Any valid jQuery selector that represents self
+ * for the "includeSelf" option
+ * @return array List of matching elements, can be zero length
+ */
+ var rPerc = /^([\d.]+)%$/;
+ function nearest(selector, options, thisObj) {
+ // Normalise selector and dimensions
+ selector || (selector = 'div'); // I STRONGLY recommend passing in a selector
+ var $container = $(options.container),
+ containerOffset = $container.offset() || {left: 0, top: 0},
+ containerWH = [
+ $container.width() || 0,
+ $container.height() || 0
+ ],
+ containerProps = {
+ // prop: [min, max]
+ x: [containerOffset.left, containerOffset.left + containerWH[0]],
+ y: [containerOffset.top, containerOffset.top + containerWH[1]],
+ w: [0, containerWH[0]],
+ h: [0, containerWH[1]]
+ },
+ prop, dims, match;
+ for (prop in containerProps) if (containerProps.hasOwnProperty(prop)) {
+ match = rPerc.exec(options[prop]);
+ if (match) {
+ dims = containerProps[prop];
+ options[prop] = (dims[1] - dims[0]) * match[1] / 100 + dims[0];
+ }
+ }
+
+ // Deprecated options - remove in 2.0
+ if (options.sameX === false && options.checkHoriz === false) {
+ options.sameX = !options.checkHoriz;
+ }
+ if (options.sameY === false && options.checkVert === false) {
+ options.sameY = !options.checkVert;
+ }
+
+ // Get elements and work out x/y points
+ var $all = $container.find(selector),
+ cache = [],
+ furthest = !!options.furthest,
+ checkX = !options.sameX,
+ checkY = !options.sameY,
+ onlyX = !!options.onlyX,
+ onlyY = !!options.onlyY,
+ compDist = furthest ? 0 : Infinity,
+ point1x = parseFloat(options.x) || 0,
+ point1y = parseFloat(options.y) || 0,
+ point2x = parseFloat(point1x + options.w) || point1x,
+ point2y = parseFloat(point1y + options.h) || point1y,
+ tolerance = parseFloat(options.tolerance) || 0,
+ hasEach2 = !!$.fn.each2,
+ // Shortcuts to help with compression
+ min = Math.min,
+ max = Math.max;
+
+ // Normalise the remaining options
+ if (!options.includeSelf && thisObj) {
+ $all = $all.not(thisObj);
+ }
+ if (tolerance < 0) {
+ tolerance = 0;
+ }
+ // Loop through all elements and check their positions
+ $all[hasEach2 ? 'each2' : 'each'](function (i, elem) {
+ var $this = hasEach2 ? elem : $(this),
+ off = $this.offset(),
+ x = off.left,
+ y = off.top,
+ w = $this.outerWidth(),
+ h = $this.outerHeight(),
+ x2 = x + w,
+ y2 = y + h,
+ maxX1 = max(x, point1x),
+ minX2 = min(x2, point2x),
+ maxY1 = max(y, point1y),
+ minY2 = min(y2, point2y),
+ intersectX = minX2 >= maxX1,
+ intersectY = minY2 >= maxY1,
+ distX, distY, distT, isValid;
+ if (
+ // .nearest() / .furthest()
+ (checkX && checkY) ||
+ // .touching()
+ (!checkX && !checkY && intersectX && intersectY) ||
+ // .nearest({sameY: true})
+ (checkX && intersectY) ||
+ // .nearest({sameX: true})
+ (checkY && intersectX) ||
+ // .nearest({onlyX: true})
+ (checkX && onlyX) ||
+ // .nearest({onlyY: true})
+ (checkY && onlyY)
+ ) {
+ distX = intersectX ? 0 : maxX1 - minX2;
+ distY = intersectY ? 0 : maxY1 - minY2;
+ if (onlyX || onlyY) {
+ distT = onlyX ? distX : distY;
+ } else {
+ distT = intersectX || intersectY ?
+ max(distX, distY) :
+ Math.sqrt(distX * distX + distY * distY);
+ }
+ isValid = furthest ?
+ distT >= compDist - tolerance :
+ distT <= compDist + tolerance;
+ if (isValid) {
+ compDist = furthest ?
+ max(compDist, distT) :
+ min(compDist, distT);
+ cache.push({
+ node: this,
+ dist: distT
+ });
+ }
+ }
+ });
+ // Make sure all cached items are within tolerance range
+ var len = cache.length,
+ filtered = [],
+ compMin, compMax,
+ i, item;
+ if (len) {
+ if (furthest) {
+ compMin = compDist - tolerance;
+ compMax = compDist;
+ } else {
+ compMin = compDist;
+ compMax = compDist + tolerance;
+ }
+ for (i = 0; i < len; i++) {
+ item = cache[i];
+ if (item.dist >= compMin && item.dist <= compMax) {
+ filtered.push(item.node);
+ }
+ }
+ }
+ return filtered;
+ }
+
+ $.each(['nearest', 'furthest', 'touching'], function (i, name) {
+
+ // Internal default options
+ // Not exposed publicly because they're method-dependent and easily overwritten anyway
+ var defaults = {
+ x: 0, // X position of top left corner of point/region
+ y: 0, // Y position of top left corner of point/region
+ w: 0, // Width of region
+ h: 0, // Height of region
+ tolerance: 1, // Distance tolerance in pixels, mainly to handle fractional pixel rounding bugs
+ container: document, // Container of objects for calculating %-based dimensions
+ furthest: name == 'furthest', // Find max distance (true) or min distance (false)
+ includeSelf: false, // Include 'this' in search results (t/f) - only applies to $(elem).func(selector) syntax
+ sameX: name === 'touching', // Only match for the same X axis values (t/f)
+ sameY: name === 'touching', // Only match for the same Y axis values (t/f)
+ onlyX: false, // Only check X axis variations (t/f)
+ onlyY: false // Only check Y axis variations (t/f)
+ };
+
+ /**
+ * $.nearest() / $.furthest() / $.touching()
+ *
+ * Utility functions for finding elements near a specific point or region on screen
+ *
+ * @param hash point Co-ordinates for the point or region to measure from
+ * "x" and "y" keys are required, "w" and "h" keys are optional
+ * @param mixed selector Any valid jQuery selector that provides elements to filter
+ * @param hash options (optional) Extra filtering options
+ * Not technically needed as the options could go on the point object,
+ * but it's good to have a consistent API
+ * @return jQuery object containing matching elements in selector
+ */
+ $[name] = function (point, selector, options) {
+ if (!point || point.x === undefined || point.y === undefined) {
+ return $([]);
+ }
+ var opts = $.extend({}, defaults, point, options || {});
+ return $(nearest(selector, opts));
+ };
+
+ /**
+ * SIGNATURE 1:
+ * $(elem).nearest(selector) / $(elem).furthest(selector) / $(elem).touching(selector)
+ *
+ * Finds all elements in selector that are nearest to/furthest from elem
+ *
+ * @param mixed selector Any valid jQuery selector that provides elements to filter
+ * @param hash options (optional) Extra filtering options
+ * @return jQuery object containing matching elements in selector
+ *
+ * SIGNATURE 2:
+ * $(elemSet).nearest(point) / $(elemSet).furthest(point) / $(elemSet).touching(point)
+ *
+ * Filters elemSet to return only the elements nearest to/furthest from point
+ * Effectively a wrapper for $.nearest(point, elemSet) but with the benefits of method chaining
+ *
+ * @param hash point Co-ordinates for the point or region to measure from
+ * @return jQuery object containing matching elements in elemSet
+ */
+ $.fn[name] = function (selector, options) {
+ if (!this.length) {
+ return this.pushStack([]);
+ }
+ var opts;
+ if (selector && $.isPlainObject(selector)) {
+ opts = $.extend({}, defaults, selector, options || {});
+ return this.pushStack(nearest(this, opts));
+ }
+ var offset = this.offset(),
+ dimensions = {
+ x: offset.left,
+ y: offset.top,
+ w: this.outerWidth(),
+ h: this.outerHeight()
+ };
+ opts = $.extend({}, defaults, dimensions, options || {});
+ return this.pushStack(nearest(selector, opts, this));
+ };
+ });
+})(jQuery);
\ No newline at end of file
diff --git a/tests/tests.js b/tests/tests.js
index d4a2fa2..14fdf21 100644
--- a/tests/tests.js
+++ b/tests/tests.js
@@ -12,7 +12,9 @@ var notes2 = Array();
test.describe('Marknote', function()
{
-
+ this.timeout(50000);
+ test.describe('Notes', function()
+ {
test.it('Has notes.', function()
{
driver.executeScript("return notes").then(function(arr)
@@ -27,14 +29,82 @@ test.describe('Marknote', function()
test.it('Can add note.', function()
{
+ driver.wait(function()
+ {
+ return driver.isElementPresent(webdriver.By.id('newNote'));
+ }, 5000);
driver.findElement(webdriver.By.id('newNote')).click();
driver.executeScript('return notes').then(function(arr)
{
notes2 = arr;
- assert.equal(notes2.length, notes.length + 1);
+ assert.notEqual(notes2.length, notes.length);
+ });
+
+
+ });
+
+ test.it('Can open editor.', function()
+ {
+
+ driver.findElement(webdriver.By.id('display')).click();
+ driver.findElement(webdriver.By.id('display')).click();
+ driver.findElement(webdriver.By.id('display')).click();
+
+ driver.executeScript('return displayShowing()').then(function(test)
+ {
+ assert.equal(test, false);
+ });
+ });
+
+ test.it('Can edit note.', function()
+ {
+ var pretext;
+ driver.executeScript('return editor.getValue();').then(function(pre)
+ {
+ pretext=pre;
+ });
+ driver.executeScript("editor.insert('test');");
+ driver.executeScript('return editor.getValue();').then(function(post)
+ {
+ assert.notEqual(pretext, post);
+ });
+ });
+
+
+ test.it('Can save note.', function()
+ {
+ driver.findElement(webdriver.By.id('note')).click();
+ driver.findElement(webdriver.By.id('note')).click();
+ driver.findElement(webdriver.By.id('note')).click();
+
+ driver.wait(function()
+ {
+ return driver.isElementPresent(webdriver.By.id('display'));
+ }, 1000);
+
+ driver.executeScript('return displayShowing()').then(function(test)
+ {
+ assert.equal(test, true);
+ });
+
+ });
+
+ test.it('Can delete note.', function()
+ {
+ driver.executeScript('$("#actions").css("display", "block");').then(function()
+ {
+ driver.findElement(webdriver.By.xpath('//paper-icon-button[@icon="close"]')).click();
});
+ driver.executeScript("return notes").then(function(arr)
+ {
+ notes = arr;
+ assert.notEqual(notes.length, notes2.length);
+ });
});
-});
\ No newline at end of file
+
+});
+
+});