Knockout-validation not working well on IE8 - knockout-validation

When I use my website using IE8, the validation is not working well because it is failing on the next function inside knockout.validation.debug.js. If I use the website with Chrome, FF or IE9, everything works fine.
The Error that is showing:
Error: Object doesn't support property or method 'hasOwnProperty'
values: function (o) {
var r = [];
for (var i in o) {
if (o.hasOwnProperty(i)) {
r.push(o[i]);
}
}
return r;
},
I also tried to replace o.hasOwnProperty(i) with Object.prototype.hasOwnProperty.call(o,i), but this is not working either. Any idea how to make it work with IE8?

Related

Ionic Prepopulated Database with Antair Cordova SQLitePlugin [help request]

____ INTRO
Hello everyone, first of all, three clarifications:
My english is not good, so I beg your pardon in advance for my mistakes,
I'm a newbie so forgive me for inaccuracies,
I have previously searched and tried the solutions I found on the internet but still I can not solve the problem of embedding a prepopulated database.
____ THE GOAL
I want to develop an app for iOS and Android with a prepopulated database.
Just for example, the database consists of 15.000 records each one made of three key-value pair (id, firstname and lastname).
___ WHAT I DID
Steps:
ionic start myapp blank
cd myapp
ionic platform add ios
ionic platform add android
Then I created an sqlite database for testing purpose, named mydb.sqlite, made of one table people containing two id, firstname, lastname records.
I decided to use the following plugin: https://github.com/Antair/Cordova-SQLitePlugin
That's because it can be installed with cordova tool.
ionic plugin add https://github.com/Antair/Cordova-SQLitePlugin
(Alert: I think that the instructions on the website show an incorrect reference - "cordova plugin add https://github.com/brodysoft/Cordova-SQLitePlugin" - which refers to another plugin).
Then, following the instructions on the plugin website, I copied the database to myapp/www/db/ so that it can now be found at myapp/www/db/mydb.sqlite
I modified the index.html including the SQLite plugin just after the default app.js script:
<!-- your app's js -->
<script src="js/app.js"></script>
<script src="SQLitePlugin.js"></script>
I also write some lines of code in index.html file to show a button:
<ion-content ng-controller="MyCtrl">
<button class="button" ng-click="all()">All</button>
</ion-content>
Finally I had modified ./js/app.js:
// Ionic Starter App
var db = null;
angular.module('starter', ['ionic' /* What goes here? */ ])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// some predefined code has been omitted
window.sqlitePlugin.importPrepopulatedDatabase({file: "mydb.sqlite", "importIfExists": true});
db = window.sqlitePlugin.openDatabase({name: "mydb.sqlite"});
}); // $ionicPlatform.ready
}) // .run
.controller('MyCtrl', function($scope){
$scope.all = function(){
var query = "SELECT * FROM people";
// I don't know how to proceed
}; // $scope.all
}); // .controller
___ THE PROBLEM
I don't know how to proceed in the controller section to query all the records (just an example of query) and show the results in the console.log.
I think that the following code must be completed in some way:
angular.module('starter', ['ionic' /* What goes here? */ ])
And also the code inside controller section must be completed:
$scope.all = function(){
var query = "SELECT * FROM people";
// I don't know how to proceed
}; // $scope.all
___ FINAL THANKS
Thank you in advance for the help you will give to me.
So this guy's code has helped a lot to encapsulate my DAL. I highly recommend that you use he's code pretty much verbatim.
https://gist.github.com/jgoux/10738978
You'll see he has the following method:
self.query = function(query, bindings) {
bindings = typeof bindings !== 'undefined' ? bindings : [];
var deferred = $q.defer();
self.db.transaction(function(transaction) {
transaction.executeSql(query, bindings, function(transaction, result) {
deferred.resolve(result);
}, function(transaction, error) {
deferred.reject(error);
});
});
return deferred.promise;
};
Let's break this down a bit. The query function takes a query string (the query param) and a list of possible bindings for ? in a query like "SELECT * FROM A_TABLE WHERE ID = ?". Because he's code is a service, the self value points to the service itself for all future invocations. The function will execute a transaction against the db, but it returns a promise that is only fulfilled once the db comes back.
His service provides a second helper function: fetchAll.
self.fetchAll = function(result) {
var output = [];
for (var i = 0; i < result.rows.length; i++) {
output.push(result.rows.item(i));
}
return output;
};
fetchAll will read the rows in their entirety into an array. The result param for fetchAll is the result variable passed in the query function's promise fulfillment.
If you copy and paste his code into your service file, you now have a bonafide DB service. You can wrap that service up in a DAL. Here's an example from my project.
.service('LocationService', function ($q, DB, Util) {
'use strict';
var self = this;
self.locations = [];
self.loadLocked = false;
self.pending = [];
self.findLocations = function () {
var d = $q.defer();
if (self.locations.length > 0) {
d.resolve(self.locations);
}
else if (self.locations.length === 0 && !self.loadLocked) {
self.loadLocked = true;
DB.query("SELECT * FROM locations WHERE kind = 'active'")
.then(function (resultSet) {
var locations = DB.fetchAll(resultSet);
self.locations.
push.apply(self.locations, locations);
self.loadLocked = false;
d.resolve(self.locations);
self.pending.forEach(function (d) {
d.resolve(self.locations);
});
}, Util.handleError);
} else {
self.pending.push(d);
}
return d.promise;
};
})
This example is a bit noisy since it has some "threading" code to make sure if the same promise is fired twice it only runs against the DB once. The general poin is to show that the DB.query returns a promise. The "then" following the query method uses the DB service to fetchAll the data and add it into my local memory space. All of this is coordinated by the self.findLocations returning the variable d.promise.
Yours would behalf similarly. The controller could have your DAL service, like my LocationService, injected into it by AngularJS. If you're using the AngularJS UI, you can have it resolve the data and pass it into the list.
Finally, the only issue I have with the guy's code is that the db should come from this code.
var dbMaker = ($window.sqlitePlugin || $window);
The reason for this is that the plugin does not work within Apache Ripple. Since the plugin does a fine job mirroring the Web SQL interface of the browser, this simple little change will enable Ripple to run your Ionic Apps while still allowing you to work your SQLite in a real device.
I hope this helps.

cordova 2.9.x iOS 8 userAgent bug

I am using Cordova 2.9.0 with phonegap to build an iOS app.
With iOS 8, I am getting error messages of
Deprecated attempt to access property 'geolocation' on a non-Navigator object.
Deprecated attempt to access property 'userAgent' on a non-Navigator object
I tried EddyVerbruggen's solution
https://gist.github.com/EddyVerbruggen/cd02c73162180793513e
But, I am getting those error messages from Cordova
Also, when my application loads completely, I have no problem using
window.navigator.userAgent
Fist of all, it seems just a warning and the apps work fine.
They have been fixed this and I suposse it will be available soon, but for people using cordova 2.9.X, we have to change the replaceNavigator function to be like this on the cordova.js file (the whole else is new)
function replaceNavigator(origNavigator) {
var CordovaNavigator = function() {};
CordovaNavigator.prototype = origNavigator;
var newNavigator = new CordovaNavigator();
// This work-around really only applies to new APIs that are newer than Function.bind.
// Without it, APIs such as getGamepads() break.
if (CordovaNavigator.bind) {
for (var key in origNavigator) {
if (typeof origNavigator[key] == 'function') {
newNavigator[key] = origNavigator[key].bind(origNavigator);
} else {
(function(k) {
Object.defineProperty(newNavigator, k, {
get: function() {
return origNavigator[k];
},
configurable: true,
enumerable: true
});
})(key);
}
}
}
return newNavigator;
}

Phonegap app won't reopen after close (Failed to load webpage with error: CDVWebViewDelegate: Navigation started when state=1)

I'm building an app for iOS using Phonegap and I've run into some problems. The app runs fine on both a simulator and real device until I close the app using the multi-tasking shutdown (double tap home button sequence..)
Upon reopening the app I find that it becomes unresponsive and you can't interact with it in any way. I've spent a fair amount of time trying to debug this and I've had no joy.
Error wise I have been getting the error Failed to load webpage with error: CDVWebViewDelegate: Navigation started when state=1 appear in the xcode console. After lots of googling it seems that this is caused due to hash tags within the URLs (something that I'm using for scrolling down to links both on the same and different pages). Most of the suggestions recommend updating phonegap/cordova to the latest version. I was previously on 2.8 and I went up to 2.9 and it still didn't work, i'm now on 3 and i'm still getting the same issues.
I've checked the cordova git and updated my CDVWebViewDelegate.m file several times with supposed fixes, nothing seems to work. I had a previous version of the app working on earlier versions of Cordova/Phonegap but I've recently upgraded and i'd rather not downgrade to get it to work..
I should probably note that I'm using zepto for my ajax calls and not JQM, for the hash tag scrolling i'm using the following code (figured this may help given it seems to be a hash issue..)
Hash Change function
// Ajax
var wrap = $('#contentScroller .scroller')
// get href
$('a.ajax').click(function () {
location.hash = $(this).attr('href').match(/(^.*)\./)[1]
return false
})
// load page
function hashChange() {
var page = location.hash.slice(1)
if (page != "" && window.location.hash) {
wrap.hide();
spinner.spin(target);
//setTimeout(function () {
wrap.load('pages/' + page + ".html .page-wrapper")
contentScroller.scrollTo(0,0);
refreshScroll();
//}, 1500);
snapper.close();
$(menuBtn).removeClass('active');
}else{
wrap.hide();
spinner.spin(target);
//setTimeout(function () {
wrap.load('pages/Welcome.html .page-wrapper')
refreshScroll();
//}, 1500);
snapper.close();
$(menuBtn).removeClass('active');
}
}
// check for hash change
if ("onhashchange" in window) {
$(window).on('hashchange', hashChange).trigger('hashchange')
} else { // lame browser
var lastHash = ''
setInterval(function () {
if (lastHash != location.hash)
hashChange()
lastHash = location.hash
contentScroller.scrollTo(0,0);
}, 100)
}
Scrolling
$(document)
.on('ajaxStart', function () {
wrap.hide();
})
.on('ajaxStop', function () {
//wrap.show();
})
.on('ajaxSuccess', function () {
//setTimeout(function () {
spinner.stop();
wrap.fadeIn(700);
refreshScroll();
//}, 1000);
// Local storage scrollTo
var storage = window.localStorage;
var url = window.location.href.substr(window.location.href.lastIndexOf("/") + 1);
$('a.scroll-link').click(function (event) {
event.preventDefault();
url = url.replace('home.html?firstrun#', "");
url = url.replace(url, url+".html");
var myHref = $(this).attr('href');
if (url == myHref) {
var sameScroll = $(this).attr('data-scroll-same-page');
sameScroll = sameScroll.replace(sameScroll, "a#" + sameScroll);
contentScroller.scrollToElement(sameScroll, 1500);
} else {
var diffScroll = $(this).attr("data-scroll-diff-page");
storage.setItem("key", diffScroll);
//Alter value for iScroll
var value = window.localStorage.getItem("key");
value = value.replace(value, "a#" + value);
location.hash = $(this).attr('href').match(/(^.*)\./)[1]
$(window).on('hashchange', hashChange).trigger('hashchange')
// Scroll to element after .5 second
setTimeout(function () {
contentScroller.scrollToElement(value, 1500);
return false;
}, 2000)
// Clear local storage to prevent scrolling on page reload
localStorage.clear();
}
Sample link
<a href="IndexOfTerms.html" class="ajax scroll-link" data-scroll-diff-page="First_year_allowance">
this will then pass the attr "first_year_allowance" through to the IndexOfTerms pages and then scroll down to the element that has that id
Can anybody shed some light on how I might be able to fix this? It's really starting to annoy me so I'd quite like to get a fix pretty sharpish!
Note: Libraries used: iScroll, Zepto, fastclick, snapjs, spinjs
Thanks!

External link in WinJS, iframe or not, doesnt matter

I work on a Windows 8 app, and from a page that I use link hystory for running back and forward through the app, I also have 3 or 4 links to external websites(eg: facebook or my site). I tried to run them in iframe, or also to make them open in the default browser like simple links. Both method resulted in an error in base.js that says it can't handle my error (!?) I searched a lot before asking here. I watched msdn sample that works just fine, but if i copy what I need in my app results in the same error. I I use it from another page where I dont have forward history, it works, but i really need it on the front page. Any ideeas? Thank you very much.
LE:
This is my items.js code: ( for the items.html page )
(function () {
"use strict";
var appViewState = Windows.UI.ViewManagement.ApplicationViewState;
var ui = WinJS.UI;
ui.Pages.define("/pages/items/items.html", {
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
var listView = element.querySelector(".itemslist").winControl;
listView.itemDataSource = Data.groups.dataSource;
listView.itemTemplate = element.querySelector(".itemtemplate");
listView.oniteminvoked = this._itemInvoked.bind(this);
this._initializeLayout(listView, Windows.UI.ViewManagement.ApplicationView.value);
listView.element.focus();
WinJS.Utilities.query("a").listen("click", this.linkClickEventHandler, false);
},
// This function updates the page layout in response to viewState changes.
updateLayout: function (element, viewState, lastViewState) {
/// <param name="element" domElement="true" />
var listView = element.querySelector(".itemslist").winControl;
if (lastViewState !== viewState) {
if (lastViewState === appViewState.snapped || viewState === appViewState.snapped) {
var handler = function (e) {
listView.removeEventListener("contentanimating", handler, false);
e.preventDefault();
}
listView.addEventListener("contentanimating", handler, false);
var firstVisible = listView.indexOfFirstVisible;
this._initializeLayout(listView, viewState);
if (firstVisible >= 0 && listView.itemDataSource.list.length > 0) {
listView.indexOfFirstVisible = firstVisible;
}
}
}
},
linkClickEventHandler: function (eventInfo) {
eventInfo.preventDefault();
var link = eventInfo.target;
WinJS.Navigation.navigate(link.href);
},
// This function updates the ListView with new layouts
_initializeLayout: function (listView, viewState) {
/// <param name="listView" value="WinJS.UI.ListView.prototype" />
if (viewState === appViewState.snapped) {
listView.layout = new ui.ListLayout();
} else {
listView.layout = new ui.GridLayout();
}
},
_itemInvoked: function (args) {
var groupKey = Data.groups.getAt(args.detail.itemIndex).key;
WinJS.Navigation.navigate("/pages/split/split.html", { groupKey: groupKey });
}
});
})();
And from items.html I have different types of links: some of them links to other application pages, from where I can return with history buttons back/forward and some of them are links to external page. Simple link.These links crashes my app with the error that I mentioned below. If I erase the next line:
WinJS.Utilities.query("a").listen("click", this.linkClickEventHandler, false);
from my js script, external links works, but I dont have anymore history buttons in my others's app pages.
You are trying to use the navigation framework to navigate to an external URI. It's usually meant to be used within the application's local context and pages that can contain 'fragments' to load up into your main nav control.
I wouldn't hook anchor tags with your function call, instead in your linkClickEventHandler I would do the following to only hook your internal links
WinJS.Utilities.query(".nav").listen("click", linkClickEventHandler, false);
in turn your internal links would be
click me
This approach only hooks the navigation framework into your internal links. Another approach is to inspect the 'this.href' in your handler and if it contains http:// or https:// then call window.open instead

breeze.debug.js javascript error

I have been building a SPA with breeze and WebAPI (starting with John Papa's sample) for a couple of months. A couple of days ago on my Windows 8 VS2012 internal IE browser started giving me javascript errors in breeze.debug.js.
JavaScript critical error at line 4663, column 13 in //http://localhost:50033/Script/breeze.debug.js
SCRIPT1028: Expected identifier, string or number
I went back to my other development machine, Windows 7 with VS2012 and it does not give the error. The code between the two machines is identical. I use Azure TFS to sync the code.
The error occurs at the closing });
function convertFromODataEntityType(odataEntityType, schema, metadataStore, serviceName) {
var shortName = odataEntityType.name;
var namespace = translateNamespace(schema, schema.namespace);
var entityType = new EntityType({
shortName: shortName,
namespace: namespace,
}); <==== line 4663
When I remove the comma after namespace, the error goes away but errors out again in another spot on line 6911.
day: { fn: function(source) { return source.day;}, dataType: "Number" },
month: { fn: function(source) { return source.month; }, dataType: "Number" },
year: { fn: function(source) { return source.year; }, dataType: "Number"},
}; <========= line 6911
Remove the comma on the line above and it errors out on line 1271
Unhandled exception at line 1271, column 17 in http://localhost:50033/Scripts/breeze.debug.js
0x800a01b6 - JavaScript runtime error: Object doesn't support property or method 'some'
at this code:
function compile(self) {
if (!self._compiledFn) {
// clear off last one if null
if (self._fns[self._fns.length - 1] == null) {
self._fns.pop();
}
if (self._fns.length === 0) {
return undefined;
}
self._compiledFn = function (that, v) {
return that._fns.some(function (fn) {
return fn(that, v);
});
};
};
return self._compiledFn;
}
Has anyone else seen this behavior?
Just a guess, but check that you are not running IE in 'compatability' mode. The 'some' method is part of the ES5 standard and is not available in 'compatability' mode.
To avoid compatability mode issues with IE browsers, we highly recommend adding the following to your HTML header:
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1"/>
I've run into it too. In fact, I often do this to myself, especially when deleting or reordering the last k/v pair during development.
While IE10 and other browsers are more forgiving, we should eliminate trailing commas on our hashmap object key/value lists ... and will do so.
FWIW, the following regex expression finds them all
,(\s*)\}\)
and the following regex substitution pattern fixes them (preserving whitespace):
$1\}\)

Resources