How to replace output properly? - replace

I recently built a dice game. I asked for help on how to build a functioning button, and was able to make it. Now I'm trying to make it so that each result replaces the previous output, so I can roll the dice over and over, but only have one dice roll on the page at a time (so not a list of rolls).
Please tell me what I'm doing wrong with my below code, as I have looked up .replace and it seems to me that it should work.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My own personal Dice Roll</title>
<script src="dice.js"></script>
</head>
<body>
<button onclick="diceRoll();" id="roll">Throw Dice</button>
<h2>Dice Game:</h2>
<div id= "output"></div>
</body>
</html>
JS
function diceRoll() {
const value = [ 1, 2, 3, 4, 5, 6 ];
let random = Math.floor(Math.random() * value.length + 1);
let roll = `You rolled: ${random}`;
output(roll);
}
function output(message) {
document.getElementById('output').innerHTML += roll.replace(message + '<br/><br/>');
}

Change
document.getElementById('output').innerHTML += roll.replace(message + '<br/><br/>');
to
document.getElementById('output').innerHTML = message;
You can't reference roll from within the output function. It doesn't exist there. It existed in the diceRoll function, and you passed its value to the output function as message, so you refer to that value as message in the output function.
x += y is shorthand for x = x + y, meaning you're adding y to x. If you want to overwrite the value instead, you just use =.
The replace method is different. To use the replace method, you need three things. You need a string that you're interested in. Then you need another string you want to search for within that first string. Then, if you found that second string within the first string, you need a third string to replace it with. It works like this:
var interestingString = "i hate js";
var searchString = "hate";
var replaceString = "love";
console.log( interestingString.replace(searchString, replaceString) );
You could use this method to accomplish what you're trying to do, but it would be way over the top. It'd be like this:
document.getElementById('output').innerHTML = document.getElementById('output').innerHTML.replace(document.getElementById('output').innerHTML, message);

Related

DataGridview I tried an if-else-condition in DataGridView cells

DataGridView
I tried an if-else-condition in DataGridView cells
Dim RowIdx As Integer
RowIdx = dgAttendance.CurrentRow.Index
If dgAttendance.Item(3, RowIdx).Value = "P" Or dgAttendance.Item(3,
RowIdx).Value = "P " Then
dgAttendance.Item(3, RowIdx).Value = "A"
EndIF
Please give the solution in C#. How do i use that if-else-statement in C#
Based on the example you provided in your comments - you should not call .ToString() when setting your value as this removes the reference to your cell and returns an independent value. Try this instead:
dg_attendance.CurrentCell.Value = "A";
You also probably want to access the value of the third cell in your row by something like this:
dg_attendance.CurrentRow[3].Value

Using ng-pattern with ng-model parsing/formatting

I'm trying to be real fancy with angular inputs by using both ng-pattern and ng-model parsing together. The regex I put in ng-pattern works fine on regex101.com, and even logging it in my app it works great. When using it in ng-pattern however, its saying my input is invalid though when it should not be. I'm wondering when ng-pattern does its thing in relation to when ngModel.$parsers/ngModel.$formatters are doing their thing, because i could see that causing it to fail. Here's some code:
Here's the ngModel parsing directive:
UI.directive('formatSeconds', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
var padZero = function (num, size) {
return ('00' + num).substr(-size);
};
var formatSeconds = function (seconds) {
var min = Math.floor(seconds / 60);
var sec = Math.floor(seconds % 60);
var ms = Math.round(((seconds % 60) - sec) * 1000);
return min + ':' + padZero(sec, 2) + ':' + padZero(ms, 3);
};
var parseTime = function (time) {
time = time.split(':');
var min = parseInt(time[0] || 0);
var sec = parseInt(time[1] || 0);
var ms = parseInt(time[2] || 0);
return min * 60 + sec + (ms / 1000);
};
ngModel.$parsers.push(parseTime);
ngModel.$formatters.push(formatSeconds);
}
};
});
Here's my regex in my controller:
$scope.timeRegex = /^([0-9]+)?\:([0-5][0-9])\:?([0-9]{3})?$/;
And here's the relevant part of my view:
<tbody ng-form name="syncForm">
<tr class="timing-entry" ng-repeat="entry in scenario.syncManifest">
<td>
<input type="text" ng-attr-name="{{'time' + $index}}" required ng-model="entry.time" format-seconds ng-pattern="timeRegex" />
</td>
</tr>
</tbody>
The time in entry is in seconds, so the formatter puts it in 0:00:000 format. Then I hoped the ng-pattern would kick in and say yes! valid! But I'm wondering if it is running when the time property is still in 0.000 format before parsing.
Angular validation is performed upon the ng-model value, that is to say:
When a value is inputted into the view, the $parsers will run and the inputted value will be transformed into how you want it stored in the ng-model. In this case, thats a number representing the number of seconds. Then the ng-pattern will work on that value - if it passes validation, ng-model will be set.
When the value is set from the controller, the ng-pattern will go to work on that raw ng-model value. I believe the $formatters will run and the formatted $viewValue will be sent to the view regardless of the validation result.
Either way - in your example, ng-pattern will be working on the integer value of seconds, not the formatted value displayed in the control.

KendoUI MVVM Table of Contents style menu

Been trying to use KendoUI templates and MVVM to create a menu that resembles a table of contents like so:
Lesson 1:
- Slide 1
- Slide 2
Lesson 2:
- Slide 1
and so on. I have the following data that I've created a kendo.observable with:
var CourseData = kendo.observable({
name: 'HTML Test Course',
lessons: [
{ // Lesson 1
name: 'Lesson 1',
slides: [
{ // Slide 1.1
name: 'Animation',
type: 'CreateJS',
cctext: '<p>...</p>',
}
]
}
]
});
Before discovering KendoUI I built the menu using plain JavaScript and for the given data it turns out like this:
<ul>
<li>
<span>Lesson 1</span>
<ul>
<li onclick="Shell.GoToSlide(1, 1)" class="unlocked"><!-- 0 = locked, 1 = unlocked, 2 = viewed, 3 = completed -->
<span>Animation</span>
</li>
</ul>
</li>
</ul>
The two pieces of this puzzle that I am having trouble expressing together are the progress (noted by the class) and the click event. Progress is stored in either a jagged array right in CourseData (like CourseData.progress = [[3]], so CourseData.progress[lesson][slide] will give the progress of that slide.) or if it would better solve this conundrum I would consider moving it to each slide object (like CourseData.lessons[lesson].slides[slide].progress). The click event calls a navigation function written elsewhere that brings up the slides using their lesson and slide number (base 1) and is not added to the item if progress is locked.
With templates, I can do something like the following:
<script type="text/x-kendo-template" id="coursemap-template">
# for (var l = 0; l < lessons.length; l++) { #
<li>
<span>#: lessons[l].name #</span>
<ul>
# for (var s = 0; s < lessons[l].slides.length; s++) { #
<li onclick="Shell.GoToSlide(#: s + 1 #, #: l + 1 #)"><span>#: lessons[l].slides[s].name #</span></li>
# } #
</ul>
</li>
# } #
</script>
To get easy access to the indices of each lesson and slide, but it won't let me bind to a specific element in an array like: data-bind="attr: { class: progress[l][s] }" when Kendo evaluates this binding later it does not know what l and s are, nor can I think of an elegant way to translate the numbers into the appropriate strings. If I use class="#: ['locked','unlocked','viewed','completed'][progress[l][s]] #" it works but does not automatically update when the progress changed. If I used nested templates and made progress a property of slide I could bind to it no problem but then I wouldn't know how to get the lesson and slide indices for the click event without tons of indexOf calls or parent().parent() shenanigans. Thoughts?
Not the ideal solution, but this question has enough views that I suppose I should provide the code I used as a workaround:
View:
<ul id="coursemap"></ul>
ViewModel:
(function () {
for (var l = 0; l < CourseData.lessons.length; l++) {
var lessonItem = document.createElement('li');
$(lessonItem).attr('data-bind', 'html: lessons[' + l + '].name');
$('#coursemap').append(lessonItem);
var slides = document.createElement('ul');
for (var s = 0; s < CourseData.lessons[l].slides.length; s++) {
var slideItem = document.createElement('li');
$(slideItem).attr('data-bind', 'html: lessons[' + l + '].slides[' + s + '].name, attr: { data-progress: progress[' + l + '][' + s + '] }');
(function (lesson, slide) {
$(slideItem).click(function () {
// If the target slide is not locked, navigate.
if ($(this).attr('data-progress') != 0) {
Shell.GoToSlide(slide, lesson);
ExtensionManager.AutoHide();
}
})
})(l + 1, s + 1);
$(slides).append(slideItem);
}
$('#coursemap').append(slides);
}
kendo.bind($('#coursemap'), CourseData);
})();

Writing methods that call other methods inside d3 ember components?

Let's say I am creating a reusable component in Ember, and I want a helper function that calls another helper function defined within. For example,
App.SomeCoolComponent = Ember.Component.extend
offset: 50
position: (x) -> x * 100
offsetPosition: # would like (x) -> position(x) + offset
So conceptually, return a function that would evaluate the position at x, add offset, and return value. Obviously this is a silly example and I could just write offSetPosition without calling position, but in a more complex scenario that is repeating code. The problem is I can't figure out how to get this to work. I tried
offsetPosition: (x) -> #get('position')(x) + #get('offset')
which fails because #get isn't defined within the function, it has the wrong scope. I've tried to insert things like Ember.computed in various places also with no luck, e.g. the following also doesn't work:
offsetPosition: Ember.computed(->
(x) -> #get('position')(x) + #get('offset')).property('position', 'offset')
What is the correct way of doing this?
Ember version 1.3.0-beta.1+canary.48513b24. Thanks in advance!
Edit: seems like my problem stems from passing the function into a d3 call. For example:
App.SomeCoolComponent = Ember.Component.extend
offset: 50
position: (d, i) -> i * 100
offsetPosition: (d, i) ->
#position(d, i) + #get('offset')
# Some other code not shown
didInsertElement: ->
data = [1, 2, 3]
i = 1
d = data[i]
console.log(#position(d, i)) # works
console.log(#offsetPosition(d, i)) # works
d3.select('svg').selectAll('circle').data(data).enter().append('circle')
.attr('cx', #position) # works
.attr('cy', #offsetPosition) # fails
.attr('r', 30)
The error message is Uncaught TypeError: Object #<SVGCircleElement> has no method 'position'
Any thoughts on how to resolve this issue?
The problem is that you are passing a function offsetPosition (which references this and expects it to point to App.SomeCoolComponent) to a D3 callback where this is replaced by the DOMElement.
You can solve the problem in two ways:
Using the fat arrow syntax:
d3.select('svg').selectAll('circle').data(data).enter().append('circle')
.attr('cx', #position) # works
.attr('cy', (d, i) => #offsetPosition(d, i))
.attr('r', 30)
Using bind explicitly:
d3.select('svg').selectAll('circle').data(data).enter().append('circle')
.attr('cx', #position) # works
.attr('cy', #offsetPosition.bind(this))
.attr('r', 30)
methods (aka not computed properties) are in the current context and should just be called like a method, and not with getters/setters.
offsetPosition: (x) ->
#position(x) + #get("offset")
position: (x) ->
x * 100
Here's an example: http://emberjs.jsbin.com/eWIYICu/3/edit
App.AnAppleComponent = Ember.Component.extend({
offset: 50,
position: function(x) {
return x * 100;
},
offsetPosition: function(x) {
return this.position(x) + this.get('offset');
},
displayOffset: function(){
return this.offsetPosition(Math.floor(Math.random() * 10) + 1);
}.property('offset')
});
Personally I'd create a mixin and add my methods in there, then add the mixin wherever that logic is needed. Mixins are in the scope of whatever they are added to.
BTW You can use Ember.Get(object, 'propertyOnObject') anywhere in the app.
In response to your edit, you are passing in methods into those attribute values instead of the values of those methods (which is why it works above, but not below). There is a good chance since you are sending in those methods jquery is applying those methods later way out of scope.
didInsertElement: ->
data = [1, 2, 3]
i = 1
d = data[i]
position = #position(d, i)
offsetPosition = #offsetPosition(d, i)
console.log position
console.log offsetPosition
d3.select("svg").selectAll("circle").data(data).enter().append("circle").attr("cx", position).attr("cy", offsetPosition).attr "r", 30
I have a feeling you are wanting this to dynamically update or something along those lines, if that's the case you really want to be using computed properties, the bacon of Ember. Here's an updated version of the apple component:
http://emberjs.jsbin.com/eWIYICu/5/edit
<div {{bind-attr style='dynamicStyle'}}>
dynamicStyle: function(){
var rgb = this.get('rgb'),
rgb1 = rgb * 21 % 255,
rgb2 = rgb * 32 % 255,
rgb3 = rgb * 41 % 255;
return 'background-color:rgb(' + rgb1 + ',' + rgb2 + ',' + rgb3 + ');';
}.property('rgb'),

Split an equation string into a list of symbols with coefficient

I'd like a user to enter an equation such as :
"(-6/8) + (2/3)x + (-2/3)bar + (5/8) = (-2) + z + (-5/1245)foo"
and then get an unordered lists of li as
<li class='monome #{side}' data-value='-6/8' data-type='rationnal'></li>
or
<li class='monome #{side}' data-value='2/3' data-type='symbol' data-symbol='x'></li>
depending on term's type for each member of the equation...
an ugly solution would be :
member_as_html = (membre,side) ->
html = "<ul>"
for monome in membre
m = monome.split(")")
if m[1]
html += "<li class='monome #{side}' data-value='#{m[0][1..]}' data-type='symbol' data-symbol='#{m[1]}'></li>"
else
html += "<li class='monome #{side}' data-value='#{m[0][1..]}' data-type='rationnel'></li>"
html += "</ul>"
s = $( "#equation_string" ).val()
s = s.replace(/\s+/g, '').split("=")
ml = s[0].split("+")
mr = s[1].split("+")
ul_left = member(ml,"left")
ul_right = member(mr,"right")
but there's no verification on the string nor any flexibility on symbol length
finally to motivate people help me with those regex, here's the link of my working project.
You can play with equation till solve them : it's quite fun and useful for teacher :
http://jsfiddle.net/cphY2/
EDIT
For now, Complex equation with any level of parenthesis and operator precedence ln, exp and factorial would be too much complicated for the state of devellopment. That's why I chose this convention of a simple equation made of a sum of terms. A term could be a rationnal or a symbol (any length) with a rationnal as coefficient. Any (better) proposal about the convention used to enter the equation would be appreciated (and especially the fu##"#[|#king regex along with !)
I don't know coffeescript but here is a python solution, maybe it will get you on the right track?
s = "(-6/8) + (2/3)x + (-2/3)y + (5/8)"
s = s.split(" + ")
D = []
for u in s:
if u[-1] == ')': D += [{u,"frac"}]
else: D += [{u[0:-1],u[-1]}]