How to insert data in ground.db in meteor when offline - javascript

i have a fully working meteor application but now i want to make it offline so I installed ground:db and appcache here is my package file:
...
ground:db
appcache
ground:localstorage
then I changed my Collections to this:
Gebiete = new Mongo.Collection('gebiete');
Straßen = new Mongo.Collection('straßen');
Nummern = new Mongo.Collection('nummern');
Ground.Collection(Gebiete);
Ground.Collection(Straßen);
Ground.Collection(Nummern);
and now when the app is online i can insert data and then i disconnect the app and relaunch (cordova) and no data is lost.
But when im offline and i want to insert sth. it doesnt work ;(. I thaught i dont have to change my methods file but here is one method just to make sure if it is right:
Meteor.methods({
neuesGebiet(Besitzer, Gebietsname, Gebietsnummer, Ort, Erstellungsdatum) {
Gebiete.insert({
Besitzer: Besitzer,
Gebietsname: Gebietsname,
Gebietsnummer: Gebietsnummer,
Ort: Ort,
Erstellungsdatum: Erstellungsdatum
});
}
});
and on the client the message is called like this:
import { Meteor } from 'meteor/meteor'
Template.neuesGebietErstellen.onCreated(function () {
this.subscribe('gebiete');
});
Template.neuesGebietErstellen.events({
"submit .add-Gebiet": function (event) {
var Gebietsname = event.target.Gebietsname.value;
var Gebietsnummer = event.target.Gebietsnummer.value;
var Ort = event.target.Ort.value;
var Besitzer = Meteor.userId();
var Erstellungsdatum = new Date();
var Datum = Erstellungsdatum.toLocaleDateString();
Meteor.call('neuesGebiet', Besitzer, Gebietsname, Gebietsnummer, Ort, Datum)
FlowRouter.go('/');
return false;
}
});
Please help me to get the data inserted when offline because i want it to be 100% offline
Thank you ;)

It's been a while since I used Ground:db but here's what I think you are missing...
First, you probably only want grounded collections on Cordova, so
if(Meteor.isCordova) {
Ground.Collection(Gebiete);
Ground.Collection(Straßen);
Ground.Collection(Nummern);
}
Then you need to use Groundmethods to store your method calls. So after the definition of the method:
Meteor.methods({
'neuesGebiet': function(...) {
...
}
});
if( Meteor.isClient ) {
Ground.methodResume([
'neuesGebiet'
]);
}

Related

Firebase Auth State Persistence vanilla JS

I'm not sure I'm even attempting the right thing. Heres my issue.
I'm loading data to a screen if the user is authenticated. Its a summary screen. I can click a item and it will send me to a new "details" page (window.location) . I'm passing the ID in the URL and then doing a GET request to get the details to display. When I implement my rules on the firebase DB, (".read": "auth != null"), I get a "401 Unauthorized" error in the console.
So somehow I need to either pass the user to the details.js or set Persistence somehow. Anyone have any suggestions?
THIS IS THE CODE FROM THE MAIN.JS
auth.onAuthStateChanged(user => {
console.log(user);
if (user) {
database.on('value', function(data) {
myData = data.val()
keys = Object.keys(myData)
buildProperties();
})
// tempBuild()
} else {
$('.eachProperty').empty()
$('.eachProperty').append($(`<h1>You must be signed in to view properties</h1>`))
}
})
$('body').on('click', '.singleProp', function() {
id = $(this).attr('id')
window.location = "/details.html?id=" + id
})
THIS IS THE CODE FROM THE DETAILS.JS
var myLocation = location.search.slice(4)
$.get(`https://XXXXXX.firebaseio.com/property/${myLocation}/.json`).then(myProperty)
function myProperty(prop) {
$('.propAddress').text(prop.address)
$('.zip').text(prop.zip)
if(prop.pictures){
for (var i = 0; i < prop.pictures.length; i++) {
var myImg = prop.pictures[i]
$('.imgContainer').append($(`<div class="eachPicDiv"><img src="${myImg}" alt="0" class="detailPic">
<ion-icon class="rBtn" name="arrow-redo-outline"></ion-icon>
</div`))
}
} else {
$('.imgContainer').append($(`<h1>THERE WERE NO PICTURES</h1>`))
}
}
You are using jQuery to fetch your data from Firebase Database,
$.get is a jQuery method, and for that to succeed you need to have some sort of auth token.
Firebase already provides best in class access, read more about access here.
Learn by example here.

Add contacts Windows 10 Universal

Is it possible to programmatically add contacts to the adress book/ people app in Windows 10 like it is possible in Android?
I have a server on which contact information is stored, and I would like to make an app to synchronise my contacts with Windows 10.
I tried several things, but it didn't really work out. This is how far I've come:
Successfully download the contact data.
put the contact data in a Contact object.
This is what I've tried:
contacts.ContactManager.requestStoreAsync().done(function (contactStore) {
contactStore.createContactListAsync("name").done(function (contactList) {
for (i = 0; i < data.length; i++) {
var contact = new contacts.Contact;
//populate Contact item
contactList.saveContactAsync(contact);
}
contactList.saveAsync;
});
});
But I'm getting an acces denied error.
Any help would be appreciated. Thanks in advance!
Firstly, ensure you have added the contacts capability in app manifest.
<Capabilities>
<Capability Name="internetClient" />
<uap:Capability Name="contacts"/>
</Capabilities>
You will also get the access denied error if you had not request the read/write permission to the contact store.
ContactStoreAccessType enumeration
In this case, you can request the “appContactsReadWrite” permission.
But as I tested, there will be some API issues when calling the createContactListAsync method.
The current workaround is adding windows Runtime Component wrapper:
public sealed class ContactManagerWrapper
{
public IAsyncAction AddContactAsync(string userName, string email)
{
return AsyncInfo.Run(async (token) =>
{
var store = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AppContactsReadWrite);
var contactLists = await store.FindContactListsAsync();
var contactList = contactLists.FirstOrDefault();
var contact = new Contact();
contact.Name = userName;
contact.Emails.Add(new ContactEmail() { Address = email, Kind = ContactEmailKind.Personal });
await contactList.SaveContactAsync(contact);
});
}
}
WinJS Project:
document.getElementById('click_me').addEventListener("click", function () {
var mgr = new UWPRuntimeComponent.ContactManagerWrapper();
mgr.addContactAsync('Jeffrey', 'jeffrey.chen#example.com').done(function () {
console.log("add contact successfully");
});
});
Try this
contacts.ContactManager.requestStoreAsync(ContactStoreAccessType.AppContactsReadWrite);
instead of this
contacts.ContactManager.requestStoreAsync()
you open the default store and I think its not accessible by developer.

Meteor pass data from client to server

I have a registration form, and when the user clicks the submit button the value in every textbox will be sent to server to insert that data, and return true/false.
Client:
Template.cust_register.events({
'click button': function(){
var email = $('#tbxCustEmail').val();
var msg = $('#tbxCustMsg').val();
var isSuccess = insertMsg(email,msg);
if(isSuccess){
alert("Success");
}else alert("Try again");
}
});
Server:
function insertMsg(email,msg){
Messages.insert({Email:email,Message:msg});
return true;
}
This turned out to not work.
How to solve this?
Many people said "use publish/subscribe", but I don't understand how to use that.
First, watch the introductory screencast and read the Data and security section of the docs.
Your code in a publish/subscribe model would look like this:
Common:
Messages = new Meteor.Collection('messages');
Client:
Meteor.subscribe("messages");
Template.cust_register.events({
'click button': function(){
var email = $('#tbxCustEmail').val();
var msg = $('#tbxCustMsg').val();
Messages.insert({Email:email,Message:msg});
}
});
Server:
Meteor.publish("messages", function() {
return Messages.find();
});
An alternative solution is to use Meteor.call('yourMethodName') (on the client).
Then, on the server, you can have
Meteor.methods({
yourMethodName: function() { /* validate input + return some data */ }
});
You can consider setting a session variable to the return value.
Meteor.call('yourMethodName', function (err, data) {
if (!err) {
Session.set('myData', data);
}
});
And then in some some template...
Template.whatever.helpers({
messages: function() {
return Session.get('myData');
}
});
Why do all this?
1) You can explicitly deny all direct `insert/update/find` queries from the client, and force usage of pre-defined Meteor methods.
2) You can manually determine when certain data is "refreshed".
Obviously, this methodology undermines the value of the subscription/publication model, and it should only be used in cases where real-time data isn't required.

Is there a very simple way to update a page in Perl Dancer using jQuery/AJAX?

I have the following code in my main Dancer app .pm:
package Deadlands;
use Dancer ':syntax';
use Dice;
our $VERSION = '0.1';
get '/' => sub {
my ($dieQty, $dieType, $bonus);
my $button = param('button');
$dieQty = param('dieQty');
$dieType = param('dieType');
$bonus = param('bonus');
if (defined $dieQty && defined $dieType) {
return Dice::Dice->new(dieType => $dieType, dieQty => $dieQty, bonus => $bonus)->getStandardResult();
}
template 'index';
};
true;
Here is my JavaScript:
$(document).ready(function() {
$('#standardRoll').click(function() {
$.get("/lib/Deadlands.pm", { button: '1', dieType: $("#dieType").val(), dieQty: $("#dieQty").val(), bonus: $("#bonus").val() }, processData);
function processData(data) {
$("#result").html(data);
}
});
});
I have a div in my web page called result that I want to be updated with the die roll result from Perl. Dancer keeps coming back with a 404 error in the command window when I push the submit button.
/lib/Deadlands.pm needs to be the URL of your route (probably / in this case), not the filesystem path of your Perl module.
Your AJAX request needs to point to a URL that actually exists, not a filename that has nothing to do with the web. Looks like $.get('/', ...) would do in this case.

Is it possible to ping a server from Javascript?

I'm making a web app that requires that I check to see if remote servers are online or not. When I run it from the command line, my page load goes up to a full 60s (for 8 entries, it will scale linearly with more).
I decided to go the route of pinging on the user's end. This way, I can load the page and just have them wait for the "server is online" data while browsing my content.
If anyone has the answer to the above question, or if they know a solution to keep my page loads fast, I'd definitely appreciate it.
I have found someone that accomplishes this with a very clever usage of the native Image object.
From their source, this is the main function (it has dependences on other parts of the source but you get the idea).
function Pinger_ping(ip, callback) {
if(!this.inUse) {
this.inUse = true;
this.callback = callback
this.ip = ip;
var _that = this;
this.img = new Image();
this.img.onload = function() {_that.good();};
this.img.onerror = function() {_that.good();};
this.start = new Date().getTime();
this.img.src = "http://" + ip;
this.timer = setTimeout(function() { _that.bad();}, 1500);
}
}
This works on all types of servers that I've tested (web servers, ftp servers, and game servers). It also works with ports. If anyone encounters a use case that fails, please post in the comments and I will update my answer.
Update: Previous link has been removed. If anyone finds or implements the above, please comment and I'll add it into the answer.
Update 2: #trante was nice enough to provide a jsFiddle.
http://jsfiddle.net/GSSCD/203/
Update 3: #Jonathon created a GitHub repo with the implementation.
https://github.com/jdfreder/pingjs
Update 4: It looks as if this implementation is no longer reliable. People are also reporting that Chrome no longer supports it all, throwing a net::ERR_NAME_NOT_RESOLVED error. If someone can verify an alternate solution I will put that as the accepted answer.
Ping is ICMP, but if there is any open TCP port on the remote server it could be achieved like this:
function ping(host, port, pong) {
var started = new Date().getTime();
var http = new XMLHttpRequest();
http.open("GET", "http://" + host + ":" + port, /*async*/true);
http.onreadystatechange = function() {
if (http.readyState == 4) {
var ended = new Date().getTime();
var milliseconds = ended - started;
if (pong != null) {
pong(milliseconds);
}
}
};
try {
http.send(null);
} catch(exception) {
// this is expected
}
}
you can try this:
put ping.html on the server with or without any content, on the javascript do same as below:
<script>
function ping(){
$.ajax({
url: 'ping.html',
success: function(result){
alert('reply');
},
error: function(result){
alert('timeout/error');
}
});
}
</script>
You can't directly "ping" in javascript.
There may be a few other ways:
Ajax
Using a java applet with isReachable
Writing a serverside script which pings and using AJAX to communicate to your serversidescript
You might also be able to ping in flash (actionscript)
You can't do regular ping in browser Javascript, but you can find out if remote server is alive by for example loading an image from the remote server. If loading fails -> server down.
You can even calculate the loading time by using onload-event. Here's an example how to use onload event.
Pitching in with a websocket solution...
function ping(ip, isUp, isDown) {
var ws = new WebSocket("ws://" + ip);
ws.onerror = function(e){
isUp();
ws = null;
};
setTimeout(function() {
if(ws != null) {
ws.close();
ws = null;
isDown();
}
},2000);
}
Update: this solution does not work anymore on major browsers, since the onerror callback is executed even if the host is a non-existent IP address.
To keep your requests fast, cache the server side results of the ping and update the ping file or database every couple of minutes(or however accurate you want it to be). You can use cron to run a shell command with your 8 pings and write the output into a file, the webserver will include this file into your view.
The problem with standard pings is they're ICMP, which a lot of places don't let through for security and traffic reasons. That might explain the failure.
Ruby prior to 1.9 had a TCP-based ping.rb, which will run with Ruby 1.9+. All you have to do is copy it from the 1.8.7 installation to somewhere else. I just confirmed that it would run by pinging my home router.
There are many crazy answers here and especially about CORS -
You could do an http HEAD request (like GET but without payload).
See https://ochronus.com/http-head-request-good-uses/
It does NOT need a preflight check, the confusion is because of an old version of the specification, see
Why does a cross-origin HEAD request need a preflight check?
So you could use the answer above which is using the jQuery library (didn't say it) but with
type: 'HEAD'
--->
<script>
function ping(){
$.ajax({
url: 'ping.html',
type: 'HEAD',
success: function(result){
alert('reply');
},
error: function(result){
alert('timeout/error');
}
});
}
</script>
Off course you can also use vanilla js or dojo or whatever ...
If what you are trying to see is whether the server "exists", you can use the following:
function isValidURL(url) {
var encodedURL = encodeURIComponent(url);
var isValid = false;
$.ajax({
url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + encodedURL + "%22&format=json",
type: "get",
async: false,
dataType: "json",
success: function(data) {
isValid = data.query.results != null;
},
error: function(){
isValid = false;
}
});
return isValid;
}
This will return a true/false indication whether the server exists.
If you want response time, a slight modification will do:
function ping(url) {
var encodedURL = encodeURIComponent(url);
var startDate = new Date();
var endDate = null;
$.ajax({
url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + encodedURL + "%22&format=json",
type: "get",
async: false,
dataType: "json",
success: function(data) {
if (data.query.results != null) {
endDate = new Date();
} else {
endDate = null;
}
},
error: function(){
endDate = null;
}
});
if (endDate == null) {
throw "Not responsive...";
}
return endDate.getTime() - startDate.getTime();
}
The usage is then trivial:
var isValid = isValidURL("http://example.com");
alert(isValid ? "Valid URL!!!" : "Damn...");
Or:
var responseInMillis = ping("example.com");
alert(responseInMillis);
const ping = (url, timeout = 6000) => {
return new Promise((resolve, reject) => {
const urlRule = new RegExp('(https?|ftp|file)://[-A-Za-z0-9+&##/%?=~_|!:,.;]+[-A-Za-z0-9+&##/%=~_|]');
if (!urlRule.test(url)) reject('invalid url');
try {
fetch(url)
.then(() => resolve(true))
.catch(() => resolve(false));
setTimeout(() => {
resolve(false);
}, timeout);
} catch (e) {
reject(e);
}
});
};
use like this:
ping('https://stackoverflow.com/')
.then(res=>console.log(res))
.catch(e=>console.log(e))
I don't know what version of Ruby you're running, but have you tried implementing ping for ruby instead of javascript? http://raa.ruby-lang.org/project/net-ping/
let webSite = 'https://google.com/'
https.get(webSite, function (res) {
// If you get here, you have a response.
// If you want, you can check the status code here to verify that it's `200` or some other `2xx`.
console.log(webSite + ' ' + res.statusCode)
}).on('error', function(e) {
// Here, an error occurred. Check `e` for the error.
console.log(e.code)
});;
if you run this with node it would console log 200 as long as google is not down.
You can run the DOS ping.exe command from javaScript using the folowing:
function ping(ip)
{
var input = "";
var WshShell = new ActiveXObject("WScript.Shell");
var oExec = WshShell.Exec("c:/windows/system32/ping.exe " + ip);
while (!oExec.StdOut.AtEndOfStream)
{
input += oExec.StdOut.ReadLine() + "<br />";
}
return input;
}
Is this what was asked for, or am i missing something?
just replace
file_get_contents
with
$ip = $_SERVER['xxx.xxx.xxx.xxx'];
exec("ping -n 4 $ip 2>&1", $output, $retval);
if ($retval != 0) {
echo "no!";
}
else{
echo "yes!";
}
It might be a lot easier than all that. If you want your page to load then check on the availability or content of some foreign page to trigger other web page activity, you could do it using only javascript and php like this.
yourpage.php
<?php
if (isset($_GET['urlget'])){
if ($_GET['urlget']!=''){
$foreignpage= file_get_contents('http://www.foreignpage.html');
// you could also use curl for more fancy internet queries or if http wrappers aren't active in your php.ini
// parse $foreignpage for data that indicates your page should proceed
echo $foreignpage; // or a portion of it as you parsed
exit(); // this is very important otherwise you'll get the contents of your own page returned back to you on each call
}
}
?>
<html>
mypage html content
...
<script>
var stopmelater= setInterval("getforeignurl('?urlget=doesntmatter')", 2000);
function getforeignurl(url){
var handle= browserspec();
handle.open('GET', url, false);
handle.send();
var returnedPageContents= handle.responseText;
// parse page contents for what your looking and trigger javascript events accordingly.
// use handle.open('GET', url, true) to allow javascript to continue executing. must provide a callback function to accept the page contents with handle.onreadystatechange()
}
function browserspec(){
if (window.XMLHttpRequest){
return new XMLHttpRequest();
}else{
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
</script>
That should do it.
The triggered javascript should include clearInterval(stopmelater)
Let me know if that works for you
Jerry
You could try using PHP in your web page...something like this:
<html><body>
<form method="post" name="pingform" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<h1>Host to ping:</h1>
<input type="text" name="tgt_host" value='<?php echo $_POST['tgt_host']; ?>'><br>
<input type="submit" name="submit" value="Submit" >
</form></body>
</html>
<?php
$tgt_host = $_POST['tgt_host'];
$output = shell_exec('ping -c 10 '. $tgt_host.');
echo "<html><body style=\"background-color:#0080c0\">
<script type=\"text/javascript\" language=\"javascript\">alert(\"Ping Results: " . $output . ".\");</script>
</body></html>";
?>
This is not tested so it may have typos etc...but I am confident it would work. Could be improved too...

Categories

Resources