breeze.debug.js javascript error - breeze

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\}\)

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.

Select2 with createSearchChoice uses newly created choice for keyboard entry even given a match, bug or am I missing something?

I'm using Select2 (version 3.4.0) to populate a tag list. The tags are matched against existing ones via ajax call, and I'm using createSearchChoice to allow creating new tags. The code works so far, and looks something like this:
$(mytags).select2({
multiple: true,
placeholder: "Please enter tags",
tokenSeparators: [ "," ],
ajax: {
multiple: true,
url: myurl,
dataType: "json",
data: function(term, page) {
return {
q: term
};
},
results: function(data, page) {
return data;
}
},
createSearchChoice: function(term) {
return {
id: term,
text: term + ' (new)'
};
},
});
All pretty standard, except note the appended (new) in createSearchChoice. I need users to know that this is not a preexisting tag.
It works as expected: if I start typing "new-tag", I get "new-tag (new)" tag suggested at the top of the list, and if I pick it, the tag list contains "new-tag (new)", as expected. If the tag already exists, Select2 detects the match, and no "(new)" choice is created. Pressing return or clicking on the match works as expected.
The problem appears when I type a comma (my single tokenSeparators entry) while there is a match. Select2 closes that token, and adds the tag to the list, but with the "(new)" label appended, i.e. it uses the return value from createSeachChoice even if it does not have to.
Is this a bug in Select2, or am I using it wrong (and what should I do instead)?
I 'm not sure if this is a bug or not -- in any case, there is no open issue referring to this behavior at the GitHub issue tracker at this moment.
You can mostly fix the behavior yourself though. The idea is that the createSearchChoice callback must be able to tell if term refers to a search result or not. But createSearchChoice does not have direct access to the search results, so how can we enable that? Well, by saving the latest batch of search results from inside the results callback.
var lastResults = [];
$(...).select2({
ajax: {
multiple: true,
url: "/echo/json/",
dataType: "json",
type: "POST",
data: function (term, page) {
return {
json: JSON.stringify({results: [{id: "foo", text:"foo"},{id:"bar", text:"bar"}]}),
q: term
};
},
results: function (data, page) {
lastResults = data.results;
return data;
}
},
createSearchChoice: function (term) {
if(lastResults.some(function(r) { return r.text == term })) {
return { id: term, text: term };
}
else {
return { id: term, text: term + " (new)" };
}
}
});
This code uses Array.some so you need something better than IE8 (which is the select2 minimum requirement) to run it, but of course it is possible to emulate the behavior.
See it in action.
There is, however, a fly in the ointment: this code works correctly only if the search results corresponding to the current search term have been already received.
This should be obvious: if you type very fast and create a search term that corresponds to an existing tag but hit comma before the search results that include that tag have arrived, createSearchChoice will be testing for the tag's presence among the previously received search results. If those results do not include the tag, then the tag will be displayed as "new" even though it is not.
Unfortunately I don't believe there is anything you can do to prevent this from happening.
Instead of tweeking the result, I think it is better to work on the server side.
If the server doesn't find a tag make it return a json answer with the new tag
{"more":false,"results":[{"id":"whatever","text":"new-tag (new)"}]}
There is another parameter for the 'createSearchChoice' - 'page', it lists all the choices, you can easily find dupes with it.
createSearchChoice = function (term, page) {
if( page.some(function(item) {
return item.text.toLowerCase() === term.toLowerCase();
}) ){
return { val: term, name: term + '*' };
}
}

Error: Unknown provider: aProvider <- a

I'm using AngularJS in a Ruby on Rails 3.2.8 project with assets.
When I load up my form which is using AngularJS on my development machine I don't have a problem. However when I load the same form up on my production server I get this error in the Javascript console:
Error: Unknown provider: aProvider <- a
I've tracked it back to my coffeescript file where I setup AngularJS for use within a form:
$ (event) ->
$("#timesheet_description").autocomplete({source: '/autocomplete/work_descs'})
# Create AngularJS module
app = angular.module 'timesheetApp', []
# Create a AngularJS controller
app.controller "TimesheetCtrl", ($scope) ->
$scope.costed_amount = 0
# Bind my module to the global variables so I can use it.
angular.bootstrap document, ["timesheetApp"]
If I comment all this out the page will load without errors and without AngularJS abilities.
Is the problem due to Rails assets compiling and minify?
Is there a way to fix this and still use coffeescript and Rails assets?
AngularJS, when using the style you're using right now (called pretotyping), uses the function argument names to do dependency injection. So yes, minification does break this completely.
The fix is simple, though. In every case where you need injection (are using '$xxx') variables, do this:
app.controller "TimesheetCtrl", ['$scope', ($scope) ->
$scope.costed_amount = 0
]
Basically, replace all function definitions with an array. The last element should be the function definition itself, and the first ones are the $names of the objects you want injected.
There's some more (albeit not clear enough) info on the docs.
If you miss the array notation somewhere , to locate this we need to modify the angular code little bit, but its very quick solution.
change is console.log("Array Notation is Missing",fn); ( line no 11 from function start)
Find out annotate function in angular.js (non-minified)
function annotate(fn) {
var $inject,
fnText,
argDecl,
last;
if (typeof fn == 'function') {
if (!($inject = fn.$inject)) {
$inject = [];
if (fn.length) {
console.log("Array Notation is Missing",fn);
fnText = fn.toString().replace(STRIP_COMMENTS, '');
argDecl = fnText.match(FN_ARGS);
forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
arg.replace(FN_ARG, function(all, underscore, name){
$inject.push(name);
});
});
}
fn.$inject = $inject;
}
} else if (isArray(fn)) {
last = fn.length - 1;
assertArgFn(fn[last], 'fn');
$inject = fn.slice(0, last);
} else {
assertArgFn(fn, 'fn', true);
}
return $inject;
}
To minify angular all you need is to do is to change your declaration to the "array" declaration "mode" for example:
From:
var demoApp= angular.module('demoApp', []);
demoApp.controller(function demoCtrl($scope) {
} );
To
var demoApp= angular.module('demoApp', []);
demoApp.controller(["$scope",function demoCtrl($scope) {
}]);
How to declare factory services?
demoApp.factory('demoFactory', ['$q', '$http', function ($q, $http) {
return {
//some object
};
}]);

MVC JSON method returning invalid JSON to JQuery?

I am having problems with Jquery parsing the JSON I am sending back... however, this is very odd because I am using MVC's JSON method.
Here's my setup. I have a very simple function:
$.ajax({
url: URLd,
dataType: 'json',
data: { Year: $('#VehicleYear').val(), Value: request.term },
success: function (data, textStatus, jqXHR) { alert("Success!"); },
error: function(XMLHttpRequest, textStatus) {
alert(textStatus + ": " + XMLHttpRequest.responseText);
}
});
It always runs the error function which shows:
parsererror: [{"Value":"Toyota","ID":160}]
I cannot figure out why in the world it is doing this... it was working with an older version of JQuery - and I read that the JQuery JSON parser is quite a bit more strict now- but I can't figure out what's wrong with my JSON.
Even if it is wrong, that's very frustrating because I'm using MVC's Json function to generate this:
public ActionResult GetVehicleModels(int Year, int MakeID, string Value = null)
{
var modlMatchs = (from VMYX in ent.VehicleMakeYearXREFs
join VM in ent.VehicleModels
on VMYX.VehicleModelID equals VM.VehicleModelID
join VMa in ent.VehicleMakes
on VM.VehicleMakeID equals VMa.VehicleMakeID
where VMYX.ModelYear == Year && VMa.VehicleMakeID == MakeID && VM.VehicleModelName.StartsWith(Value)
orderby VMa.VehicleMakeName
select new { Value = VM.VehicleModelName, ID = VM.VehicleModelID }).Distinct().Take(10).ToList();
return this.Json(modlMatchs, "application/json", JsonRequestBehavior.AllowGet);
}
I must be missing something glaringly obvious... still getting the hang of JQuery/MVC but these things are really slowing my progress.
Sure enough, the JQuery result looks as follows (according to Chrome's developer toolbar)
[{"Value":"Toyota","ID":160}]
Change your dataType in the jQuery AJAX call to "text json". I suspect there may be a problem with the response content-type header, or something else that's causing jQuery not to acknowledge the dataType as json. Using "text json" will cause jQuery to accept it as plaintext before converting it to a js object.
var parsed = jQuery.parseJSON('[{"Value":"Toyota","ID":160}]');
I've just tried the above and it parses it fine, however remember it has returned it as a single record in an array (due to returning an IEnumerable from the C#).

XMLHttpRequest different in IE8 vs. FireFox/Chrome

I'm having a problem similar to jQuery $.ajax Not Working in IE8 but it works on FireFox & Chrome, but with a different use case.
I'm using the jQuery Form plug-in to handle a file upload to an ASP.NET MVC controller, which sends the file off for parsing and processing. If an Exception is thrown, it should alert the user to the issue.
//client side code
//make an ajax call, sending the contents of the file
$("#ajaxUploadForm").ajaxSubmit({
dataType: 'json',
url: '/plan/Something/ExcelImport',
iframe: true,
beforeSend: function () {
$(".ui-dialog-buttonpane").find("#my_progress").fadeIn();
},
success: function (data, textStatus) {
output = "<center><span class='flash'>" + data.message + "</span></center>";
$("#flash_message").html(output).fadeIn('slow');
setTimeout(function () { $("#flash_message").fadeOut() }, 5000);
cleanup();
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("XMLHttpRequest is " + XMLHttpRequest);
var contents = "";
for (prop in XMLHttpRequest) {
contents += "\na property is " + prop + " it's value is " + XMLHttpRequest[prop];
}
alert("the contents are " + contents);
alert("textStatus is " + textStatus);
alert("errorThrown is " + errorThrown);
//comes back in an HTML envelope. This should be parsed with regex, but I can't get it to work. Dirty hack
response = XMLHttpRequest.responseText.substring(XMLHttpRequest.responseText.indexOf("<body>"));
response = response.replace("<body>", "");
response = response.replace("</body>", "");
alert("There was a problem with the upload.\r\n" + response);
},
complete: function (XMLHttpRequest, textStatus) {
$(".ui-dialog-buttonpane").find("#my_progress").remove();
something_import.dialog('close');
something_import.dialog('destroy');
}
});
//server side code
public FileUploadJsonResult ExcelImport()
{
FileUploadJsonResult result = new FileUploadJsonResult();
HttpPostedFileBase hpf = Request.Files[0] as HttpPostedFileBase;
if (hpf.ContentLength == 0)
return new FileUploadJsonResult { Data = new { message = "File contained no data" } };
String fileName = Path.GetFileName(hpf.FileName);
String timeStampedFile = fileName.Insert(fileName.IndexOf('.'),"_"+DateTime.Now.ToFileTimeUtc());
string savedFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "tempo", timeStampedFile);
hpf.SaveAs(savedFileName);
try
{
result = ProcessFile(savedFileName, Request["Id"]) as FileUploadJsonResult;
}
catch (ArgumentException e)
{
this.Response.StatusCode = 500;
this.Response.StatusDescription = System.Net.HttpStatusCode.BadRequest.ToString();
Response.Write(e.Message);
result = Json(new { message = e.Message, stackTrace = e.StackTrace }) as FileUploadJsonResult;
}
return result;
}
This works perfectly in Chrome and Firefox. In IE, the XMLHttpRequest object coming back is different:
FF:
IE:
I've been Googling around for differences between the browser implementations of XMLHttpRequest, but haven't found anything that deals specifically with this case. Stymied.
The reason this is happening is because of the iframe fallback strategy that ajaxSubmit employs. I think since the response gets posted into the iframe IE tries to figure out how to dipslay it and decides that it wants to ask you to download the response instead of just putting it in the iframe.
I came across this same situation a while ago and found an article (that I can't find now) that offered a workaround.
If you surround your json response in a textarea nobody is going to complain(IE,FF,Chrome,probably Safari) and you'll get your response parsed correctly.
E.g. if you are returning
{Id: 1, Name: 'Me'}
just return:
<textarea>{Id: 1, Name: 'Me'}</textarea>
You see now IE thinks it's html so it inserts it into the hidden iframe. Your ajaxSubmit function still gets called and parses the json correctly and then everybody's happy. :)
If you're using ASP.NET MVC you could shamelessly copy this extension method :)
public static class ControllerExtensions
{
public static ActionResult JsonSafe(this IController controller, object obj)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return new WriteResult(string.Format("<textarea>{0}</textarea>", serializer.Serialize(obj)));
}
}
The wikipedia article on XMLHttpRequest seems to give a good overview of the history behind the XMLHttpRequest. It seems Microsoft and Mozilla developed/adopted their own versions of the object and hence why you are probably seeing different properties.
Here is a link to Microsoft's implementation of the XMLHttpRequest interface members, which seem to match the properties in your alert.
Here is the a link to Mozilla's implementation of XMLHttpRequest.
So while we wait for the W3C to standardize the XMLHttpRequest you will continue to have different implementations across the browsers like you are seeing in this case.
For some added fun here is Apple's and Opera's specifications on XMLHttpRequest.

Resources