I've been doing JavaScript exercises since i haven't been doing this for too long. Got most of them working but i've been staring blind at this one.
I need to make all lowercase upper & vice versa. I checked the solution and it was helpfull but i'm sure i can get my own code ( which is very different from the answer ) working as well.
Thanks for all bits of help.
function swapCase (str) {
var sen = str;
for ( var i = 0; i < sen.length; i++) {
if (sen.charAt(i) === sen.charAt(i).toLowerCase()) {
sen.charAt(i).toUpperCase();
} else if (sen.charAt(i) === sen.charAt(i).toUpperCase()) {
sen.charAt(i).toLowerCase();
}
} return sen;
}
console.log(swapCase("UPlowUPlow"));
P.s: I am aware that it's not the cleanest bit of code but i've been working on it for a while. :)
toUpperCase and toLowerCase return the modified string, they don't modify it in place. So you'd have to put that value into the string you're processing, e.g.:
sen = sen.substring(0, i - 1) + sen.charAt(i).toUpperCase() + sen.substring(i + 1);
As that's fairly awkward, you'd probably be better off converting the string into an array of single-character strings, processing the array, then combining it again.
You can convert a string into an array of single character strings like this:
theArray = theString.split("");
...then process each entry, in a loop or via Array#map:
theArray[i] = theArray[i].toUpperCase();
...and then convert it back when done:
theString = theArray.join("");
Here's an example using Array#map:
function swapCase (str) {
var theArray = str.split("");
theArray = theArray.map(function(ch) {
var lower = ch.toLowerCase();
return ch === lower ? ch.toUpperCase() : lower;
});
return theArray.join("");
}
var str = "UPlowUPlow";
snippet.log("Before: " + str);
str = swapCase(str);
snippet.log("After: " + str);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Here's the concise version:
function swapCase (str) {
return str.split("").map(function(ch) {
var lower = ch.toLowerCase();
return ch === lower ? ch.toUpperCase() : lower;
}).join("");
}
var str = "UPlowUPlow";
snippet.log("Before: " + str);
str = swapCase(str);
snippet.log("After: " + str);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
sen.charAt(i).toUpperCase() does not change the character at the position. You need to manually update it.
function swapCase (str) {
var sen = str;
var updatedStr = "";
for ( var i = 0; i < sen.length; i++) {
if (sen.charAt(i) === sen.charAt(i).toLowerCase()) {
updatedStr += sen.charAt(i).toUpperCase();
} else if (sen.charAt(i) === sen.charAt(i).toUpperCase()) {
updatedStr += sen.charAt(i).toLowerCase();
}
}
return updatedStr;
}
As a side note, remember that strings are immutable, quoting:
In JavaScript, strings are immutable objects, which means that the
characters within them may not be changed and that any operations on
strings actually create new strings. Strings are assigned by
reference, not by value. In general, when an object is assigned by
reference, a change made to the object through one reference will be
visible through all other references to the object. Because strings
cannot be changed, however, you can have multiple references to a
string object and not worry that the string value will change without
your knowing it
Thanks for the great answers, people!
Thanks to you guys, i "solved" this in seconds while i was working on it for a good amount of time.
I'd love to upvote your answers instead of writing a thank you note, but i'm not yet allowed to do that. So, i'll do it this way.
Related
I am working on a PDF with some scripting, and I am applying code to fields using the console and some simple loops to save on repeated efforts. In some cases, I am applying a custom calculation script to a field where one integer needs to change from one field to the next. If all the scripts were the same, I would run this in the debugger console:
var s = "if(this.getField(\"Span A\").value >= 60){\n\
event.value = Math.round(((this.getField(\"Span A\").value*41500 - 1674500)/233));\n\
}else{\n\
event.value = Math.round((this.getField(\"Span A\").value*3500/60));\n\
}";
for (var i = 0; i < this.numFields; i++){
var f = this.getField(getNthFieldName(i));
if(f.name.match(/quant a/i) != null){
var n = f.name.match(/\d/g);
f.setAction("Calculate", s);
}
}
I have many 'Quant' fields, and each group (A, B, etc) will have a similar calculation. The fields are name "Quant A1", "Quant A2" etc. Quant A1 needs to calculate with the input from Span A1.
In the above script, it would be really cool if I could have a variable within the script string that I can pass a value (n) to be plugged in to the string, essentially the same way a function call works.
Is this possible?
Here is my fantasy version of what I imagine it could look like (this is just to further explain my intent; I don't think this would actually work this way):
var s(x) = "if(this.getField(\"Span A\""x").value >= 60){\n\
event.value = Math.round(((this.getField(\"Span A\""x").value*41500 - 1674500)/233));\n\
}else{\n\
event.value = Math.round((this.getField(\"Span A\""x").value*3500/60));\n\
}";
for (var i = 0; i < this.numFields; i++){
var f = this.getField(getNthFieldName(i));
if(f.name.match(/quant a/i) != null){
var n = f.name.match(/\d/g);
f.setAction("Calculate", s(n));
}
}
You could use string litterals if you're useing ES6 and higher.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals?retiredLocale=nl
const greetings = "I'm a variable!";
let string = `Hi! this is a variable: ${greetings}`;
console.log(string);
Otherwise concatenate it with the + operator.
If I understand correctly your question. I think you want to use template literals.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
Use backticks instead of " or ' to insert your variables inside a string.
const a ='Cheese'
const b= 'is Delicious'
${a} ${b} will output 'Cheese is Delicious'
I am trying to do a simple If function in zapier that returns a number between 1-10 based on another number input. for example if the number input is equal to 7200000 it should output 2. so far i have this:
if (inputData.num === '7200000') {
output = '2';
} else {
output = inputData.num;
}
This is giving me the error "You must return a single object or array of objects."
Can anyone help with this?
Thanks in advance :)
I found the solution,
Input Data: ms = TimeEstimate
var d = new Date(1000*Math.round(inputData.ms/1000));
function pad(i) { return ('0'+i).slice(-2); }
var str = d.getUTCHours() + ',' + pad(d.getUTCMinutes());
console.log(str);
output = [{str}];
I'm fairly new to Javascript, and am confused on something. Why can't the command "println("..."); be called as a variable such as: var num = println("...");. I could be wrong, and if you are able to, I'd be happy to know how. But after some testing it seems like I can't. My test code is:
function start() {
var SENTINEL = "1 1";
var rollOne = Randomizer.nextInt(1, 6);
var rollTwo = Randomizer.nextInt(1, 6);
var num = println(rollOne + rollTwo);
if(num == SENTINEL) {
println("You did it");
}
}
All it's supposed to do is give to random numbers in a # # form and, if it sees that the numbers are 1,1, it will give a message. It wont give the message and can't seem to view the variable "num" as an actual variable. But when I change the variable num to simply asking the user for a number:
function start() {
var SENTINEL = -1;
var rollOne = Randomizer.nextInt(1, 6);
var rollTwo = Randomizer.nextInt(1, 6);
var num = readInt("Enter number");
if(num == SENTINEL) {
println("You did it");
}
}
And type in -1, it triggers the sentinel, thus promptly displaying the message. This is a really roundabout way to ask a simple question but I hope I can get some help. Thank you :)
Why can't the command "println("..."); be called as a variable such as: var num = println("...");
[...] It wont give the message and can't seem to view the variable
If the value returned is unusable, it is most likely undefined; i.e. The function println doesn't explicitly return anything.
In your case, you could try something like this:
var printInt = function(num) { println(num); return num; }
Note, println isn't part of the standard JavaScript language. For modern web browsers, it can be adapted to use (console.log(...)).
var printInt = function(num) { console.log(num); return num; }
And then to adapt to your code:
var num = printInt(rollOne + rollTwo);
But this still won't validate because you're comparing against "1 1" whereas your logic will return 2. JavaScript (as well as many other languages) implicitly uses addition when supplied with two numbers, but concatenation when supplied with at least one string.
var SENTINEL = "1 1"; // <---- String!
var SENTINEL = -1; // <---- Number!
So you should consider something like this instead (renamed accordingly):
var printRolls = function(text) { println(text); return text; }
var rolls = printRolls(rollOne + " " + rollTwo);
if(rolls == SENTINEL) {
println("You did it");
}
Or to simplify it a bit:
if(printRolls(rollOne + " " + rollTwo) == SENTINEL)
println("You did it");
It is possible that println doesn't return the string that is passed into. In that case, you can use
if (SENTINEL === rollOne + " " + rollTwo)
to format the string and properly test equality.
In JavaScript it is possible to assign the return value from any function to a variable similar to how you've done it:
var anyVariable = anyFunction();
But, some functions return the value undefined. Or they return a number, or an array, or...whatever.
I imagine your println() function prints the value you pass to it somewhere (on the screen? to the console?) and then returns undefined. Or if it is returning the printed value it is in a format different to what you have used in your SENTINEL variable. So then when you try to compare that with SENTINEL it won't be equal.
To fix your original function, assign the sum of the rolls to a variable, then print and test that:
function start() {
var SENTINEL = 2;
var rollOne = Randomizer.nextInt(1, 6);
var rollTwo = Randomizer.nextInt(1, 6);
var num = rollOne + rollTwo;
println(num);
if(num == SENTINEL) {
println("You did it");
}
}
EDIT: if you want the println() to display a string like "1 1" or "3 5" to show what each of the two rolls were then do this:
println(rollOne + " " + rollTwo);
That is, create a new string that is the result of concatenating rollOne's value with a single space and then rollTwo's value.
I'm programming my own autocomplete textbox control using C# and javascript on clientside. On client side i want to replace the characters in string which matching the characters the user was searching for to highlight it. For example if the user was searching for the characters 'bue' i want to replace this letters in the word 'marbuel' like so:
mar<span style="color:#81BEF7;font-weight:bold">bue</span>l
in order to give the matching part another color. This works pretty fine if i have 100-200 items in my autocomplete, but when it comes to 500 or more, it takes too mutch time.
The following code shows my method which does the logic for this:
HighlightTextPart: function (text, part) {
var currentPartIndex = 0;
var partLength = part.length;
var finalString = '';
var highlightPart = '';
var bFoundPart = false;
var bFoundPartHandled = false;
var charToAdd;
for (var i = 0; i < text.length; i++) {
var myChar = text[i];
charToAdd = null;
if (!bFoundPart) {
var myCharLower = myChar.toLowerCase();
var charToCompare = part[currentPartIndex].toLowerCase();
if (charToCompare == myCharLower) {
highlightPart += myChar;
if (currentPartIndex == partLength - 1)
bFoundPart = true;
currentPartIndex++;
}
else {
currentPartIndex = 0;
highlightPart = '';
charToAdd = myChar;
}
}
else
charToAdd = myChar;
if (bFoundPart && !bFoundPartHandled) {
finalString += '<span style="color:#81BEF7;font-weight:bold">' + highlightPart + '</span>';
bFoundPartHandled = true;
}
if (charToAdd != null)
finalString += charToAdd;
}
return finalString;
},
This method only highlight the first occurence of the matching part.
I use it as follows. Once the request is coming back from server i build an html UL list with the matching items by looping over each item and in each loop i call this method in order to highlight the matching part.
As i told for up to 100 items it woks pretty nice but it is too mutch for 500 or more.
Is there any way to make it faster? Maybe by using regex or some other technique?
I also thought about using "setTimeOut" to do it in a extra function or maybe do it only for the items, which currently are visible, because only a couple of items are visible while for the others you have to scroll.
Try limiting visible list size, so you are only showing 100 items at maximum for example. From a usability standpoint, perhaps even go down to only 20 items, so it would be even faster than that. Also consider using classes - see if it improves performance. So instead of
mar<span style="color:#81BEF7;font-weight:bold">bue</span>l
You will have this:
mar<span class="highlight">bue</span>l
String replacement in JavaScript is pretty easy with String.replace():
function linkify(s, part)
{
return s.replace(part, function(m) {
return '<span style="color:#81BEF7;font-weight:bold">' + htmlspecialchars(m) + '</span>';
});
}
function htmlspecialchars(txt)
{
return txt.replace('<', '<')
.replace('>', '>')
.replace('"', '"')
.replace('&', '&');
}
console.log(linkify('marbuel', 'bue'));
I fixed this problem by using regex instead of my method posted previous. I replace the string now with the following code:
return text.replace(new RegExp('(' + part + ')', 'gi'), "<span>$1</span>");
This is pretty fast. Much faster as the code above. 500 items in the autocomplete seems to be no problem. But can anybody explain, why this is so mutch faster as my method or doing it with string.replace without regex? I have no idea.
Thx!
I am iterating NodeList to get Node data, but while using Node.innerHTML i am getting the tag names in lowercase.
Actual Tags
<Panel><Label>test</Label></Panel>
giving as
<panel><label>test</label></panel>
I need these tags as it is. Is it possible to get it with regular expression? I am using it with dojo (is there any way in dojo?).
var xhrArgs = {
url: "./user/"+Runtime.userName+"/ws/workspace/"+Workbench.getProject()+"/lib/custom/"+(first.type).replace(".","/")+".html",
content: {},
sync:true,
load: function(data){
var test = domConstruct.toDom(data);
dojo.forEach(dojo.query("[id]",test),function(node){
domAttr.remove(node,"id");
});
var childEle = "";
dojo.forEach(test.childNodes,function(node){
if(node.innerHTML){
childEle+=node.innerHTML;
}
});
command.add(new ModifyCommand(newWidget,{},childEle,context));
}
};
You cannot count on .innerHTML preserving the exact nature of your original HTML. In fact, in some browsers, it's significantly different (though generates the same results) with different quotation, case, order of attributes, etc...
It is much better to not rely on the preservation of case and adjust your javascript to deal with uncertain case.
It is certainly possible to use a regular expression to do a case insensitive search (the "i" flag designates its searches as case insensitive), though it is generally much, much better to use direct DOM access/searching rather than innerHTML searching. You'd have to tell us more about what exactly you're trying to do before we could offer some code.
It would take me a bit to figure that out with a regex, but you can use this:
var str = '<panel><label>test</label></panel>';
chars = str.split("");
for (var i = 0; i < chars.length; i++) {
if (chars[i] === '<' || chars[i] === '/') {
chars[i + 1] = chars[i + 1].toUpperCase();
}
}
str = chars.join("");
jsFiddle
I hope it helps.
If you are trying to just capitalise the first character of the tag name, you can use:
var s = 'panel';
s.replace(/(^.)(.*)/,function(m, a, b){return a.toUpperCase() + b.toLowerCase()}); // Panel
Alternatively you can use string manipulation (probably more efficient than a regular expression):
s.charAt(0).toUpperCase() + s.substring(1).toLowerCase(); // Panel
The above will output any input string with the first character in upper case and everything else lower case.
this is not thoroughly tested , and is highly inefficcient, but it worked quite quickly in the console:
(also, it's jquery, but it can be converted to pure javascript/DOM easily)
in jsFiddle
function tagString (element) {
return $(element).
clone().
contents().
remove().
end()[0].
outerHTML.
replace(/(^<\s*\w)|(<\/\s*\w(?=\w*\s*>$))/g,
function (a) {
return a.
toUpperCase();
}).
split(/(?=<\/\s*\w*\s*>$)/);
}
function capContents (element) {
return $(element).
contents().
map(function () {
return this.nodeType === 3 ? $(this).text() : capitalizeHTML(this);
})
}
function capitalizeHTML (selector) {
var e = $(selector).first();
var wrap = tagString(e);
return wrap[0] + capContents(e).toArray().join("") + wrap[1];
}
capitalizeHTML('body');
also, besides being a nice exercise (in my opinion), do you really need to do this?