Get chrome tabs and windows from localStorage - json

I am trying to access tabs and windows data inside a Google Chrome extension. I've apparently managed to get this info and loading it through localStorage but I don't know how to use the information, since I can't seem to parse the data back to arrays of objects through JSON parse.
Here's the code:
<html>
<head>
<script>
tabs = {};
tabIds = [];
focusedWindowId = undefined;
currentWindowId = undefined;
localStorage.windowsTabsArray = undefined;
function loadItUp() {
return arrays = chrome.windows.getAll({ populate: true }, function(windowList) {
tabs = {};
tabIds = [];
var groupsarr = new Array();
var tabsarr = new Array();
var groupstabs = new Array();
for (var i = 0; i < windowList.length; i++) {
windowList[i].current = (windowList[i].id == currentWindowId);
windowList[i].focused = (windowList[i].id == focusedWindowId);
groupsarr[windowList[i].id] = "Untitled"+i;
for (var j = 0; j < windowList[i].tabs.length; j++) {
tabsarr[windowList[i].tabs[j].id] = windowList[i].tabs[j];
groupstabs[windowList[i].id] = windowList[i].tabs;
}
}
localStorage.groupsArray = JSON.stringify(groupsarr);
localStorage.tabsArray = JSON.stringify(tabsarr);
localStorage.groupsTabsArray = JSON.stringify(groupstabs);
});
}
function addGroup() {
var name = prompt("NEW_GROUP_NAME");
var groupsarr = JSON.parse(localStorage.groupsArray);
groupsarr.push(name);
localStorage.groupsArray = JSON.stringify(groupsarr);
}
</script>
</head>
<body onload="loadItUp()">
WINDOW_QTY:
<script type="text/javascript">
var wArray = JSON.parse(localStorage.groupsArray);
document.write(wArray);
</script>
<br/>
TABS_QTY:
<script type="text/javascript">
var tArray = JSON.parse(localStorage.tabsArray)
document.write(tArray);
</script>
<br/>
WINDOWS_TABS_QTY:
<script type="text/javascript">
document.write(JSON.parse(localStorage.groupsTabsArray));
</script>
<br/>
</body>
</html>

1)
The page shows bunch of [object Object].
That's expected, objects are implicitly converted to string when you call document.write(tArray);; custom object without a custom toString implementation are converted to "[object Object]". It doesn't mean they're not "parsed".
To inspect the object you can use the Developer Tools. You can open the inspector for a background page from the Extensions page and if you get your page to open in a tab (e.g. if you use chrome_url_overrides) you can inspect it as you would inspect a regular web page.
If you replace the document.write calls with console.log(), you'll be able to inspect the objects in the Developer Tools' console.
2)
Do you realize that the document.write calls in tags run before loadItUp()?
Had no idea that the page code was being executed before loadItUp().
Scripts are executed at the moment they are inserted in the DOM by the parser (unless they are deferred or async) - see MDC documentation on <script>, - while various load events, in particular <body onload=...>, are executed after the page is finished parsing.
So right now your document.write calls print the values that were saved to localStorage the previous time the page was loaded, it's probably not what you wanted.
Instead of using document.write() from inline scripts, you should use element.innerHTML or element.textContent to update the page's text. There are many ways to get a reference to the element you need, document.getElementById() is one.
3)
Last, note that not every object can be saved to and then loaded from localStorage. For example, methods will not survive the round-trip, and the identity of the object is not preserved, meaning that the object you got from a Chrome API will not be the same object after you store it in localStorage and load it back.
You have not explained why you think you need localStorage - it's used when you want to preserve some data after the page is closed and reloaded - so maybe you don't really need it?

Related

angularjs download file via POST on IE8/9 without page refresh

I'm trying to download a dynamically generated file from the server using a hidden form.
Below is the angular function that I'm using to submit the hidden form
$scope.downloadCsv = function() {
var dataset = JSON.stringify($scope.dataset);
var body = $('body');
var reportParamJson = angular.toJson($scope.dataset);
var hiddenForm = "<form action='/Reports/SaveTestCsv' method='POST' target='_blank'><input type='hidden' name='dataset' value='" + dataset + "'/ ><button id='submitCSV' type='submit'></button></form>";
body.append(hiddenForm);
$('#submitCSV').click();
}
Below is the .net mvc method to generate the response with the file
[HttpPost]
public ActionResult SaveTestCsv(string dataset)
{
var data = JsonConvert.DeserializeObject<MyObject>(dataset);
var binary = getTestCSV(data);
var file = File(binary, "text/csv", "test.csv");
return file;
}
Below is the relevant html code from the partial html page that I'm including in the view using ng-include
<div>Download CSV</div>
<div ng-grid="gridOptions"></div>
.
When I click on "Download CSV", Chrome, FF and IE10 prompts me to save the file without refreshing the page/view, but on IE8/9, the page is refreshed, so the content from the ng-include tag is gone, in particular the html I posted above is no longer present.
I'm wondering if this has something to do with the hashbang in the url from IE8/9 and is there any way to fix this?
Edit
I ended up removing routing from angular completely and just use .net MVC to do the routing for me, and then it's working on IE8

using history.js with IE9

In one of my applications i use window.history.pushState() method to update the window URL. But as IE < 10 does not support HTML5's history api, I was looking for an alternative. Answers to a lot of other questions on SO suggested to use history.js plugin.
From the documentation provided by the history.js plugin it's usage is not really clear. I have added the plugin to the <head></head> section in my templates but on IE9 i am still receiving the error that says:
SCRIPT438: Object doesn't support property or method 'pushState'
params.js, line 37 character 5
the function that errors out is as follows
/**
* updates the window url according to the given parameters.
*/
function updateUrl(params) {
var path = window.location.pathname;
var url = $.param.querystring(path, params);
url = decodeURIComponent(new_url).replace("#", "", "g");
window.history.pushState(null, null, new_url);
}
You need to initiatialize the History and State variables for it to work.
(function(window, undefined) {
// Define variables
var History = window.History,
State = History.getState();
// Bind statechange event
History.Adapter.bind(window, 'statechange', function() {
var State = History.getState();
});
})(window)
and now you can use pushState method for all browsers as follows:
History.pushState(null, null, '?your=hash')

HTML5 offline JSON doesn't work

I have a small HTML5 (using jQuery mobile) web app that caches its files to use them offline, however some parts don't seem to work once it's offline.
The files are cached OK (I can see them in the web inspector) but when I try to visit a page that uses jQuery to load a JSON file it doesn't load.
I tried creating an empty function to load the JSON files (when the index page is loaded) to see if that would help but it doesn't seem to make a difference.
Here's the function that doesn't want to work offline.
My question is: should it work offline or am I missing something?
// events page listing start
function listEvents(data){
$.getJSON('/files/events.json', {type: "json"},function (data) {
var output = '';
for (i in data)
{
var headline = data[i].headline;
var excerpt = data[i].rawtext;
output += '<div id="eventsList">';
output += '<h3>'+headline+'</h3>';
output += '<p>'+ excerpt +'<p>';
output += '</div>';
}
$("#eventsPageList").html(output).trigger("create");
});
}
I'm not really sure, if i'm right about this. But i think an ajax request will always fail when you are offline. It won't use the locally cached file. What you should try is, to cache the data in localStorage. When the ajax request fails, fallback to localStorage.
OK here's a version which seems to work, I read the json file and place it in localstorage then use the localstorage in the listEvents function.
When the page loads I call this function to add the json to localstorage
function cacheJson(data){
$.getJSON('/files/events.json',
{type: "json", cache: true},function (data) {
localStorage['events'] = JSON.stringify(data); });
}
Then this function to output the json (from localstorage) to the page, with an if else incase the localstorage doesn't contain the json.
function listEvents(data){
if (localStorage.getItem("events") === null) {
var output = '';
output += 'Sorry we have an error';
$("#eventsPageList").html(output).trigger("create");
}
else {
data = JSON.parse(localStorage['events']);
var output = '';
for (i in data)
{
var headline = data[i].headline;
var excerpt = data[i].rawtext;
output += '<div id="eventsList">';
output += '<h3>'+headline+'</h3>';
output += '<p>'+ excerpt +'<p>';
output += '</div>';
}
$("#eventsPageList").html(output).trigger("create");
}
}
It seems to work ok but am I missing something that could cause issues?
Is there a more efficient way of doing this?

HTML5/websockets/javascript based real-time logfile viewer?

Im looking for the equivalent of "tail -f" that runs in a browser using html5 or javascript.
A solution would need a client side code written in HTML5/websockets/javascript and a back-end server side application. Im looking for one in c# but i'm willing to rewrite it from php or python.
This is the only thing that i've seen that comes close is
http://commavee.com/2007/04/13/ajax-logfile-tailer-viewer/
However, modern browsers have WebSockets which makes the problem much simpler.
http://www.websocket.org/echo.html
Ideally, I would like to have some of the capabilities of BareTail
http://www.baremetalsoft.com/baretail/
Such as Color Coding of lines, sorting and multi-file tabbing.
I have located a similar posting where someone is looking for windows based log file programs
https://stackoverflow.com/questions/113121/best-tail-log-file-visualization-freeware-tool
Anyone have any suggestions?
It is not exactly like tail but the live logs feature of https://log4sure.com does allow you to monitor your client side logs realtime. You would have to setup and do the logs appropriately as you would do for tailing, but you can see all the logs with extra information about your client, example browser, os, country etc. You can also create your own custom logs to log stuff. Checkout the demo on the site to get a better idea.
The setup code is really easy, and the best part is, its free.
// set up
var _logServer;
(function() {
var ls = document.createElement('script');
ls.type = 'text/javascript';
ls.async = true;
ls.src = 'https://log4sure.com/ScriptsExt/log4sure-0.1.min.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ls, s);
ls.onload = function() {
// use your token here.
_logServer = new LogServer("use-your-token-here");
};
})();
// example for logging text
_logServer.logText("your log message goes here.")
// example for logging error
divide = function(numerator, divisor) {
try {
if (parseFloat(value) && parseFloat(divisor)) {
throw new TypeError("Invalid input", "myfile.js", 12, {
value: value,
divisor: divisor
});
} else {
if (divisor == 0) {
throw new RangeError("Divide by 0", "myfile.js", 15, {
value: value,
divisor: divisor
});
}
}
} catch (e) {
_logServer.logError(e.name, e.message, e.stack);
}
}
// another use of logError in window.onerror
// must be careful with window.onerror as you might be overwriting some one else's window.onerror functionality
// also someone else can overwrite window.onerror.
window.onerror = function(msg, url, line, column, err) {
// may want to check if url belongs to your javascript file
var data = {
url: url,
line: line,
column: column,
}
_logServer.logError(err.name, err.message, err.stack, data);
};
//example for custom logs
var foo = "some variable value";
var bar = "another variable value";
var flag = "false";
var temp = "yet another variable value";
_logServer.log(foo, bar, flag, temp);
While I wish it had better JSON object prettification for live tailing and historical logs, the following JS client works and supports your server-side requirement also:
https://github.com/logentries/le_js/wiki/API
<html lang="en">
<head>
<title>Your page</title>
<script src="/js/le.min.js"></script>
<script>
// Set up le.js
LE.init('YOUR-LOG-TOKEN');
</script>
</head>
.....
<script>
// log something
LE.log("Hello, logger!");
</script>
Personally to get the above code to work however, I've had to add the following line of code just above LE.init('YOUR-LOG-TOKEN'):
window.LEENDPOINT = 'js.logentries.com/v1'
.. Alternatively, Loggly may be a fit as well: https://www.loggly.com/docs/javascript/

Trouble Using LocalStorage to Store Cookie in Mobile Web App

Gurus of SO
I have posted a web app to the iOS Home Screen & want to not have to login each time the app opens up. So I am trying to push the cookie into LocalStorage.
I am using the following code to try to store my cookies in LocalStorage for a mobile web app (code copied from iphone web app ruby gem). But somehow its not working. Any suggestions?
Thank you.
<script type="text/javascript">
(function(){
var RESEND_REQUEST = {{RESEND}};
function isFullScreen(){
return navigator.userAgent.match(/WebKit.*Mobile/) &&
!navigator.userAgent.match(/Safari/);
}
if(isFullScreen()){
if(document.cookie == ''){
var storedValues = localStorage.getItem('__cookie__');
if(storedValues){
var values = storedValues.split(';');
for(var i=0; i < values.length; i++)
document.cookie = values[i];
}
document.cookie = '_cookieset_=1';
if(RESEND_REQUEST){
window.location.reload();
}
}
var lastCookie = null;
setInterval(function(){
if(lastCookie != ''+document.cookie){
lastCookie = ''+document.cookie;
localStorage.setItem('__cookie__', ''+document.cookie);
}
},1000);
}
})()
There are couple thing that does fit in the above code
1. if(document.cookie == '')
The above statement not always suppose return true even when you are opening your web_app from iOS Home Screen for the first time i.e the document.cookie does contain some value (junk though but still) even opening from Home screen(atleast what I found). I urge you to prompt the same with alert
Something like alert(document.cookie) before running into the above mentionif clause
If yes(document.cookie does contain some value) then I guess you need to fix the above if clause something like this
> if(!document.cookie.match(/_session_id/) ) {
> // Rest of the code goes here
> }
if your using ActiveRecord::Base.session_store
or
> if (!document.cookie.match(/{{YOUR SESSION KEY}}/) {
> // Rest of the code goes here
> }
your Session Key if using Cookie Store "the following key can be found my looking at the config/initializer/session_store.rb file
2. As notice the below code
localStorage.setItem('__cookie__', ''+document.cookie)
does make sense when reading though it but there is twist to it
one would except the document.cookie to contain cookie for the application maintained
and stored by the browser but as I notice that document.cookie does not turn out to be same
e.g browser stored the following cookie for my application
"__cookieset=1;KBD=0en-3;_session_id=896c455928f3dd9e7bb0b660efb7063c"
but when inspected the document.cookie I found it to be contain
"__cookieset=1;KBD=0en-3;"
Notice that document.cookie doesnot contain "_session_id=896c455928f3dd9e7bb0b660efb7063c"
Which is must as It used by various authorization gem(devise or authlogic) to determine whether the current user has a valid session ?
so I request you store the cookie from the request object obtain from Rack::Request.new(env)
into the localStorage
3. The middleware placement make sure your placing middleware at right place.
If your using ActiveRecord::Base.session_store I guess the patch code of the same gem can be found here solve your purpose