After looking at many solutions, I got the following solutions that does exactly what I want.
SOLUTION 1 : works well except it does not work in IE(11)
I will much appreciate if someone can help me out fixing this for IE.
code taken from :https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
function checkRows(oField, oKeyEvent) {
var nKey = (oKeyEvent || /* old IE */ window.event || /* check is not supported! */ { keyCode: 38 }).keyCode,
// put here the maximum number of characters per line:
nCols = 30,
// put here the maximum number of lines:
nRows = 5,
nSelS = oField.selectionStart, nSelE = oField.selectionEnd,
sVal = oField.value, nLen = sVal.length,
nBackward = nSelS >= nCols ? nSelS - nCols : 0,
nDeltaForw = sVal.substring(nBackward, nSelS).search(new RegExp("\\n(?!.{0," + String(nCols - 2) + "}\\n)")) + 1,
nRowStart = nBackward + nDeltaForw,
aReturns = (sVal.substring(0, nSelS) + sVal.substring(nSelE, sVal.length)).match(/\n/g),
nRowEnd = nSelE + nRowStart + nCols - nSelS,
sRow = sVal.substring(nRowStart, nSelS) + sVal.substring(nSelE, nRowEnd > nLen ? nLen : nRowEnd),
bKeepCols = nKey === 13 || nLen + 1 < nCols || /\n/.test(sRow) || ((nRowStart === 0 || nDeltaForw > 0 || nKey > 0) && (sRow.length < nCols || (nKey > 0 && (nLen === nRowEnd || sVal.charAt(nRowEnd) === "\n"))));
return (nKey !== 13 || (aReturns ? aReturns.length + 1 : 1) < nRows) && ((nKey > 32 && nKey < 41) || bKeepCols);
}
<form>
<p>Textarea with fixed number of characters per line:<br />
<textarea cols="50" rows="10" onkeypress="return checkRows(this, event);" onpaste="return false;" /></textarea></p>
</form>
SOLUTION 2
It works in IE but it fails in when editing the lines. You type a line, go back using left arrow keys and type you can type 1 letter and the cursor goes back to the end.
code taken from : http://cgodmer.com/?p=55 that
//limit # of lines of a text area and length of those lines
//<textarea rows="4" chars="40" onkeyup="limitTextareaLine(this, event)" ></textarea>
//Author: CGodmer (Feb 22, 2012)
function limitTextareaLine(x, e, nRows, nChars) {
var rows = $(x).val().split("\n").length; //number of rows
var lineCharLimit = nChars; //number of characters to limit each row to
var rowLimit = nRows; //number of rows to allow
//limit length of lines
for (var i = 0; i < rows; i++) {
var rowLength = $(x).val().split("\n")[i].length;
//check to see if any of the rows have a length greater than the limit
if (rowLength > lineCharLimit) {
//if it does save the beg index of the row
var rowstartindex = $(x).val().indexOf($(x).val().split("\n")[i]);
//use the index to get a new value w/ first lineCharLimit number of characters
var newval = $(x).val().substring(0, rowstartindex + lineCharLimit)
+ $(x).val().substring(rowstartindex + rowLength, $(x).val().length);
//replace that value in the textarea
$(x).val(newval);
//set character position back to end of the modified row
setCaretPosition($(x)[0], rowstartindex + lineCharLimit);
}
}
//limit # of lines to limit to is rows attribute
while($(x).val().split("\n").length > rowLimit) {
$(x).val($(x).val().substring(0, $(x).val().length - $(x).val().split("\n")[rowLimit].length - 1));
}
}
//Set caret position in the supplied control to position
//From: http://blog.vishalon.net/index.php/javascript-getting-and-setting-caret-position-in-textarea/
function setCaretPosition(ctrl, pos) {
if (ctrl.setSelectionRange) {
ctrl.focus();
ctrl.setSelectionRange(pos, pos);
}
else if (ctrl.createTextRange) {
var range = ctrl.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea rows="5" cols="10" onkeyup="limitTextareaLine(this, event, 5, 10)" ></textarea>
Try this one, it may solve this problem.
function ValidationAddress() {
var allText;
allText = document.getElementById("<%= txtAdd1.ClientID %>").value;
allText = document.getElementById('<%=txtAdd1.ClientID%>').value;
var A = allText.split('\n');
var L = A.length;
if (L > 3 && event.keyCode != 8 && event.keyCode != 46) {
alert("You have exceeded maximum limit.Cannot insert more than 3 lines.");
valert = false;
return false;
}
var arr = allText.split("\n");
for (var i = 0; i < arr.length; i++) {
if (arr[i].length > 10) {
alert("You have exceeded the Maximum Limit..Characters per line is 70 in Address Field !");
valert = false;
return false;
}
}
}
Related
Currently using Dart with gsheets_api, which don't seem to have a function to convert column letters to numbers (column index)
As an example , this is what I use with AppScript (input: column letter, output: column index number):
function Column_Nu_to_Letter(column_nu)
{
var temp, letter = '';
while (column_nu > 0)
{
temp = (column_nu - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
column_nu = (column_nu - temp - 1) / 26;
}
return letter;
};
This is the code I came up for Dart, it works, but I am sure there is a more elegant or correct way to do it.
String colLetter = 'L'; //Column 'L' as example
int c = "A".codeUnitAt(0);
int end = "Z".codeUnitAt(0);
int counter = 1;
while (c <= end) {
//print(String.fromCharCode(c));
if(colLetter == String.fromCharCode(c)){
print('Conversion $colLetter = $counter');
}
counter++;
c++;
}
// this output L = 12
Do you have any suggestions on how to improve this code?
First we need to agree on the meaning of the letters.
I believe the traditional approach is "A" is 1, "Z" is 26, "AA" is 27, "AZ" is 52, "BA" is 53, etc.
Then I'd probably go with something like these functions for converting:
int lettersToIndex(String letters) {
var result = 0;
for (var i = 0; i < letters.length; i++) {
result = result * 26 + (letters.codeUnitAt(i) & 0x1f);
}
return result;
}
String indexToLetters(int index) {
if (index <= 0) throw RangeError.range(index, 1, null, "index");
const _letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (index < 27) return _letters[index - 1];
var letters = <String>[];
do {
index -= 1;
letters.add(_letters[index.remainder(26)]);
index ~/= 26;
} while (index > 0);
return letters.reversed.join("");
}
The former function doesn't validate that the input only contains letters, but it works correctly for strings containing only letters (and it ignores case as a bonus).
The latter does check that the index is greater than zero.
A simplified version base on Irn's answer
int lettersToIndex(String letters) =>
letters.codeUnits.fold(0, (v, e) => v * 26 + (e & 0x1f));
String indexToLetters(int index) {
var letters = '';
do {
final r = index % 26;
letters = '${String.fromCharCode(64 + r)}$letters';
index = (index - r) ~/ 26;
} while (index > 0);
return letters;
}
How can I create function that convert large number into shorten number with character in Dart?
like
1000 => 1K
10000 => 10K
1000000 => 1M
10000000 => 10M
1000000000 => 1B
There is a built-in function in Dart that can be used and it's simple:
var f = NumberFormat.compact(locale: "en_IN");
print(f.format(12345));
to make it a method:
getShortForm(var number) {
var f = NumberFormat.compact(locale: "en_US");
return f.format(number);
}
for this to work import
import 'package:intl/intl.dart';
Refer to this doc for more https://pub.dev/documentation/intl/latest/intl/NumberFormat-class.html
If you are looking for a hard way:
getShortForm(int number) {
var shortForm = "";
if (number != null) {
if (number < 1000) {
shortForm = number.toString();
} else if (number >= 1000 && number < 1000000) {
shortForm = (number / 1000).toStringAsFixed(1) + "K";
} else if (number >= 1000000 && number < 1000000000) {
shortForm = (number / 1000000).toStringAsFixed(1) + "M";
} else if (number >= 1000000000 && number < 1000000000000) {
shortForm = (number / 1000000000).toStringAsFixed(1) + "B";
}
}
return shortForm;
}
String toString(int value) {
const units = <int, String>{
1000000000: 'B',
1000000: 'M',
1000: 'K',
};
return units.entries
.map((e) => '${value ~/ e.key}${e.value}')
.firstWhere((e) => !e.startsWith('0'), orElse: () => '$value');
}
A simpler approach, if you only need the suffix. It may not be compiling, but this is the idea.
String getSuffix (int t)
{
int i = -1;
for ( ; (t /= 1000) > 0 ; i++ );
return ['K','M','B'][i];
}
Edit
This is the mathematical way to do it, and it compiles. The point is you are searching for the amount of "groups of 3 decimal" places:
x 000 - 1
x 000 000 - 2
and so on. Which is log1000 number.
String getSuffix (int num)
{
int i = ( log(num) / log(1000) ).truncate();
return (num / pow(1000,i)).truncate().toString() + [' ','K','M','B'][i];
}
The Intl package does this as "compact" numbers, but it has a fixed format and it will also change with different locales, which might or might not be what you want.
Make a class and used its static method every where.
class NumberFormatter{
static String formatter(String currentBalance) {
try{
// suffix = {' ', 'k', 'M', 'B', 'T', 'P', 'E'};
double value = double.parse(currentBalance);
if(value < 1000){ // less than a thousand
return value.toStringAsFixed(2);
}else if(value >= 1000 && value < (1000*100*10)){ // less than a million
double result = value/1000;
return result.toStringAsFixed(2)+"k";
}else if(value >= 1000000 && value < (1000000*10*100)){ // less than 100 million
double result = value/1000000;
return result.toStringAsFixed(2)+"M";
}else if(value >= (1000000*10*100) && value < (1000000*10*100*100)){ // less than 100 billion
double result = value/(1000000*10*100);
return result.toStringAsFixed(2)+"B";
}else if(value >= (1000000*10*100*100) && value < (1000000*10*100*100*100)){ // less than 100 trillion
double result = value/(1000000*10*100*100);
return result.toStringAsFixed(2)+"T";
}
}catch(e){
print(e);
}
}
}
I have a converted for-loop in Swift 3.2 that looks similar to this:
for var i in 0..<char.characters.count {
if(self.characters.count > len && ((currentIndex + length2323) < length))
{
i = i - 1
}
}
But, It doesn't work properly. I want to continue loop when set value for i is i = i - 1 but this code getting out of loop
And my previous Swift 2 code is :
for(var i = 0 ; i < char.characters.count ; i += 1) {
if(self.characters.count > len && ((currentIndex + length2323) < length))
{
i = i - 1
}
}
for (index, item) in char.enumerated()
{
//your loop
}
Swift 4 syntax
import UIKit
var char = "char"
var len = 9
var currentIndex = 1
var length2323 = 2323
var length = 17
for var i in 0..<char.count {
if (self.count > len) && ((currentIndex + length2323) < length) {
i = i - 1
}
}
Swift 3.2 syntax
import UIKit
var char = "char"
var len = 9
var currentIndex = 1
var length2323 = 2323
var length = 17
for var i in 0..<char.characters.count {
if (self.characters.count > len) && ((currentIndex + length2323) < length) {
i = i - 1
}
}
I have a Google Sheet with the following layout:
Number | Counted? | Cumulative Total
4 | Y | 4
2 | | 6
9 | Y | 15
... | ... | ...
The first cell in the Cumulative Total column is populated with this formula:
=ArrayFormula((SUMIF(ROW(C2:C1000),"<="&ROW(C2:1000),C2:C1000)
However this counts all rows in the 'Number' column. How can I make the Cumulative Total only count rows where the Counted? cell is Y?
Try this in C2 and copy down:
= N(C1) + A2 * (B2 = "Y")
Update
Doesn't seem to work with SUMIFS, but there is a very slow matrix multiplication alternative:
=ArrayFormula(MMult((Row(2:1000)>=Transpose(Row(2:1000)))*Transpose(A2:A1000*(B2:B1000="Y")), Row(2:1000)^0))
Assuming "Number" in column A and "Counted?" in column B, try in C1
={"SUM"; ArrayFormula(if(ISBLANK(B2:B),,mmult(transpose(if(transpose(row(B2:B))>=row(B2:B), if(B2:B="Y", A2:A,0), 0)),row(B2:B)^0)))}
(Change ranges to suit).
Example
custom formula sample:
=INDEX(IF(B3:B="","", runningTotal(B3:B,1,,A3:A)))
sample file
source code
related
code:
/**
* Get running total for the array of numbers
* by makhrov.max#gmail.com
*
* #param {array} numbers The array of numbers
* #param {number} total_types (1-dafault) sum, (2) avg, (3) min, (4) max, (5) count;
* 1-d array or number
* #param {number} limit number of last values to count next time.
* Set to 0 (defualt) to take all values
* #param {array} keys (optional) array of keys. Function will group result by keys
* #return The hex-code of cell background & font color
* #customfunction
*/
function runningTotal(numbers, total_types, limit, keys) {
// possible types to return
var oTypes = {
'1': 'sum',
'2': 'avg',
'3': 'min',
'4': 'max',
'5': 'count'
}
// checks and defaults
var errPre = '🥴 ';
if( typeof numbers != "object" ) {
numbers = [ [numbers] ];
}
total_types = total_types || [1];
if( typeof total_types != "object" ) {
total_types = [ total_types ];
}
if( keys && typeof keys != "object" ) {
keys = [ [keys] ];
}
if (keys) {
if (numbers.length !== keys.length) {
throw errPre + 'Numbers(' +
numbers.length +
') and keys(' +
keys.length +
') are of different length'; }
}
// assign types
var types = [], type, k;
for (var i = 0; i < total_types.length; i++) {
k = '' + total_types[i];
type = oTypes[k];
if (!type) {
throw errPre + 'Unknown total_type = ' + k;
}
types.push(type);
}
limit = limit || 0;
if (isNaN(limit)) {
throw errPre + '`limit` is not a Number!';
}
limit = parseInt(limit);
// calculating running totals
var result = [],
subres = [],
nodes = {},
key = '-',
val;
var defaultNode_ = {
values: [],
count: 0,
sum: 0,
max: null,
min: null,
avg: null,
maxA: Number.MIN_VALUE,
maxB: Number.MIN_VALUE,
maxC: Number.MIN_VALUE,
minA: Number.MAX_VALUE,
minB: Number.MAX_VALUE,
minC: Number.MAX_VALUE
};
for (var i = 0; i < numbers.length; i++) {
val = numbers[i][0];
// find correct node
if (keys) { key = keys[i][0]; }
node = nodes[key] ||
JSON.parse(JSON.stringify(defaultNode_));
/**
* For findig running Max/Min
* sourse of algorithm
* https://www.geeksforgeeks.org
* /sliding-window-maximum-maximum-of-all-subarrays-of-size-k/
*/
// max
//reset first second and third largest elements
//in response to new incoming elements
if (node.maxA<val) {
node.maxC = node.maxB;
node.maxB = node.maxA;
node.maxA = val;
} else if (node.maxB<val) {
node.maxC = node.maxB;
node.maxB = val;
} else if (node.maxC<val) {
node.maxC = val;
}
// min
if (node.minA>val) {
node.minC = node.minB;
node.minB = node.minA;
node.minA = val;
} else if (node.minB>val) {
node.minC = node.minB;
node.minB = val;
} else if (node.minC>val) {
node.minC = val;
}
// if limit exceeds
if (limit !== 0 && node.count === limit) {
//if the first biggest we earlier found
//is matching from the element that
//needs to be removed from the subarray
if(node.values[0]==node.maxA) {
//reset first biggest to second and second to third
node.maxA = node.maxB;
node.maxB = node.maxC;
node.maxC = Number.MIN_VALUE;
if (val <= node.maxB) {
node.maxC = val;
}
} else if (node.values[0]==node.maxB) {
node.maxB = node.maxC;
node.maxC = Number.MIN_VALUE;
if (val <= node.maxB) {
node.maxC = val;
}
} else if (node.values[0]==node.maxC) {
node.maxC = Number.MIN_VALUE;
if (val <= node.maxB) {
node.maxC = val;
}
} else if(node.values[0]==node.minA) {
//reset first smallest to second and second to third
node.minA = node.minB;
node.minB = node.minC;
node.minC = Number.MAX_VALUE;
if (val > node.minB) {
node.minC = val;
}
}
if (node.values[0]==node.minB) {
node.minB = node.minC;
node.minC = Number.MAX_VALUE;
if (val > node.minB) {
node.minC = val;
}
}
if (node.values[0]==node.minC) {
node.minC = Number.MAX_VALUE;
if (val > node.minB) {
node.minC = val;
}
}
// sum
node.sum -= node.values[0];
// delete first value
node.values.shift();
// start new counter
node.count = limit-1;
}
// add new values
node.count++;
node.values.push(val);
node.sum += val;
node.avg = node.sum/node.count;
node.max = node.maxA;
node.min = node.minA;
// remember entered values for the next loop
nodes[key] = node;
// get the result depending on
// selected total_types
subres = [];
for (var t = 0; t < types.length; t++) {
subres.push(node[types[t]]);
}
result.push(subres);
}
// console.log(JSON.stringify(nodes, null, 4));
return result;
}
This ActionScript code I have been working on for a few days now works 100% just fine in JavaScript, but when I try to compile it in ActionScript it says I have unexpected /, ), and } symbols. Is this syntax wrong and if so how should I fix it? I figured I could test it as Javascript for quicker testing using http://jsfiddle.net/ but now I'm like =(
var txt = "This is a [rainbow]test to show that I can[/rainbow] make whatever I want [rainbow]appear as a rainbow[/rainbow] because I am [rainbow]awesome[/rainbow].";
if ((txt.indexOf("[rainbow]") > -1) && (txt.indexOf("[/rainbow]") > -1)) {
var colors = ['f0f', 'f0c', 'f09', 'f06', 'f03', 'f00', 'f30', 'f60', 'f90', 'fc0', 'ff0', 'cf0', '9f0', '6f0', '3f0', '0f0', '0f3', '0f6', '0f9', '0fc', '0ff', '0cf', '09f', '06f', '03f', '00f', '30f', '60f', '90f', 'c0f'];
function rainbowify(text) {
return text.replace(/\[rainbow\](.+?)\[\/rainbow\]/g, function(_, inner) {
return inner.replace(/./g, function(ch, i) {
return '<font color="#' + colors[i % colors.length] + '">' + ch + '</font>';
});
})
}
txt = rainbowify(txt);
document.write(txt);
}​
Well, this is it:
txt = txt.replace("'", "#");
if ((txt.indexOf("[rainbow]") > -1) && (txt.indexOf("[/rainbow]") > -1)) {
var firstChar = txt.indexOf("[rainbow]") + 9;
var lastChar = txt.indexOf("[/rainbow]");
while (lastChar <= txt.lastIndexOf("[/rainbow]")) {
var RAINBOWTEXT = '';
var i = firstChar;
while (i < lastChar) {
RAINBOWTEXT += txt.charAt(i);
i++
}
var text = RAINBOWTEXT;
var texty = '';
colors = new Array('ff00ff','ff00cc','ff0099','ff0066','ff0033','ff0000','ff3300','ff6600','ff9900','ffcc00','ffff00','ccff00','99ff00','66ff00','33ff00','00ff00','00ff33','00ff66','00ff99','00ffcc','00ffff','00ccff','0099ff','0066ff','0033ff','0000ff','3300ff','6600ff','9900ff','cc00ff');
i = 0;
while (i <= text.length) {
var t = text.charAt(i);
if (t != undefined) {
texty += "<font color=\"#" + colors[i % colors.length] + "\">" + t + "</font>";
i++;
}
}
texty = texty.replace("> <", "> <");
var REPLACEME = "[rainbow]" + RAINBOWTEXT + "[/rainbow]";
txt = txt.replace(REPLACEME, texty);
if (lastChar == txt.lastIndexOf("[/rainbow]")) {
break;
}
nextChar = lastChar + 10;
firstChar = txt.indexOf("[rainbow]", lastChar) + 9;
lastChar = txt.indexOf("[/rainbow]", lastChar);
}
}
txt = txt.replace("#", "'");