var app = angular.module('plunker', []);
app.value('fileSystem', {requestFileSystem: window.requestFileSystem || window.webkitRequestFileSystem});
//default sessionStorage
app.provider('storageService', function () {
this.$get = function () {
return {
setItem: function (key, value) {
sessionStorage.setItem(key, value);
console.log('Fetching newly added key from sessionStorage for verification = ', sessionStorage.getItem(key));
}
};
};
});
//File System storage if supported. Decorator will take care of it.
app.provider('storageServiceFile', function () {
this.$get = ['$window', 'fileSystem', function($window, fileSystem) {
var fs;
function onInitFs(fSys) {
console.log('Opened file system: ' + fSys.name);
fs = fSys;
}
function errorHandler(e) {
var msg = '';
switch (e.code) {
case FileError.QUOTA_EXCEEDED_ERR:
msg = 'QUOTA_EXCEEDED_ERR';
break;
case FileError.NOT_FOUND_ERR:
msg = 'NOT_FOUND_ERR';
break;
case FileError.SECURITY_ERR:
msg = 'SECURITY_ERR';
break;
case FileError.INVALID_MODIFICATION_ERR:
msg = 'INVALID_MODIFICATION_ERR';
break;
case FileError.INVALID_STATE_ERR:
msg = 'INVALID_STATE_ERR';
break;
default:
msg = 'Unknown Error';
break;
}
console.log('Error: ' + msg);
}
var reqFileSystem = fileSystem.requestFileSystem;
if (reqFileSystem) {
reqFileSystem($window.TEMPORARY, 1*1024*1024 /*1MB*/, onInitFs, errorHandler);
}
return {
setItem: function (key, value) {
fs.root.getFile(key, {create: true}, function(fileEntry) {
// Create a FileWriter object for our FileEntry (log.txt).
fileEntry.createWriter(function(fileWriter) {
fileWriter.onwriteend = function(e) {
console.log('Write completed.');
};
fileWriter.onerror = function(e) {
console.log('Write failed: ' + e.toString());
};
// Create a new Blob and write it to log.txt.
var blob = new Blob([value], {type: 'text/plain'});
fileWriter.write(blob);
}, errorHandler);
}, errorHandler);
}
};
}];
});
app.config(function($provide) {
$provide.decorator('storageService', ['$delegate', '$injector', '$rootScope', 'fileSystem', function ($delegate, $injector, $rootScope, fileSystem) {
if (fileSystem.requestFileSystem) {
$rootScope.isFileSystemSupported = true;
return $injector.get('storageServiceFile');
} else {
$rootScope.isFileSystemSupported = false;
return $delegate;
}
}]);
});
app.directive('dirResult', ['$rootScope', '$timeout', function ($rootScope, $timeout) {
function getSessionStorageData() {
var data = {};
for (var i = 0; i < sessionStorage.length; i++) {
var key = sessionStorage.key(i);
data[key] = sessionStorage[key];
}
return data;
}
return {
scope: {},
controller: function ($scope, $element) {
$scope.data = getSessionStorageData();
$rootScope.$on('saveSuccess', function () {
if ($rootScope.isFileSystemSupported) {//refresh iframe
var fsIframe = $('iframe[name=fs]')[0];
$timeout(function () {
fsIframe.src = fsIframe.src;
}, 100);
} else {//refresh data from sessionScope
$scope.data = getSessionStorageData();
}
});
}
};
}]);
app.controller('MainCtrl', ['$scope', 'storageService', function($scope, storageService) {
$scope.record = {};
$scope.save = function (rec) {
storageService.setItem(rec.key, rec.value);
$scope.$emit('saveSuccess');
toastr.options = {
"positionClass": "toast-bottom-right",
"timeOut": 2000
};
toastr.success('Data added to storage');
};
}]);
<!doctype html>
<html ng-app="plunker" >
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://raw.github.com/CodeSeven/toastr/master/toastr.js"></script>
<script src="http://code.angularjs.org/1.1.4/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-switch="isFileSystemSupported">
<h3 ng-switch-when="true">File System API supported by this browser!</h3>
<h3 ng-switch-when="false">File System API NOT supported by this browser!</h3>
</div>
<!--<div class="alert alert-info">
Verifying the results:
<ul>
<li>Browsers that support File System API (only Chrome at the moment. Tested on v26) - Click the following URL <a href="filesystem:http://run.plnkr.co/temporary/" target="_blank">filesystem:http://run.plnkr.co/temporary/</a>. You'll see the list of files added.</li>
<li>Other browsers that don't support File System API - Watch the console for confirmation message. Data will be added to sessionStorage.</li>
</ul>
</div>-->
<form class="form-inline">
<fieldset>
<legend>Enter the data to be stored ...</legend>
<input type="text" class="input-small" placeholder="Key" ng-model="record.key">
<input type="text" class="input-small" placeholder="Value" ng-model="record.value">
<button type="submit" class="btn" ng-click="save(record)">Save</button>
</fieldset>
</form>
<h4>Results</h4>
<div class="well well-large result" ng-switch="isFileSystemSupported">
<div ng-switch-when="true" dir-result>
<iframe name="fs" seamless src="filesystem:http://run.plnkr.co/temporary/" height="200"></iframe>
</div>
<div ng-switch-when="false" dir-result>
<ul>
<li ng-repeat="(key, value) in data">{{key}} = {{value}}</li>
</ul>
</div>
</div>
</body>
</html>
/* Put your css in here */
.result ul {
list-style-type: none;
padding: 0;
margin: 0;
}
.toast-title {
font-weight: bold;
}
.toast-message {
-ms-word-wrap: break-word;
word-wrap: break-word;
}
.toast-message a,
.toast-message label {
color: #FFF;
}
.toast-message a:hover {
color: #CCC;
text-decoration: none;
}
.toast-top-full-width {
top: 0;
right: 0;
width: 100%;
}
.toast-bottom-full-width {
bottom: 0;
right: 0;
width: 100%;
}
.toast-top-left {
top: 12px;
left: 12px;
}
.toast-top-right {
top: 12px;
right: 12px;
}
.toast-bottom-right {
right: 12px;
bottom: 12px;
}
.toast-bottom-left {
bottom: 12px;
left: 12px;
}
#toast-container {
position: fixed;
z-index: 999999;
}
#toast-container > div {
margin: 0 0 6px;
padding: 15px 15px 15px 50px;
width: 300px;
-moz-border-radius: 3px 3px 3px 3px;
-webkit-border-radius: 3px 3px 3px 3px;
border-radius: 3px 3px 3px 3px;
background-position: 15px center;
background-repeat: no-repeat;
-moz-box-shadow: 0 0 12px #999999;
-webkit-box-shadow: 0 0 12px #999999;
box-shadow: 0 0 12px #999999;
color: #FFFFFF;
opacity: 0.8;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
filter: alpha(opacity=80);
}
.toast {
background-color: #030303;
}
.toast-success {
background-color: #51A351;
}
.toast-error {
background-color: #BD362F;
}
.toast-info {
background-color: #2F96B4;
}
.toast-warning {
background-color: #F89406;
}
#toast-container > :hover {
-moz-box-shadow: 0 0 12px #000000;
-webkit-box-shadow: 0 0 12px #000000;
box-shadow: 0 0 12px #000000;
opacity: 1;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
filter: alpha(opacity=100);
cursor: pointer;
}
#toast-container > .toast-info {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important;
}
#toast-container > .toast-error {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important;
}
#toast-container > .toast-success {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important;
}
#toast-container > .toast-warning {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important;
}
/*Responsive Design*/
@media all and (max-width: 240px) {
#toast-container > div {
padding: 8px 8px 8px 50px;
width: 108px;
}
}
@media all and (min-width: 241px) and (max-width: 320px) {
#toast-container > div {
padding: 8px 8px 8px 50px;
width: 128px;
}
}
@media all and (min-width: 321px) and (max-width: 480px) {
#toast-container > div {
padding: 8px 8px 8px 50px;
width: 192px;
}
}
@media all and (min-width: 481px) and (max-width: 768px) {
#toast-container > div {
padding: 15px 15px 15px 50px;
width: 300px;
}
}
/* overrides */
#toast-container.toast-top-full-width > div,
#toast-container.toast-bottom-full-width > div {
width: 96%;
margin: 1px auto;
}