0

For my javascript project, I have a list that looks like this:

<li id="1">101.33, "book name 1"</li>
<li id="2">600.01, book name 2</li>
<li id="3">001.11, book name 3</li>

etc...

Of which I am supposed to do the following:

  1. Remap the bullet list entries to a new (consistent) tag type (your choice – make it look pretty!).
  2. For entries between 100 and 200, add 100 to the Dewey decimal number.
  3. For entries between 400 and 500, add 200 to the Dewey decimal number.
  4. Entries between 850 and 900 need to have 100 removed from the Dewey decimal number.
  5. Entries between 600 and 650 need to have 17 added to the Dewey decimal number
  6. For items that get changed, append “changed” to the record.
  7. For items that do not get changed, append “no change” to the record.
  8. For records that are incorrect, append “invalid record” to the record

But I'm not sure how to go about it. I want to target any number in the body, or within a list item. Right now I have this:

var z = document.body.li.innerHTML;
if (z >+ 100 && z <= 200)
{
var q = z + 100;
document.body.li.innerHTML=q;
}

}

Can anyone point me in the right direction of the best approach to do this in javascript? Should I be using find/replace instead?

EDIT: Attempted to amend the last ternary if else statement in David Thomas' code. Can't seem to get it to work:

//define valid record number as at-least-one-integer.at-least-one-integer
var reggie = /\d+(.)+d/

if (_newText = reggie) {
'Invalid Record';
}
else if (_newText === a[textProp]) {
'no change';
}
else(_newText != a[textProp]) {
'changed';
}
+ ')';
1
  • For starters have a look at the getElementById document method and don't use find/replace - else this would made javascript needless in this case. Commented Oct 21, 2013 at 22:09

3 Answers 3

1

One approach, is the following (using plain JavaScript, albeit you'll need to use an up-to-date browser):

// first, we need to get all the 'li' items:

var lis = document.querySelectorAll('ul > li'),
    // find the relevant text-property for this browser:
    textProp = 'textContent' in document ? 'textContent' : 'innerText',
    // empty string variable to allow assessment of changes:
    _newText = '';

// Remap the bullet list entries to a new (consistent) tag type (your choice – make it look pretty!).
// do this one yourself.

// a function to zero-pad the numbers (I believe a requirement of Dewey Decimal):
function leftPadNumber(num, numLength, padChar) {
    var nString = num.toString(),
        major = parseInt(num, 10),
        minor = parseFloat(nString.substring(nString.indexOf('.'))),
        diff = numLength - major.toString().length;
    if (diff > 0) {
        return new Array(diff + 1).join(padChar || 0) + (major + minor);
    } else {
        return num;
    }

}

// For entries between 100 and 200, add 100 to the Dewey decimal number.
// For entries between 400 and 500, add 200 to the Dewey decimal number.
// Entries between 850 and 900 need to have 100 removed from the Dewey decimal number.
// Entries between 600 and 650 need to have 17 added to the Dewey decimal number

// note that I've taken a very literal interpretation of 'between' (amend if necessary):
function amendedDeweyDecimal(num) {
    if (num > 100 && num < 200) {
        num += 100;
    } else if (num > 400 && num < 500) {
        num += 200;
    } else if (num > 850 && num < 900) {
        num -= 100;
    } else if (num > 600 && num < 650) {
        num += 17;
    }
    // happens if num falls somewhere outside of the above constraints:
    return num;
}

// iterates over each element in the 'lis' nodeList/collection:
[].forEach.call(lis, function (a) {
    /* replaces the found numbers ('m') in the string, using the two
       functions, above, and assigns those to the _newText variable:
    _newText = a[textProp].replace(/(\d{3}\.\d{2})/, function (m) {
        return leftPadNumber(amendedDeweyDecimal(parseFloat(m)).toFixed(2), 3);
    });

    // For items that get changed, append “changed” to the record.
    // For items that do not get changed, append “no change” to the record.

    // returns the original text to the element, along with '(no change)'
    // (if 'a[textProp]' is exactly equal to '_newText') or with '(changed)'
    // (if the two variables are not identical):
    a[textProp] = _newText + ' (' + (_newText === a[textProp] ? 'no change' : 'changed') + ')';
});

// For records that are incorrect, append “invalid record” to the record
// I have absolutely no idea how to assess an 'incorrect' record.

JS Fiddle demo.

References:

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks. Some of the records do not have numbers, so I assume those are invalid. I also forgot to mention I am supposed to add a button to the page that will perform the corrections.
And the problem with doing that is..? Where are you stuck, and what have you tried? The above I did, more or less, for fun and because it looked interesting. The remainder seems quite simple, so I'm unsure why you're having problems.
The only thing I'm stuck on with what you sent is getting the number to change. the 'changed' text works, but the record numbers stay the same
Miles, yeah: that's because I put the original text (a[textProp]) back into the element, rather than the _newText (which held the changed-numbers). Sorry, I was clearly too sleepy when I wrote it all out. The edit I just made, and the updated demo (in the answer as well) should now work; also, of course, I've corrected the error in the code in the answer. Sorry about the confusion, and the stupidity on my part... "_"
No apology necessary, you have provided great insight. Question though - I've been trying to include a conditional in the amendedDeweyDecimal function for instances where there is no record number. I've got this: else if (typeof num !== 'undefined') { num == 'Invalid Record'; } but haven't gotten it to work. Any tips?
|
0

try jQuery .each

$('li').each(function(index, value) {
    var val = $(this).text().split(','); //split into array
    if (index >= 100 && index < 200) {
        //do stuff
    }
    if (index >= 400 && index < 500) {
        //do stuff
    }
    //etc
});

Comments

0

Regardless if you want to solve this using pure JavaScript or a helper library (like jQuery for example), i would suggest to disassemble your problem into smaller tasks and solve them one by one. At the end they will fit one into another and will build the complete solution. I would have started with three simple functions (reading your description they will be needed often):

  • the ability to list all LI elements separately
  • extract the number from the LI content
  • check if the number in in a given range

The code can look like this:

// count of all LI items
var elements = 0; 
// fetch LI item one at a time
var element = document.getElementById(elements+1);
while (element != undefined) {
    // get the number
    var number = Number(getNumber(element.innerHTML));
    // do something with number and or LI element
    if (inRange(number, 100, 200)) { /* add 100 ...*/ } // and so on
    // go to next element
    elements++;
    element = document.getElementById(elements+1);
}

function getNumber(elementContent) {
    return elementContent.split(",")[0]; // TODO error handling
}

function inRange(number, min, max) {
    return (number >= min) && (number <= max);
}

You can introduce simple objects and arrays to store information and states to track the changes of your content.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.