Can I shorten a string of childNodes[0]? - javascript

I have this line of code. It works just fine, but I'm wondering if there's a smarter (read: shorter) way of doing it?
svg.getElementById($(this).attr('id')).childNodes[0].childNodes[0].nodeValue = $(this).val();
I'm using jQuery as well, so any jQuery methods are fine :)
The markup being reached is
<text id=n>
<tspan>text to reach</tspan>
</text>
It would be ideal, however, if I could reach the text even if the tags were removed.

This should let you change the text:
$("#" + $(this).attr("id") + " tspan").text($(this).val());

This might be a kludge, but it'll substitute the end node value of a text element whether it has a tspan element or not. This example acts on an input field with a class of 'replace'.
$('.replace').keyup(function() {
if ($("#" + $(this).attr("id")).has("tspan").length) {
$("#" + $(this).attr("id") + " tspan").text($(this).val());
} else {
$("#" + $(this).attr("id")).text($(this).val());
}
}

Related

How to change Jquery selector based on an param passed through a function

I have a function:
function factCheck(index) {
if (arrayOfSites[index].indexOf("pdf") > -1) {
$('#20').attr('style', 'color: red');
$('#' + index).attr('style', 'color: red');
console.log('index: ' + index);
console.log($("#" + index).text());
}
}
So my question is. The text color of the element changes color when I use $('#20') but when I use, $('#' + index) it doesn't work.
Funny thing is, I with console.log.. it logs the text of the element but I can't effect the css of it.
Why is this happening?
// after a three hour meeting.. I came back with some really great answers!! Thank you!!
edit:
the code below shows how I'm snagging all the links on the page and add the id equal to the index of that item. So that's why I'm trying to grab that link, and effect it in some way. I appreciate all you guys.. I think I'm going to take the string and add a letter to it as they come in through the function and then manipulate the anchor from that point. I just wonder if there's a more efficient way of doing this.
$(".lpage a").each(function (index) {
// console.log(index + ": " + $(this).text());
str = $(this).attr('href');
arrayOfSites.push(str);
str = arrayOfSites[index];
title = $(this).attr('title');
parseURL(str);
$('.colContent2').append(cellOpen + '<a onclick="whichFunction(' + index + ');" id= "' + index + '"style="cursor:pointer;" class="injectedLinkCol2" >' + str + '</a>' + cellClose).prop("id", index);
});
Maybe it has something to do with the name of your id attribute. Take a look at this answer.
Try to use the toString() function:
function factCheck(index) {
if (arrayOfSites[index].indexOf("pdf") > -1) {
$('#20').attr('style', 'color: red');
$('#' + index.toString()).attr('style', 'color: red');
console.log('index: ' + index);
console.log($( "#" + index.toString() ).text());
}
}
An id name or class name must begin with a name must begin with an underscore (_), a hyphen (-), or a letter(a–z).
So something like
'#d20'
would work.
See this: Valid CSS Selectors.
I couldn't reproduce the exact problem. I made a pen (link) and tried what you asked but it works well. So it must be some error in the remaining code.
on a related note
In CSS id's are not allowed to start with a number(classes are allowed). So writing something like
#20{
color: red;
}
won't work, but the rule only applies to css. JQuery will still work, which means your only option's are to write inline styles or use JQuery's .attr or .css, but jQuery.attr() will reset all your inline styles. you are left with using .css(). So, it's better to not start your id's with numbers.
try using .css instead of .attr and see if it works.
$('.exampleClass:eq(' + index + ')').css("color", "yellow");
for some reason works
$('.exampleClas').eq(index).css("color", "yellow");
does not work.

Problems passing parameters, and getting code ready for MYSQL integration

I've been working on a project for 4 days now, completely written by hand, to see where I'm at with javascript (I've been going through the codecademy courses). I'm trying to create a browser based checklist program. So far I've written a clean menu interface that can dynamically create <div>s.
Here's what I've got on jsfiddle:
http://jsfiddle.net/SdCaf/1/
My questions:
Can I write the taskToggle() function more efficiently? Is there a jquery way to simplify it?
If you have the time to examine my code in the Fiddle; will it take to mysql easily, or have I created some goofy redundant kludges, that will make it difficult to update?
FIXED Why won't my formatTask() constructor add the check boxes and descriptions (as seen in it's if/else) - is there something wrong with my taskToggle() function, is it the checkbox <div> I'm trying to add, both, or something else?
The formatTask() constructor:
function formatTask(target, divId, content, description, complete) {
function taskToggle() {
if ($(this).hasClass("completeTask")) {
$("#" + divId).attr("class", "incompleteTask");
$("#" + divId + "Box").attr("class", "incompleteBox");
}
else if ($(this).hasClass("incompleteTask")) {
$("#" + divId).attr("class", "completeTask");
$("#" + divId + "Box").attr("class", "completeBox");
}
};
if (complete) {
var div = new formatDiv(target, divId, "completeTask", content, taskToggle, description);
formatDiv(divId, divId + "Box", "completeBox", "O");
div.addDescription();
}
else {
var div = new formatDiv(target, divId, "incompleteTask", content, taskToggle, description);
formatDiv(divId, divId + "Box", "incompleteBox", "[ ]");
div.addDescription();
}
}
When I call it, it seems to accept all of it's parameters and I get no errors in the console, but it doesn't seem to run formatDiv(divId, divId + "box", "completeBox", "O"); and div.addDescription. You can see this for yourself if you click on "»Show Lists" in the result pane of the Fiddle (and you'll get an example of how the .addDescription() function should work)
Any other feedback you may wish to provide would be greatly appreciated. I need to know if I'm on the right track, or if I'm starting to write junky code that will become inelegant.
Thank you for your time if you give it!
The issue here is that the DOM ID that you're assigning for your task is "atask!" which isn't valid (because of the !) character. Make sure you remove invalid characters from your IDs and class names!
Are you sure that when you say this:
$("#" + divId).attr("class", "incompleteTask");
You don't mean this?
$("#" + divId).addClass("incompleteTask");
$("#" + divId).removeClass("completeTask");
seperate the taskToggle() from formatTask() and simply call taskToggle() in formatTask() like this
function formatTask(target, divId, content, description, complete) {
taskToggle();
if (complete) {
var div = new formatDiv(target, divId, "completeTask", content, taskToggle, description);
formatDiv(divId, divId + "Box", "completeBox", "O");
div.addDescription();
}
else {
var div = new formatDiv(target, divId, "incompleteTask", content, taskToggle, description);
formatDiv(divId, divId + "Box", "incompleteBox", "[ ]");
div.addDescription();
}
}
function taskToggle() {
if ($(this).hasClass("completeTask")) {
$("#" + divId).attr("class", "incompleteTask");
$("#" + divId + "Box").attr("class", "incompleteBox");
}
else if ($(this).hasClass("incompleteTask")) {
$("#" + divId).attr("class", "completeTask");
$("#" + divId + "Box").attr("class", "completeBox");
}
};

Cross-browser input text focus system?

I have the following code, where soundid is an integer between (not including) 0 and 11, and all the element names exist. Currently, it does not focus in many browsers. What should I add, modify or change it into to make it able to focus into an input type="text" element?
Code:
document.getElementById("fo" + soundid + "cus").click();
document.getElementById("fo1cus").click();
$("#spellingf" + soundid).select();
$("#spellingf" + soundid).focus();
document.getElementById("spellingf" + soundid).focus();
$("#fo" + soundid + "cus").click();
Thank you!
Native HTML Elements don't have an click method. So this:
document.getElementById("fo" + soundid + "cus").click();
and this:
document.getElementById("fo1cus").click();
will throw an error. The error will stop the code execution s the rest of the code won't be executed. That's why it doesn't work. So use this code:
$("#fo" + soundid + "cus").click();
$("#fo1cus").click();
$("#spellingf" + soundid).focus();
$("#fo" + soundid + "cus").click();
Not really sure what you're asking here tbh.
Giving your input and id attribute and selecting on that id will work cross browser.
$('#fo1cus').focus(function() {
alert('Handler for .focus() called.');
});

Trouble with jquery's append and prepend

I use the following code to check whether or not a certain div exists. And if it doesn't it adds it to the dom in the proper place.
if (!($("#col"+lastSlide).length))
{
$('#schDisplay').prepend('<div id="col' + (lastSlide) + '"></div>');
}
My problem is that when this if statement checks again for a div that had already once been appended/prepended, it doesn't see the div that I added. So it will continue to add the div that was already prepended/appended.
Is there any way this issue can be fixed?
more code:
//fillin added column
function fillElement(colnum)
{
var URL = 'schedule.php';
$("#col"+colnum).text("Loading...").show();
$.post(URL,{fecolnum: colnum},
function (data)
{
$("#col"+colnum).html(data).show();
});
}
//...irrelevant code...
// Create event listeners for .arrows clicks
$('.arrows')
.bind('click', function(){
numberOfSlides++;
// Determine new position
if ($(this).attr('id')=='arrow_right')
{
lastSlide++;
currentPosition++;
if (!($("#col"+lastSlide).length))
{
$('#schDisplay').append('<div id="col' + lastSlide + '" class="schColumn" style="float: left; width: ' +slideWidth+ 'px"></div>');
fillElement(lastSlide);
}
}
else
{
lastSlide--;
currentPosition--;
if (!($("#col"+lastSlide-2).length))
{
$('#schDisplay').prepend('<div id="col' + (lastSlide-2) + '" class="schColumn" style="float: left; width: ' +slideWidth+ 'px"></div>');
fillElement(lastSlide-2);
}
}
I don't have much context to go off of, but checkout this jsfiddle I made from what you gave me.
Notice the line where I've made a comment that you can comment out the increment statement. Basically, this is how you can test what happens when "lastSlide" is the same value. (versus if "lastSlide" is indeed a different value).
You might just try debugging your actual code and make sure that lastSlide has the value you actually expect.
If I understand your question correctly, you're saying that it keeps adding the div if you do the same thing again. However, I can't reproduce this. The following code shows one div. According to you, it would show two divs.
lastSlide = 1;
if (!($("#col"+lastSlide).length))
{
$('#schDisplay').prepend('<div id="col' + (lastSlide) + '"></div>');
}
if (!($("#col"+lastSlide).length))
{
$('#schDisplay').prepend('<div id="col' + (lastSlide) + '"></div>');
}
If I didn't miss something, your problem must lie elsewhere.
This will work:
if (!($("#col"+lastSlide).length)) {
var newdiv = $('<div id="col'+lastSlide+'"/>');
$('#schDisplay').prepend(newdiv);
}
It keeps adding because your if condition is always true.
I haven't tested this though...
Can you try something like this to see if it helps?
var len = 0;
len = $("#col"+lastSlide).length;
if (len < 1)
{
$('#schDisplay').prepend('<div id="col' + (lastSlide) + '"></div>');
}
You can use jQuery filters to remove the selected div if it has already been prepended to. This should work for your particular scenario:
$('#schDisplay').filter(':not(:has(div[id^=col]))')
This says "select the div with id 'schDisplay' and then remove it from the selection if it has any descendent divs with ids start with 'col'".
In your example, you would chain on your prepend statement to this code like so (no need for an if statement):
$('#schDisplay').filter(':not(:has(div[id^=col]))').prepend('<div id="col' + (lastSlide) + '"></div>');
A special note: I believe that the :has selector is a jQuery content filter selector, meaning that it will not work without jQuery. You are clearly using jQuery, but readers with different implementations should keep this in mind.

Numbering in jQuery

How could I change the text below so that the text within it has a number appended to it.
<div class="right">This is some text</div>
<div class="right">This is some text</div>
<div class="right">This is some text</div>
So the code above would become,
This is some text
This is some text
This is some text
you should use an ordered list... ol
or else you will need use css and add the content property your selector with the :after pseudo element.
How about the following?
$("div.right").each(function(i){
$(this).prepend((i + 1) + ". ");
});
UPDATE:
Here is one way that should work.
"number" is a custom element (it can be anything you want) that will/should be ignored by browsers.
$("div.right").each(function(i){
$(this).find("number").remove().end()
.prepend("<number>(i + 1) + ". </number>");
});
OR use the following which is probably a little slower but semantically correct...
$("div.right").each(function(i){
$(this).find("span.number").remove().end()
.prepend("<span class='number'>" + (i + 1) + ". </span>");
});
OR an even better way would be to prepend span.number before your first drag:
$(function(){ // document ready...
// caching the "numbers" will only work if you use the DOM
// for updating div position (like jQuery's "append()", "prepend()", "before()", and "after()") and not "innerHTML" or "html()"
var numbers = $("div.right").each(function(i){
$(this).prepend("<span class='number'>" + (++i) + "</span>. ");
}).find("span.number");
function dragEnd(){
// do your drag end stuff here...
numbers.each(function(i){
this.innerHTML = ++i;
});
)};
});
This is really an elaboration on another comment. I can't format code in a comment, I guess. You could use jQuery core's each:
$('div.right').each(function(ii){
html = $(this).html();
$(this).html(ii + '. ' + html);
});
jQuery selectors are your friend...
Get your stuff and loop on through something like this:
texts = $("div.right");
for(i = 0;i < texts.length;i++)
{
node = $(texts[i]);
content = node.html();
number = i + 1;
node.html(number + ". " + content);
}
Update: Jeez, last time post untested code straight off the dome here (disclaimer: not actually the last time). In the interest of correctness, I've updated it to at least run (and work!) if you still want to do it this way. Although I admit the other solutions are cleaner and more elegant.
Does this have to be done dynamically through jquery? Can't you just combine all that text into one div and then make a ordered list around it?
Using [] notation with a result set will give you the raw DOM element which does not have the html() function. Use the eq() function to get each element wrapped in a jQuery object.
You can also use each() as mentioned above, but I prefer straight 'for loops' so I don't have to adjust for 'this' if I'm in an event handler.
var texts = $("div.right");
var elem;
for(i = 1; i < texts.length; i++) {
elem = texts.eq(i);
html = elem.html();
elem.html(i + '. ' + html);
}

Categories

Resources