How to detect browser using angularjs? - angularjs

I am new to angularjs. How can I detect userAgent in angularjs. Is it possible to use that in controller? Tried something like below but no luck!
var browserVersion = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);
I need to detect IE9 specifically!

Like Eliran Malka asked, why do you need to check for IE 9?
Detecting browser make and version is generally a bad smell. This generally means that you there is a bigger problem with the code if you need JavaScript to detect specific versions of browser.
There are genuine cases where a feature won't work, like say WebSockets isn't supported in IE 8 or 9. This should be solved by checking for WebSocket support, and applying a polyfill if there is no native support.
This should be done with a library like Modernizr.
That being said, you can easily create service that would return the browser. There are valid cases where a feature exists in a browser but the implementation is outdated or broken. Modernizr is not appropriate for these cases.
app.service('browser', ['$window', function($window) {
return function() {
var userAgent = $window.navigator.userAgent;
var browsers = {chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer/i};
for(var key in browsers) {
if (browsers[key].test(userAgent)) {
return key;
}
};
return 'unknown';
}
}]);
Fixed typo broswers
Note: This is just an example of how to create a service in angular that will sniff the userAgent string. This is just a code example that is not expected to work in production and report all browsers in all situations.
UPDATE
It is probably best to use a third party library like https://github.com/ded/bowser or https://github.com/darcyclarke/Detect.js. These libs place an object on the window named bowser or detect respectively.
You can then expose this to the Angular IoC Container like this:
angular.module('yourModule').value('bowser', bowser);
Or
detectFactory.$inject = ['$window'];
function detectFactory($window) {
return detect.parse($window.navigator.userAgent);
}
angular.module('yourModule').factory('detect', detectFactory);
You would then inject one of these the usual way, and use the API provided by the lib. If you choose to use another lib that instead uses a constructor method, you would create a factory that instantiates it:
function someLibFactory() {
return new SomeLib();
}
angular.module('yourModule').factory('someLib', someLibFactory);
You would then inject this into your controllers and services the normal way.
If the library you are injecting does not exactly match your requirements, you may want to employ the Adapter Pattern where you create a class/constructor with the exact methods you need.
In this example we just need to test for IE 9, and we are going to use the bowser lib above.
BrowserAdapter.$inject = ['bowser']; // bring in lib
function BrowserAdapter(bowser) {
this.bowser = bowser;
}
BrowserAdapter.prototype.isIe9 = function() {
return this.bowser.msie && this.browser.version == 9;
}
angular.module('yourModule').service('browserAdapter', BrowserAdapter);
Now in a controller or service you can inject the browserAdapter and just do if (browserAdapter.isIe9) { // do something }
If later you wanted to use detect instead of bowser, the changes in your code would be isolated to the BrowserAdapter.
UPDATE
In reality these values never change. IF you load the page in IE 9 it will never become Chrome 44. So instead of registering the BrowserAdapter as a service, just put the result in a value or constant.
angular.module('app').value('isIe9', broswerAdapter.isIe9);

Angular library uses document.documentMode to identify IE . It holds major version number for IE, or NaN/undefined if User Agent is not IE.
/**
* documentMode is an IE-only property
* http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
*/
var msie = document.documentMode;
https://github.com/angular/angular.js/blob/v1.5.0/src/Angular.js#L167-L171
Example with $document (angular wrapper for window.document)
// var msie = document.documentMode;
var msie = $document[0].documentMode;
// if is IE (documentMode contains IE version)
if (msie) {
// IE logic here
if (msie === 9) {
// IE 9 logic here
}
}

you should use conditional comments
<!--[if IE 9]>
<script type="text/javascript">
window.isIE9 = true;
</script>
<![endif]-->
You can then check for $window.isIE9 in your controllers.

Not sure why you specify that it has to be within Angular. It's easily accomplished through JavaScript. Look at the navigator object.
Just open up your console and inspect navigator. It seems what you're specifically looking for is .userAgent or .appVersion.
I don't have IE9 installed, but you could try this following code
//Detect if IE 9
if(navigator.appVersion.indexOf("MSIE 9.")!=-1)

You can easily use the "ng-device-detector" module.
https://github.com/srfrnk/ng-device-detector
var app = angular.module('myapp', ["ng.deviceDetector"]);
app.controller('DeviceCtrl', ["$scope","deviceDetector",function($scope,deviceDetector) {
console.log("browser: ", deviceDetector.browser);
console.log("browser version: ", deviceDetector.browser_version);
console.log("device: ", deviceDetector.device);
}]);

So, you can declare more utilities for angular by create file with content (I follow RGraph Library)
(function(window, angular, undefined) {'use strict';
var agl = angular || {};
var ua = navigator.userAgent;
agl.ISFF = ua.indexOf('Firefox') != -1;
agl.ISOPERA = ua.indexOf('Opera') != -1;
agl.ISCHROME = ua.indexOf('Chrome') != -1;
agl.ISSAFARI = ua.indexOf('Safari') != -1 && !agl.ISCHROME;
agl.ISWEBKIT = ua.indexOf('WebKit') != -1;
agl.ISIE = ua.indexOf('Trident') > 0 || navigator.userAgent.indexOf('MSIE') > 0;
agl.ISIE6 = ua.indexOf('MSIE 6') > 0;
agl.ISIE7 = ua.indexOf('MSIE 7') > 0;
agl.ISIE8 = ua.indexOf('MSIE 8') > 0;
agl.ISIE9 = ua.indexOf('MSIE 9') > 0;
agl.ISIE10 = ua.indexOf('MSIE 10') > 0;
agl.ISOLD = agl.ISIE6 || agl.ISIE7 || agl.ISIE8; // MUST be here
agl.ISIE11UP = ua.indexOf('MSIE') == -1 && ua.indexOf('Trident') > 0;
agl.ISIE10UP = agl.ISIE10 || agl.ISIE11UP;
agl.ISIE9UP = agl.ISIE9 || agl.ISIE10UP;
})(window, window.angular);
after that, in your function use can use it like
function SampleController($scope){
$scope.click = function () {
if(angular.ISCHROME) {
alert("is chrome");
}
}

I modified the above technique which was close to what I wanted for angular and turned it into a service :-). I included ie9 because I was having some issues in my angularjs app, but could be something I'm doing, so feel free to take it out.
angular.module('myModule').service('browserDetectionService', function() {
return {
isCompatible: function () {
var browserInfo = navigator.userAgent;
var browserFlags = {};
browserFlags.ISFF = browserInfo.indexOf('Firefox') != -1;
browserFlags.ISOPERA = browserInfo.indexOf('Opera') != -1;
browserFlags.ISCHROME = browserInfo.indexOf('Chrome') != -1;
browserFlags.ISSAFARI = browserInfo.indexOf('Safari') != -1 && !browserFlags.ISCHROME;
browserFlags.ISWEBKIT = browserInfo.indexOf('WebKit') != -1;
browserFlags.ISIE = browserInfo.indexOf('Trident') > 0 || navigator.userAgent.indexOf('MSIE') > 0;
browserFlags.ISIE6 = browserInfo.indexOf('MSIE 6') > 0;
browserFlags.ISIE7 = browserInfo.indexOf('MSIE 7') > 0;
browserFlags.ISIE8 = browserInfo.indexOf('MSIE 8') > 0;
browserFlags.ISIE9 = browserInfo.indexOf('MSIE 9') > 0;
browserFlags.ISIE10 = browserInfo.indexOf('MSIE 10') > 0;
browserFlags.ISOLD = browserFlags.ISIE6 || browserFlags.ISIE7 || browserFlags.ISIE8 || browserFlags.ISIE9; // MUST be here
browserFlags.ISIE11UP = browserInfo.indexOf('MSIE') == -1 && browserInfo.indexOf('Trident') > 0;
browserFlags.ISIE10UP = browserFlags.ISIE10 || browserFlags.ISIE11UP;
browserFlags.ISIE9UP = browserFlags.ISIE9 || browserFlags.ISIE10UP;
return !browserFlags.ISOLD;
}
};
});

There is a library ng-device-detector which makes detecting entities like browser, os easy.
Here is tutorial that explains how to use this library. Detect OS, browser and device in AngularJS
ngDeviceDetector
You need to add re-tree.js and ng-device-detector.js scripts into your html
Inject "ng.deviceDetector" as dependency in your module.
Then inject "deviceDetector" service provided by the library into your controller or factory where ever you want the data.
"deviceDetector" contains all data regarding browser, os and device.

Why not use document.documentMode only available under IE:
var doc = $window.document;
if (!!doc.documentMode)
{
if (doc.documentMode === 10)
{
doc.documentElement.className += ' isIE isIE10';
}
else if (doc.documentMode === 11)
{
doc.documentElement.className += ' isIE isIE11';
}
// etc.
}

Browser sniffing should generally be avoided, feature detection is much better, but sometimes you have to do it. For instance in my case Windows 8 Tablets overlaps the browser window with a soft keyboard; Ridiculous I know, but sometimes you have to deal with reality.
So you would measure 'navigator.userAgent' as with regular JavaScript (Please don't sink into the habit of treating Angular as something distinct from JavaScript, use plain JavaScript if possible it will lead to less future refactoring).
However for testing you want to use injected objects rather than global ones. Since '$location' doesn't contain the userAgent the simple trick is to use '$window.location.userAgent'. You can now write tests that inject a $window stub with whatever userAgent you wan't to simulate.
I haven't used it for years, but Modernizr's a good source of code for checking features. https://github.com/Modernizr/Modernizr/issues/878#issuecomment-41448059

Detection ie9+
var userAgent, ieReg, ie;
userAgent = $window.navigator.userAgent;
ieReg = /msie|Trident.*rv[ :]*11\./gi;
ie = ieReg.test(userAgent);
if (ie) {
// js for ie9,10 and 11
}

Related

Loading a new window from local files and accessing it's contents

I am setting up a local webpage which shows videos in a HTML5 video tag. I just want to be able to do database search from a PHP request and show the results from which I can click on and show the video I want. The problem I have is that hte videos load WAY faster when loading from a "file:///" link than from the "http://" link. Server works flawlessly when in "HTTP" mode but nothing works in "file:///" mode which is normal as PHP codes only execute on the server side when requested to the server.
I have spent my full day trying soo much stuff. I changed my server to accept CORS, I tried window.open, storing the reference in a variable, local or global but I lose this as soon as I get out of my javascript function. I tried window.open in a function which is called from another function but no matter what I do, the window reference gets lost as soon as I leave the functions, or once the functions have finished. Since my browser is used as my main browser, I do not want to disable the security arround CORS but since my webpage's link comes from "file:///" requesting to "HTTP" on the same computer, CORS blocks me and wants an HTTP request which I can't give.
I have done all the searching for retrieving information from another webpage but I am always stuck with the "same domain" problem. I tried AJAX HTTPRequest, I just have no more solution for this simple problem which finished way more complicated than expected. The initial problem was just my videos not loading fast enough in HTTP mode (The speed difference is extreme, for 10 min videos, I can wait 5-10 seconds to skip through it while as in FILE:/// urls, It's almost instant, no waiting. longer videos of 1h, I can wait up to 20 and 30 seconds while as in file:/// mode, almost instant.) and I had to learn all that Allow cross domains stuff which ended up with no success either. I figure that maybe a few other heads may have better ideas than mine now.
#In my httpd.conf file from Apache
DocumentRoot "e:/mainwebfolder"
Alias "/lp" "d:/whatever"
//////////////////////////////////////
// index.php file that does not contain PHP contents
// window.location.href: file://d:/whatever/index.php
//////////////////////////////////////
<head>
<script src="html/servcom.js" type="text/javascript"></script>
</head>
<video id="vplayer" width="1280" height="720" controls></video>
<div id="search-form">
<input id="srch" name="srch" type="text">
<button class="bbut" onclick="ServInfo('search-results','http://127.0.0.1/lp/html/db.php','mode=s','search-form');">Search</button>
</div>
<div id='search-results'></div>
<script>
var dplay = document.getElementById("vplayer");
ShowVideo('MyVideo.mp4');
function ShowVideo (vidUrl) {
dplay = document.getElementById("vplayer");
dplay.src = vidUrl;
dplay.load;
}
</script>
//////////////////////////////////////
// Now this is in my javascript file servcom.js
//////////////////////////////////////
var win_ref = -1;
function ServInfo(pop_field_id,web_page,params="",form_id="",exec_string = "") {
var sparams = params;
var swpage = web_page;
var eobj = document.getElementById(pop_field_id);
var moreparams = "";
// If we entered extra parameters including form fields,
// add the the "&" before the form field list
if (sparams != "") {moreparams = "&";}
// Get form field values if a form id is specified
if (form_id != "") {
var efrm = document.getElementById(form_id);
sparams += moreparams+GetDivFields(form_id);
}
// Add the question mark if there is any parameters to pass
if (sparams != "") {
sparams = "?"+sparams;
// Add recieving objects reference
sparams += "&srco="+pop_field_id;
}
// If HTML element to populate does not exist, exit
if (typeof(eobj) == "!undefined" || eobj == null) {return;}
win_ref = window.open(swpage+sparams,"_blank");
//////////////////////////////////////
// right here win_ref will never be available once the code from this function has been finished executing although the variable is global. The problem starts here.
//////////////////////////////////////
// Execute a string if a user defined one
if (exec_string != "") {eval(exec_string);}
}
// Build a parameter string with div fields of type text, hidden or password
function GetDivFields(div_id) {
var ediv = document.getElementById(div_id);
var elem = ediv.children;
var retval = "";
var ssep = "";
for (var i = 0; i < elem.length; i++) {
if (elem[i].type == "text" || elem[i].type == "hidden" || elem[i].type == "password") {
retval += ssep+elem[i].name+"="+pURL(elem[i].value);
ssep = "&";
}
if (elem[i].type == "checkbox") {
if (elem[i].checked == true) {
retval += ssep+elem[i].name+"="+elem[i].value;
ssep = "&";
}
}
}
return retval;
}
//////////////////////////////////////
// And this is a brief overview of my db.php page
//////////////////////////////////////
<?php // Search Database code ?>
<div id="output"></div>
<script>
document.getElementById('output').innerHTML = "<?php echo $search_results; ?>";
// I actually want to retrieve the info from this div element once it has been populated from the initial page that called window.open for this page. BUT again. window.opener becomes empty once my initial window.open script finishes.
</script>
Access my newly loaded page's "output" div innerHTML OR loading videos through local HTTP as fast as "FILE:///".
Well, I fanally found a solution. Since this is for local and presentation use only, I could bypass some securities. Basically, doing what we would normally NOT do in a website but all this WITHOUT modifying your webserver config or touching any .htaccess file. Basically, no security restrictions, just a plain old hack that poses no security breaches for your browser or your server.
To be noted:
2 different websites exist (so 2 different folders at very different locations), 1 for developpement and serious releases, one for internal and/or presentation purposes.
Every file is local abd inside the presentation folder.
No PHP code can be ran from a "file:///" link.
Access to the mysql database is done through PHP and server is on Apach24
Reading video locally from a "file:///" link are WAY faster than from an "http://" link
Searching needs to be done in MySQL database frm a "http://" link and results need to be displayed on a webpage opened from a "file:///" link.
No changes must be made in the Browser's configuration so disabling CORS is not a solution.
Bypassing cors with methods proposed by many site won't work because of security reasons or because CORS bypass does not accept "file:///" links
PHP can write files on the server which is where I decided to bypass CORS. Since XML requests through AJAX can be done on the same origin domain an thus, purely in javascript. If a file exists which contains no PHP code AND resides on the same domaine i/e "file:///", the contents can the be read wothout any problems.
So I simply do the following in my db.php file:
$s_mode = "";
$s_text = "";
$sres = "";
if (isset($_REQUEST["srch"])) {$s_text=$_REQUEST["srch"];}
if (isset($_REQUEST["mode"])) {$s_mode=$_REQUEST["mode"];}
if ($s_mode == "s") {
$sres = SearchDB($s_text);
WriteFile("D:/whatever/my_path/dbres.html",$sres);
}
// Writes the contents of the search in a specified file
function WriteFile($faddress,$fcontents) {
$ifile = fopen($faddress,"w");
fwrite($ifile,$fcontents);
fclose($ifile);
}
Now using a normal AJAX request, I do 2 things. I opted to use an iframe with a "display:none" style to not bother seeing another tab openup.
Do the actual request which opens the "cross-doamin" link in the iframe WHICH executes my db.php code. I basically open "http://127.0.0.1/whatever/db.php?param1=data&parma2=data" inside my iframe.
Once my search is done and I have the results, my db.php will save an html file with the results as it's contents in my "file:///" direct location's path so: "D:/whatever/my_path/dbres.html".
I added a new function in my servcom.js. So my new file's contents looks like this:
// Show page info in another page element or window with parameters (for local use only)
function ServInfoLocal(dest_frame,web_page,params="",form_id="") {
var sparams = params;
var swpage = web_page;
var iweb = document.getElementById(dest_frame);
var moreparams = "";
// If we entered extra parameters including form fields,
// add the the "&" before the form field list
if (sparams != "") {moreparams = "&";}
// Get form field values if a form id is specified
if (form_id != "") {
var efrm = document.getElementById(form_id);
sparams += moreparams+GetDivFields(form_id);
}
// If destination frame does not exist, exit
if (typeof(iweb) == "!undefined" || iweb == null) {return;}
// Add the question mark if there is any parameters to pass
if (sparams != "") {sparams = "?"+sparams;}
// Show results in iframe
iweb.src = swpage+sparams;
}
// AJAX simple HTTP GET request
function ServInfo(pop_field_id,web_page,params="",form_id="",append_data_to_output = "",exec_string = "",dont_show_results = "") {
var sparams = params;
var swpage = web_page;
var eobj = document.getElementById(pop_field_id);
var moreparams = "";
// If we entered extra parameters including form fields,
// add the the "&" before the form field list
if (sparams != "") {moreparams = "&";}
// Get form field values if a form id is specified
if (form_id != "") {
var efrm = document.getElementById(form_id);
sparams += moreparams+GetDivFields(form_id);
}
// If HTML element to populate does not exist, exit
if (typeof(eobj) == "!undefined" || eobj == null) {return;}
if (window.XMLHttpRequest) {
// IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else {
// IE6-
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Do not show any results if requested
if (dont_show_results == "") {
if (append_data_to_output == "y") {
document.getElementById(pop_field_id).innerHTML += this.responseText;
}
if (append_data_to_output == "") {
document.getElementById(pop_field_id).innerHTML = this.responseText;
}
}
// Execute a string if a user defined one
if (exec_string != "") {
eval(exec_string);
}
}
};
// Add the question mark if there is any parameters to pass
if (sparams != "") {swpage += "?";}
xmlhttp.open("GET",swpage+sparams,true);
xmlhttp.send();
}
// Build a parameter string with div fields of type text, hidden or password
function GetDivFields(div_id) {
var ediv = document.getElementById(div_id);
var elem = ediv.children;
var retval = "";
var ssep = "";
for (var i = 0; i < elem.length; i++) {
if (elem[i].type == "text" || elem[i].type == "hidden" || elem[i].type == "password") {
retval += ssep+elem[i].name+"="+pURL(elem[i].value);
ssep = "&";
}
if (elem[i].type == "checkbox") {
if (elem[i].checked == true) {
retval += ssep+elem[i].name+"="+elem[i].value;
ssep = "&";
}
}
}
return retval;
}
Now, my dbres.html file will contain just the div elements and all the information I need to show up in my "file:///" page from which the search request came from. So I simply have this inside my page:
<div id="search-form" style="color:white;font-weight:bold;">
<input id="srch" name="srch" type="text">
<button class="bbut" onclick="ServInfoLocal('iweb','http://127.0.0.1/whatever/html/db.php','mode=s','search-form');">Search</button>
<button class="bbut" onclick="ServInfo('search-results','dbres.html');">Click here</button>
</div>
<div id="search-results">Results here</div>
<iframe id="iweb" style="display:none;" src=""></iframe>
For now I have 2 buttons, one for the search and one to show the results from my newly created file. Now, I can show my local videos which will load in my video container with "file:///" source directly without passing through http. I'll make my results display automatic which I will be able to do myself from here on.
So, if someone on planet earth wants to be able to do cross-domain searches in a MySQL database from a local file ran directly from the Windows explorer, there's not too many solutions, actually, I found none so here is at least one for who would ever need this solution.
For the curious ones out there, my next step will be to loop my folder until my dbres file is present using another js function. Once my file has been fetched, call another php file which wil destroy the created file and I'll be ready for another database request from my webpage situated in a "file:///" location.

Logic in the controller that isn't assigned directly to the scope should be fulfilled else where before it gets to the controller [duplicate]

This question already has answers here:
Why use services in Angular?
(5 answers)
Closed 5 years ago.
$scope.listValueChanged = function (name) {
listId = [];
$scope.listType= name;
};
if ($scope.contacts && $scope.contacts.length > 0) {
var gsSelectedContacts =$scope.contacts;
for (var i = 0; i < $scope.contacts.length; i++) {
contactIds.push(gsSelectedContacts[i].id);
}
}
for the above code I got review comments from my superior like below Logic in the controller that isn't assigned directly to the scope should be fulfilled elsewhere before it gets to the controller, then applied to the $scope.
I am using this method at one place only. Do, i really need to move this logic to services?
Well it depends on whats the use case here . If you are going to reuse something its better to create a service for that but if you are not going to reuse or the code is not enough to be used as a service then you should avoid using service . Service are meant to make your code more organized and give better usability so it depends on whats you're requirement really is.
details on where to use service can be found here
Try to do following changes and move commented logic to service
create getter and setter in service for listType
Js code
$scope.listType = '';
$scope.listValueChanged = function(name) {
listId = [];
$scope.listType = name;
};
if ($scope.contacts && $scope.contacts.length > 0) {
var contactIds = [];
var gsSelectedContacts = $scope.contacts;
//
// this logic you can keep in service
//
$scope.contacts.map(function(contact) {
contactIds.push(contact);
});
}
Hope this will help you

Creating batch documents using pouchdb slows the webapp

I am trying to save documents using pouchdb's bulkSave() function.
However, when these documents are saved it starts to sync with master database using sync gateway & in doing so the webapp slows down and when I try to navigate to different tabs no content is displayed on that tab.
Below is an example of how the documents are being created:
for (var i = 0; i <= instances; i++) {
if (i > 0) {
advTask.startDate = new Date(new Date(advTask.startDate).setHours(new Date(advTask.startDate).getHours() + offset));
}
if (advTask.estimatedDurationUnit == 'Minutes') {
advTask = $Date.getAdvTaskEndTimeIfMinutes(advTask);
} else if (advTask.estimatedDurationUnit == 'Hours') {
advTask = $Date.getAdvTaskEndTimeIfHours(advTask);
} else if (advTask.estimatedDurationUnit == 'Days') {
advTask = $Date.getAdvTaskEndTimeIfDays(advTask);
}
if(new Date(advTask.endDate).getTime() >= new Date($scope.advTask.endDate).getTime()) {
// here save the task array using bulkSave() function
$db.bulkSave(tasks).then(function (res) {
$db.sync();
});
break;
}
advTask.startDate = $Date.toGMT(advTask.startDate);
advTask.endDate = $Date.toGMT(advTask.endDate);
var adv = angular.copy(advTask);
tasks.push(adv); // here pushing the documents to an array
offset = advTask.every;
}
Thanks in advance!
bulkSave is not a core PouchDB API; are you using a plugin?
Also one piece of advice I'd give is that Couchbase Sync Gateway does not have 100% support for PouchDB and is known to be problematic in some cases.
Another piece of advice is that running PouchDB in a web worker can prevent your UI thread from getting overloaded, which would fix the problem of tabs not showing up.
Do you have a live test case to demonstrate?

Markers and Windows(Angular google maps) not working after upgrade to angular 1.3.8

I have been using angular-google-maps for sometime. I have not faced any major issues till now. But one of my colleagues had upgraded angular to 1.3.8 recently. And since then I am getting the following errors while instantiating the and directives and I do not see any markers. Here are the errors I get. Any inputs or directions to debug will be awesome. Thanks in advance.
Here is the first error:
Error: this.mapCtrl.getMap is not a function
this.MarkersParentModel</MarkersParentModel.prototype.createMarkers#http://localhost/scripts/1b3f05c4.modules.js:2637:75
__bind/<#http://localhost/scripts/1b3f05c4.modules.js:2569:16
this.MarkersParentModel</MarkersParentModel.prototype.onTimeOut#http://localhost/scripts/1b3f05c4.modules.js:2612:16
__bind/<#http://localhost/scripts/1b3f05c4.modules.js:2569:16
__bind/<#http://localhost/scripts/1b3f05c4.modules.js:2234:16
IMarkerParentModel/<#http://localhost/scripts/1b3f05c4.modules.js:2290:11
timeout/timeoutId<#http://localhost/bower_components/angular/angular.js:16205:28
completeOutstandingRequest#http://localhost/bower_components/angular/angular.js:4902:7
Browser/self.defer/timeoutId<#http://localhost/bower_components/angular/angular.js:5282:7
http://localhost/bower_components/angular/angular.js
Line 11594
And here is the second error:
Error: this.linked.ctrls[0].getMap is not a function
this.WindowsParentModel</WindowsParentModel.prototype.createChildScopesWindows#http://localhost/scripts/1b3f05c4.modules.js:2860:21
__bind/<#http://localhost/scripts/1b3f05c4.modules.js:2726:16
WindowsParentModel/<#http://localhost/scripts/1b3f05c4.modules.js:2785:18
timeout/timeoutId<#http://localhost/bower_components/angular/angular.js:16205:28
completeOutstandingRequest#http://localhost/bower_components/angular/angular.js:4902:7
Browser/self.defer/timeoutId<#http://localhost/bower_components/angular/angular.js:5282:7
http://localhost/bower_components/angular/angular.js
Line 11594
Line 2860:
var markersScope, modelsNotDefined, _this = this;
this.isIconVisibleOnClick = true;
if (angular.isDefined(this.linked.attrs.isiconvisibleonclick)) {
this.isIconVisibleOnClick = this.linked.scope.isIconVisibleOnClick;
}
>>>> this.gMap = this.linked.ctrls[0].getMap();
markersScope = this.linked.ctrls.length > 1 && this.linked.ctrls[1] != null ? this.linked.ctrls[1].getMarkersScope() : void 0;
modelsNotDefined = angular.isUndefined(this.linked.scope.models);
if (modelsNotDefined && (markersScope === void 0 || markersScope.markerModels === void 0 && markersScope.models === void 0)) {
this.$log.info('No models to create windows from! Need direct models or models derrived from markers!');
return;
}
Line 2637:
this.gMarkerManager = new directives.api.managers.MarkerManager(this.mapCtrl.getMap());

How to use Ext.state.Manager with localStorage instead cookies?

Ext JS Ext.state.Manager has only Coockie provider. Cookie can hold only 4096 bites and if my grid or tree has many columns - it overflow 4096 bites and cant save state.
one else issue - every request to server sends all cookies in request, so Apache or anoter web server can not permit huge cookies.
I want to use Provider to save data in localStorage. Is any ready solution? Or I have to write it ?
Here is workaround that I use for now, but may be any more complex solution?
Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
setCookie : function(name, value){
var me = this;
localStorage.setItem(me.prefix+name,me.encodeValue(value));
},
clearCookie : function(name){
var me = this;
localStorage.removeItem(me.prefix+name);
},
readCookies : function(){
var prefix = this.prefix,
len = prefix.length,
cookies = {};
keys = Object.keys(localStorage),
i = 0;
for (; i < keys.length; i++) {
console.log(keys[i].substring(0, len));
if (keys[i] && keys[i].substring(0, len) == prefix){
cookies[keys[i].substr(len)]= this.decodeValue(localStorage.getItem(keys[i]));
}
}
return cookies;
}
}));
The class Ext.state.LocalStorageProvider has been added to ExtJS in Ext JS 4 Beta 1 released on March 30, 2011. See original Docs and Implementation and current Docs and Implementation as of March 11, 2022.
Ext.state.Manager.setProvider(new Ext.state.LocalStorageProvider());

Resources