I am in the process of learning JavaScript and jQuery, so apologies if any of this sounds naive or obvious. I started what I thought was a fairly simple project to practice and hopefully learn something in the process.
What I want to do is this: the user inputs a sentence and hits a submit button. The sentence gets added to a list of other sentences submitted by people (preferably on a separate file, preferably encrypted, but not necessary). Then, the website grabs a random sentence from the list and displays it.
I am not asking on how to build all of this. I have already put most of it together, but I am including it here for reference.
I have a separate javascript file with the array of quotes.
var quotes=new Array();
quotes[0]="<p>Quote 1</p>";
quotes[1]="<p>Quote 2</p>";
quotes[2]="<p>Quote 3</p>";
quotes[3]="<p>Quote 4</p>";
quotes[4]="<p>Quote 5</p>";
quotes[5]="<p>Quote 6</p>";
quotes[6]="<p>Quote 7</p>";
Then I randomly display one using this:
function getQuote(){
var thisquote=Math.floor(Math.random()*(quotes.length));
document.write(quotes[thisquote]);
}
And adding <script> getQuote(); </script> to the html.
This all works fine.
The part I cannot seem to figure out is taking user input and adding it to the jQuery array. I am using a contenteditable div instead of an <input> because I want it to have multiple lines of text and have a character limit, which as far as I know can only be done with a contenteditable div (according to the research I did at the time, I may be wrong).
I have looked around and tried many if not all the examples I found of how to do this, and none of them worked. This is the last method I tried, if it helps:
$(".submit").click(function() {
quotes[quotes.length] = document.getElementsByClassName("input").value;
});
So, to reiterate, I want to take user input and add it to a JavaScript array. I have scoured stackoverflow and the interet but nothing has worked. Please help!
UPDATE: Arvind got it right. I still have a lot to learn, and it seems I need to read up on localstorage and cookies. I will also need to use PHP to save the sentences on the server. Thank you to all who answered!
Problem is document.getElementsByClassName("input") gives you a NodeList and not just a single html element. So if you do this document.getElementsByClassName("input").value, you will end up quotes as [undefined, undefined ... undefined]. Assuming you have single element with the class name input, go with index 0. Also as you stated that you are using div with attribute contenteditable, you may try this instead. document.getElementsByClassName("input")[0].innerHTML
Try this example.
var quotes = localStorage.getItem('quotes'); //get old, if any, gives you string
quotes = quotes ? [quotes] : []; // if got quotes then make it as array else make new array
$(function() {
var quote = $('#quote'); //get the quote div
quote.html(quotes.join('') || quote.html()); //set the default text
$('#btn').on('click', function(e) {
quotes.push(quote.html());
localStorage.setItem('quotes', quotes.join('')); //save the quotes
alert(quotes.join(''));
});
});
#quote {
border: 1px solid grey;
height: 100px;
overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div contenteditable='' id='quote'>
<ol>
<li>Quote 1</li>
<li>Quote 2</li>
</ol>
</div>
<input type='button' id='btn' value='Submit' />
P.S.
In order to preserve the old quotes you may possibly use cookie, localStorage, etc.
Are these "quotes" being saved locally?
Yes, to share it among several users visiting by different browsers, you have to save it with the server script like PHP, Java, ASP, etc. Here you can either use ajax, if you wana avoid page reload on submit, else you can go for form submit.
$(".submit").click(function() {
quotes[quotes.length] = document.getElementsByClassName("input").value;
});
should be
$(".submit").click(function() {
quotes.push(document.getElementsByClassName("input").text());
});
EDIT: With a content editable div you need to use text() instead. Here is an example fiddle. https://jsfiddle.net/
var quotes=[];// better
// function to add to array
function addQuote(myquote){
quotes.push('<p>'+myquote+'</p>');
}
addQuote("Quote 1");
addQuote("Quote 2");
addQuote("Quote 3");
addQuote("Quote 4");
addQuote("Quote 5");
addQuote("Quote 6");
addQuote("Quote 7");
addQuote("Quote 8");
$(".submit").on('click',function() {
addQuote(document.getElementsByClassName("input")[0].value);
});
NOTE: suggest NOT using the "input" class name and use some other one as that might be confusing to others at some point later (confused by element named input)
I also added the paragraph tags as that would provide a consistent pattern for your input text. Assumption on my part however.
NOTE I also assume that the element IS an input type with the .value since that is NOT provided (the markup)
Related
I've a page with about 10 short articles.
Each of them as a "Read More" button which when pressed displays hidden text
The issues I have at the moment is when I press the "Read More" on any of the 10 button it shows the 1st articles hidden content and not the selected one.
I think I need to set a unique ID to each article.. and the read more button be linked to it.. But I don't know how to set it.
I looked at this but couldn't get it working how to give a div tag a unique id using javascript
var WidgetContentHideDisplay = {
init:function() {
if ($('#content-display-hide').size() == 0) return;
$('.triggerable').click(function(e){
var element_id = $(this).attr('rel');
var element = $('#'+element_id);
element.toggle();
if (element.is(':visible')) {
$('.readmore').hide();
} else {
$('.readmore').show();
}
return false;
});
}
}
var div = documentElemnt("div");
div.id = "div_" + new Date().gettime().toString;
$(document).ready(function(){ WidgetContentHideDisplay.init(); });
OP Edit: Sorry, the original code wasn't in caps. I kept getting errors when trying to post, so I copied the code into Dreamweaver and it made it all caps for some reason.
Instead of selecting the element to toggle with an ID (i.e. $('#'+ELEMENT_ID)) you could setup a class for your item and use the class selection (e.g. $('.DETAILED-ARTICLE)') to select the child (or the brother, etc. depending how you built the HTML page).
In theory each ID should point to a single element but each class can be put to as many elements as you want.
If you're getting errors, read the errors and see what they are. Off of a quick read of your code, here are a couple things I noticed that will probably cause issues:
"documentElemnt" is misspelled, which will render it useless. Also, documentElement is a read-only property, not a function like you're using it.
toString is a function, not a property, without the parentheses (.toString()) it isn't going to function like you want it to.
Run the code, look at the errors in the console, and fix them. That's where you start.
I've recently been learning JavaScript by creating a little to do list web app here.
So far almost everything's working, but I have an issue if you try to check and uncheck an item more than once. If you keep checking/unchecking you'll see the delete button disappear and --> appear after the urgency icon.
The change of icon is done by a Regex changing code from commented to un-commented. I just don't understand why if it works once, it doesn't work every time?
if (tr.outerHTML.indexOf("checked=\"\"") >= 0) {
// replace checked with unchecked
var cookieHTML = tr.outerHTML.replace(/checked=\"\" class=\"list-checkbox\"/, 'class=\"list-checkbox\"')
.replace(/<tr class=\"list-row done\"/, '<tr class=\"list-row\"')
// change delete button to urgency.
.replace(/<!--<span aria-hidden=\"true\" data-icon=\"c\"/, '<span aria-hidden="true" data-icon="c"')
.replace(/alt=\"Neutral\"><\/span>-->/, 'alt="Neutral"></span>')
.replace(/<!--<span aria-hidden=\"true\" data-icon=\"f\"/, '<span aria-hidden="true" data-icon="f"')
.replace(/alt=\"Urgent\"><\/span>-->/, 'alt="Urgent"></span>')
.replace(/<span aria-hidden=\"true\" data-icon=\"e\"/, '<!--<span aria-hidden="true" data-icon="e"')
.replace(/onclick=\"deletetodo\(this\)\"><\/span>/, 'onclick="deletetodo(this)"></span>-->');
} else {
// else add checked to the input.
var cookieHTML = tr.outerHTML.replace(/class=\"list-checkbox\"/, 'checked class=\"list-checkbox\"')
.replace(/<tr class=\"list-row\"/, '<tr class=\"list-row done\"')
// change urgency to delete button.
.replace(/<span aria-hidden=\"true\" data-icon=\"c\"/, '<!--<span aria-hidden="true" data-icon="c"')
.replace(/alt=\"Neutral\"><\/span>/, 'alt="Neutral"></span>-->')
.replace(/<span aria-hidden=\"true\" data-icon=\"f\"/, '<!--<span aria-hidden="true" data-icon="f"')
.replace(/alt=\"Urgent\"><\/span>/, 'alt="Urgent"></span>-->')
.replace(/<!--<span aria-hidden='true' data-icon='e'/, '<span aria-hidden="true" data-icon="e"')
.replace(/onclick='deletetodo\(this\)'><\/span>-->/, 'onclick="deletetodo(this)"></span>');
}
This is the (rather large!) chunk of JS that controls this. Any ideas what's wrong? Or maybe a better way of changing these icons around?
Thanks!
I would say: you're are doing it wrong. Using a string / regex replacement method is not the right way to go imho.
Instead of doing those replacement use DOM methods, i.e.:
someElement.setAttribute('data-icon', 'f');
someElement.setAttribute('alt', 'Urgent');
A simple example can be found here: http://jsbin.com/iwakof/1/edit
I know this isn't a direct answer to your question, but trust me this is the way to go
That's awesome that you are learning JavaScript. Nice job. But, I'm quite glad that you posted this question as it looks like you could use a couple of pointers.
The answer to your question is - yes there is a much simpler way to achive this effect - which I will get to shortly. But first - I notice that at the bottom of your todo app you include a library called JQuery
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
This library will be of huge help to you, not only in the function you describe above, but to the majority of the code you have written. You will end up with much cleaner and self explanatory code.
http://jquery.com/
Basically what JQuery allows you to do, is to manipulate the state of the DOM. You definatly want to begin here.
Here is small sample which shows a check box who can be checked or unchecked, and on change, have an element shown' or hidden as desired.
http://jsfiddle.net/m4vGE/5/
Please - do take the time to have a look into JQuery - its a great first step you can take to increase your produtivity and reduce complexity in your JavaScript
Also - as a side note, if you find yourself using js to build HTML with strings, the answer is invariably "there is a better way"
If all you are trying to do is change icons based on a checkbox being checked or no, you could do something like this.
function getVisibility()
{
var temp = document.getElementById("iconName").style.visibility;
return temp;
}
function switchIfChecked()
{
var current = getStyle();
if( current == "visible" )
{
document.getElementById("iconName").style.visibility = "hidden";
}
else
{
document.getElementById("iconName").style.visibility = "visible";
}
}
<div id="iconName" style="visibility: visible">INSERT ICON IMG here</div>
What the above does is that it makes the div of the icon visible or hidden. Ofcourse you will need to have two divs and then set either or to hidden or visible.
With what you are doing currently, you are not really making the browser do anything.
Try to use the global option of Regex (have a look at the g after the second slash):
// ...
.replace(/<tr class=\"list-row done\"/g, '<tr class=\"list-row\"')
// ...
Here is an example.
From developer.mozilla.org:
global: Whether to test the regular expression against all possible
matches in a string, or only against the first.
I'm trying to update numbers on a page based on button pushing by a user. I have it working, but when the number updates, the text is no longer formatted like it came in a <code></code> block. Here's the code I'm using minus any effort to control the format:
<script>
var countUp = function() {
$("#num").html(parseInt($("#num").html()) + 1);
$("#textWithNumInIt").html("The number is now"+$("#num").html() );
}
</script>
<p id="textWithNumInIt"><code>The number is 0</code></p>
I've tried putting <code></code> tags inside the jQuery, with and without escape characters. I've tried using .val() and .text() to set the text in an effort to leave the formatting alone. I've tried using a span around the number itself, but then the value doesn't even update.
This is the first time I have changed HTML using jQuery inside a javascript function, so the trouble might have something to do with that. Any help would be awesome, and if you have advice on a totally different way to do this, please share.
When you edit the contents of the textWithNumInIt paragraph, the <code> tags inside that paragraph are naturally replaced as well. This should work:
$("#textWithNumInIt").html("<code>The number is now "+$("#num").text()+"</code>" );
Maybe try this -
$('#textWithNumInIt code').html("The number is now "+$("#num").text() )
When you parseInt it, it gets converted into plain text and the <code> wrapper is gone. Use this and you will be on your path.
var countUp = function() {
var t = parseInt($("#num").text()) + 1);//using text() to avoid any unintentional html tag issues
$("#num").html(t);
$("#textWithNumInIt").html("<code>The number is now "+t+"</code>" );
}
or otherwise you can continue with your code by making a simple edit.
var countUp = function() {
$("#num").html(parseInt($("#num").html()) + 1);
$("#textWithNumInIt code").html("The number is now"+$("#num").html() );
}
I have a loop for my input checkboxes (see below).
<cfloop query="qGetCBList">
<input name="#qGetCBList.CheckBox#" type="checkbox" id="#qGetCBList.CheckBox#"onclick="CheckBoxSelect('#qGetCBList.CBNum#','#qGetCBList.CheckBox#','#qGetCBList.RecordCount#');"> #qGetCBList.CBDesc#
<br /><br />
</cfloop>
and my javascript function is,
<script language="JavaScript">
CheckBoxSelect = function(CB,cbID,rCnt){
var myVar_CB=CB;
var myVar_CB_ID=cbID;
var myVar_RCNT=rCnt;
if(myVar_CB == 2) //"Chemical(s)........."
{
for(i=1;i<=myVar_RCNT;i++){
var myVar_CB_ID_FMT="cb"+i; //check box ID format
if(i!=2){
//alert(myVar_CB_ID_FMT);
document.getElementById("myVar_CB_ID_FMT").disabled=true;
}
}
}
else{
alert('good to go');
}
}
</script>
what's happening here is, if the selected checkbox is 2 (which is the CBNum), then I want all other checkboxes to be disabled.
P.S. This is the bind page of the main page. When I un-comment my alert tag, it gives me the correct CBNums, but the disabling is not working. If it any useful I'm using CF8.
Feedbacks and/or alternate methods are appreciated. Thank you.
I know nothing about ColdFusion but the basic JavaScript tips you can use are:
Check the return value of document.getElementById(); don't assume it'll always return a node you can disable.
Most browsers have a built-in or downloadable debugger that allows you to inspect variables. Use that instead of plain alerts. E.g.:
console.log(myVar_CB_ID_FMTT, document.getElementById(myVar_CB_ID_FMT));
getElementById("myVar_CB_ID_FMT") is looking for an element called myVar_CB_ID_FMT. Does that element exist? No. Your variable myVar_CB_ID_FMT is not going to be evaluated as getElementById just sees it as the string "myVar_CB_ID_FMT".
Try document.getElementById("cb"+i)
The id in getElementById(id) is case sensitive so ensure that "cb"+i exists.
#Barry Jordan answer kinda woke me up and I was error checking along the line #Álvaro G. Vicario mentioned, I then finally figured out what's going on.
In my loop when I trim my id value ...id="#trim(qGetCBList.CheckBox)#"... it works.
of course it had be something simple stupid and my fault.
Thanks guys for support, you all rock.
This will probably be a very easy question to answer. I am creating a form for a simple "contact manager" type php based site, with a basic data-base. I have a text field in which multiple tags can be added each profile. Currently, this is done manually. The client would like me add a predefined list of "tags" they can click on which will then add the appropriate text to that field. I was thinking I would hard code in the tags, and then use the title tag to contain the text which would be added to the field. Does anyone have any suggestion on how to do this, or alternate suggestions? This would be adding text to an already existing field (separated by comma, preferably the comma wouldn't be part of the text I am passing. I would like to automatically have a comma appear after each tag is added.
The alternate request was to create a series of check boxes, but I thought this might make searching the easiest. I realize this is probably super simple, but I am more of a design guy, so if anyone could point me in the right direction or provide any suggestions, it would be much appreciated. Also, I might have to have more than once instance of this on a page, so I might have to have more than one function for this. Thanks!
You want something like the following:
<script type="text/javascript">
function addToValue(el, s) {
if (typeof el == 'string') el = document.getElementById(el);
el.value += (el.value.length > 1)? ', ' + s : s;
}
</script>
<textArea id="someText"></textarea>
<button title="foo" onclick="addToValue('someText',this.title)">Add foo</button>
<button title="bar" onclick="addToValue('someText',this.title)">Add bar</button>
<button title="baz" onclick="addToValue('someText',this.title)">Add baz</button>