How can I optimize the below code with less number of line? - javascript

I have coded the below piece of code which handle the number bigger than 999 and add a comma to it. For example 1,000 and 1,000,000. Wheare as once the number increase the comma will be placed in the correct position. I used DRY principle and I feel still there is another easy way to handle it.
Now, I want to know if there is much better way than that I did.
Waiting for your opinion.
Thanks.
function seperate_num_by_comma() {
var num = '199228754645.25',
withOutComma = num.split('.'),
addNewCommaAfter = 3,
x = withOutComma[0].length % addNewCommaAfter,
lenOfWithOutComma_0 = withOutComma[0].length,
length_1 = withOutComma[0].length - x,
starter = 0,
wholeNumber = ' ';
for (var i = 0; i < lenOfWithOutComma_0; i++) {
function run_first_func() {
wholeNumber += withOutComma[0].substr(starter, addNewCommaAfter);
};
function run_second_fun() {
wholeNumber += withOutComma[0].substr(starter, addNewCommaAfter) + ",";
starter += addNewCommaAfter;
length_1 -= addNewCommaAfter;
};
if (x > 0) {
if (length_1 == 0) {
run_first_func();
break;
} else if (wholeNumber == ' ') {
wholeNumber += withOutComma[0].substr(starter, x) + ",";
length_1 -= addNewCommaAfter;
starter = x;
} else {
run_second_fun();
}
} else if (x == 0) {
if (length_1 == 3) {
run_first_func();
break;
}
run_second_fun();
}
}
console.log(wholeNumber + '.' + withOutComma[1]);
}
seperate_num_by_comma();

One Line:
165B minified version (no IE): seperate_by_comma=t=>(x=(""+t).split("."),z=x[0].replace(/((\d{3})*?)(\.|$)/,"|$1").split("|"),x[0]=z[0]+z[1].replace(/(.{3})/g,",$1").slice(!z[0].length),x.join("."))
OR 180B, IE-friendly: seperate_by_comma=function(t){x=(""+t).split(".");z=x[0].replace(/((\d{3})*?)(\.|$)/,"|$1").split("|");x[0]=z[0]+z[1].replace(/(.{3})/g,",$1").slice(!z[0].length);return x.join(".")}
Explanation:
seperate_num_by_comma = function(number){//12345678.9
var str = String(t);
var withoutDot = str.split("."); //["12345678", "9"]
var chunksOfThree = withoutDot[0].replace(/((\d{3})*?)(\.|$)/,"|$1");//"12|345678"
chunksOfThree = chunksOfThree.split("|");//["12", "345678"]
chunksOfThree[1] = chunksOfThree[1].replace(/(.{3})/g,",$1") //",345,678"
if(chunksOfThree[0].length==0){
chunksOfThree[1] = chunksOfThree[1].slice(1); //Fix for specific cases
}
withoutDot[0] = chunksOfThree[0] /*"12"*/ + chunksOfThree[1] /*",345,678"*/
return withoutDot.join(".") //"12,345,678.9"
}

Related

How to display image related to an array element whenever the element is mouseovered

I have an arrays of strings (warmUpAll, legsAll) . Then I have a function that randomly picks up few of them (getRandom) and displays them.
I want to display an image somewhere in DOM when the randomly picked elements are mouseovered/clicked. Do you think this could be possible? Should this be added in getRandom function or somewhere else?
here's my getRandom function:
function getRandom(arr, n) {
var result = new Array(n),
len = arr.length,
taken = new Array(len);
if (n > len)
throw new RangeError("getRandom: more elements taken than available");
while (n--) {
var x = Math.floor(Math.random() * len);
result[n] = arr[x in taken ? taken[x] : x];
taken[x] = --len in taken ? taken[len] : len;
}
if (arr == warmUpAll) {
document.getElementById("warmup").innerHTML = '<span class="exerciseheader">Warm Up - 10 minutes</span>' + "</br>" + result.join(" ");
}
else if (arr == legsAll){
document.getElementById("legsDisplay").innerHTML = '<span class="exerciseheader">Legs</span>' + "</br>" + result.join(" ");
}
}
}
HTML part of this:
<body>
<div id="warmup"></div>
<div id="legsDisplay"></div>
</body>
Thank you guys in advance.
You can write another function for hover or click ex:
function mouseHover()
{
//do something
}
and add it in your function
function getRandom(arr, n) {
//...
if (arr == warmUpAll) {
document.getElementById("warmup").innerHTML = '<span class="exerciseheader" onmouseover="mouseHover()">Warm Up - 10 minutes</span>' + "</br>" + result.join(" ");
}
else if (arr == legsAll){
document.getElementById("legsDisplay").innerHTML = '<span class="exerciseheader" onmouseover="mouseHover()">Legs</span>' + "</br>" + result.join(" ");
}
}
}

javascript random gen nr + loops

I'm trying to make an program where it randomly picks 10 questions out of X questions(got 14 random ones written at the moment) without it picking the same questions again but i've been stuck for 4 hours on this junk.
My problem is with "randomNumbers()" function. This function generates random number (which marks the question respectively) and then checks if the numberArray already has generated number. If it doesnt, the number is supposed to be pushed to array.
I think I figured out the problem to be ## VERSION 1 ## for-loops if/else conditions. Any help ? :(
//edit, is while (true) correct way to handle this?
// dont mind ##VERSION 2## it was the first way I tried solving the problem.
(a lot of console logs to determine the bug :P )
HTML
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<title>Testimiskeskkond</title>
<!--<link rel="stylesheet" type="text/css" href="style.css"/> -->
<script src="scripts/jquery-2.1.4.min.js"></script>
<script src="scripts/js.js"></script>
</head>
<body>
<button onclick="startQuiz()">Alusta testimist</button>
<div id="question1"></div>
<div id=questions></div>
</body>
JAVASCRIPT
var amountOfQuestions = 11;
var questionCounter = 0;
var numberArray = new Array();
var questions = new Array();
questions[0] = 'Mitu kassi elab P2rnus?',
questions[1] = 'Mis on kassi nimi?',
questions[2] = 'Mida kass teeb?',
questions[3] = 'Millal kass syndis?',
questions[4] = 'Mitu hammast kassil on?',
questions[5] = 'Mitu kyynt on kassil?',
questions[6] = 'Mitu k6rva on kassil?',
questions[7] = 'Mis v2rvi on kass?',
questions[8] = 'Tooli v2rvus?',
questions[9] = 'Laua suurus?',
questions[10] = 'Lemmik jook?',
questions[11] = 'Lemmik s88k?',
questions[12] = 'Raamatupoe nimi?',
questions[13] = 'Viinapoe nimi?';
function startQuiz() {
var setQuestions = "";
while (questionCounter < amountOfQuestions) {
var random = randomNumbers();
console.log(random + "appppppi");
if (questionCounter < amountOfQuestions) {
setQuestions += questions[random] + "<br>";
questionCounter += 1;
} else {
setQuestions += questions[random];
questionCounter += 1;
}
}
$('#questions').html(setQuestions);
}
function randomNumbers() {
var arrLength = numberArray.length;
while (true) {
console.log(arrLength);
var randomNr = Math.floor(Math.random() * 14);
console.log(randomNr + " tereeeeeeeeee");
/*
######################
########### VERSION 1
######################*/
if (arrLength == 0) {
console.log("pppppppppppp");
numberArray.push(randomNr);
break;
} else if (arrLength == 1) {
console.log("oooooooooooo");
if (numberArray[0] == randomNr) {
console.log("xxxxxxxxxxxxx");
break;
} else {
console.log("rrrrrrrrrrrrrrr");
numberArray.push(randomNr);
break;
}
} else {
for (var i = 0; i < arrLength-1; i++) {
console.log("yyyyyyyyyyyyyyyyyyyy");
if (numberArray[i] == randomNr) {
console.log("qqqqqqqqqqqqqqqqqqqq");
continue;
} else {
console.log("zzzzzzzzzzzzzz")
numberArray.push(randomNr);
break;
}
}
}
/*
######################
########### VERSION 2
######################
if (arrLength > 0) {
console.log("oooooooooooo");
for (var i = 0; i < arrLength; i++) {
console.log("yyyyyyyyyyyyyyyyyyyy");
if (numberArray[i] == randomNr) {
console.log("qqqqqqqqqqqqqqqqqqqq");
continue;
} else {
console.log("zzzzzzzzzzzzzz")
numberArray.push(randomNr);
break;
}
}
} else {
console.log("pppppppppppp");
numberArray.push(randomNr);
break;
} */
}
return randomNr;
}
let selectionCount = 10;
let randomQuestions = [];
while(randomQuestions.length < selectionCount) {
let randomNr = Math.floor(Math.random() * questionList.length);
if(!randomQuestions.includes(randomNr)) {
randomQuestions.push(randomNbr);
}
}

How can I change the number of columns in Gridster?

I have a a gridster based layout that will start with a set number of columns and a fixed number of tiles. Is there a way to change the number of columns once it has been set up? -- for example starting with 3 columns :
(tile1 | tile2 | tile3
tile4 | tile5 | tile6)
and changing it to a two column layout:
(tile1 | tile2
tile3 | tile4
tile5 | tile6)
The change will be driven by user interaction.
I have tried to use something like:
gridster = $("#gridster-container").gridster({
widget_margins: [30, 30],
widget_base_dimensions : [ 200, 170 ],
max_cols:numberOfColumns,
avoid_overlapped_widgets: true
}).data('gridster');
// user interaction
gridster.options.max_rows = 2;
gridster.init();
but that does not seem to work...
I have tried manually changing the data-row and data-col values to the new positions, and called init() (and not called init).
I have even tried changing the gridster code adding
// HACK
if (max_cols && max_cols < this.cols) {
this.cols = max_cols;
}
to the method fn.generate_grid_and_stylesheet (just after the line:
if (max_cols && max_cols >= min_cols && max_cols < this.cols) {
this.cols = max_cols;
}
).
I can get the tiles to move the the correct position using any of these options, but subsequent dragging behaviour is... odd.
I have set up a jsfiddle (http://jsfiddle.net/qT6qr/) to explain what I mean (please excuse the gridster.min.js in line at the top of the fidddle, I couldn't find a cdn that I could use for it...).
Thanks in advance
I just spent a couple of hours and ran across this piece of code. I just put it in a .js file and did:
var gr = $(elem).gridster(options).data('gridster');
// update options and then call this at a later point:
gr.resize_widget_dimensions(options);
And then it just worked.
Here's the code:
(function($) {
$.Gridster.generate_stylesheet = function(opts) {
var styles = '';
var max_size_x = this.options.max_size_x;
var max_rows = 0;
var max_cols = 0;
var i;
var rules;
opts || (opts = {});
opts.cols || (opts.cols = this.cols);
opts.rows || (opts.rows = this.rows);
opts.namespace || (opts.namespace = this.options.namespace);
opts.widget_base_dimensions || (opts.widget_base_dimensions = this.options.widget_base_dimensions);
opts.widget_margins || (opts.widget_margins = this.options.widget_margins);
opts.min_widget_width = (opts.widget_margins[0] * 2) +
opts.widget_base_dimensions[0];
opts.min_widget_height = (opts.widget_margins[1] * 2) +
opts.widget_base_dimensions[1];
/* generate CSS styles for cols */
for (i = opts.cols; i >= 0; i--) {
styles += (opts.namespace + ' [data-col="'+ (i + 1) + '"] { left:' +
((i * opts.widget_base_dimensions[0]) +
(i * opts.widget_margins[0]) +
((i + 1) * opts.widget_margins[0])) + 'px;} ');
}
/* generate CSS styles for rows */
for (i = opts.rows; i >= 0; i--) {
styles += (opts.namespace + ' [data-row="' + (i + 1) + '"] { top:' +
((i * opts.widget_base_dimensions[1]) +
(i * opts.widget_margins[1]) +
((i + 1) * opts.widget_margins[1]) ) + 'px;} ');
}
for (var y = 1; y <= opts.rows; y++) {
styles += (opts.namespace + ' [data-sizey="' + y + '"] { height:' +
(y * opts.widget_base_dimensions[1] +
(y - 1) * (opts.widget_margins[1] * 2)) + 'px;}');
}
for (var x = 1; x <= max_size_x; x++) {
styles += (opts.namespace + ' [data-sizex="' + x + '"] { width:' +
(x * opts.widget_base_dimensions[0] +
(x - 1) * (opts.widget_margins[0] * 2)) + 'px;}');
}
return this.add_style_tag(styles);
};
$.Gridster.add_style_tag = function(css) {
var d = document;
var tag = d.createElement('style');
tag.setAttribute('generated-from', 'gridster');
d.getElementsByTagName('head')[0].appendChild(tag);
tag.setAttribute('type', 'text/css');
if (tag.styleSheet) {
tag.styleSheet.cssText = css;
} else {
tag.appendChild(document.createTextNode(css));
}
return this;
};
$.Gridster.resize_widget_dimensions = function(options) {
if (options.widget_margins) {
this.options.widget_margins = options.widget_margins;
}
if (options.widget_base_dimensions) {
this.options.widget_base_dimensions = options.widget_base_dimensions;
}
this.min_widget_width = (this.options.widget_margins[0] * 2) + this.options.widget_base_dimensions[0];
this.min_widget_height = (this.options.widget_margins[1] * 2) + this.options.widget_base_dimensions[1];
var serializedGrid = this.serialize();
this.$widgets.each($.proxy(function(i, widget) {
var $widget = $(widget);
this.resize_widget($widget);
}, this));
this.generate_grid_and_stylesheet();
this.get_widgets_from_DOM();
this.set_dom_grid_height();
return false;
};
})(jQuery);
I had a similar problem and was able to get it working through this approach:
var gridster = $(".gridster ul").gridster().data('gridster');
gridster.options.min_cols = 5; // Not necessarily required because of the following size changes, but I did it for clarity
gridster.options.widget_base_dimensions = [240, 400];
gridster.options.min_widget_width = 240;
// This section was for existing widgets. Apparently the code for drawing the droppable zones is based on the data stored in the widgets at creation time
for (var i = 0; i < gridster.$widgets.length; i++) {
gridster.resize_widget($(gridster.$widgets[i]), 1, 1);
}
gridster.generate_grid_and_stylesheet();

Having issues with live calculations, calculating each key stroke

I have a table that calculates a total depending on the input the user types. My problem is that the jquery code is calculating each key stroke and not "grabbing" the entire number once you stop typing. Code is below, any help woud be greatly appreciated.
$(document).ready(function() {
$('input.refreshButton').bind('click', EstimateTotal);
$('input.seatNumber').bind('keypress', EstimateTotal);
$('input.seatNumber').bind('change', EstimateTotal);
});
//$('input[type=submit]').live('click', function() {
function EstimateTotal(event) {
var tierSelected = $(this).attr('data-year');
var numberSeats = Math.floor($('#numberSeats_' + tierSelected).val());
$('.alertbox_error_' + tierSelected).hide();
if (isNaN(numberSeats) || numberSeats == 0) {
$('.alertbox_error_' + tierSelected).show();
} else {
$('.alertbox_error_' + tierSelected).hide();
var seatHigh = 0;
var seatLow = 0;
var seatBase = 0;
var yearTotal = 0;
var totalsArray = [];
var currentYear = 0;
$('.tier_' + tierSelected).each(function() {
seatLow = $(this).attr('data-seat_low');
firstSeatLow = $(this).attr('data-first_seat_low');
seatHigh = $(this).attr('data-seat_high');
seatBase = $(this).attr('data-base_cost');
costPerSeat = $(this).attr('data-cost_per_seat');
years = $(this).attr('data-year');
seats = 0;
if (years != currentYear) {
if (currentYear > 0) {
totalsArray[currentYear] = yearTotal;
}
currentYear = years;
yearTotal = 0;
}
if (numberSeats >= seatHigh) {
seats = Math.floor(seatHigh - seatLow + 1);
} else if (numberSeats >= seatLow) {
seats = Math.floor(numberSeats - seatLow + 1);
}
if (seats < 0) {
seats = 0;
}
yearTotal += Math.floor(costPerSeat) * Math.floor(seats) * Math.floor(years) + Math.floor(seatBase);
});
totalsArray[currentYear] = yearTotal;
totalsArray.forEach(function(item, key) {
if (item > 1000000) {
$('.totalCost_' + tierSelected + '[data-year="' + key + '"]').append('Contact Us');
} else {
$('.totalCost_' + tierSelected + '[data-year="' + key + '"]').append('$' + item);
}
});
}
}
You'll need a setTimeout, and a way to kill/reset it on the keypress.
I'd personally do something like this:
var calc_delay;
$(document).ready(function() {
$('input.refreshButton').bind('click', runEstimateTotal);
$('input.seatNumber').bind('keypress', runEstimateTotal);
$('input.seatNumber').bind('change', runEstimateTotal);
});
function runEstimateTotal(){
clearTimeout(calc_delay);
calc_delay = setTimeout(function(){ EstimateTotal(); }, 100);
}
function EstimateTotal() {
....
What this does is prompt the system to calculate 100ms after every keypress - unless another event is detected (i.e. runEstimateTotal is called), in which case the delay countdown resets.

javascript countdown with showing milliseconds

I want to do a count down and want to show like format as Minutes:Seconds:Milliseconds. I made a count down with jquery plug-in countdown but it shows just Minutes:Seconds format.
Is there any way to make it right?
Many Thanks!
Hi guys I have developed a code for my self use the following code
counter for 20 seconds
var _STOP =0;
var value=1999;
function settimer()
{
var svalue = value.toString();
if(svalue.length == 3)
svalue = '0'+svalue;
else if(svalue.length == 2)
svalue = '00'+svalue;
else if(svalue.length == 1)
svalue = '000'+svalue;
else if(value == 0)
svalue = '0000';
document.getElementById('cn1').innerHTML = svalue[0];
document.getElementById('cn2').innerHTML = svalue[1];
document.getElementById('cn3').innerHTML = svalue[2];
document.getElementById('cn4').innerHTML = svalue[3];
value--;
if (_STOP==0 && value>=0) setTimeout("settimer();", 10);
}
setTimeout("settimer()", 10);
Try this: http://jsfiddle.net/aamir/TaHtz/76/
HTML:
<div id="timer"></div>
​
JS:
var el = document.getElementById('timer');
var milliSecondsTime = 10000;
var timer;
el.innerHTML = milliSecondsTime/1000;
timer = setInterval(function(){
milliSecondsTime = milliSecondsTime - 1000;
if(milliSecondsTime/1000 == 0) {
clearTimeout(timer);
el.innerHTML = 'BOOOOM';
}
else {
el.innerHTML = milliSecondsTime/1000;
}
},1000);
​
If you want to make your own timer.
read this earlier question
How to create a JQuery Clock / Timer
Try setting the format parameter - http://keith-wood.name/countdownRef.html#format
On further reading, this plugin doesn't do milliseconds. At this point, you either have to edit the actual plugin code or find a new plugin.
I completely agree with #Matt Ball's comment.It may also cause the browser to crash.
Why don't you try this solution instead
jQuery 1 minute countdown with milliseconds and callback
I did it like this (generic counter from N to X (X > N)):
var dynamicCounterAddNewValue = 20;
var currentDynamicUpdater;
function dynamicCounterForValueForControlUpdater(_updaterData) {
_updaterData.from += dynamicCounterAddNewValue;
if (_updaterData.from > _updaterData.to) {
_updaterData.from = _updaterData.to;
}
_updaterData.c.html(_updaterData.from.toString());
if (_updaterData.from < _updaterData.to) {
currentDynamicUpdater = setTimeout(
dynamicCounterForValueForControlUpdater,
10,
{
c: _updaterData.c,
from: _updaterData.from,
to: _updaterData.to
}
);
}
else {
clearTimeout(currentDynamicUpdater);
}
return;
}
// _c -> jQuery object (div,span)
// _from -> starting number
// _to -> ending number
function dynamicCounterForValueForControl(_c, _from, _to) {
clearTimeout(currentDynamicUpdater);
dynamicCounterForValueForControlUpdater(
{
c: _c,
from: _from,
to: _to
}
);
return;
}
EDIT: Updated version (more flexible - for N elements one after another):
(input element is Array of elements for making them dynamic-counts)
var dynamicCounterTimeout = 10;
var currentDynamicUpdater;
function odcArray(_odca) {
this.odca = _odca;
return;
}
function odc(_c, _from, _to) {
this.c = _c; // $('#control_id')
this.from = _from; // e.g. N
this.to = _to; // e.g. M => (M >= N)
var di = parseInt(_to / 45, 10);
if (di < 1) {
di = 1;
}
this.dynamicInc = di;
return;
}
function dynamicCounterForValueForControlUpdater(_odca) {
if (
_odca.odca === null
||
!_odca.odca.length
) {
clearTimeout(currentDynamicUpdater);
return;
}
var o = _odca.odca[0];
o.from += o.dynamicInc;
if (o.from > o.to) {
o.from = o.to;
_odca.odca.shift(); // Remove first element
}
o.c.html(o.from.toString());
currentDynamicUpdater = setTimeout(
dynamicCounterForValueForControlUpdater,
dynamicCounterTimeout,
_odca
);
return;
}
function dynamicCounterForValueForControl(_odca) {
clearTimeout(currentDynamicUpdater);
// SETUP all counters to default
for (var i = 0; i < _odca.odca.length; i++) {
_odca.odca[i].c.html(_odca.odca[i].from.toString());
}
dynamicCounterForValueForControlUpdater(
_odca
);
return;
}

Categories