I am building an app with Meteor and I am looking to create a first time user launch screen- something like an "About/Welcome" page. Essentially, something that would pull a one-time screen after launching the app for the first time and never appear again; if the user has already opened the app they would be directed to another page.
I am not using login credentials, so I need a different solution than checking to see if the user is logged in or not.
How would I go about configuring this? I have tried searching all over the web and can't seem to find a solution for this. Please note this is different from a "Launch Screen".
You will need to either use localstorage, or set a cookie.
I'd suggest trying localstorage first. There are several packages on atmosphere that should help,
Using the frozeman:storage package (meteorpad example):
Template.body.helpers({
beenHereBefore: function() {
var beenHereBefore = LocalStore.get('BeenHereBefore', {reactive: false});
console.log(LocalStore.get('BeenHereBefore', {reactive: false}));
if (beenHereBefore !== true){
LocalStore.set('BeenHereBefore', true, {reactive: false})
console.log(LocalStore.get('BeenHereBefore', {reactive: false}));
}
return beenHereBefore;
},
});
<body>
{{#unless beenHereBefore}}
<h1> Welcome first time visitor! </h1>
{{else}}
<div class="outer">
<div class="logo"></div>
<h1 class="title">Leaderboard</h1>
<div class="subtitle">Select a scientist to give them points</div>
{{> leaderboard}}
</div>
{{/unless}}
</body>
Just some simple JavaScript should do the trick:
if (Boolean(localStorage.getItem('visitedApp'))) {
// user's been here before
} else {
// do stuff for first time user
localStorage.setItem('visitedApp', true);
}
Related
I am developing mobile app with ionic framework.it has a side menu with following links
1.Home
1.Login
2.About
3.Settings
When user is logged in i want to change the login in side menu to myprofile link
In the login controller
.controller('LoginCtrl',function($scope,$http,$ionicPopup,$state){
$scope.login=function(user){
//http call for login api
//set the auth token
window.localStorage.setItem('usertoken',response.token);
$state.go('app.profile');
}
}})
In Menu controller
.controller('MenuCtrl', function($scope, $ionicModal, $timeout) {
//shows the login link when the user is not logged in othewise show profile.
if(window.localStorage.getItem('usertoken')==null){
$scope.showloginlink=true;
$scope.showprofilelink=false;
}else{
$scope.showloginlink=false;
$scope.showprofilelink=true;
}
});
Here is htmll
<ion-list >
<ion-item menu-close href="#/app/login" ng-show="showloginlink">
Login
</ion-item>
<ion-item menu-close href="#/app/profile" ng-show="showprofilelink">
Profile
</ion-item>
The problem it dosen't show the profile link after login,but when i refresh the entire page it will works as i expected
How to solve this problem?
UPDATE
I have solved the problem via reload the state
$state.go('app.profile',null,{reload: true});
But i wil get another error,side menu is missing from my user_profilepage
I've added this enable-menu-with-back-views="true" in menu.html ,but still i have the menu missing problem:(
Note:I am using ionic tabs template
Try wrapping your assignment with $apply, like this:
$scope.$apply(function() {
if(window.localStorage.getItem('usertoken')==null){
$scope.showloginlink=true;
$scope.showprofilelink=false;
}else{
$scope.showloginlink=false;
$scope.showprofilelink=true;
}
});
If you get an error to say a digest is already running, swap out $scope.$apply with $timeout, which is a service you'll need to inject. That will defer the update until the next digest if you don't specify a specific delay.
So first inject it into your controller by adding it as a parameter:
.controller('LoginCtrl',function($scope,$http,$ionicPopup,$state, $timeout){
Then, replace $scope.$apply from the previous listing:
$timeout(function() {
if(window.localStorage.getItem('usertoken')==null){
$scope.showloginlink=true;
$scope.showprofilelink=false;
}else{
$scope.showloginlink=false;
$scope.showprofilelink=true;
}
});
I was working through the Ionic tutorial for using the Cordova Camera API.
http://learn.ionicframework.com/formulas/cordova-camera/
Far as I can tell everything is working correctly with the Camera API functions, but I cannot get my image to display back into the view.
I am able to return a file URI, but when I attempt to put it to the ng-src I get nothing in the view. I am assuming that the application/code cannot access the file location?
My config:
.config(function($stateProvider, $urlRouterProvider, $compileProvider) {
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|blob|content):|data:image\//);
...
The function in my controller:
$scope.getPhoto = function() {
Camera.getPicture().then(function(imageURI) {
console.log(imageURI);
$scope.cameraPic = imageURI;
}, function(err) {
$scope.cameraPic = "error";
console.err(err);
});
};
My view:
<ion-view>
<ion-content>
<div class="form-group padding-top">
<button class='button button-positive' data-ng-click="getPhoto()">
Take Photo
</button>
</div>
<div class="item item-image">
<img ng-src="{{cameraPic}}"/>
</div>
{{cameraPic}}
</ion-content>
</ion-view>
This appears to be the recommended method by the tutorial, and is also repeated on this thread. It sounds like it should work without using a Cordova file service implementation. I have found one such implementation which I guess I could use, but am I missing something here?
EDIT
Using chrome://inspect/#devices, I was able to look into the Webview/Console. I also rebuilt the project, just to see if that would help.
Definitely looking like a local file access issue.
As it turns out, this is an issue unique to using the emulator. I finally found the following on the ngCordova project:
NOTE: The camera API only works on a real device, and not in the
emulator.
Source: http://ngcordova.com/docs/plugins/camera/
This led me to test the code on an actual device using the USB debugger, where the file is accessed by the application and shared with the view as expected. This should be noted as a quirk of the library.
I can't get all of these to work together. I have phonegap/JQM running with fastclick.js perfectly on iOS. It's a dream. But for some reason I still get a 300ms delay on android. I put some alerts in and the code is being called. It's baffling really. I am testing on a motorola droid razor maxx.
In my index.html file:
<!DOCTYPE html>
<html>
<head>
...
<script type='application/javascript' src='js/fastclick.js'></script>
</head>
<script>
$(document).on("pagebeforechange", function (e, data) {
FastClick.attach(document.body);
alert('fastclick attached');
var to_page = data.toPage[0].id;
// skip showing #myPage if condition is true
if (to_page == "index") {
$.mobile.pageContainer.pagecontainer('change', 'event-list.html');
e.preventDefault();
}
});
</script>
<body>
<div id="index" data-role="page">
This is the index page.
</div>
</body>
</html>
But it doesn't seem to work. I've also tried attaching it like:
window.addEventListener('load', function() {
new FastClick(document.body);
}, false);
Which both work on iOS but don't seem to have any effect on android. Any suggestions?
edit: It seems if I remove the JQuery libraries it works fine. There has got to be a conflict somewhere. Any idea what it may be? I am using JQM 1.4.
edit: I have also tried using vclick to no avail
$("#test-element").bind('vclick',function() {
$.mobile.pageContainer.pagecontainer('change', 'description.html?lunch_pk=2133',{
transition: "slide",
});
});
...
<h1 id='test-element'> CLICK HERE FOR TEST </h1>
I am also using gestures to change pages which are also being delayed by 300ms, so I don't think that even if vclick was working that it would be a complete solution.
edit: ok, so after some further testing, I am pretty sure the delay is coming from inside JQM pagechange functions. I did a console.log inside the vclick and I the log is pretty responsive when hitting the button. I am trying to dig through JQM but not being very successful, I mean why would it be seemless on iOS and not work on android? And maybe I just need to find a better mobile library.
Answer
I was never able to solve this problem. My solution was to switch libraries. I went to Intel's mobile app framework which was able to do everything I was doing with JQM only more successfully.
You can try vclick without trying onclicks. These built-in jQuery Mobile vclick omits the 300ms delay. I do this by doing this.
$("#element").bind('vclick',function(event) {
yourFunction(this.id);
event.preventDefault();// this prevents the default click event
});
Have you tried opening jQueryMobile library file? There are some functions like:
setTimeout(function() {
$link.removeClass( $.mobile.activeBtnClass );
}, 300 );
I am sure, that searching this file for "delay" or "timeout" and changing it would give a good result. Line above is from
.mobile.popup.handleLink = function( $link ) {
...
}
Try registering FastClick inside the deviceready event handler:
document.addEventListener('deviceready', function() {
FastClick.attach(document.body);
}, false);
Have you tryed to juse the tap event?
$("#test-element").off('tap').on('tap', function(event) {...do your stuff});
Note that .bind is deprecated - better use on / off
Note that depending upon, where you're attaching your eventhandler the eventhandler might get bound multiple times on pagechange and revisit.
You best bind your tap-event-handler in ther pageinit event in order to make sure, that you attaching to the event only once and not every time, you revisit a certain page.
In case you're attaching on pageshow use the "off" first (see above)
I had the same problem with some menu buttons. My solution works for all platforms without a helper library, however, I wish there was a better way like setting a JQM variable:
$('#button').unbind('touchstart click').bind('touchstart click', function(event) {
$('#button').addClass('ui-btn-active');
//doSomethingHere();
setTimeout(function() {
$('#button').removeClass('ui-btn-active');
}, 300); //this 300ms is just the delay for styling the button
event.preventDefault(); //if touchstart is supported, do not let the event propagate to the click handler. Having this here avoids a double trigger.
});
The key is binding to touchstart which triggers immediately.
NOTE- I have this code within a pageshow handler which is why I unbind and then bind it. Otherwise, you'd end up with the same event bound multiple times as the user navigates to and from this page.
There are durations associated with the page transition animations in JQM. Here is some of the CSS for the default 'fade' transition (from jquery.mobile.structure.css v1.4.2):
.fade.out {
opacity: 0;
-webkit-animation-duration: 125ms;
-webkit-animation-name: fadeout;
-moz-animation-duration: 125ms;
-moz-animation-name: fadeout;
animation-duration: 125ms;
animation-name: fadeout;
}
.fade.in {
opacity: 1;
-webkit-animation-duration: 225ms;
-webkit-animation-name: fadein;
-moz-animation-duration: 225ms;
-moz-animation-name: fadein;
animation-duration: 225ms;
animation-name: fadein;
}
JQM changes classes on the to and from pages when transitions start and complete, so in the case of the 'fade' transition, the page being changed to will become the active page 225ms after the from page has completed fading out (125ms) i.e. after 350ms.
You could try disabling the transition by specifying {transition: 'none'} in your call to $.mobile.pageContainer.pagecontainer('change' or by setting $.mobile.defaultPageTransition = "none"; in your mobileinit event handler to rule it as the cause of the delay.
I've always disabled page transitions in my Phonegap JQM apps because of the poor performance and flickering (Android), but I still have responsiveness issues, especially on Android. I think it is down to how the webview prioritises rendering the DOM. I've found that a strategically positioned setTimeout can make page changes seem more responsive by allowing the webview to postpone my application logic until after it has rendered the DOM.
I've got a button.
<button type="button" id="mybutton" class="btn btn-success">Send</button>
And 'click' function in my client/client.js
Template.index.events({
'click #mybutton' : function () {
// template data, if any, is available in 'this'
Meteor.call('voteMe', some parameters, function(error,result){
if (error){
console.log(error);
}
else{
console.log(result);
}
});
$(".testing").css({'display':'none'});
$(".voted").css({'display':'block'});
},
//Here some other functions
And it works, but on android 4.1.2 browser it doesn't call 'voteMe' function, hovewer these lines works
$(".testing").css({'display':'none'});
$(".voted").css({'display':'block'});
Thanks.
Sorry - not enough reputation yet to comment so posting an answer:
This may be the same problem as I posted here:
FIXED - Meteor app wrapped in cordova does not see same published data as browser on same device or simulator
I have provided an answer there that may help you.
I'm writing an app with Phonegap and I have a register form that is sent through ajax. It works fine when you hit the register button and execute the formcheck() function. However, when I hit the GO button from my android phone it submits the form instead of going through the formcheck() process. I tried:
<form id="RegForm" onsubmit="formcheck();return false;">
My form has no proper submit button but a button like this:
<input type="button" id="submitbtn" onclick="formcheck()"/>
I also tried to create a new OnSubmitForm() function that calls the formcheck() one but with no avail. Thank you for helping.
Found it!
1) Add this to the JS section:
$(document).ready(function() {
$("#YourFormName").submit(function() {
FormCheck();
return false;
});
});
function FormCheck() {
... validation process here ...
}
2) Make sure to include a Submit button in your form .. ( <input type="submit" )
Hope it'll help others so my 5 hour trying & testing time won't go wasted :)
Simply ensure your form tag is:
<form type='submit' onsubmit='return false;'></form>
This makes the submit action not do anything.
If you also need to hide the keyboard refer to How can I hide the Android keyboard using JavaScript?. A simple onsubmit='hideKeyboard(); return false;' will take care of this.