I have a flow of few pages/views starting from first page to last page. This is pretty much based on the Ionic tutorial.
I update a factory "Info" with some data as I proceed with the flow. In the final page, after displaying the "summary info" to the user, I use $state.go('firstPage') to navigate back to the first page.
When I make a different selection in the first page this time, it doesn't seem to take effect in the view.
I tried the suggestion from here but that didn't help me. I tried resetting the variables again, but that doesn't help either.
angular.module('my.services', [])
.factory("Info", function(){
// All user data
var infoData = {
type: "",
level: 0
};
var originalInfoData = angular.copy(infoData);
// Reset data
infoData.resetUserDetails = function() {
userData = angular.copy(originalInfoData);
};
Final Page Controller
$scope.finish = function() {
UseInfo.resetUserDetails();
$state.go('firstPage');
}
This takes me back to first page but even though I select something different this time, the pages seem to remember what I did in my first run.
The question is - how do I clear things up so the user can do something else after getting back to the first page without remembering previous selections.
Related
I have two contact 7 forms on my page (section 3 and 10), only the top one will follow the javascript function. If I add another form to the top of the page, the new top one works and the other one stops working. It doesn't seem to matter if I make a new function for each form or not.
Page is http://www.sportshosts.com/new-home/
If it works, the pop up on the following page will have registered your details - it currently only does it for the first. Don't forget to clear in Javascript console before testing next one with localStorage.clear();
I have this in the additional settings of the top form:on_sent_ok: "js_viralloopsinfo();"
and this in the second: on_sent_ok: "js_bottomviralloopform();"
This is the javascript
function js_viralloopsinfo() {
VL.extraData = {}
VL.options.form_fields.form_firstName = jQuery("#firstname").val();
VL.options.form_fields.form_email = jQuery("#email").val();
VL.createLead(function() {
//any logic to run after the participation
});
}
function js_bottomviralloopform() {
VL.extraData = {}
VL.options.form_fields.form_firstName = jQuery("#firstname").val();
VL.options.form_fields.form_email = jQuery("#email").val();
VL.createLead(function() {
//any logic to run after the participation
});
}
Even if I add a form that works on another page to the top, the new top one will work and the previous top one no longer works.
I am trying to implement a navigation to my ajax controlled site, and I am encountering some strange errors.
I am using History JS, the HTML5 only version.
This is how I initialize it:
function initializeHistory() {
var History = window.History;
if ( !History.enabled ) {
console.log("Not enabled!");
return false;
}
// Changing the main page state to -1.
History.replaceState({id:-1}, baseTitle, baseUrl);
// Bind to StateChange Event
History.Adapter.bind(window,'statechange',function(){
var State = History.getState();
console.log(History.savedStates);
if (historyData.manualStateChange)
{
if (State.data.id=='-1') alert('History start');
historyData.allowHistoryPushPop=false;
var gotoState=historyData.data[State.data.id];
var currentState=historyData.currentNavigation;
/* Some code here to revert to the previous state */
historyData.allowHistoryPushPop=true;
}
History.log(State.data, State.title, State.url);
});
};
I am using a global object, named historyData, in which I store the following things:
var historyData={
data: new Array(), //an array which contains objects that refer to the data that needs to be shown, when back or forward button is pushed
manualStateChange: true, //using this to figure out if the back or forward button was pressed in the browser, or if I am adding or removing a state from History programmatically
allowHistoryPushPop: true, //using this to prevent history from being changed in certain situations
currentNavigation: {
page: 'dashboard',
pageid: null,
module: null,
moduleid: null
}, // stores the current object from the historyData.data array
status: true // boolean that enables or disables History on my page
}
Whenever I click on a link in my page, a function, called navigation fires, which changes the History's state, and eventually runs a chain of functions to display the page which was asked for by the user. The relevant parts from the navigation function are as follows:
function navigation(gotofunc, navData) {
if ((historyData.allowHistoryPushPop) && (historyData.status))
{
if (navData['urlData']==null) // if this is null, then the title and the url for the asked page, will be returned by the server, after an ajax call, so we set it to the current url and current title
{
var curState=History.getState();
urlData={
title: curState.title,
url: curState.url
};
} else {
urlData=navData['urlData'];
if (!urlData['title']) urlData['title']=curState.title;
if (!urlData['url']) urlData['url']=curState.url;
}
navData['parameters']=new Array();
if (arguments.length>2) for (i=2;i<arguments.length ;i++) navData['parameters'].push(arguments[i]);
historyData.manualStateChange=false; // we are making a programmatic change, so we don't want the binded 'statechange' to fire
historyData.data.push(navData); // store the history data in our own array
History.pushState({id:historyData.data.length-1}, urlData['title'], urlData['url']); // push the History state, and set it's id to point to our newly added array element
historyData.manualStateChange=true; // re-enable the manual state change
}
}
If I don't know up front what the URL will be after I fetch the data via ajax, my Ajax call, replaces the current state with the correct data, this way:
if ((dataArray['navDat']) && (historyData.status))
{
historyData.manualStateChange=false;
var State = History.getState();
History.replaceState(State.data, dataArray['navDat']['title'], dataArray['navDat']['url']);
historyData.manualStateChange=true;
}
This works fine for the most part. If I navigate forward a few pages, and then go backwards, everything works greatly, if I then go forward once again(all by using the browsers back and forward button), it works greatly. There is only one exception: if I load the page, load a subpage, then try to click on the back button, this line never fires:
if (State.data.id=='-1') alert('History start');
It basicaly won't figure out that I arrived back at the front page, when I only navigate one page forward.
The other strange thing is the following(perhaps this is what's causing my original problem also): I tried fetching the savedStates of the History object, to see what is going on, and strangely, when I use the replaceState event, it adds a new state in savedStates. One of the objects that is added, is with the correct data id, the other one is with the previous data id.
What could be causing the problem, is there an error in my script somewhere? Or is this completly normal? (the part of adding multiple objects to History.savedStates after replaceState)
Thanks for the help in advance!
If I replace the url, or the title of the page with the first replaceState, the program realizes when I return to the front page, I dunno why, but till then this is the best solution I can figure.
I was asked to develop a tab panel with 6 tabs, each having 30 to 40 elements. Each tab is acting as a form in accumulating the details of a person and the last tab is a Summary page which displays all the values entered in the first five tabs. I was asked to provide summary as a tab because, the user can navigate to summary tab at any instance and look at the details entered by him/ or glace the summary. i am following ExtJs MVC pattern. Payload is coming from / going to Spring MVC Application. (JSON)
Using tab change event in controller and if the newtab is summary I am rendering the page with show hide functionality.
Method 1 :In controller I have used Ext.getCmp('id of each element inside the tabs') and show hide the components in summary tab based on the value entered by the user. This killed my app in IE8 popping a message saying that the "script is slow and blah blah..." i had to click on NO for 5 to 6 times for the summary tab to render and display the page.
Method 2 :In controller I used ref and selectos to acccess all the items in tabs. I have used itemId for each and every field in summary tab. like this.getXyz().show(). I thought it would be fast. Yes it was in Google chrome. but my app in IE8 is slow compared to goolge chrome/firefox
Any suggestions regarding this and plan to decrease page render time. The summary page has more than 1000 fields. Please feel free to shed ur thoughts or throw some ideas on this.
thank you!!
I've got a few suggestions you can try. First, to answer your title, I think the fastest simple way to lookup components in javascript is to build a hash map. Something like this:
var map = {};
Ext.each(targetComponents, function(item) {
map[item.itemId] = item;
});
// Fastest way to retrieve a component
var myField = map[componentId];
For the rendering time, be sure that the layout/DOM is not updated each time you call hide or show on a child component. Use suspendLayouts to do that:
summaryTabCt.suspendLayouts();
// intensive hide-and-seek business
// just one layout calculation and subsequent DOM manipulation
summaryTabCt.resumeLayouts(true);
Finally, if despite your best efforts you can't cut on the processing time, do damage control. That is, avoid freezing the UI the whole time, and having the browser telling the user your app is dead.
You can use setTimeout to limit the time your script will be holding the execution thread at once. The interval will let the browser some time to process UI events, and prevent it from thinking your script is lost into an infinite loop.
Here's an example:
var itemsToProcess = [...],
// The smaller the chunks, the more the UI will be responsive,
// but the whole processing will take longer...
chunkSize = 50,
i = 0,
slice;
function next() {
slice = itemsToProcess.slice(i, i+chunkSize);
i += chunkSize;
if (slice.length) {
Ext.each(slice, function(item) {
// costly business with item
});
// defer processing to give time
setTimeout(next, 50);
} else {
// post-processing
}
}
// pre-processing (eg. disabling the form submit button)
next(); // start the loop
up().down().action....did the magic. I have replaced each and every usage of Ext.getCmp('id'). Booooha... it's fast and NO issues.
this.up('tabpanel').down('tabName #itemIdOfField').actions.
actions= hide(), show(), setValues().
Try to check deferredRender is true. This should only render the active tab.
You also can try a different hideMode. Especially hideMode:'offsets ' sounds promising
Quote from the sencha API:
hideMode: 'offsets' is often the solution to layout issues in IE specifically when hiding/showing things
As I wrote in the comment, go through this performance guide: http://docs.sencha.com/extjs/4.2.2/#!/guide/performance
In your case, this will be very interesting for you:
{
Ext.suspendLayouts();
// batch of updates
// show() / hide() elements
Ext.resumeLayouts(true);
}
I've been trying to solve a pretty irritating for the last couple of days now, and I'm finally admitting defeat, and appealing to SO.
First I'll give an overview of what I'm trying to do, then I'll give you specifics of where I'm running into issues.
The Goal:
A user is filling out a form, and if any element is changed on the form and the user tries to leave the form without saving the changes, a modal should display with the following message:
You have made changes to this record. Do you want to save the changes?
The user gets a Yes/No/Cancel option.
If the user selects:
Yes: The record should save, then navigate to the originally intended route.
No: The record should not save, and the user should be navigated to the intended route.
Cancel: The modal should close and the user will remain on the current page with no route change.
I am using the backbone.routefilter library to detect route changes before the route change happens.
The Problem:
To solve the problem, I put a route change listener within my initialize method in the view that contains the form. Below is that code:
// If the user tries go to a different section but the record has been changed, confirm the user action
app.circulationRouter.before = function( route, params ) {
app.fn.clearNotifications();
if(app.recordChanged){
var confirmView = new app.views.confirm({
header:"Patron Record Changed",
bodyText:"You have made changes to this record. Do you want to save the changes?",
trueLabel:"Yes",
falseLabel:"No",
cancelLabel:"Cancel",
hasTrue:true,
hasFalse:true,
hasCancel:true,
trueCallback:function(){
// Ignore the patron record change
_this.saveRecord();
// Render the patron section AFTER the save
_this.model.on({
'saved' : function(){
// Render the new seciton
app.circulationRouter.renderPatronSection(_this.model, params[1]);
app.currentPatronSection = params[1];
// Set the record changed to false
app.recordChanged = false;
// Remove the 'before' listener from the circulationRouter
app.circulationRouter.before = function(){};
if(con)console.log('in saved');
// Remove the listener
_this.model.off('saved');
},
'notsaved' : function(){
// Stay on the patron record page, keep the url at record
app.circulationRouter.navigate("patrons/"+_this.model.get('PatronID')+"/record",false);
_this.model.off('notsaved');
}
}, _this);
},
falseCallback:function(){
if(con)console.log(params);
if(params.length){
// Ignore the patron record change
app.circulationRouter.renderPatronSection(_this.model, params[1]);
app.currentPatronSection = params[1];
}else{
if(con)console.log('blah');
setTimeout(function(){
if(con)console.log('should navigate');
app.circulationRouter.navigate("", true);
}, 5000);
}
app.recordChanged = false;
app.circulationRouter.before = function(){};
},
cancelCallback:function(){
// Stay on the patron record page, keep the url at record
app.circulationRouter.navigate("patrons/"+_this.model.get('PatronID')+"/record",false);
}
});
app.el.append(confirmView.render().el);
return false;
}
};
Each of the three options has a callback that gets called within the initialize function that will control the outcome. The Cancel button always behaves correctly. The issue I'm running into is when the user wants to navigate to the home page, ie when this line is called: app.circulationRouter.navigate("", true);. Everything else works correctly if there is a new, defined route to navigate to.
Here is the sequence of events that creates the issue:
1) Modify a record
2) Try to navigate to the home page
3) Route is changed home page route, but record is still in view
4) Modal is automatically displayed with three options
5) Select the No button
6) falseCallback is triggered
7) Modal is closed and view remains on record page, but route displayed in browser is for home page
The expected behavior for #7 was to display the view for home page, but only the url reflects that.
You can see in the falseCallback I even tried delaying the trigger for the redirection to make sure it wasn't a DOM issue, but that didn't work.
Does anyone know what may be happening?
Here's the problem. Once the route is changed, if you re-navigate to the same route, even if you set the param {trigger:true}, the page won't reload. There is a long discussion about it here.
Based off of the discussion listed in github, I am using this solution and adding the refresh option. If the refresh option is set to true, then the view will reload, even if the url doesn't change. Otherwise, the functionality remains the same.
_.extend(Backbone.History.prototype, {
refresh: function() {
this.loadUrl(this.fragment);
}
});
var routeStripper = /^[#\/]/;
var origNavigate = Backbone.History.prototype.navigate;
Backbone.History.prototype.navigate = function (fragment, options) {
var frag = (fragment || '').replace(routeStripper, '');
if (this.fragment == frag && options.refresh)
this.refresh();
else
origNavigate.call(this, fragment, options);
};
We have a intermittent bug that it's been hard to track, the bug consists in randomly (so we think) when redeeming a code, the entire code value disappears upon making the order...
Doing our self the same process manually, it does not, never ever, happen!
So I thought recording the user actions, every action:
click links
submit inputs
page views
ended up making up this set of rules, and appending to the end of the master page:
$(function() {
// log this page view
log2Loggly('Page View', '');
// for each click
$("a").click(function() {
var ref = $(this).attr("onclick").length > 0 ? $(this).attr("onclick") : $(this).attr("href");
log2Loggly('Link clicked', ref);
});
// forms
$("form").submit(function() {
var dt = $(this).serialize();
log2Loggly('Form submited', dt);
});
});
and using Loggly I can send each action, as they get the hold of the date and IP, it's easier to match a user IP upon our system.
I keep seeing this services like CrazyEgg that record all user actions, but we can't match the user, it's anonymous data!
What I really liked was to search for IP and get the entire user tree as kind'a of an organigram of what the user did... maybe I'm able to pull this off with the data I have, but I would like to ask 2 things prior to adventure on this idea
Is there any kind of service for this outthere that you might come across before?
what more should I track to make it "almost perfect"?