Appending and removing URL parameters based on checkboxes - javascript

I have some filters that are being displayed as checkboxes on my website. Each time someone checks or unchecks one of these inputs I either want to add or remove the filter to/from the URL. I have this mostly working, but the problem comes when removing the last filter in the list.
Here's an example:
var getUrlParameter = function getUrlParameter(sParam) {
var sPageURL = window.location.search.substring(1),
sURLVariables = sPageURL.split('&'),
sParameterName,
i;
for (i = 0; i < sURLVariables.length; i++) {
sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] === sParam) {
return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
}
}
};
$(function () {
var colors = getUrlParameter('colors');
var currentUrl = location.href;
$('input[type="checkbox"]').change(function () {
var inputVal = $(this).val();
if (this.checked) {
// Add filter to URL params
colors = getUrlParameter('colors');
if (!colors) {
// No filters exist yet
currentUrl += '?colors=' + inputVal;
} else {
// At least one filter exists
currentUrl += ',' + inputVal;
}
console.log(currentUrl);
window.history.pushState("object or string", "Title", currentUrl);
} else {
// Remove filter from URL params
currentUrl = currentUrl.replace(inputVal + ',', '');
console.log(currentUrl);
window.history.pushState("object or string", "Title", currentUrl);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filters">
<label><input type="checkbox" value="blue" />Blue</label>
<label><input type="checkbox" value="red" />Red</label>
<label><input type="checkbox" value="green" />Green</label>
</div>
This works if the color is first(if there or other filters) or in the middle of the list of filters, since it matches my replace(), wondering how I can do this dynamically so that it will remove both the color and the comma if necessary or remove the colors= altogether if none are checked.
For example, if all 3 colors are checked the url would look like this:
http://example.net?colors=blue,red,green
If you then remove blue it should look like this:
http://example.net?colors=red,green
If you then remove green it would look like this:
http://example.net?colors=red
And finally, removing red would look like this:
http://example.net

You'll want to split your colors into an array and then merge it back again at the end.
$(function () {
var colors = getUrlParameter('colors');
var currentUrl = location.href;
$('input[type="checkbox"]').change(function () {
var inputVal = $(this).val();
var colorsQuery = getUrlParameter('colors') || "";
//Split into an array after each `,`
colors = colors.split(",");
if (this.checked) {
//Add to our current colors
colors.push(inputVal);
} else {
// Remove from our current colors
const index = colors.indexOf(inputValue);
colors.splice(index, 1);
}
colorString = "";
if(colors.length){
//Merge back into a string with a `,`
colorString = "?colors=" + colors.join(",")
}
window.history.pushState("object or string", "Title", currentUrl + colorString);
});
});
It's much easier to work with arrays in this instance so we just split and join to convert to and from an string to array.
For adding its easy we can just push onto our array
To remove a color we find out where it is in our colors array. Then using splice remove it from our array.

I'd seperate adding and removing objects, and the logic to get your querystring.
You'll see here two basic events:
Update an object based on the current checkbox (Binding directly to the state is even better!)
Generating the string based off of current values.
var colors = {
'red': false,
'blue': false,
'green': false
};
update = function(color) {
colors[color] = !colors[color];
}
getParams = function() {
var setQuery = false;
var expr = [];
for (var color in colors) {
if (colors[color]) {
expr.push(color);
setQuery = true;
}
}
if (setQuery) {
console.log("www.example.com" + "?colors=" + expr.join(","));
} else {
console.log("www.example.com");
}
}
<input type="checkbox" onchange="update('red')" /> Red
<input type="checkbox" onchange="update('blue')" /> Blue
<input type="checkbox" onchange="update('green')" /> green
<button type="button" onclick="getParams()">Get params</button>

Related

Add user input to array // Javascript

This is the code I have so far. When the user enters a word into the input box, I want that word to be stored in an array via the Add Word button. Once a number of words have been entered, the user clicks the Process Word button and I want all the words in the array to appear. How would I do this? Also could someone also explain why when nothing is entered into the input box "field is empty" does not appear?
function begin() {
var word = "List of words";
var i = returnword.length
if (userinput.length === 0) {
word = "Field is empty"
}
document.getElementById('message2').innerHTML = word
while (i--) {
document.getElementById('message').innerHTML = returnword[i] + "<br/>" + document.getElementById('message').innerHTML;
}
}
function addword() {
var arrword = [];
returnword = document.getElementById('userinput').value;
arrword.push(returnword);
}
Addword()
Your function contains an array arrword. If you keep it inside your function it will be reset every time you call the function. You need to keep your array of words outside the function
Empty input
The empty input message should be shown when you click on the Add word button. Check the input and display a message if needed
Display word
You can simply use join() to display you array
var arrayOfWord = [];
var inputElement = document.getElementById('userinput');
var errorElement = document.getElementById('error');
var wordsElement = document.getElementById('words');
function addWord() {
errorElement.innerHTML = "";
var word = inputElement.value;
if (word.trim() === "")
errorElement.innerHTML = "Empty input";
else
arrayOfWord.push(word);
inputElement.value = "";
}
function process(){
words.innerHTML = arrayOfWord.join(' - ');
}
#error {
color: tomato;
}
#words {
color: purple;
}
Enter a word <input id="userinput" /><button onclick="addWord()">Add word</button>
<div id="error"></div>
<button onclick="process()">Process</button>
<div id="words"></div>
you can do something a bit clearer with jQuery! :)
if you handle the input with jquery you can write something like:
var arrWord = [] // your array
/* Attaching a click handler on your "Add Word" button that will
execute the function on user click */
$("#addWordButtonID").on("click", function () {
var wordTyped = $('#textInputID').val() // your var that collect userInput
if (wordTyped.length != 0) { // your if statement with length === 0 condition
arrWord.push(wordTyped) // adding word typed to the array
}
})
to add jquery to your html page, just add
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
in your html header
Hopefully you already have the right html. Then you can modify your script like below:
<script>
var arrword = [];
var returnword;
function begin() {
var word = "List of words";
var i = arrword.length;
if (arrword.length === 0) {
word = "Field is empty";
}
document.getElementById('message2').innerHTML = word;
while (i--) {
document.getElementById('message').innerHTML = arrword[i] + "<br/>" + document.getElementById('message').innerHTML;
}
}
function addword() {
returnword = document.getElementById('userinput').value;
arrword.push(returnword);
}
</script>
var arrword = [];
var returnword;
function begin() {
var word = "List of words";
var i = arrword.length;
if (arrword.length === 0) {
word = "Field is empty";
}
document.getElementById('message2').innerHTML = word;
while (i--) {
document.getElementById('message').innerHTML = arrword[i] + "<br/>" + document.getElementById('message').innerHTML;
}
}
function addword() {
returnword = document.getElementById('userinput').value;
arrword.push(returnword);
}
<button id="addWord" onclick="addword()">Add Word</button>
<button id="processWords" onclick="begin()">ProcessWords</button>
<input type="text" id="userinput" value=" " />
<div id="message2">
</div>
<div id="message">
</div>

Unable to call function within jQuery

I am trying to call a function in this javascript code. My code needs to check for whether the user selects var num, var letters and var symbols to be true or false. In the code, I preset the values but I still search the object choices for the variables that are true and push it into the array choices_made. However, since I need to randomly choose the order in which the num, letters and symbols appear, I randomly choose the class based on the Math.random(). However, it doesn't show me the alert(jumbled_result) afterwards.
http://jsfiddle.net/bdaxtv2g/1/
HTML
<input id="num" type="text" placeholder="Enter desired length">
<br/><br/>
<input id="press" type="button" value="jumble it up">
JS
$(document).ready(function(){
var fns={};
$('#press').click(function(){
var length = parseInt($('#num').val());
var num = true;
var letters = true;
var symbols = false;
gen(length, num, letters, symbols);
});
function gen(len, num, letters, sym){
var choices = {
1:num,
2:letters,
3:sym
};
var choice_made = ['0'];
var choice = 0;
var jumbled_result = '';
for(x in choices){
if(choices[x]==true){
choice_made.push(x);
}
}
for(i=0;i<len;i++){
var funName = 'choice';
choice = Math.round(Math.random() * (choice_made.length-1));
funName += choice_made[choice];
jumbled_result = fns[funName](jumbled_result);
}
alert(jumbled_result);
}
fns.choice0 = function choice0(jumbled_result){
var numbers = '0123456789';
return jumbled_result += numbers.charAt(Math.round(Math.random() * numbers.length));
}
fns.choice1 = function choice1(jumbled_result) {
var alpha = 'abcdefghijklmnopqrstuvwxyz';
return jumbled_result += alpha.charAt(Math.round(Math.random() * alpha.length));
}
});
You never declare functions within document.ready of jQuery. The functions should be declared during the first run(unless in special cases).
Here is a working code made out of your code. What I have done is just removed your functions out of document.ready event.
$(document).ready(function() {
$('#press').click(function() {
var length = parseInt($('#num').val());
var num = true;
var letters = true;
var symbols = false;
gen(length, num, letters, symbols);
});
});
var fns = {};
function gen(len, num, letters, sym) {
var choices = {
1: num,
2: letters,
3: sym
};
var choice_made = ['0'];
var choice = 0;
var jumbled_result = '';
for (x in choices) {
if (choices[x] == true) {
choice_made.push(x);
}
}
for (i = 0; i < len; i++) {
var funName = 'choice';
choice = Math.round(Math.random() * (choice_made.length - 1));
funName += choice_made[choice];
jumbled_result = fns[funName](jumbled_result);
}
alert(jumbled_result);
}
fns.choice0 = function choice0(jumbled_result) {
var numbers = '0123456789';
return jumbled_result += numbers.charAt(Math.round(Math.random() * numbers.length));
}
fns.choice1 = function choice1(jumbled_result) {
var alpha = 'abcdefghijklmnopqrstuvwxyz';
return jumbled_result += alpha.charAt(Math.round(Math.random() * alpha.length));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="num" type="text" placeholder="Enter desired length">
<br/>
<br/>
<input id="press" type="button" value="jumble it up">
Its because of the way the object choices have been intitialized.. Try this..
var choices = {
0:num,
1:letters,
2:sym
};
And also
var choice_made = [];
JS fiddle link : http://jsfiddle.net/8dw7nvr7/2/

Matching radio button selection with nested Array content in Javascript

UPDATE 6-25-2014
Any insight would be appreciated!
UPDATE 6-21-2014
I tried to make the radio variables, global so the 'if block' in the 'answerFwd' function could be compared to the correctAnswer Array, but that didn't work!
UPDATE 6-16-2014
ADDED JS FIDDLE
I am building a quiz and creating an array of radio buttons dynamically, and would like to match the selected button with the correct answer I have established in the question array.
html
<div id="responses">
<input type="radio" name="choices" class="radioButtons" value="0" id="choice0">
<div id="c0" class="choiceText">The Observers</div>
<input type="radio" name="choices" class="radioButtons" value="1" id="choice1">
<div id="c1" class="choiceText">The Watchers </div>
<input type="radio" name="choices" class="radioButtons" value="2" id="choice2">
<div id="c2" class="choiceText">The Sentinels</div>
<input type="radio" name="choices" class="radioButtons" value="3" id="choice3">
<div id="c3" class="choiceText">The Oa</div>
</div>
questions:
var allQuestions = [{
"question": "Who was Luke's wingman in the battle at Hoth?",
"choices": ["Dak", "Biggs", "Wedge", "fx-7"],
"correctAnswer": 0 }, {
"question": "What is the name of Darth Vader's flag ship?",
"choices": ["The Avenger", "Devastator ", "Conquest", "The Executor"],
"correctAnswer": 3 },{},{} //other questions];
var item = allQuestions[0];
var currentQuestion = 0;
var playersScore = 0;
//function which creates the buttons
function createRadioButtonFromArray(array) {
var len = array.length;
var responses = document.getElementById("responses");
responses.innerHTML = '';
for (var i = 0; i < len; i++) {
radio = document.createElement("input"); //Updated 6-21-2014 removed 'var'
radio.type = "radio";
radio.name = "choices";
radio.className = "radioButtons";
radio.value = i;
radio.id = "choice" + i;
ar radioText = document.createElement("div");
radioText.id = "c" + i;
radioText.className = "choiceText";
radioText.innerHTML = array[i];
responses.appendChild(radio);
responses.appendChild(radioText);
}
}
function answerFwd() {
var answerOutput = " ";
var itemAnswers = allQuestions;
var playerTally = 0; //Updated 6-9-2014
var playerFeedback = " "; //Updated 6-9-2014
var playerMessage = document.getElementById("playerMessage"); //Updated 6-9-2014
if (currentAnswer <= itemAnswers.length) {
currentAnswer++;
}
createRadioButtonFromArray(itemAnswers[currentQuestion].choices);
* Updated 6-9-2014 I am stumped; This doesn't work but I was encouraged I got a score tally on the page! Am I comparing the elements correctly? Updated 6-21-2014 This reversed the gain, where I had the tally render on the screen*
if (itemAnswers.correctAnswer === responses.id) { //Updated 6-21-2014
playerTally += 1;
playerFeedback += "<h5>" + playerTally + "</h5> <br/>";
playerMessage.innerHTML = playerFeedback;
}
}
At first I tried to debug this but had trouble finding where the error was coming from.
One thing I noticed was currentAnswer variable was only being set once. (when it was declared)
Another thing that would make this cleaner is storing each response to each question as a property of the questions object.
For example: {"question": "What is the registry of the Starship Reliant?","choices": ["NX-01", "NCC-1864", "NCC-1701", "NCC-2000"],"correctAnswer": 1,"selectedAnswer": 0}
This is a good example of why you may want to use object oriented programming. You can keep the global namespace clean, while also having tighter control over your variables.
I put together this Quiz Code using some object oriented principles:
JavaScript
var Quiz = function(questions) {
this.questions = questions;
this.$template = {
"header": document.querySelector(".question"),
"options": document.querySelector(".question-choices")
};
this.init();
}
Quiz.prototype = {
"init": function() {
this.question = 0;
this.generateQuestion();
this.bindEvents();
},
//gets called when this.question == this.questions.length, calculates a score percentage and alerts it
"score": function() {
var correctCount = 0;
this.questions.forEach(function(question){
if ( (question.selectedAnswer || -1) === question.correctAnswer ) correctCount += 1
})
alert("Score: " + ((correctCount / this.questions.length) * 100) + "%")
},
//Gets called during initialization, and also after a nav button is pressed, loads the question and shows the choices
"generateQuestion": function() {
var question = this.questions[this.question];
this.$template.header.innerHTML = question.question;
this.$template.options.innerHTML = "";
question.choices.forEach(this.createRadio.bind(this));
},
//Binds the previous, and next event handlers, to navigate through the questions
"bindEvents": function() {
var _this = this,
$nextBtn = document.querySelector(".question-navigation--next"),
$prevBtn = document.querySelector(".question-navigation--prev");
$nextBtn.addEventListener("click", function(e) {
//Go to the next question
_this.question++;
if ( _this.question == _this.questions.length ) {
_this.score();
} else {
_this.generateQuestion();
}
});
$prevBtn.addEventListener("click", function(e) {
_this.question--;
if ( _this.question <= 0 ) _this.question = 0
_this.generateQuestion();
});
},
//Create each individual radio button, is callback in a forEach loop
"createRadio": function(choice, index) {
var question = this.questions[this.question];
var radio = document.createElement("input");
radio.type = "radio";
radio.name = "options";
radio.id = "option-"+index;
if ( question.selectedAnswer === index ) {
radio.checked = true;
}
radio.addEventListener("click", function(e) {
question.selectedAnswer = index;
})
var radioText = document.createElement("label");
radioText.setAttribute("for", "option-"+index)
radioText.innerHTML = choice;
radioText.insertBefore(radio, radioText.firstChild);
this.$template.options.appendChild(radioText);
}
}
var q = new Quiz(allQuestions)

Javascript pass value to url

I woult to use checkbox and javascript to filter search results.
Actually I use this code to alterate url and obtain results but I would to obtain results in this format: ?A=A1,A2&B=B1,B2&C=C1,C2 instead ?A=A1&A=A2&B=B1$B=B2&C=C1&C=C2
This is the code
<input type="checkbox" name="a" value="A1" /> A1 Value
<input type="checkbox" name="a" value="A2" /> A2 Value
<input type="checkbox" name="b" value="B1" /> B1 Value
<input type="checkbox" name="b" value="B2" /> B2 Value
<input type="checkbox" name="c" value="C1" /> C1 Value
<input type="checkbox" name="c" value="C2" /> C2 Value
<input type="button" value="Test" onclick="javascript:checkbox_test()">
<script type="text/javascript">
// function will loop through all input tags and create
// url string from checked checkboxes
function checkbox_test() {
var counter = 0, // counter for checked checkboxes
i = 0, // loop variable
url = '', // final url string
// get a collection of objects with the specified 'input' TAGNAME
input_obj = document.getElementsByTagName('input');
// loop through all collected objects
for (i = 0; i < input_obj.length; i++) {
// if input object is checkbox and checkbox is checked then ...
if (input_obj[i].type === 'checkbox' && input_obj[i].checked === true) {
// ... increase counter and concatenate checkbox value to the url string
counter++;
url = url + '&c=' + input_obj[i].value;
}
}
// display url string or message if there is no checked checkboxes
if (counter > 0) {
// remove first "&" from the generated url string
url = url.substr(1);
// display final url string
alert(url);
// or you can send checkbox values
// window.location.href = 'my_page.php?' + url;
}
else {
alert('There is no checked checkbox');
}
}
</script>
Here you go:
function checkbox_test() {
var counter = 0, // counter for checked checkboxes
i = 0, // loop variable
url = '', // final url string
// get a collection of objects with the specified 'input' TAGNAME
input_obj = document.getElementsByTagName('input');
// loop through all collected objects
var arr = [];
for (i = 0; i < input_obj.length; i++) {
// if input object is checkbox and checkbox is checked then ...
if (input_obj[i].type === 'checkbox' && input_obj[i].checked === true) {
// ... increase counter and concatenate checkbox value to the url string
if (arr.indexOf(input_obj[i].name) == -1) {
arr.push(input_obj[i].name);
url = url + '&' + input_obj[i].name + '=';
counter = 0;
}
if (counter > 0) {
url = url + ',';
}
url = url + input_obj[i].value;
counter++;
}
}
// display url string or message if there is no checked checkboxes
if (counter > 0) {
// remove first "&" from the generated url string
url = url.substr(1);
// display final url string
alert(url);
// or you can send checkbox values
// window.location.href = 'my_page.php?' + url;
}
else {
alert('There is no checked checkbox');
}
}
See DEMO
try this:
function checkbox_test() {
var counter = 0, // counter for checked checkboxes
i = 0, // loop variable
url = new Array(), // final url string
input_obj = document.getElementsByTagName('input');
ck = {};
for (i = 0; i < input_obj.length; i++) {
if (input_obj[i].type === 'checkbox' && input_obj[i].checked === true) {
if(ck[input_obj[i].name] == undefined) ck[input_obj[i].name] = new Array();
ck[input_obj[i].name].push(input_obj[i].value);
counter++;
}
}
for (k in ck) {
url.push(k + '=' + ck[k].join(','));
}
if (counter > 0) {
alert('?' + url.join('&'));
}
else {
alert('There is no checked checkbox');
}
}
You're better off using document.querySelectorAll() instead of looping through all this yourself. See this fiddle.
here's the relvant part:
var boxes = document.querySelectorAll("input[type='checkbox']:checked");
if (boxes.length > 0) {
//convert nodeList to Array and transform to name=value pairs
var querystring = Array.prototype.slice.call(boxes)
.map(function (box, index) {
alert(box);
return escape(box.name) + '=' + escape(box.value);
})
.join("&"); //turn into querystring
alert(querystring);
}

How to update counter and replace text with button click

I have a form where people can add more input with a button.
The javascript function clones the "origin-item", but I can't seem to get the function to correctly update the value in #id_nested-TOTAL_FORMS and __prefix__ does not get replaced with a counter-number, It just copies and adds __prefix__ instead of 1 or 2 and so on.
Anyone know what is wrong with the function?
The script was found here: https://github.com/rotaris/dynamicformdjango/blob/master/todo/templates/edit_items_in_list.html
<input id="id_nested-TOTAL_FORMS" name="nested-TOTAL_FORMS" type="hidden" value="1">
<input id="id_nested-INITIAL_FORMS" name="nested-INITIAL_FORMS" type="hidden" value="0">
<input id="id_nested-MAX_NUM_FORMS" name="nested-MAX_NUM_FORMS" type="hidden" value="1000">
<div id="origin-item" class="hide item">
<div id="div_id_nested-__prefix__-name">
<label for="id_nested-__prefix__-name">Name</label>
<div class="controls col-lg-10">
<input id="id_nested-__prefix__-name" name="nested-__prefix__-name" type="text" />
</div>
</div>
<p><a id="add-new-item" href="#">Add new person</a></p>
<script type="text/javascript">
var prefix = 'nested';
var MAX_FORMS = '1000';
var MIN_FORMS = 1;
/*
* Perform any enhancements you'd like to a given item here
* e.g. add datepicker widgets, popovers etc.
*/
function enhanceItem(item) {
$('.btn.delete', item).popover({
offset: 10
});
}
function enhanceItems() {
$('.item').each(function() {
enhanceItem(this);
});
}
/*
* The opposite of enhanceItem()
*/
function diminishItem(item) {
$('.btn.delete', item).unbind();
}
function diminishItems() {
$('.item').each(function() {
diminishItem(this);
});
}
$(document).ready(function() {
enhanceItems();
});
function getFormCount() {
return parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
}
function updateFormCount(newValue) {
$('#id_' + prefix + '-TOTAL_FORMS').val(newValue);
}
/*
* ====================================================
* General Notes: 'Form' and 'Item' are used somewhat interchangeably.
* ====================================================
*/
$.fn.clearForm = function() {
return this.each(function() {
var type = this.type, tag = this.tagName.toLowerCase();
if (tag == 'form')
return $(':input',this).clearForm();
if (type == 'text' || type == 'password' || tag == 'textarea')
this.value = '';
else if (type == 'checkbox' || type == 'radio')
this.checked = false;
else if (tag == 'select')
this.selectedIndex = -1;
});
};
/*
* Given an element, this function replaces a given string/regex
* with another specified replacement (new_value) within the element
*/
function updateElement(el, target_regex, replacement) {
var id_regex = target_regex;
if ($(el).attr("for")) {
$(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
}
if (el.id) {
el.id = el.id.replace(id_regex, replacement);
// Update the value of the hidden ID
// This hidden ID represents the ID of the model instance
var hidden_ID_patt = new RegExp('id_(' + prefix + '-\\d+)-id');
// Only update if an ID exists (i.e. if a corresponding model instance exists)
if (hidden_ID_patt.test(el.id)) {
$(el).val(new_value + 1);
}
}
if (el.name) {
el.name = el.name.replace(id_regex, replacement);
}
}
/*
* Given an element, this function replaces (the first?) occurence of a number
* that follows a specific prefix (e.g. 'exampleprefix-n')
* with another specified number (new_value) within the element
* where n is a number
*/
function updateElementIndex(el, prefix, new_value) {
var id_regex = new RegExp('(' + prefix + '-\\d+-)');
var replacement = prefix + '-' + new_value + '-';
updateElement(this, id_regex, replacement);
}
function reapplyEnhancements() {
// Apply some fresh enhancements
diminishItems();
enhanceItems();
}
/*
* btn = the button (or link or some source object) that instigated this action
* prefix = the prefix used in the formset (?)
*/
function addItem(btn, prefix) {
var formCount = getFormCount();
// You might like/want to do some validation before proceeding in this function
// i.e. before adding an item
// In this case, I'm limiting it to max number of forms
if (formCount < MAX_FORMS) {
// Clone a item (without event handlers) from the first item
//var item = $(".item:first").clone(false).get(0);
// Clone the origin item
var item = $("#origin-item").clone(false).get(0);
$(item).removeAttr("id");
$(item).removeClass("hide");
// Clear its values
$(':input', item).clearForm();
// Insert it after the last item
$(item).removeAttr('id').hide().insertAfter("form .item:last").slideDown(300);
$(':input, label', item).each(function() {
// Relabel/rename all the relevant bits
// '__prefix__' comes from #origin-item
// see 'empty_form': https://docs.djangoproject.com/en/1.4/topics/forms/formsets/#empty-form
var target_regex = new RegExp('(' + prefix + '-__prefix__-)');
var replacement = prefix + '-' + formCount + '-';
updateElement(this, target_regex, replacement);
// Remove error classes
$(this).removeClass("error");
});
reapplyEnhancements();
// Update the total form count (in the management form)
updateFormCount(formCount + 1);
}
else {
// Feel free to notify the user using some other technique instead of an JS alert
alert("Sorry, you can only have a maximum of " + MAX_FORMS + " goals.");
}
}
/*
* Relabel all items
*/
function relabelItems() {
var forms = $('.item'); // Get all the forms
// Update the total number of forms (likely 1 less than before)
$('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
var i = 0;
// Go through the forms and set their indices, names and IDs
for (formCount = forms.length; i < formCount; i++) {
$(":input, label", forms.get(i)).each(function() {
updateElementIndex(this, prefix, i);
});
}
}
/*
* Removes an item from a list of items
*/
function removeItem(btn, prefix) {
var formCount = getFormCount();
// Do some validation before proceeding
// In this case, just make sure there is at least one item
if (formCount > MIN_FORMS) {
var item = $(btn).parents('.item');
// Delete the item
$("*", item).fadeOut();
$(item).animate({'backgroundColor':'#fb6c6c'}, 300).slideUp('slow', function() {
$(item).remove();
relabelItems();
});
// Apply enhancements
enhanceItems();
}
else {
// Feel free to notify the user using some other technique instead of an JS alert
alert("Come on now, you need to have at least a minimum of " + MIN_FORMS + " item(s).");
}
}
// JavaScript to create a new items/entries
$(document).ready(function() {
$('#add-new-item').click(function(e) {
addItem(this, prefix);
return false;
});
$('a.delete').live("click", function(e) {
removeItem(this, prefix);
return false;
});
});
</script>
The bugs in this code seem to be caused by the variable named prefix being used for 2 different tasks.
Here it is used like this
$('#id_' + prefix + '-TOTAL_FORMS').val(newValue);
where I assume prefix is assigned '_prefix_', but later it is used like this
var target_regex = new RegExp('(' + prefix + '-__prefix__-)');
where I assume prefix is assigned 'id'
If you where to sort out the variable prefix to only contain one type of piece of information, by have 2 variables with different names.
I'm pretty sure everything would fall into place.

Categories

Resources