diff --git a/app/css/app.css b/app/css/app.css index bfd83b1..0042991 100644 --- a/app/css/app.css +++ b/app/css/app.css @@ -165,6 +165,7 @@ buttons { padding-bottom: 5px; border-bottom:1px solid #e0c0e0; padding-right: 16px; + cursor:pointer; } #sidedrawer .entry:after { diff --git a/app/index.html b/app/index.html index b26ff82..b634bec 100644 --- a/app/index.html +++ b/app/index.html @@ -13,10 +13,12 @@ + + diff --git a/app/js/app.js b/app/js/app.js index 231d40b..32cf4df 100644 --- a/app/js/app.js +++ b/app/js/app.js @@ -15,7 +15,10 @@ $.fn.pressEnter = function (fn) { }); }; -(function () { +var Keeper = (function () { + + var self = this; + console.log('GO!'); var $list = $('#listContainer'); var displayList = function (obj) { @@ -28,12 +31,37 @@ $.fn.pressEnter = function (fn) { getRecipe(this.id); }); }, displayPage = function (obj) { - var $bodyContents = $('#bodyContents'); + var $bodyContents = $('#bodyContents'); - if (obj.reduced.length > 0) { - $bodyContents.empty(); - $bodyContents.append(obj.reduced); + if (obj.reduced.length > 0) { + var vdata = { + data: { + _id: obj._id, + _rev: obj._rev, + title: obj.title, + reduced: obj.reduced, + url:obj.url } + }; + + var redoData = { + _id: obj._id, + _rev: obj._rev, + url: obj.url + }; + + + var html = new EJS({url: 'partials/view.ejs'}).render(vdata); + + $bodyContents.empty(); + $bodyContents.append(html); + + $('#redo').on('click', function () { + self.trigger('redo', redoData); + + }); + + } }, getRecipe = function (id) { console.log('get recipe'); var url = '/entry/' + id; @@ -124,10 +152,40 @@ $.fn.pressEnter = function (fn) { } }); }, - start = function () { + redo = function (d) { + console.log('redooing'); + var url = '/redo'; - getList(); - }; + $.ajax({ + type: 'POST', + url: url, + data: d, + dataType: 'json', + + timeout: 10000, + + //contentType: ('application/json'), + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'PUT, GET, POST, DELETE, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type' + + }, + success: function () { + // console.log(data); + // displayList(data); + }, + error: function (xhr, type) { + console.log('ajax error'); + console.log(xhr); + console.log(type); + } + }); + }, + start = function () { + + getList(); + }; $('#newurl').pressEnter(function () { var url = $(this).val(); @@ -146,5 +204,14 @@ $.fn.pressEnter = function (fn) { getList(); }); + + + this.bind('redo', function (data) { + redo(data); + }); start(); -})(); +}); + +MicroEvent.mixin(Keeper); + +var keeper = new Keeper(); diff --git a/app/libs/microevent.js b/app/libs/microevent.js new file mode 100644 index 0000000..e9cdb5c --- /dev/null +++ b/app/libs/microevent.js @@ -0,0 +1,55 @@ +/** + * MicroEvent - to make any js object an event emitter (server or browser) + * + * - pure javascript - server compatible, browser compatible + * - dont rely on the browser doms + * - super simple - you get it immediatly, no mistery, no magic involved + * + * - create a MicroEventDebug with goodies to debug + * - make it safer to use + */ + +var MicroEvent = function(){}; +MicroEvent.prototype = { + bind : function(event, fct){ + this._events = this._events || {}; + this._events[event] = this._events[event] || []; + this._events[event].push(fct); + }, + unbind : function(event, fct){ + this._events = this._events || {}; + if( event in this._events === false ) return; + this._events[event].splice(this._events[event].indexOf(fct), 1); + }, + trigger : function(event /* , args... */){ + this._events = this._events || {}; + if( event in this._events === false ) return; + for(var i = 0; i < this._events[event].length; i++){ + this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1)); + } + } +}; + +/** + * mixin will delegate all MicroEvent.js function in the destination object + * + * - require('MicroEvent').mixin(Foobar) will make Foobar able to use MicroEvent + * + * @param {Object} the object which will support MicroEvent + */ +MicroEvent.mixin = function(destObject){ + var props = ['bind', 'unbind', 'trigger']; + for(var i = 0; i < props.length; i ++){ + if( typeof destObject === 'function' ){ + destObject.prototype[props[i]] = MicroEvent.prototype[props[i]]; + }else{ + destObject[props[i]] = MicroEvent.prototype[props[i]]; + } + } + return destObject; +} + +// export in common js +if( typeof module !== "undefined" && ('exports' in module)){ + module.exports = MicroEvent; +} diff --git a/app/partials/view.ejs b/app/partials/view.ejs new file mode 100644 index 0000000..82bdd85 --- /dev/null +++ b/app/partials/view.ejs @@ -0,0 +1,19 @@ +
+
+
<%=data.title%>
+
+ Redo + <%=link_to('Link',data.url) %> +
+ +
+
+
+
+ <%=data.reduced%> +
+
+ +

<%=data._id%>

+

<%=data._rev%>

+ diff --git a/package.json b/package.json index db48a7a..27171ca 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "nano": "^6.2.0", "require-dir": "^0.3.0", "serve-favicon": "^2.3.0", - "string": "^3.3.1" + "string": "^3.3.1", + "url": "^0.11.0" }, "devDependencies": { "del": "^2.2.0", diff --git a/server/keeper.js b/server/keeper.js index 8b064b2..10e0422 100644 --- a/server/keeper.js +++ b/server/keeper.js @@ -8,6 +8,7 @@ var jsonfile = require('jsonfile'), fs = require('fs'), STRING = require('string var zlib = require("zlib"); var log4js = require('log4js'); var logger = log4js.getLogger(); +var URL = require('url'); var router = express.Router(); @@ -49,14 +50,39 @@ function insertBookmark(obj) { logger.debug('Insert done..'); } +function updateBookmark(obj,_id, _rev) { + logger.debug('Updating couch...'); + var _obj = obj; + _obj._id = _id; + _obj._rev = _rev; + logger.info(util.inspect(_obj)); + + dbCouch.insert(_obj, function(err, body,header) { + if (err) { + logger.error('Error updating into couch'); + return; + } + }); + logger.debug('Update done..'); +} var doInsertBookmark = (obj) =>{ // logger.info('sendSocket: ' + JSON.stringify(obj)); insertBookmark(obj); }; -var doGetBookmark = (url) =>{ +var doUpdateBookmark = (obj, _id, _rev) =>{ + // logger.info('sendSocket: ' + JSON.stringify(obj)); + updateBookmark(obj,_id, _rev); +}; + +var doGetBookmark = (obj) =>{ // logger.info('sendSocket: ' + JSON.stringify(obj)); - genericGrab(url); + genericGrab(obj); +}; + +var doGetBookmarkRedo = (obj) =>{ + // logger.info('sendSocket: ' + JSON.stringify(obj)); + genericGrab(obj); }; var doGetBookmarkRes = (url,res) =>{ @@ -67,25 +93,28 @@ var doGetBookmarkRes = (url,res) =>{ // Events busEmitter.on('saveBookmarkData', doInsertBookmark); +busEmitter.on('updateBookmarkData', doUpdateBookmark); busEmitter.on('getBookmark', doGetBookmark); busEmitter.on('getBookmarkRes', doGetBookmarkRes); -function processBody(body, url) { +busEmitter.on('getBookmarkRedo', doGetBookmarkRedo); +function processBody(body, url, _id, _rev) { + + var obj, tdihbody, i, urlObj, urlPrefix; var $ = cheerio.load(body); var title = $('TITLE').text(); // try to find a body to grab - var i = 0; + i = 0; while (($(generics[i]).length == 0) && (i < generics.length)) { i++; } logger.debug(i); - var tdihbody; - var obj = {}; + obj = {}; if (i < generics.length) { tdihbody = $(generics[i]); logger.debug(tdihbody.length); @@ -100,34 +129,53 @@ function processBody(body, url) { logger.debug(title); } - try - { - tdihbody.find('IMG').each(function(i, elem) { - //fruits[i] = $(this).text(); - var s = 'http://image.silvrtree.co.uk/900,fit/' + $(this).attr("src"); + urlObj = URL.parse(url); + urlPrefix = urlObj.protocol + '//' + urlObj.host + '/'; + try { + tdihbody.find('IMG').each(function (i, elem) { + let s, src = $(this).attr("src"); + + if (!STRING(src).startsWith('http')) { + src = urlPrefix + STRING(src).stripLeft('/').s; + } + s = 'http://image.silvrtree.co.uk/900,fit/' + src; $(this).attr("src", s); }); } - catch(e) - { + catch (e) { logger.error(e); } - obj.url = url; obj.html = $.html(); obj.reduced = STRING(tdihbody.html()).trim().s; obj.title = STRING(title).collapseWhitespace().s; - busEmitter.emit("saveBookmarkData", obj); + if (_id !== null ) + { + busEmitter.emit("updateBookmarkData", obj, _id, _rev); + } + else + { + busEmitter.emit("saveBookmarkData", obj); + } + return obj; } -function genericGrab(url,res) { +function genericGrab(obj,res) { + + var url = obj.url; + var _id = obj._id || null; + var _ver = obj._rev || null; + logger.info(url); + logger.info(_id); + logger.info(_ver); + request(url, function (err, resp, body) { if (err) throw err; @@ -155,7 +203,7 @@ function genericGrab(url,res) { } else { - var b = processBody(body,url); + var b = processBody(body,url, _id, _ver); if (res != null) { res.render('grabbed'); @@ -164,7 +212,7 @@ function genericGrab(url,res) { } else { - var b = processBody(body,url); + var b = processBody(body,url, _id, _ver); if (res != null) { res.render('grabbed',{data:b}); @@ -206,8 +254,11 @@ router.get('/entry/:id', function (req, res) { if (!err) { var outJSON = {}; + outJSON._id = body._id; + outJSON._rev = body._rev; outJSON.title = body.title; outJSON.reduced = body.reduced; + outJSON.url = body.url; //logger.debug(util.inspect(body)); res.writeHead(200, {"ContentType": "application/json"}); res.end(JSON.stringify(outJSON)); @@ -228,7 +279,7 @@ router.post('/add', function (req, res) { if (t.hasOwnProperty('url')) { var url = JSON.parse(t.url.toString()); logger.debug(url); - busEmitter.emit("getBookmark", url); + busEmitter.emit("getBookmark", t); } else { logger.error('No data block!'); @@ -238,6 +289,26 @@ router.post('/add', function (req, res) { }); +router.post('/redo', function (req, res) { + logger.debug('redoing entry..'); + + var t = req.body; + console.log(t); + if (t.hasOwnProperty('url')) { + var url = t.url.toString(); + logger.debug(url); + busEmitter.emit("getBookmark", t); + } + else { + logger.error('No data block!'); + } + res.writeHead(200, {"ContentType": "application/json"}); + res.end(JSON.stringify({adding: url})); + +}); + + + router.get('/new', function (req, res) { logger.debug('Save new'); busEmitter.emit("getBookmarkRes", req.query.url ,res);