Breezejs Double trouble in angularjs - javascript

I am trying to change a value in a angular view from a integer to a float/double value that is bind to ngmodel. The input don’t except anything other than a integer.
My guess is that breeze does something in the background to validate the value or something on the "defined properties". But my knowledge of JavaScript prototyping is very limiting aka I need to learn it..
This is really hard to explain so I created a plunk that can hopefully help: http://plnkr.co/edit/Gcj0VvBE3f8DRbIjMtqt?p=preview
In the plunk I also added a normal object to test the same values and it is working as expected when changing the numbers to floats/doubles.
So the question is why won’t the value changed when binding to a float/double value from breeze?

I've checked a preliminary fix into GitHub for this. Please check it out and let me know if it works ( or not). We are still testing it.
This issue is caused by Angular's (new) behavior where if the angular digest cycle does not see a change to a model property then it seems to reset the UI to what it was on the previous digest cycle. So.. the idea behind this fix is to convince angular that the model value has changed even when it hasn’t.
and.. nice catch ( this was not obvious and your plunkr helped) :)
Ward adds: You must love the breeze team responsiveness :-) Jay jumped right on this and came up with an interesting solution. But please note the word "preliminary" in Jay's answer. We are discussing this "fix" internally and it may be withdrawn. Consider the zEquivalent directive in this new plunker or just wait until the dust settles.

Update 12 March
I found what I believe is a better solution for your use case because it does not involve "debouncing" nor any change to Breeze. See the zEquivalent directive in this new plunker
Reminder: the "best" resolution of the problem you discovered is still up in the air within the Breeze core team. You should not lock into a particular outcome until we can make a more definitive recommendation.
p.s.: I should have mentioned that Jay and I are on the Breeze core team. We are doing our best to get you out of a jam but sometimes we move a wee too quickly. Bear with us please.
This answer deprecated as of 12 March
Leaving it here for "historical" purposes.
I think you should try the zEquivalent directive first.
It is important to know that the Angular team is working on a robust extension to data binding that includes "debounce" which is still a good idea for many scenarios. See this (long) pull request thread on the Angular GitHub site.
Original Answer
Consider the zDebounce directive currently located in this plunker which is based on #qorsmond's second attempt.
I'd like to know your thoughts. I'm inclined to call this "the solution" and to add it to Breeze Labs. I'll update this answer when/if I do add it to the labs.

you can use input type="number" step="any" and hide the arrows using css

I tracked down the behaviour in the breeze code, when the value change it is intercepted and parsed:
var coerceToFloat = function (source, sourceTypeName) {
if (sourceTypeName === "string") {
var src = source.trim();
if (src === "") return null;
var val = parseFloat(src);
return isNaN(val) ? source : val;
}
return source;
};
So when the value change this function is called that parse the string to a float, the problem is as soon as the value entered is some number and a point like 5. it parse it to the number 5 witch is obviously correct. So you will never be able to get past the point.
When changing the input to a number type it works because its sourceTypeName is not a string.
Update
I ended up changing the breeze code to enable the decimal to be entered, I’m still not sure if I missed something but this works for me.
var coerceToFloat = function (source, sourceTypeName) {
if (sourceTypeName === "string") {
var src = source.trim();
if (src === "") return null;
var val;
if (src.indexOf('.', src.length - 1) !== -1) {
val = src;
}
else {
val = parseFloat(src);
}
return isNaN(val) ? source : val;
}
return source;
};

This doesn't work for large or small numbers that might be entered using an exponent form. If I want to enter 2.55e35 (a large salary ;)) the current implementation stops at the 'e'. Is there an easy way to fix this?

Related

How does SpeechSynthesis return a chosen list of languages?

Good Morning everybody,
I am still working on a questionnaire for illiterate people. For that I am using a Text to Speech application (thanks to #JO3-W3B-D3V)
The Problem is that the questionnaire will be developped in several languages, which means, that the text to speech application has to support several languages as well.
SpeechSynthesis.getVoices()
If I understood it correctly, the function above returns a list of all objects representing all the available voices on the current device. Now to my questions:
Is there a way to return a selection of these languages? For example, the listshould not return all 15 languages which are available on the device, but only 4 chosen ones?
Is there a way to add more languages to the device? I am using Chrome. If I understood it correctly Chromes gets the languages from Microsoft and Google. Therefore Chrome should display new language-option if I add a new language to my operation system (Windows 10). Is that assupmtion correct? I am asking because I did that already and nothing changed, so I might be missing something.
Hope my questions make sense :)
Have a great day!
Explained
Okay, so I'll answer this in two parts, considering the fact that you've kinda asked two questions, both are relatively simple & straightforward thankfully.
Question One
You've asked how to get _ chosen languages that you'd like to support, well that's simple, it's as easy as manipulating an array, within my example I've used the reduce function, fairly straightforward stuff.
P.S. For the sake of some form of consistence, I've written this snippet in a very similar fashion to the one that I wrote in the other question that you asked regarding speechSynthesis.
Assumptions
As stated within the code comments, I've written this snippet in such a way that there's no duplicated entries, i.e. within the snippet below, you will end up with a list that only contains one entity that supports the English language. In other words, you won't have both en-GB & en-US, of course you can change this, I just assumed that you'd want this type of feature, of course this is down to you & your requirements entirely.
// IIFE for the sake of it.
(function() {
"use strict";
// This is a simple list of languages that you wish to support.
var supportedLanguages = ['en', 'de', 'es', 'fr'];
var languages = [];
// This is essentially similar to jQuery's $.ready.
var ready = function(callback) {
var d = document,
s = d.readyState;
// DOMContentLoaded was fired
if (s == "complete" || s == "loaded" || s == "interactive") {
callback();
} else {
if (d.addEventListener) {
d.addEventListener("DOMContentLoaded", callback, false);
} else {
d.attachEvent("onDOMContentLoaded", callback);
}
}
};
// This is just a simple function to process whether or not you'd like to
// push a voice onto the array or not.
var shouldPush = function(array, object) {
var language = object.lang || '';
var snipped = language.substring(0, 2);
// Generate a list of all of the known languages.
var languageList = array.map(function(object) {
return object.lang;
});
// Create a list of short hand language names.
var snippedList = languageList.map(function(language) {
return language.substring(0, 2);
});
// Save having a bloated if statement, personally I find this
// more readable.
//
// Only push relevant ones, saves having any duplicated entities, i.e.
// this will not allow for both en-US & en-GB to be among the list,
// this can be altered, this is merely based on an assumption that you
// wouldn't want both en-US & en-GB, etc.
var isToPush = !snippedList.includes(snipped) &&
!languageList.includes(language) &&
supportedLanguages.includes(snipped);
// If true, push to array.
if (isToPush) {
array.push(object);
}
// Then of course return the array object.
return array;
};
// This is essentially the list of voices that you've picked to support.
var getSelectedLanguages = function() {
languages = speechSynthesis.getVoices().reduce(shouldPush, []);
};
// A starting point for this snippet.
var start = function() {
speechSynthesis.onvoiceschanged = function() {
getSelectedLanguages();
console.log(languages);
};
};
// Run the code when ready.
ready(start);
})();
Question Two
I'm not entirely sure if there's a "clean & easy" way to do this, having conducted my own research on the matter I've found that it looks like this would require some form of tinkering. One of the better sources of information that I've found is this question.
Having further looked into this question, it looks like Artyom also suggests that there's no simple way to achieve this, it looks like you can only add a language by installing the language into the operating system, so I'm lead to believe.
Conclusion
One possible idea is that you could, and I emphasise the word could possibly do this via implementing an API of your own, however I can't imagine this would be a solid or reliable implementation, as my conclusion is based on research suggests in order for an additional language to be included, the user is somewhat responsible for that, as it looks like it needs the user to have _ language installed on their OS in order for speechSynthesis to make use of _ language.
I actually find it a little odd that it appears that there's little/no formal documentation on this subject, rather I've just found mostly informal documentation, suggestions and assumptions. This could however be down to my lack of investigation, bear in mind that I've spent ~15 minutes at most looking into this issue.
Sources
A link to flaviocopes.com regarding speechSynthesis.
A link to Artyom.js, a library for speech related APIs.
A link to a previous stack overflow question similar to the second part of this question.
A link to a medium article.
MDN documentation.
A treehouse blog post.
While I may not have the answer that you desire for your second question, I hope that this entire answer has helped in some form or another! :)

need direction on how to update this code, language, tutorial?

I can usually Google and find my answer, but I have no idea with this issue on where to even start. If someone could point me in the right direction here as to what language and syntax is being used here, I'd appreciate it.
This is saying "if input1 = 'option1', then output text1 into span1 and if not, input text2.
I'm sorry this is so basic, but need to learn how to edit this but I'm lost without a tutorial or guide.
$('#span1').html(input1='option1'?'text1':'text2');
This is kind of a repost from an earlier question I had where I was accused of trying to get free coding advice so I've made this as basic as possible. I'm not looking for free coding here - if someone could give me a hint as to where I could find more information, I'd appreciate it.
This is a snippet of jQuery - a javascript framework.
$('#span1').html(input1='option1'?'text1':'text2');
$ This is the jQuery "object", and passing a selector argument to it will return a jQuery-wrapped object that you can chain methods to.
#span1 selector argument (may as well be CSS)
input1='option1'?'text1':'text2' Will output "text1" or "text2" depending on wether or not the variable option1 evaluates to true. It's very likely, as u_mulder points out, that this is going to fail. Use two == or three === for comparisons!
html(...) The html method chained onto the output of the selector accepts the new value to write to that element's contents in the DOM.
Suggested reading:
What is a jQuery Object?
Which equals operator (== vs ===) should be used in JavaScript comparisons?
http://api.jquery.com/html/
https://api.jquery.com/category/selectors/
Was able to do it not using that code but a code I'm more familiar with like this:
if(pay_type == 'onetime') {
$('#bank_card_pay_type').html('one time payment');
}
else if(pay_type == 'montly') {
$('#bank_card_pay_type').html('3 monthly payments');
}
else if(pay_type == 'monthly12') {
$('#bank_card_pay_type').html('12 monthly payments');
}

Object has no method 'charAt' in jQuery plugin

I am attempting to use the autoNumeric jQuery plug-in which helps with the conversion of various currencies in jQuery.
The plug-in itself works when I use it in a jsFiddle example.
$(function () {
$('.money').autoNumeric('init', {
aSign: '$',
vMin: '-999999999.99',
nBracket: '(,)'
});
});
However, as soon as I integrate it into a big, legacy project, I start receiving the above error on line 194. I know why I'm getting the error - a string is not being passed into the negativeBracket function (negativeBracket(s, nBracket, oEvent) is the signature). Instead, it seems to be a jQuery object - e.fn.init1. I'm confused on how this might be happening. I realize the community may not be able to give a direct answer, but I would love (and will accept as an answer) being pointed in the right direction as nothing has jumped out at me so far.
Update
So, have some additional info that may be of help. It still has me stumped how it's happening (unfortunately, the answers below didn't help to provide any additional insight). When I link in autoNumeric, I key it off of any text field with the class money. It does work as I am typing in the box. I can see see formatting. However, when I tab into a new box, the box I just finished typing in clears itself completely after hitting line 152 in autoNumeric with the same exact error.
#Carlos487 was correct in his answer when he said I have an object that is not a string. I instead have an object that, I believe, is a function. Here's what I'm seeing in Chrome debugger tools:
e.fn.init[1]
> 0: input#price.money required
> context: input#price.money required
length: 1
selector: ""
> __proto__: Object[0]
The "arrowed" items can be further expanded out. I don't know if this provides any more clues, but it's at least something a bit different.
The errors like
no method XXXXX in Object
are produced because you are trying to call obj.XXXX() and obj is not of the desired type, in your particular case a string.
Have you tried in another browser because older or IE can be a little troublesome. I would recomend using chrome developer tools with your legacy app to see if anything else is conflicting or producing the error
I will bet money that you are using a second library which is interfering with jQuery. It has probably overridden $ with its own function.
Try using jQuery instead of $:
jQuery(function () {
jQuery('.money').autoNumeric('init', {
aSign: '$',
vMin: '-999999999.99',
nBracket: '(,)'
});
});
It turns out that the issue was a myriad of issue compounding into the error I saw. A couple things that was happening:
The validator plug-in was wrapping the jQuery object in its own structure (hence the charAt issue).
Once I fixed that, I also learned that some homegrown code was also wiping and rewriting data into the field to provide formatting (which is what autoNumeric is also doing), so autoNumeric would bomb out because it would get a null value and attempt to format it.
There was some other random craziness that also needed cleaned up. So...issue resolved! Still more to work on, but at least this hurdle is past. Thanks all for your help.

jQuery .val() works correctly - unless I pass it the vaue I really need

Here is a simple chunk of code:
1 var selected_clone = selected.clone();
2 alert(selected_clone.text());
3 var new_value = selected_clone.text();
4 form_li.find('input.ajax_selection').val(new_value);
Now.
Line 2 (debugging) outputs exactly the value I expect it to.
Line 3 is redundant, I know, but I used it for testing: when passing an arbitrary string to new_value, the val in line 4 works perfectly.
It does not change the value if I assign it the result of selected_clone.text()
The question is: why does it behave in such a puzzling way?
From chrome's debugging console, just chilling silence.
Additional info:
typeof(new_value) is string;
the value in the form field is actually updated: the value attribute, however is not.
about the latter point: no, it's not my debugger. the values sent on submit are non-updated.
the request sends the unupdated value; while the form displays the updated one.
Holy Shitzu this is weird.
I solved the problem by changing line 4 to: form_li.find('input.ajax_selection').attr('value',new_value);.
That does not make the slightest amount of sense to me though, and I would still like to know why.
The answer to your new question can be found in that question: .prop() vs .attr()
To understand you will need to know that val() is a shortcut to prop('value')
I would first try to know how many objects the form_li.find(...) method returns. Then I would check if
form_li.find('input.ajax_selection').attr("value",new_value)
works or not. Difficult to answer with so few code, sorry

Dojo marginBox return different value

Anyone can guide me what's the difference between
this.marginBox
and
dojo.marginBox(this.node)
I'm confusing with this two where they return different value.
What are the two values you're getting back? (I haven't used dojo for a while, but I seem to remember one of them including padding and the other not?)
Dojo only provides a dojo.marginBox() method — I am not aware of Dojo providing any kind of prototype or mixin that enables a this.marginBox method. In other words, only dojo.marginBox(this.node) is correct.
It would have helped if you provided examples of what those methods are returning for you.
I would expect:
var example = this.marginBox;
to return undefined in most circumstances. However if you have tried to assign to this.marginBox like this:
// Don't do this - marginBox is not a DOM property!
this.marginBox = 10;
then future calls to this.marginBox would return 10... it might look like it is doing something, but it's got nothing to do with Dojo or CSS and will just return what you put in... not very useful!
I would be very careful in using dojo.marginBox, I was browsing around an issue about it and I found the following:
https://bugs.dojotoolkit.org/ticket/12492
unfortunately the dojo team won't fix the problem because the method dojo.marginBox(..) will not work for hidden nodes, quoting the ticket "the behavior is undefined when called on hidden nodes".
What I did I checked the node's clientWidth / Height.

Categories

Resources