Switching views within a Marionette region - javascript

I have a region in my Marionette project called the "primary" region for which I show a loading view and then a download view once the loading (decrypting) is finished. Here's what I have it doing right now:
var loadingView = new fileView.Loading();
appManager.regions.primary.show(loadingView);
//Promise waiting for file to decrypt before
//switching views
decryptFile(file).then(function (decryptedFile) {
var downloadView = new fileView.Download({
model: decryptedFile
});
appManager.regions.primary.show(downloadView);
})
As of now, when the decrypt function is finished, my primary region goes blank instead of showing my downloadView. I've made sure downloadView exists and works fine by logging it to the console so that's not the problem. Any ideas why it isn't showing up?
Edit: Also, my downloadView does render just fine when I pull the code outside of the promise.

Found out what was going wrong! My model was invalid and was causing the view to not load. Unfortunately an error didn't show when this happened.

Related

How to write this window.history.go(-historyCount) correct

In a piece of code that I am writing, I need the user to go back in its history depending on the number of products there are in a shopping cart.
So I wrote this code:
var productCount = $('.rdsubs-cart-name').length;
var historyCount = productCount + 1;
console.log(historyCount);
$("a.btn-continue").click(function() {
window.history.go(-historyCount);
});
But as I expected this part is written wrong.
window.history.go(-historyCount);
I don't know the naming so it is really difficult for me to find something about it in Google. So I was hoping one of you could point me in the right direction!
Thanks!
Some More Info:
When there are 4 products in the cart and the user removes 1 product then it reloads the page. So when the user removes all 4 products it has also reloaded the page 4 times. So if the user clicks on continue shopping then it needs to go back into the history 5 pages. Otherwise, there would be an endless loop of reloading the shopping cart.
When I write window.history.go(-5); it works but when I write window.history.go(-historyCount); nothing happens.
The code was actually correctly written!
The culprit was my browser. After opening another browser and going to the same page everything worked as expected. I am thankful for everyone helping out!
I think one mistake that could be happening is that productCount has changed since the event has been defined, but since you're retrieving the value outside the event, you're not using the latest value and therefore are seeing an unexpected result.
Move the retrieval of productCount into the event function and see if that fixes whatever issue you're experiencing.
$("a.btn-continue").click(function() {
var productCount = $('.rdsubs-cart-name').length;
var historyCount = productCount + 1;
window.history.go(-historyCount);
});
The code was actually correctly written! The culprit was my browser. After opening another browser and going to the same page everything worked as expected. I am thankful for everyone helping out!

ORACLE APEX PL/SQL Process not responding when called with AJAX during onbeforepageunload

I'm using Oracle APEX 4.2. I built a PLSQL process that is set to execute "On Demand - When this process is called by AJAX". This process is designed to update two member attributes in a collection that I created when the page loaded. Its code follows:
DECLARE
v_seq_id NUMBER;
BEGIN
--get sequence id
SELECT seq_id into v_seq_id FROM apex_collections
WHERE collection_name = 'THE_COLLECTION' and c001 = :APP_SESSION;
--I've tried uncommenting this script to see if this works, too
--htp.script('alert(''PLSQL Process works'');');
--update first member attribute
apex_collection.update_member_attribute(
p_collection_name =>'THE_COLLECTION',
p_seq => v_seq_id,
p_attr_number => 2,
p_attr_value => 0);
--update second member attribute
apex_collection.update_member_attribute(
p_collection_name =>'THE_COLLECTION',
p_seq => v_seq_id,
p_attr_number => 3,
p_attr_value => sysdate);
END;
When I try calling this process with AJAX/javascript before the page unloads, nothing happens. I placed this code in the "Execute on Page Load" portion of my page:
window.onbeforeunload = function(){
//this alert box works, so I know the function is called
alert('Unloading...');
//call the PLSQL process
var get = new htmldb_Get(null,$v('pFlowId'), 'APPLICATION_PROCESS=THE_PROCESS',1234);
get.get();
//this also works, so I know the function completes
alert('end');
};
I test this two ways. First, I have some logic built into my page that depends on whether or not these member attributes were updated. When I reload the page, it behaves as if the PLSQL process never ran. Second, I have tried uncommenting the htp.script line in the PLSQL code above, but it will not execute either.
When I try running the following in my browser's F12 tools, the console prints "alert('test');" without actually displaying an error message:
var get = new htmldb_Get(null,$v('pFlowId'), 'APPLICATION_PROCESS=THE_PROCESS',1234);
get.get();
I've also tried running it with window.onload, but that doesn't seem to work either.
When I run the PLSQL process as an "After Header" process, the htp.script code launches an alert box successfully, and the process seems to work.
Does anyone know how to get this to work with AJAX? Am I missing something obvious?
It looks like the problem was in the PLSQL process, after all. Following the suggestion from Tom's comment, I looked at wwv_flow.show in the network tab of my browser's development tools. When I viewed the "Response body" tab under "detailed view", I found that the process was returning the results of the htp.script command; it just wasn't generating the alert box itself.
After a bit of troubleshooting, I figured out that the following code in my PLSQL process was not working:
--update first member attribute
apex_collection.update_member_attribute(
p_collection_name =>'THE_COLLECTION',
p_seq => v_seq_id,
p_attr_number => 2,
p_attr_value => 0);
I changed it to :
UPDATE apex_collections SET n001 = 0 WHERE c001 = :APP_SESSION and collection_name = 'THE_COLLECTION';
In order to make this work, I had to execute a command to grant the update permission to my database user:
GRANT UPDATE ON apex_collections TO USER

Deleting a view and onclick opening it again, as if it is new - SAPUI5

I have a multiple View setup, a main View and then modules who are opened on button click after certain actions.
Right now the view is reset by me whenever its opened, but what I want to accomplish is, when the view is left, that its gone from the core and its initiated again as if it is opened for the first time.
I am not certain how, and I tried multiple things, none worked as I intended (.destroy(), .removeAllContent(), ... ).
Did I miss a function or is there a way to accomplish that?
Some code:
index.js (how the View is instantiated the first time, its not called a second time)
module.exports.Partner = function(place) {
View = require('./app/js/suche.view');
Bearbeiten = require('./app/js/bearbeiten.view');
var ctrl = View.getController();
ctrl.setPlace(ctrl, place);
ctrl.setEditPlace(ctrl, place);
ctrl.setCreatePlace(ctrl, place);
sap.ui.getCore().byId('suche').placeAt(place);
sap.ui.getCore().byId('suche').byId('searchBtn').attachPress(ctrl.nummerSearch, ctrl);
};
controller (how the View and the index.js is called)
handlePartnerSuche : function(){
this.hideView(); //this is the main view
var p = require('bit-js-business-partner');
var partner_view = p.Partner('content');
p.setCallbackForSchliessen(this, this.callbackForSchliessen);
},
controller (callback function)
callbackForSchliessen: function(){
this.showView();
},
The second View (how its closed)
handleSchliessen : function () {
var p = this.getView('suche');
p.setVisible(false);
this.callbackMethodSchliessen.call(this.callbackCtrlSchliessen);
},
You mentioned you cannot use the Router mechanism due to company restrictions -- am really curious to know what these restriction are then ;-) -- and toggle the visibility properties of the respective views instead.
In that case, I would trigger the OData service in the method where you set the view's visibility to visible, and (re)bind the ODataModel to that view.
From a performance perspective, I would not advise to destroy views from the core

Is there a way to reinitialize/refresh/reload an actual JavaScript/jQuery method?

So, for a little backstory, I'm using the jRecorder plugin for jQuery on a page that is dynamically fed some HTML via ajax. The user can record a .wav narration for an image in a slideshow, then (via ajax) flip over to another image, record another narration, rinse and repeat. End backstory!
The question itself is geared more towards jQ/JS in general, I believe. When I run the 'record' function again, I get this error in the console:
Uncaught TypeError: Object # has no method 'jStartRecording'
This only appears when I switch to the second image and click "record". The first narration records just fine, and can be played back and whatnot with no issue. I'm thinking I'm receiving the error because I need to re-initialize or reload the jRecorder plugin/method/function since I am trying to call jRecorder again using a different set of options (after switching to another image in the slideshow). Since I'm calling it again, it would appear that something hasn't completely loaded, or there is some sort of conflict between each instance of the plugin's operation.
Bottom line: is there a way to reinitialize a jQuery plugin so it can be run again after dynamically switching parameters?
Perhaps I'm barking up the wrong tree entirely -- I don't know. Any insight from a different set of eyes would be greatly appreciated. Thanks so much!
EDIT: As requested, here's a little bit of code. And here is the plugin source. Hope it helps!
renderPanes() is called each time the widget containing the narration recorder is refreshed with a new image's data. Obviously some things have been edited out for brevity and security.
function renderPanes(type, bucket_id) {
var isRecording = false;
$.getJSON( [endpoint] )
.done(function(json){
[....]
$.jRecorder({
host : [endpoint],
callback_started_recording: function(){callback_started(); },
callback_stopped_recording: function(){callback_stopped(); },
callback_activityLevel: function(level){callback_activityLevel(level); },
callback_activityTime: function(time){callback_activityTime(time); },
callback_finished_sending: function(time){ callback_finished_sending() },
swf_path : '/assets/js/jrecorder/jRecorder.swf',
});
$("#narration_play").click(function(){
var audio = new Audio("[folder path]/"+bucket_id+".wav");
audio.play();
});
$("#narration_record").click(function(){
if (!isRecording) {
$.jRecorder.record(30);
$("#narration_record").html("<i class='icon-stop'></i> Stop");
isRecording = true;
} else {
isRecording = false;
$("#narration_record").html("<i class='icon-comment'></i> Record");
$("#narration_play").removeClass('disabled');
$.jRecorder.stop();
$.jRecorder.sendData();
}
});
});
}

backbone.js and local storage with multiple browser tabs / windows overwrites data

just a very short question on using Backbone.js with LocalStorage:
I'm storing a list of things (Backbone collection) in LocalStorage. When my website is open in multiple browser windows / tabs and the user in both windows adds something to the list, one window's changes will overwrite the changes made in the other window.
If you want to try for yourself, just use the example Backbone.js Todo app:
Open http://backbonejs.org/examples/todos/index.html in two browser tabs
Add an item 'item1' in the first tab and 'item2' in the second tab
Refresh both tabs: 'item1' will disappear and you'll be left with 'item2' only
Any suggestions how to prevent this from happening, any standard way to deal with this?
Thxx
The issue is well-known concurrency lost updates problem, see Lost update in Concurrency control?.
Just for your understanding I might propose the following quick and dirty fix, file backbone-localstorage.js, Store.prototype.save:
save: function() {
// reread data right before writing
var store = localStorage.getItem(this.name);
var data = (store && JSON.parse(store)) || {};
// we may choose what is overwritten with what here
_.extend(this.data, data);
localStorage.setItem(this.name, JSON.stringify(this.data));
}
For the latest Github version of Backbone localStorage, I think this should look like this:
save: function() {
var store = this.localStorage().getItem(this.name);
var records = (store && store.split(",")) || [];
var all = _.union(records, this.records);
this.localStorage().setItem(this.name, all.join(","));
}
You may want to use sessionStorage instead.
See http://en.wikipedia.org/wiki/Web_storage#Local_and_session_storage.
Yaroslav's comment about checking for changes before persisting new ones is one solution but my suggestion would be different. Remember that localStorage is capable of firing events when it performs actions that change the data it holds. Bind to those events and have each tab listen for those changes and view re-render after it happens.
Then, when I make deletions or additions in one tab and move over to the next, it will get an event and change to reflect what happened in the other tab. There won't be weird discrepancies in what I'm seeing tab to tab.
You will want to give some thought to making sure that I don't lose something I was in the middle of adding (say I start typing a new entry for my to-do list), switch to another tab and delete something, and then come back I want to see the entry disappear but my partially typed new item should still be available for me.

Categories