Let's say I'm writing an extension that needs to use a few collections, let it be list/array of strings. localStorage only allows to save data as a string so my current options are:
fetch string on a tab
process it into collection
work with it
save
this has to be done EVERY TIME for each tab/instance and EVERY operation because I cant be sure in the collection integrity sine other tab may have written something else into that localStorage item (that means I also have to implement locking mechanism and respect it).
What I want is some kind of way of having shared/global collections ("variable") I can initialize on extension load (either browser start or first matching by url tab that activates extension code) that I can re-use. This way locking is somewhat more sensible and overall usage makes sense. I assume I can save/write it on browser exit.
I tried to google but could not find any relevant info about that. If my question does not make much sense than may be someone can redirect to some write up how to handle data in such cases for browser extensions?
Related
Are there any patterns for cases when something (in my case it's a filters) is stored on client (e.g. localStorage) and you need to run a script once per user/version to migrate data you store. For example, initially there is a filter saved in localStorage with a key myFilter after some time you decide that you need to separate filters per environment, so you need separate dev-myFilter, train-myFilter, etc. You update your code to work with environment-dependant filters, but there are users who have old myFilter and you want with next deployed version to run script which will update the key of saved filter if there is one.
Question is - what are patterns/best practices for that?
I don't know about "best practices", but the obvious technical solution, just like with any API or storage format, is to store a version number alongside the data. If you didn't do so from the start, assume version == 1 when absent.
You may be able to avoid this if the data structure is so unique between versions that the version can be determined simply by examining it.
Either way, you simply perform the translation whenever you spot that the user's data is in the old format.
The downside of this is that you have to keep checking; for a web application this is unlikely to be a bottleneck, but if you can make your data forward-compatible from the outset then you may save a bit of processing time on each request. But for the data to be useful you've got to read it anyway, so a little branching for as long as you wish to maintain backward-compatibility is, again, unlikely to be a big problem.
I have a restartless firefox extension in which I have an array which is used for some decision making. The elements of this array can change overtime.
Currently I have my bootstrap.js file which calls various functions present in another .js files. And within one of these functions is this array.
I am trying to figure out how can I restructure my code in such a way that I can update this array (not entire extension) after installation.
What I have thought of is; to pull this array out into a separate .js file and plan to swap this when I make the array 'update' after installation.
However, I still don't understand how to do it. The way I understand is, I bundle my add-on as an .xpi it gets installed and then is it possible to do a partial upgrade?
I don't want to push another .xpi for this. And I assume that will also make the user aware that the extension has updated. Since, the array updates can be frequent this can look really weird for the user updates happening every week or so.
Can I do this over an API that will fetch the updated array and swap it in the code ( Do .push to existing array ) ? Basically, I want this to be invisible to the user and lightweight as well.
How can I do it in a better/correct way? If I am asking for something not presently possible let me know.
Anything that you include in xpi, will be updated when there is a new install of that xpi.
As you mentioned that the updates would be frequent, you could possibly fetch the array from a remote end-point. This could be a json file or rest call whatever you think is more suitable. To improve performace, you can fetch array from remote end-point, store it in user profile directory and only fetch it again based on some expiry period (e.g. every week or fortnight).
Be aware in that case, if your extension needs to be distributed through AMO, the review process may require some additional steps e.g. including a privacy policy, barring use of eval on array contents.
I'm interested how does google docs store documents on server side because I need to create similar application.
Does it use pure RTF/ODF files or own database?
How do they make possible versioning and undo/redo feature?
If anybody have knowing according this question please share with me.
To answer you question specifically to how Google Docs works. They use a technology called
Operational Transformation
You may be able to use one of operational transformation engines listed on: https://en.wikipedia.org/wiki/Operational_transform#OT_software
The basic idea is that every operation has a context, e.g. "delete the fourth word in the fifth paragraph" or "add an input box after the button". The clients all send each other operations thru the server. The clients and server each keep their own version of the document and apply operations as they come.
When operations have overlapping contexts, there are a bunch of rules that kick in to resolve conflicts. Like you can't modify something that's been deleted, so the delete must come last in a sequence of concurrent operations on that context.
It's possible that the various clients and server will get out of sync, so you need a secondary algorithm to maintain consistency. One way would be to reload the data from the server whenever a conflict is detected.
--This is an answer I got from a professor when I asked the same thing a couple of years ago.
You should use a database. Perhaps a table storing each document revision. First, find a way to determine whether an update is significant or not. You can store minor changes client side for redo/undo, and then, either periodically or per some condition (e.g., user hits save), create a database entry per revision (you can store things like bytes changed, bytes added, bytes deleted, etc.).
Take a look at MediaWiki, which is open source, and essentially does what you're asking (i.e., take a look at their tables and code).
RTF/ODF would typically be generated, and served, when a user requests exporting the document.
Possibly, you should consider utilizing Google Drive's public API. See link for details.
I have a lobby written in HTML5 / javascript. A .json file provides a few config parameters for the lobby and for the various other HTML5 games that can be launched from it. These parameters can either be passed to the games in the window.open string ( in the form of:
window.open(http://www.myLovelyDomain.com/index.html?username=bob&token=aaaXXX")
or could be held in localStorage and accessed by the game following it's launch.
My question is, what is the best (most secure/likely to cause least errors/etc) method? I know users can turn off localStorage, but I don't know how many do. Any thoughts?
Advantages of localStorage over URL query strings
Less likely to be user edited
Less likely to be copy&pasted to someone else
Can persist across sessions
Wider choice of characters
(Marginally) less bandwidth usage (shorter GETs)
Can store whole files
Invisible to basic user
Disadvantages
Server doesn't get access to the variables without additional ajax
May be harder to debug
May need extra checks if things change every session (or consider sessionStorage)
Not supported by old browsers
Can't use cross-domain directly (may be advantage, depending on how you look at it)
For supported list and max sizes see here.
I'm integrating an external application to SharePoint 2010 by developing custom ribbon tabs, groups, controls and commands that are made available to editors of a SharePoint 2010 site. The ribbon commands use the dialog framework to open dialogs with custom application pages.
In order to pass a number of query string parameters to the custom applications pages, I'm therefore looking for the equivalent of SPContext.Current.ListItem in the Client Object Model (ECMAScript).
Regarding available tokens (i.e. {ListItemId} or {SelectedItemId}) that can be used in the declarative XML, I already emitting all tokens, but unfortunately the desired tokens are not either not parsed or simply null, while in the context of a Publishing Page (i.e. http://domain/pages/page.aspx). Thus, none of the tokes that do render, are of use to establishing the context of the calling SPListItem in the application page.
Looking at the SP.ClientContext.get_current() provides a lot of information about the current SPSite, SPWeb etc. but nothing about the current SPListItem I'm currently positioned at (again, having the page rendered in the context of a Publishing Page).
What I've come up with so far is the idea of passing in the url of the current page (i.e. document.location.href) and parse that in the application page - however, it feels like I'm going in the wrong direction, and SharePoint surely should be able to provide this information.
I'm not sure this is a great answer, or even fully on-topic, but is basically something I originally intended to blog about - anyway:
It is indeed a pain that the Client OM does not seem to provide a method/property with details of the current SPListItem. However, I'd venture to say that this is a simple concept, but actually has quite wide-ranging implications in SharePoint which aren't apparent until you stop to think about it.
Consider:
Although a redirect exists, a discussion post can be surfaced on 2 or 3 different URLs (e.g. Threaded.aspx/Flat.aspx)
Similarly, a blog post can exist on a couple (Post.aspx/EditPost.aspx, maybe one other)
A list item obviously has DispForm.aspx/EditForm.aspx and (sort of) NewForm.aspx
Also for even for items with an associated SPFile (e.g. document, publishing page), consider that these URLs represent the same item:
http://mydomain/sites/someSite/someLib/Forms/DispForm.aspx?ID=x, http://mydomain/sites/someSite/someLib/Filename.aspx
Also, there could be other content types outside of this set which have a similar deal
In our case, we wanted to 'hang' data off internal and external items (e.g. likes, comments). We thought "well everything in SharePoint has a URL, so that could be a sensible way to identify an item". Big mistake, and I'm still kicking myself for falling into it. It's almost like we need some kind of 'normalizeUrl' method in the API if we wanted to use URLs in this way.
Did you ever notice the PageUrlNormalization class in Microsoft.SharePoint.Utilities? Sounds promising doesn't it? Unfortunately that appears to do something which isn't what I describe above - it doesn't work across the variations of content types etc (but does deal with extended web apps, HTTP/HTTPS etc).
To cut a long story short, we decided the best approach was to make the server emit details which allowed us to identify the current SPListItem when passed back to the server (e.g. in an AJAX request). We hide the 'canonical' list item ID in a JavaScript variable or hidden input field (whatever really), and these are evaluated when back at the server to re-obtain the list item. Not as efficient as obtaining everything from context, but for us it's OK because we only need to resolve when the user clicks something, not on every page load. By canonical, I mean:
SiteID|WebID|ListID|ListItemID
IIRC, one of the key objects has a CanonicalId property (or maybe it's internal), which may help you build such a string.
So in terms of using the window.location.href, I'd avoid that if you're in vaguely the same situation as us. Suggest considering an approach similar to the one we used, but do remember that there are some locations (e.g. certain forms) where even on the server SPContext.Current.ListItem is null, despite the fact that SPContext.Current.Web (and possibly SPContext.Current.List) are populated.
In summary - IDs are your friend, URLs are not.