Refresh the content without page refresh - node.js

hello i have developed the chat application using socket.io, expressjs and mongoose it works fine. it refreshes after some seconds and fetches new clients from db if exist. problem is that user can feel that div is refreshsing.and also some time take soem time in response. how to avoid this case. here is my code
This is my server side code
setInterval(function () {
var allOnLine;
allOnLine = io.sockets.clients();
for (var client in allOnLine) {
if (allOnLine[client].username == "undefined") {
continue;
} else {
notifyAll(allOnLine[client].username);
}
}
}, 50000);
and here is notify all method
function notifyAll(userName) {
contactModel.find({'userId':userName}, (function (err, contactModel) {
usernames = [];
var contacts = contactModel;
for (var a = 0; a < contacts.length; a++) {
usernames[a] = contacts[a].contactId;
}
var allOnLine;
allOnLine = io.sockets.clients();
for (var client in allOnLine) {
if (allOnLine[client].username == "undefined") {
continue;
} else {
for (var i = 0; i < usernames.length; i++) {
if (allOnLine[client].username == usernames[i]) {
usernames[i] = usernames[i] + " -On";
}
allOnLine[client].username);
}
}
}
io.sockets.to(userName).emit('updateusers', usernames);
}));
}
This is my client code
socket.on('updateusers', function(usernames) {
jQuery('#usernames').html('');
jQuery.each(usernames, function(key, value) {
jQuery('#usernames').append('<div class="chatContact" id="chatLink" onclick="privateChat(\''+value+'\')">' );
}}
any help i had also posted this question but no answer

Your problem is that youdelete everything from usernames and after that you write all contacts. You would better remove the offline contacts from the $('#usernames') and after that to add to that list the online contacts. I writed some functions to show you the functionality. I created html list of online contacts and I also created an array of new online contacts. Here is the code:
<div id="u">
<div class="d" onclick="chat('asd1')">asd1</div>
<div class="d" onclick="chat('asd12')">asd12</div>
<div class="d" onclick="chat('asd13')">asd13</div>
<div class="d" onclick="chat('asd142')">asd14</div>
</div>
Here you have the javascript that you need to run after the DOM is ready:
var onlineUsernames = ["asd211","asd12","asd13","asd14"];
var usernamesContainerID = 'u';
var $usernamesContainer = $('#'+usernamesContainerID);
function extractUsernameFromAttr(onclickValue)
{
return onclickValue.split("'")[1];
}
function buildExistingUsernames($userDivs)
{
var existingUsernames = [];
$userDivs.each(function(index,value){
var username = extractUsernameFromAttr($userDivs[index].getAttribute('onclick'));
existingUsernames.push(username);
})
return existingUsernames;
}
function removeUserFromList($user)
{
document.getElementById(usernamesContainerID).removeChild($user);
}
function addUserToList(value)
{
$('<div/>',{
onclick:"chat('"+value+"')",
class :'d',
text:value
}).appendTo($usernamesContainer);
}
function deleteOfflineContacts(existingUsernames,usernames,$userDivs)
{
$.each(existingUsernames,function(index,value)
{
if($.inArray(value,usernames)==-1)
{
removeUserFromList($userDivs[index]);
}
})
}
function addOnlineContacts(existingUsernames,usernames)
{
$.each(usernames,function(index,value)
{
if($.inArray(value,existingUsernames)==-1)
{
addUserToList(value);
}
})
}
function update($userDivs)
{
var existingUsernames = buildExistingUsernames($userDivs);
deleteOfflineContacts(existingUsernames,onlineUsernames,$userDivs);
addOnlineContacts(existingUsernames,onlineUsernames);
}
var $userDivs = $usernamesContainer.children("div");
setTimeout(function()
{
update($userDivs);
},3000);
If you need it here is a working example: http://jsfiddle.net/9gRyQ/2/

Related

How to connect my electron app using PouchDB (leveldb) with Cloudant or any other database that support couchDB and sync

I'm creating an electron app using pouchDB and I want the app to be able to diferents customers and sync the data between them. As an example I'm making the tutorial: https://github.com/nolanlawson/pouchdb-getting-started-todo, I adapt the code to electron and I created a noSQL database at cloudant.
At the moment I can save data but I cannot sync with my remote db that is in cloudant. Here is the endpoint I'm using to sync data between both database.
Here is the error that I'm getting.
Here is the code of my script.js
(function() {
'use strict';
var $ = document.querySelector.bind(document);
var ENTER_KEY = 13;
var newTodoDom = document.getElementById('new_todo');
var syncDom = document.getElementById('sync-wrapper');
// EDITING STARTS HERE (you dont need to edit anything above this line)
var NodePouchDB = require('pouchdb');
var db = new NodePouchDB('todos');
var couchdb = require('felix-couchdb')
var remoteCouch = couchdb.createClient(5984, 'https://ac725f4e-29ec-4614-8e96-02ebc74a529b-bluemix.cloudant.com/')
db.info(function(err, info) {
console.log("is working", info)
db.changes({
since: info.update_seq,
live: true
}).on('change', showTodos);
});
// We have to create a new todo document and enter it in the database
function addTodo(text) {
var todo = {
_id: new Date().toISOString(),
title: text,
completed: false
};
db.put(todo).then(function (result) {
console.log("everything is A-OK");
console.log(result);
}).catch(function (err) {
console.log('everything is terrible');
console.log(err);
});
}
// Show the current list of todos by reading them from the database
function showTodos() {
db.allDocs({include_docs: true, descending: true}).then(function(doc) {
redrawTodosUI(doc.rows);
}).catch(function (err) {
console.log(err);
});
}
function checkboxChanged(todo, event) {
todo.completed = event.target.checked;
console.log(todo);
db.put(todo);
}
// User pressed the delete button for a todo, delete it
function deleteButtonPressed(todo) {
db.remove(todo);
}
// The input box when editing a todo has blurred, we should save
// the new title or delete the todo if the title is empty
function todoBlurred(todo, event) {
var trimmedText = event.target.value.trim();
if (!trimmedText) {
db.remove(todo);
} else {
todo.title = trimmedText;
db.put(todo);
}
}
// Initialise a sync with the remote server
function sync() {
syncDom.setAttribute('data-sync-state', 'syncing');
var opts = {live: true};
db.sync(remoteCouch, opts, syncError);
}
// EDITING STARTS HERE (you dont need to edit anything below this line)
// There was some form or error syncing
function syncError() {
syncDom.setAttribute('data-sync-state', 'error');
}
// User has double clicked a todo, display an input so they can edit the title
function todoDblClicked(todo) {
var div = document.getElementById('li_' + todo._id);
var inputEditTodo = document.getElementById('input_' + todo._id);
div.className = 'editing';
inputEditTodo.focus();
}
// If they press enter while editing an entry, blur it to trigger save
// (or delete)
function todoKeyPressed(todo, event) {
if (event.keyCode === ENTER_KEY) {
var inputEditTodo = document.getElementById('input_' + todo._id);
inputEditTodo.blur();
}
}
// Given an object representing a todo, this will create a list item
// to display it.
function createTodoListItem(todo) {
var checkbox = document.createElement('input');
checkbox.className = 'toggle';
checkbox.type = 'checkbox';
checkbox.addEventListener('change', checkboxChanged.bind(this, todo));
var label = document.createElement('label');
label.appendChild( document.createTextNode(todo.title));
label.addEventListener('dblclick', todoDblClicked.bind(this, todo));
var deleteLink = document.createElement('button');
deleteLink.className = 'destroy';
deleteLink.addEventListener( 'click', deleteButtonPressed.bind(this, todo));
var divDisplay = document.createElement('div');
divDisplay.className = 'view';
divDisplay.appendChild(checkbox);
divDisplay.appendChild(label);
divDisplay.appendChild(deleteLink);
var inputEditTodo = document.createElement('input');
inputEditTodo.id = 'input_' + todo._id;
inputEditTodo.className = 'edit';
inputEditTodo.value = todo.title;
inputEditTodo.addEventListener('keypress', todoKeyPressed.bind(this, todo));
inputEditTodo.addEventListener('blur', todoBlurred.bind(this, todo));
var li = document.createElement('li');
li.id = 'li_' + todo._id;
li.appendChild(divDisplay);
li.appendChild(inputEditTodo);
if (todo.completed) {
li.className += 'complete';
checkbox.checked = true;
}
return li;
}
function redrawTodosUI(todos) {
var ul = document.getElementById('todo-list');
ul.innerHTML = '';
todos.forEach(function(todo) {
ul.appendChild(createTodoListItem(todo.doc));
});
}
function newTodoKeyPressHandler( event ) {
if (event.keyCode === ENTER_KEY) {
addTodo(newTodoDom.value);
newTodoDom.value = '';
}
}
function addEventListeners() {
newTodoDom.addEventListener('keypress', newTodoKeyPressHandler, false);
}
addEventListeners();
showTodos();
if (remoteCouch) {
sync();
}
})();
To get to where the problem sits, can you verify that you can speak to the Cloudant database normally, that is using curl from the command-line? Using curl, fetch a document by its _id, perhaps a document you created manually using the Cloudant dashboard. That should shake out any problems with authentication: I note you're using IAM, which isn't always straight-forward -- and to my knowledge, not supported by PouchDB (or wasn't, last time I looked).
If that is the problem, create a new Cloudant instance with IAM+Legacy credentials.

How to change the id of a socket?

I'm making an app in node.js and I noticed that every time users open a new page or change page they get a different socket id. It is possible to change the id of that socket so the user has always the same socket id?
When the user connects to the server, it saves the uid and the id of the socket in mongodb and get that data each time he connects.
This is my code:
nspm.on('connection', function(socket) {
db.c_oneusr(socket.decoded_token, function(err, docs){
if(docs) {
if(docs.ban=='1') {
nspm.to(socket.id).emit('ckusr', 'banned');
socket.disconnect();
return;
}
else {
nspm.to(socket.id).emit('ckusr', 'ok');
if (!docs.laston) {
docs.laston = 0;
}
initializeConnection(socket, docs.laston);
}
}
else {
nspm.to(socket.id).emit('ckusr', 'ok');
initializeConnection(socket, 0);
}
});
});
function initializeConnection(socket, laston){
var online = [];
laston = new Date(laston);
socket.uid = socket.decoded_token.uid;
socket.buddies = socket.decoded_token.buddies;
// id contains all ids of each user
if (!id[socket.uid]) {
id[socket.uid] = {};
}
id[socket.uid][socket.id] = 1;
socket.join(socket.uid);
for (var buddy in socket.buddies) {
var buddy_id = socket.buddies[buddy];
socket.join(buddy_id);
if (uidlist[buddy_id]) {
online.push(parseInt(buddy_id, 10));
}
}
socket.emit('login', {
online: online
});
socket.broadcast.to(socket.uid).emit('user joined', {
uid: socket.uid
});
data = [];
data["uid"] = socket.decoded_token.uid;
data["id"] = socket.id;
db.updpml(data); // Update user data
}

I can't get my desktop push notification for chrome extension to open in the same tab

Once I click the view product button I created on the notification, the link opens in a new tab but for a second notification, the link opens two similar tabs and it goes on.
The tabs keep increasing as the notifications increase.
It is an ecommerce website
Here's my code. I don't know where I went wrong.
var messages = [] ;
var ids = [] ;
var latestItem;
$(function(){
engine();
setInterval(engine, 60000);
});
function engine(){
var newItems = [];
$.get('https://www.mysite.or/electronics-video/', function(data){
var htmlData = data;
$data = ($(htmlData).find('.offer').eq(0));
$data.find('.fleft').remove();
$data.find('.rel.observelinkinfo.inlblk.zi3').remove();
$data.find('.suggesttitleright.small.top.abs.zi2.br4.hidden').remove();
$data.find('.thumb.vtop.inlblk.rel.tdnone.linkWithHash.scale4.detailsLink').remove();
$data.find('.color-9.lheight16.margintop5').remove();
$data.find('.breadcrumb.x-normal').remove();
$data.find('.normal.inlblk.pdingtop5.lheight16.color.2').remove();
$('body').append($data);
for(i = 0; i<$data.find('h3.x-large.lheight20.margintop5').length; i++){
ids[i]=($($data).find('td.wwnormal.tright.td-price').eq(i).find('p.price').text()).replace(/\n\r/g, '').trim();
messages[i]= ($($data).find('h3.x-large.lheight20.margintop5').eq(i).find('a.marginright5.link.linkWithHash.detailsLink').text()).replace(/\n\r/g, '').trim();
}
if (latestItem == ids[0]) {
}else if(latestItem === undefined) {
var firstRun = {
type: "basic",
title: "Site Notifier",
message: 'Visit the website for updates on new products',
iconUrl: "origi.png"
}
chrome.notifications.create(firstRun);
latestItem = ids[0];
}else if(latestItem != ids[0]) {
for(j = 0; j<ids.length; j++){
if(latestItem == ids[j]){
break;
}else{
if (messages[j] != " "){
newItems[j]= messages[j].concat(" - ").concat(ids[j]);
}
}
}
latestItem = ids[0];
}
if (newItems.length == 0){
}else{
for(i=0;i<newItems.length; i++){
var myItem = {
type: "basic",
title: "New Product Alert!",
message: newItems[i],
contextMessage: "Site Notifier",
buttons: [{
title: "View Product"
}],
iconUrl: "origi.png"
};
chrome.notifications.onButtonClicked.addListener(function(){
window.open('https://www.mysite.or/electronics-video/');
});
chrome.notifications.create(myItem);
}
}
});
}
try below code
chrome.notifications.onButtonClicked.addListener(function (notificationId, buttonIndex) {
if (notificationId == '1234567' && buttonIndex == 0) {
var $ismysite = false;
chrome.windows.getAll({ populate: true }, function (windows) {
windows.forEach(function (window) {
window.tabs.forEach(function (tab) {
if (tab.url.toString().lastIndexOf('mysite') > -1) {
$ismysite= true
}
});
});
if (!$ismysite) {
$ismysite = false;
chrome.tabs.create({ url: "YourSire" }, function () {
});
}
});
}
});
in your code, at the end if (newItems.length == 0)
else statement will create notification for every element of newItems array AND it will add onClicked listener.
You need to pull out
chrome.notifications.onButtonClicked.addListener(function(){
window.open('https://www.mysite.or/electronics-video/');
});
somewhere out of that loop.
If you need to know which notification is clicked, you can find out by ID in callback. For that you probably need to maintain some ID - url connection in global object.

Transform publish MeteorJS with count of show

I try to use limit : count with transform observer in Meteor and don't understand how to do it without "dirty" solutions.
Code I have on Client (not all, but main part)
var self = this;
self.autorun(function() {
self.subscribe('posts', Session.get('count')); // some Number like 10
}); // client
And on server where I try to use it
Meteor.publish('posts', function(count){
check(count, Number);
let i = 0;
var transform = function(doc) {
console.log(i,count);
if (i < count){ // I try something here
doc.description = new Date();
i++;
return doc;
}
else self.ready();
}
var self = this;
var observer = Posts.find().observe({
added: function (document) {
self.added('posts', document._id, transform(document));
},
changed: function (newDocument, oldDocument) {
self.changed('posts', document._id, transform(newDocument));
},
removed: function (oldDocument) {
self.removed('posts', oldDocument._id);
}
});
self.onStop(function () {
observer.stop();
});
self.ready();
});
Any idea how to limit count of shown documents with transform in publish ?
Just use Posts.find({},{limit:count}) in your query.

Looking for a way or a plugin that save my marked text and could restore it after loose of focus

like i menthioned in the topic i'm looking for a plugin that save my marked text and could restore it after loose of focus. Like a JS Library called Rangy i used in the past. Is there such a plugin or does anyone has an idea how i could deal with this kind of problem?
Regardings Adrian
function gEBI(id) {
return document.getElementById(id);
}
var savedSel;
var savedSelActiveElement;
function saveSelection() {
if (savedSel) {
// rangy.removeMarkers(savedSel);
}
savedSel = rangy.saveSelection();
savedSelActiveElement = document.activeElement;
}
function restoreSelection() {
if (savedSel) {
rangy.restoreSelection(savedSel, true);
window.setTimeout(function() {
if (savedSelActiveElement && typeof savedSelActiveElement.focus != "undefined") {
savedSelActiveElement.focus();
}
}, 1);
}
}
$(document).ready(function()
{
try {
document.execCommand("MultipleSelection", null, true);
} catch(ex) {}
rangy.init();
// Enable buttons
var saveRestoreModule = rangy.modules.SaveRestore;
if (rangy.supported && saveRestoreModule && saveRestoreModule.supported) {
var saveButton = gEBI("saveButton");
//saveButton.disabled = false;
saveButton.ontouchstart = saveButton.onmousedown = function() {
saveSelection();
return false;
};
$('.EditorTab').mousedown(function(){
saveSelection();
return false;
});
});
The following solution would allow you to store and restore any number of ranges, but it assumes that you have not destroyed the nodes that the ranges are attached to when it comes time to restore those ranges.
var SelectionStore = (function() {
var savedRanges = {};
return {
store: function(saveIdentifier) {
var ranges = rangy.getSelection().getAllRanges();
savedRanges[saveIdentifier] = ranges;
return ranges;
},
restore: function(saveIdentifier) {
var i, selection;
selection = rangy.getSelection();
if (!savedRanges[saveIdentifier]) throw new Error('Invalid saved selection identifier used. Selection not found for ID: ' + saveIdentifier);
selection.removeAllRanges();
for (i in savedRanges[saveIdentifier]) selection.addRange(savedRanges[saveIdentifier][i]);
}
}
})();
Usage examples:
//store the current selection
SelectionStore.store('Tab1');
//restore a selection
SelectionStore.restore('Tab1');

Resources