1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

Javascript Help

Discussion in 'JavaScript' started by KewL, May 18, 2015.

  1. #1
    I use some very light jquery on my blog and am trying to convert everything to normal javascript so i can drop the dependency.

    I'm having trouble creating my post "jump to section box". You can see the effect here.

    Here's where i got stuck:

    // Append list items for each heading
    var post = document.getElementById("left");
    var headings = post.getElementsByTagName("h3");
    var side_bar = document.getElementById("sections");
    var jump_list = side_bar.getElementsByTagName("ul")[0];
    
    for (i = 0; i < headings.length; i++) {
       var text = headings[i].innerHTML
       var list_item = document.createElement("li");
       list_item.innerHTML = (text);
    
       jump_list.appendChild(list_item);
    }
    
    // Get top positions of each heading
    var heading_positions = [];
    
    for (i = 0; i < headings.length; i++) {
       var position = headings[i].offsetTop
       heading_positions.push(position)
    }
    
    
    // Need to get li's index inside jump_list
    // Then scroll to the corresponding heading_position
    var lis = jump_list.getElementsByTagName("li");
    
    for (i = 0; i < headings.length; i++) {
      lis[i].onclick = function () {
        console.log(i)
      }
    }
    Code (javascript):
    Could someone explain how to do this? Here's the current jquery:

    
      // Appends li for each heading
      $('#left h3').each(function(){
        var heading = $(this).text()
        $('#sections ul').append('<li>' + heading + '</li>')
      })
    
      // Jumps to section on click
      $('#sections li').click(function(){
        var index = $(this).index()
        var position = $( '#left h3:eq(' + index + ')' ).offset().top
    
        $('html,body').animate({
          scrollTop: position - 10
        });
    
      })
    
    Code (javascript):
     
    KewL, May 18, 2015 IP
  2. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #2
    "jump to section"? As in on-page or off-page? Either what what the devil does JS even have to do with doing the job of anchors and ID's (or name attributes if going old-school)

    Kinda looks like you are dicking with stuff client side that should be static on the page... well, other than the goofy animated scrolling crap that I'd not be putting on a website in the first damned place.

    EVEN if I were to do that animation, I'd have the anchors in the markup, pointing at ID's, and use the scripting to enhance the existing functionality instead of supplanting it. HTML can all on it's own do this type of jump, the only thing the scripting needs to add is animating it.
     
    Last edited: May 19, 2015
    deathshadow, May 19, 2015 IP
  3. KewL

    KewL Well-Known Member

    Messages:
    245
    Likes Received:
    16
    Best Answers:
    3
    Trophy Points:
    128
    #3
    Hmmm i wasn't aware i could do that with just HTML. I don't car about the animation, but i don't want a page reload.

    Another issue is pulling the headers. I try to make writing a post as simple as possible. I don't think it'd be worth an extra database column and i really don't want the backend to have to do this every page load.

    Regardless, i'd still like to know how to create click functions like that for future js wrtting. Can you show me how to convert the jquery click function. Don't care about the anination. How can i get the clicked li's index in ul? Can i do this with 1 click function?
     
    KewL, May 19, 2015 IP
  4. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #4
    You need to have ID's on your H3 you are pointing at:
    <h3 id="whatWereCreating">What We’re Creating</h3>

    Then make ANCHORS to point at them.

    <a href="#whatWereCreating">What We’re Creating</a>

    You don't need to trap onclick unless you are going to animate it.

    If I were to try and do that "on the fly" assuming there were no id's and you wanted to have the scripttardery add them to make sure it's JS for nothing and an inaccessible mess...

    (function(d) {
    
    	function camelCase(str) {
    		return str.replace(/[\W_]+/g, ' ').replace(
    			/(?:^\w|[A-Z]|\b\w)/g,
    			function(letter, index) {
    				return index == 0 ? letter.toLowerCase() : letter.toUpperCase();
    			}
    		).replace(/\s+/g, '');
    	}
    
    	var
    		headingList = d.getElementById('left').getElementsByTagName('h3'),
    		ul = d.getElementById('sections').getElementsByTagName('ul')[0];
    		
    	for (var i = 0; i < headingList.length; i++) {
    		var
    			h3 = headingList[i],
    			h3Text = h3.innerText || h3.textContent,
    			li = ul.appendChild(d.createElement('li')),
    			a = li.appendChild(d.createElement('a'));
    		h3.id = camelCase(h3Text);
    		a.href = '#' + h3.id;
    		a.appendChild(d.createTextNode(h3Text));
    	}
    	
    })(document);
    Code (markup):
    See, no event handlers needed! But again, I would NOT be doing that in the first place, I'd have that in the bloody page with no scripting involved since that's a bunch of scriptard bullshit.

    I would instead change all your h3 to be:

    <h3 id="whatWereCreating">What We’re Creating</h3>
    <p>blah blah blah</p>
    
    <h3 id="settingUpDependencies">Setting Up Dependencies</h3>
    <p>blah blah blah</p>
    
    <h3 id="writingOurHTML">Writing our HTML</h3>
    <p>blah blah blah</p>
    
    <h3 id="writingOurCSS">Writing our CSS</h3>
    <p>blah blah blah</p>
    
    <h3 id="writingOurJavaScript">Writing Our JavaScript</h3>
    <p>blah blah blah</p>
    Code (markup):
    and just put this in the markup for that ul:

    <div id="sections">
    	<h3>Jump to Section</a></h3>
    	<ul>
    		<li><a href="#whatWereCreating">What We’re Creating</a></li>
    		<li><a href="#settingUpDependencies">Setting Up Dependencies</a></li>
    		<li><a href="#writingOurHTML">Writing our HTML</a></li>
    		<li><a href="#writingOurCSS">Writing our CSS</a></li>
    		<li><a href="#writingOurJavaScript">Writing Our JavaScript</a></li>
    	</ul>
    <!-- #sections --></div>
    Code (markup):
    ... and forget wasting time on scripting altogether... and again if I did want the animated scroll, I'd hook those anchors in pretty much the same way as the script above would -- grab the parent DIV by it's ID, grab all the anchors inside that DIV, and then attach an onclick handler to them to override the default behavior with the animated one. Since the h3 would have their own ID's already, you just strip the leading number sign off the hrefs and use getElementById to find it, then use DOM walking to figure out it's true position from top and animate the x scroll towards it.

    Again if you can build the functionality without the scripttardery, DO IT. Then enhance it with the scripting. Again, category 2 of my list of things people do with jquery -- things that HTML and CSS can do without scripting. Also something else I'm always ranting about -- people diving for the scripting before they know enough about HTML and CSS to know if they NEED the scripting.
     
    deathshadow, May 19, 2015 IP
  5. ketting00

    ketting00 Well-Known Member

    Messages:
    772
    Likes Received:
    27
    Best Answers:
    3
    Trophy Points:
    128
    #5
    Simple. You don't need an ID. What you need is an array of that list.
    The document.getElementsByTagName("li") will return an array and length. That's all what you need.
    Pick one from that array as ID.

    Like this simple yet, effective method of mine. [I hate those fancy function that do simple thing.]
    HTML:
    
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    
    Code (markup):
    JS:
    
    var lis = document.getElementsByTagName("li");
      
    for (var i = 0, j = lis.length; i < j; i += 1 ) {
        (function(x) {
            lis[x].addEventListener('click', function() {
                console.log('Item ' + x + ' got clicked.\r\n What are you going to do now?');
            });
        })(i);
    }
    
    Code (markup):
     
    Last edited: May 20, 2015
    ketting00, May 19, 2015 IP
  6. KewL

    KewL Well-Known Member

    Messages:
    245
    Likes Received:
    16
    Best Answers:
    3
    Trophy Points:
    128
    #6
    Thanks for the help, all worked perfect
     
    KewL, May 21, 2015 IP