Simplifying some jQuery code of keyup inputs - javascript

Thing that I'm making
I am making a webpage, which is to generate forum code automatically
when I enter content into inputs. Each character will be in different colors and the sentence will look like a gradient.
This is the jsfiddle sample.
When I enter a-p-p-l-e in to those inputs, the result will be as follow:
[color=3173d8]a[/color][color=416cd9]p[/color][color=5e5bdb]p[/color][color=8248dd]l[/color][color=a335df]e[/color]
Question
When more and more inputs and spans are created, the js code will be so bulky. But I don't know how to simplify them. I have tried to use thing like $(this).attr('target') , it just doesn't work. Can anyone help me to make it shorter if I would like to add more inputs, like saying 30.
More
What if i want the focus move itself to the next input if that input is typed with character already? Then I will be able to type word with 'tab'.

You can simplify your code like this.
Bind the keyup event once by using the id starts with selector.
var colors = ["3173d8", "416cd9", "5e5bdb", "8248dd", "a335df"]
$("[id^=input]").each(function (i) {
$(this).css('background', '#' + colors[i]);
});
$("[id^=input]").keyup(function () {
var index = $("[id^=input]").index(this);
$("span[id^=span]").eq(index).html('[color=' + colors[index] + ']' + $(this).val() + '[/color]');
});
Note that $("[id^='input']") will return all the elements whose id starts with "input".
Demo Fiddle
Edit for changing the focus
var colors = ["3173d8", "416cd9", "5e5bdb", "8248dd", "a335df"]
$("[id^=input]").each(function(i) {
$(this).css('background', '#' + colors[i]);
});
$("[id^=input]").keyup(function() {
if ($(this).val().trim().length) {
$(this).next().focus();
}
var index = $(this).index();
$("span[id^=span]").eq(index).html('[color=' + colors[index] + ']' + $(this).val() + '[/color]');
});
Edited Fiddle

Automatic making input, and full js solution. And it's easy to add new color.
// Define color separately
var colors = [
"3173d8", "416cd9", "5e5bdb", "8248dd", "a335df"
];
(function() {
$("body")
.append('<div id="parent"></div>')
.append('<code id="output"></code>');
var f = function() {
$("#output").html("");
for (var i = 0, val = ""; i < colors.length; i++) {
val = $("#parent input[data-num=" + i + "]").val();
$("#output").append('[color=' + colors[i] + ']' + val + '[/color]');
//or $("#output").append('<span id="span'+i+'">'+c+'</span>');
}
};
for (var i = 0; i < colors.length; i++) {
$('<input size="4" maxlength="1" />')
.attr("data-num", i)
.css('background', '#' + colors[i])
.keyup(f)
.appendTo("#parent");
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

Javascript add letter after specific number of letters in a loop

I am trying to add a br sign in a input text field if it has more than 5 letters.(while writing)
My Code creates br signs after 5 letters, but it creates for than 1 br sign.
Code:
(function(i){
$('#input' + i).on('keyup', function() {
if($('#input' + i).val().length > 5) {
$('#input' + i).val($('#input' + i).val() + '<br>');
}
});
}(i))
I strongly recommend not doing this (seem comments on the question).
But if you really want to, use input, not keyup, remove previous <br> markers you've added, and break up the whole string rather than just appending at the end. See comments:
(function(i) {
$('#input' + i).on('input', function() {
// No need to look it up repeatedly, remember the jQuery wrapper for this input
var $this = $(this);
// Get the value
var val = $this.val();
if (val.length > 5) {
// Remove old <br>s
val = val.replace(/<br>/g, "");
// Add new ones
var result = "";
while (val) {
result += val.substring(0, 5);
val = val.substring(5);
if (val) {
result += "<br>";
}
}
// Set the value
$this.val(result);
}
});
}(0))
<input type="text" id="input0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Dynamic generation of select clear other elements in javascript

I have a for loop that creates as many as I write in an input field. first time I write a number in the imput all is ok... he generates for example 3 fields. When I delete 3 and write 5, he add two objects but he also clear other... if I select an option in the first , I want to keep it selected when I add some other fields....
this is an example: https://jsfiddle.net/exv8s2sq
and this is the code:
Insert number<input type="text" id="number" name="number" ><br><br>
<div id="container"></div>
<script>$('#number').on('keyup', function () {
changenumber(this.value);
});
$('#number').on('paste', function () {
changenumber(this.value);
});
var now = 0;
function changenumber(val) {
container = document.getElementById("container");
var diff = val - now;
if (diff > 0) {
for (var u = now + 1; u <= val; u++) {
container.innerHTML = container.innerHTML +
" Select from options <select id='selectobj" + u + "' name='selectobj" + u + "' style='width:25%;'>" +
"<option>A</option>" +
"<option>B</option>" +
"<option>C</option>" +
"</select><br><br>";
now = u;
}
}
}</script>
thanks
Lorenzo from Rome
Instead of using innerHTML, i would suggest using jQuery as selector and use element.append(selectbox) to add new items. I've updated your fiddle with a working example based on your code:
http://jsfiddle.net/exv8s2sq/1/
There is also room to refactor your code a bit. When using jQuery, native javascript isn't really necessary for dom manipulation.
Wrap your elements in a div with a specific class so you can easily count how many items you already have. Then depending on the number you enter, check whether you need to add or remove elements from your container.
Use jQuery selectors all the way, it is easier to identify your elements, and use the methods it provides such as .each() and .append()
$('#number').on('input', function () {
changenumber(this.value);
});
function changenumber(val) {
if (val !== '') {
// Wrap your elements in a div with a specific class
var select = '<div class="select-wrapper">Select from options <select><option>A</option><option>B</option><option>C</option></select></div>';
// Count number of selects div
var nbOfSelects = $('.select-wrapper').length;
// Check if you need to add or remove elements
if (nbOfSelects < val) {
// Add an element
for (var i = 0; i < (val - nbOfSelects); i++) {
$('#container').append(select);
}
} else {
// Loop through elements
$('.select-wrapper').each(function (i) {
// Remove an element
if (i >= val) {
$(this).remove();
}
});
}
}
}
JSFiddle demo
Try this, it adds an attribute of selected to the previous selected option using an onchange event listener
$('#number').on('keyup', function () {
changenumber(this.value);
});
$('#number').on('paste', function () {
changenumber(this.value);
});
var now = 0;
function changenumber(val) {
container = document.getElementById("container");
var diff = val - now;
if (diff > 0) {
for (var u = now + 1; u <= val; u++) {
container.innerHTML = container.innerHTML +
" Select from options <select onchange='updateDom(this)' id='selectobj" + u + "' name='selectobj" + u + "' style='width:25%;'>" +
"<option>A</option>" +
"<option>B</option>" +
"<option>C</option>" +
"</select><br><br>"; now = u;
}
}
}
function updateDom(s){
s.options[s.selectedIndex].setAttribute("selected","selected")
}

Looping through an array with CSS rules, and applying them to element

I want users to be able to input CSS input, and have that CSS applied to the last selected element(selected by the "rangeselector" variable). The code selects the right element, but only the first CSS-rule is applied.
ex: "background: blue; color:red;" only applies the background.
The function runs through the array correctly.
function customCss(){
css = $("input.css").val();
if(css.length < 10){
alert("Insert valid CSS");
}else{
cssArray = css.split(";");
counter = 0;
cssArray.forEach(function(){
var ruleSplit = cssArray[counter].split(":");
target = $("[content_child=" + rangeselector + "]");
target.css(ruleSplit[0] , ruleSplit[1]);
counter = counter + 1;
});
}
}
If you know the problem, or have a better way of achieving the same goal, i would gladly hear you suggestions.
Thanks
By using Array.forEach() you already have the index and the reference to Array. You don't need use a counter
cssArray = css.split(";");
// counter = 0;
cssArray.forEach(function(obj, key, array){
var ruleSplit = obj.split(":");
target = $("[content_child=" + rangeselector + "]");
target.css(ruleSplit[0] , ruleSplit[1]);
// counter = counter + 1;
});
have you tried stripping the elements before you set them? What's probably happening is that it's trying to set something like "color " instead of "color"
function customCss(){
css = $("input.css").val();
if(css.length < 10){
alert("Insert valid CSS");
}else{
cssArray = css.split(";");
counter = 0;
cssArray.forEach(function(){
var ruleSplit = cssArray[counter].split(":");
target = $("[content_child=" + rangeselector + "]");
target.css(ruleSplit[0].trim() , ruleSplit[1].trim());
counter = counter + 1;
});
}
}

Jquery- Dynamic added fields - prevent the last Item to be removed

I have a form field that is being duplicated / removed dynamically
See the fiddle here : http://jsfiddle.net/obmerk99/y2d4c/6/
In this feature, I also need to increment the NAME of the field ( and ID etc.. ) like so :
o99_brsa_settings[brsa_dash_wdgt_content][0]
o99_brsa_settings[brsa_dash_wdgt_content][1]
o99_brsa_settings[brsa_dash_wdgt_content][2] ...
It is working, but the problem is that when I add / remove fields , when it gets to the last ( actually first one ) , it will give me "undefined" and will not add anymore fields .
To see the problem you will need to "play" a bit with add/remove .
I believe the main problem is how to keep all of those on the same array level if we have [0] and [0][2]
I am far from a JS guru, and this code was somehow assembled from various sources. But I am kind of stuck right now, So any help will be appreciated .
Try this way:
$(function () {
$(".addScnt").on("click", function () {
var i = checkNumberOfElements();
var scntDiv = $("div[id^='widget_dup']:last");
var prevDiv = scntDiv.clone();
var newname = $(prevDiv).find("textarea").attr("name").substring(0, $(prevDiv).find("textarea").attr('name').indexOf(']'));
prevDiv.find('textarea').attr('name', newname + "][" + i + "]");
prevDiv.find('textarea').attr('id', newname + "][" + i + "]");
prevDiv.find('label').attr('for', newname + "][" + i + "]");
prevDiv.attr('id', $(prevDiv).attr('id') + "_" + i);
$(scntDiv).after(prevDiv);
});
$(document).on("click", ".remScnt", function (event) {
var i = checkNumberOfElements();
if (i <= 1) {
return false;
} else {
var target = $(event.currentTarget);
target.parent("div").remove();
}
});
});
function checkNumberOfElements() {
// Number of textareas
var i = $("textarea[name^='o99_brsa_settings[brsa_dash_wdgt_content]']").length;
// Number of divs
// var i = $("div[id^='widget_dup']").length;
if (typeof i === undefined) {
return 0;
} else {
return i;
}
}
Demo: http://jsfiddle.net/y2d4c/7/

Why doesn't .find work with this second css selector in JQuery?

When I do a .find with a name=value selector, I'm getting no elements. My syntax looks correct and I can't see what I'm doing wrong. I know the object that it is selecting from has elements, 7 to be exact, with the attribute I'm looking for. So I'm stumped as to why the .find is not working.
Javascript on page:
$(document).ready(function () {
var mainCatName = 'category.SelectedValue'
$('#Button1').on('click', function () {
var td = $('input[name="' + mainCatName + '"]:checked').parent('td');
var tdIndex = td.index();
if (selectElems == null) {
//1
selectElems = $("#pumpConfigTable td:nth-child(" + (tdIndex + 1) + ") select, #pumpConfigTable td:nth-child(" + (tdIndex + 1) + ") input");
}
var projectInfoID = $('#ProjectInfoID').attr('value');
var mainCategoryID = $('input[name="' + mainCatName + '"]:checked').attr('value');
var postBackObject = makeProjectInfoObjects(projectInfoID, mainCategoryID, selectElems);
var blah = "blah";
});
});
Partial source for makeProjectInfoObjects:
function makeProjectInfoObjects(pInfoID, mainCatID, pcOptions) {
//var pc = new PumpConfig();
var pc = new Array();
var dbIDs = _.pluck(pcOptions, "data-dbid");
var uniquedbIDs = _.unique(dbIDs);
uniquedbIDs = _.reject(uniquedbIDs, function (checkID) { return checkID == undefined; });
var len = uniquedbIDs.length;
for (var i = 0; i < len; ++i) {
//2
var categories = $(pcOptions).find("[data-dbid='" + uniquedbIDs[i] + "']");
var uniqueNames = _.pluck(categories, "name");
var singleOptions = $(categories).find(':not([name]');
var soLen = singleOptions.length;
for (var j = 0; j < soLen; ++j) {
pc.push({
pcID: uniquedbIDs[i],
pInfoID: pInfoID,
configCatID: mainCatID,
configSubCatID: $(singleOptions[i]).attr('data-subcatid'),
configValue: $(singleOptions[i]).attr('value')
});
I'm using JQuery 1.8.1 and IE8 on XP.
According to IE Developer Tools the first selector comes out to be this (and it works):
//1 "#pumpConfigTable td:nth-child(2) select, #pumpConfigTable td:nth-child(2) input"
The second selector comes out to be this (and it doesn't work):
//2 "#pumpConfigTable td:nth-child(2) select, #pumpConfigTable td:nth-child(2) input [data-dbid='1']"
If you wish to find input and select elements with a specific attribute data-dbid then you shouldn't use find() as this method searches for elements that are descendants of the elements you are selecting with your selector string:
"#pumpConfigTable td:nth-child(" + (tdIndex + 1) + ") select, #pumpConfigTable td:nth-child(" + (tdIndex + 1) + ") input"
Your matched elements will be select elements and input elements. I think I'm correct in assuming you want to find specific elements within this set? If so, try using jQuery's filter() method instead of find.
.filter( selector )
Returns: jQuery
Description: Reduce the set of matched elements to those that match the selector or pass the function's test.
So you would do this:
var categories = $(pcOptions).filter("[data-dbid='" + uniquedbIDs[i] + "']");
If you want the input to have data-dbid='1' you need to remove the space between the two:
"#pumpConfigTable td:nth-child(2) select, #pumpConfigTable td:nth-child(2) input[data-dbid='1']"

Categories

Resources