最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Anchor CyclerDropdown to import school class data periodically - Stack Overflow

programmeradmin4浏览0评论

SO,

I've been working on some html/javascript/css recently to create an online table for my students to view details, scores and various bits of information but I've hit a brick wall and am unsure how to do what I'm trying to do.

The reason I'm posting all of these in one thread is because several of these I think could conflict and cause the previous edit(s) to fail to function...

I realise that there are a lot of questions in one here and don't expect someone to code the entire thing, I'm just looking for some help / snippits / ideas and would greatly appreciate especially those with comments/descriptions so that I can continue to learn and improve :)


Update 13/11/2013 @ 02:43 GMT

LATEST: /

  • I'm trying to get Next Class | Previous Class to be cycle buttons to move to and from classes the same way the dropdown works.
  • The scroll bar what used to be at the bottom of the page has disappeared because of the width has been changed...
  • The footer at the bottom doesn't show correctly on mobile devices and the Scroll Left and Scroll buttons don't appear at all on mobile devices.
  • The scroll left button is unable to be clicked
  • Refreshing the page resets the horizontal scroll position to far left (I'm pretty sure this relates to the scroll bar)

  • In regards to the loading/refreshing I guess I'll have to make another post as the current options are nearly there but not quite, I'll example below the way(s) that I ideally want it to work.

    • main.html will not contain any class details it would be: .php?i=HwXM67up
    • The "option" (dropdown) would somehow poll a json file to gather a list of classes avaliable
    • The "option" (dropdown) will have options for each individual school class aswell as "All Updating" and "All Non-Updating"
    • Selecting an individual school class will import ONLY that specific school class into the page.
    • Selecting a different individual school class will destory the old school class and import the newly selected school class.
    • Individual school classes will periodically poll the json file to check for updates / changes to that school classes data and on a change/update it will re-draw/re-import.
    • Selecting "All Updating" will import ALL school classes and periodically poll the json file to check for updates / changes to any school class (if possible only updating the school class what has changed/updated) but with all classes visible on the page.
    • Selecting "All Non-Updating" will do the same as above but won't need to poll the json file to update.
  • I can split the data into blocks like: .php?i=MRpjvJp0 (first block example) fairly easily and give them correct titles (titles that would be used in the Option dropdown), unsure how to put them into json format though

SO,

I've been working on some html/javascript/css recently to create an online table for my students to view details, scores and various bits of information but I've hit a brick wall and am unsure how to do what I'm trying to do.

The reason I'm posting all of these in one thread is because several of these I think could conflict and cause the previous edit(s) to fail to function...

I realise that there are a lot of questions in one here and don't expect someone to code the entire thing, I'm just looking for some help / snippits / ideas and would greatly appreciate especially those with comments/descriptions so that I can continue to learn and improve :)


Update 13/11/2013 @ 02:43 GMT

LATEST: http://jsfiddle.net/pwv7u/

  • I'm trying to get Next Class | Previous Class to be cycle buttons to move to and from classes the same way the dropdown works.
  • The scroll bar what used to be at the bottom of the page has disappeared because of the width has been changed...
  • The footer at the bottom doesn't show correctly on mobile devices and the Scroll Left and Scroll buttons don't appear at all on mobile devices.
  • The scroll left button is unable to be clicked
  • Refreshing the page resets the horizontal scroll position to far left (I'm pretty sure this relates to the scroll bar)

  • In regards to the loading/refreshing I guess I'll have to make another post as the current options are nearly there but not quite, I'll example below the way(s) that I ideally want it to work.

    • main.html will not contain any class details it would be: http://pastebin.com/raw.php?i=HwXM67up
    • The "option" (dropdown) would somehow poll a json file to gather a list of classes avaliable
    • The "option" (dropdown) will have options for each individual school class aswell as "All Updating" and "All Non-Updating"
    • Selecting an individual school class will import ONLY that specific school class into the page.
    • Selecting a different individual school class will destory the old school class and import the newly selected school class.
    • Individual school classes will periodically poll the json file to check for updates / changes to that school classes data and on a change/update it will re-draw/re-import.
    • Selecting "All Updating" will import ALL school classes and periodically poll the json file to check for updates / changes to any school class (if possible only updating the school class what has changed/updated) but with all classes visible on the page.
    • Selecting "All Non-Updating" will do the same as above but won't need to poll the json file to update.
  • I can split the data into blocks like: http://pastebin.com/raw.php?i=MRpjvJp0 (first block example) fairly easily and give them correct titles (titles that would be used in the Option dropdown), unsure how to put them into json format though
Share Improve this question edited Nov 13, 2013 at 2:45 Dennis Sylvian asked Nov 7, 2013 at 20:05 Dennis SylvianDennis Sylvian 9771 gold badge10 silver badges31 bronze badges 9
  • I think it would be wise to put a fixed width on the container and to use overflow-x:scroll to handle scrolling in the table – Danny Commented Nov 7, 2013 at 20:23
  • 1 @Danny It is already in a container and has a scroll bar but I'm trying to get some buttons working correctly, they scroll at the moment but too far (as shown: i.imgur.com/4YBHXgs.png) – Dennis Sylvian Commented Nov 7, 2013 at 20:26
  • 1 Have you considered using "pagination/page-numbers" rather than displaying the entire thing in 1 page? It would make your life easier – evilReiko Commented Nov 10, 2013 at 13:32
  • @DennisSylvian I have updated my answer once again, hope I got all of your questions – Sijav Commented Nov 11, 2013 at 4:16
  • 1 This question appears to be off-topic because, as it now stands, there isn't one specific question that will be of widespread interest to future readers - it's more of a debugging session. Pleased you solved it, though! – halfer Commented Dec 4, 2013 at 20:38
 |  Show 4 more comments

4 Answers 4

Reset to default 8 +250

Update 13/11/2013 @ 12:09 GMT
Just because you have done an entire edit to your post I just did the same! no need those data!
however I have answered a lot of your questions that you are asking already!
LATEST: http://jsfiddle.net/sijav/pwv7u/1/

  • I have done it simply, Just use the blow code: (It's minified!)

    $("#PreviousClass").click(function(){if(currentClass>1){currentClass--;$('.class-selector').val("CLASS"+currentClass);scrollToAnchor("CLASS"+currentClass);}});
    $("#NextClass").click(function(){if(currentClass<6){currentClass++;$('.class-selector').val("CLASS"+currentClass);scrollToAnchor("CLASS"+currentClass);}});
    

Also you need to set Next Class and Previous class ID to the proper one and remove href!

  • you need to remove overflow: auto; from container class! and then replace $("#container") with $("body") in scroll left /right button! so:

    #container {
    margin: 0 auto;
    /*overflow: auto;*/
    padding: 80px 0;
    width: 100%;
    }
    

    and:

    $("a.def").click(function () {
            $('body').animate({
                "scrollLeft": "-=204"
            }, 200);
    });
    
    $("a.abc").click(function () {
        $("body").animate({
                "scrollLeft": "+=204"
            }, 200);
    });
    
  • It is because you just put that under the footer1! of you bring it to forward it will appear correctly, also why not put a semy transparent black background? background: rgba(0, 0, 0, 0.58);

  • I'm not seeing any issue on that after that changes mentioned above!

  • Good Idea ... let's see...:

  • Again I have already give you the code of how to ajax twice! and again you no need to put those in json format! html format will be quite great for what you want to do! just save them as class1.html, class2.html, class3.html, etc. and get the proper html and insert the table instead the current one in container! the code would be:

    $.ajax({
    url: "class1.html", //this can be anything! better to use a variable like "class"+currentClass
    dataType: "HTML",
    error: function(){alert("Error on communicate to server"}, //what to do on error
    success: function(html){$("#container").html(html)}, //replace the container on success
    });
    

Simple right? you can put http://fiddle.jshell.net/pwv7u/show/ in url to test and see what will happen?!

  • why not put those options in a html file and get it like i mention above?!
  • well, I have told you enough on above,
  • the $("#container").html(SomeHtmlString) will change the whole container with current one
  • you can have ... (wait for it) ... setInterval(functionThatIncludeAjaxName,milisecond) (I have told you before)
  • you can get all data from them and append what you want with '+' and then $("container").html(TheAppendedHTMLString)
  • you can have something like this => http://jsfiddle.net/sijav/WJ8Js/
  • One thing, for mobile view, you can use some api that scale the whole webpage according to body width! it's very useful on tablet and mobile devices.

Good luck and feel free to ask if you couldn't understands my answer properly or just have a new questions.

Lets see (scroll down for update)

(demo at http://jsfiddle.net/u7UkS/2/)

  1. Left & Right Table Scrollers (Fixing the overscroll?)
    You need to animate the scrollLeft instead of the margin. It will automatically take care of excess values, as it cannot scroll more than allowed..

    $("a.abc").click(function () {
        $('#container').animate({
            "scrollLeft": "-=204"
        }, 200);
    });
    
    $("a.def").click(function () {
        $("#container").animate({
            "scrollLeft": "+=204"
        }, 200);
    });
    
  2. Anchor Cycler / Dropdown List to jump to each class?
    You can loop over the a elements, get their id and popuplate a select element. Then handle the change event and animate to the selected position with your scrollToAnchor class

    <select class="class-selector">
        <option value="">-select class-</option>
    </select>
    

    and

    // gather CLASS info
    var selector = $('.class-selector').on('change', function(){
        var id = this.value;
        if (id!==''){
            scrollToAnchor(id);
        }
    });
    $('a[id^="CLASS"]').each(function(){
        var id = this.id,
            option = $('<option>',{
                value: this.id,
                text:this.id
            });
        selector.append(option);
    });
    
  3. Column autosizing?
    Just set white-space:nowrap to the th/td elements

    td, th {
        white-space:nowrap;
    }
    
  4. Loading/Updating class sections from JSON.
    You have not provided any code for this. So i will just describe how to do it..
    For the repeating AJAX request use a timeout and once you handle its result fire a new one

    function handleData(data){
       //loop over data and edit the DOM
       $.each(data, function(index, item){
         // variable item refers to the current CLASS of the iteration
         // assuming that the JSON is an array of CLASS groups describing the rows..
    
         //find the DOM section with the current class info and update data..
       });
       setTimeout(checkData, 30000);
    }
    function checkData(){
        $.getJSON('the-url-to-your-json', handleData);
    }
    // initiate the first timeout
    setTimout(checkData, 30000); // 30000 ms is 30sec.
    
  5. Cookies? to remember and restore selected rows
    No need to use cookies, just in step #4 do not remove the whole row and reinsert, but instead edit the contents of the td elements. This way the tr will maintain its class and the styling will persist. Alternatively, before overwriting the row chack if it has the selected class, and if so add it to the row you are about to insert..

Demo at http://jsfiddle.net/u7UkS/2/


I have also edited your scrollToAnchor and removed 80 from the scrollTop to account for the heading

function scrollToAnchor(aid) {
    var aTag = $("a[id='" + aid + "']");
    $('html,body').animate({
        scrollTop: aTag.offset().top - 80
    }, 1);
}


Update

Assuming from your update to the question, that you do not need to show all classes all the time nor update all of them

you could show/hide the CLASSes depending on the selection to the dropdown with this css and code

#container tbody, #container thead {
    display:none;
}
#container tbody.current {
    display:table-row-group;
}
#container thead.current {
    display:table-header-group;
}

and

    var classSelector = $('.class-selector');

    // gather CLASS info
    classSelector.on('change', function () {

        var id = this.value;
        $('#container').find('thead, tbody').removeClass('current');
        if (id !== '') {
            //scrollToAnchor(id);
            var group = $('#' + id).closest('thead');
            group.add(group.next('tbody'))
                .addClass('current');
        }

        // since we changed the current CLASS, initiate a checkdata() so that we can update as soon as possible.. 
        checkData();
    }).trigger('change');

Now when we do an AJAX request we can send with it some data to the server to limit the returned info. So in the checkData we do

function checkData() {
        var currentId = classSelector.val();

        if (currentId !== ''){
            // Start AJAX request
            alert('starting ajax request for ' + currentId);
            // change /echo/json/ with the url to your json
            // delay should be removed, it just for jsfiddle..
            jsonRequest = $.getJSON('/echo/json/', {'delay':2,'class' : currentId}, handleData);        
        }
    }

and handleData

function handleData(data) {
    alert('handling data');
    //loop over data and edit the DOM        
    var classBody = $('#container').find('tbody.current');
    $.each(data, function (index, item) {
        // variable item refers to the current CLASS of the iteration
        // assuming that the JSON is an array of CLASS groups describing the rows..

        // populate classBody with the JSON data

    });
    jsonTimeout = setTimeout(checkData, 10000); // change the 10000 to whatever you want.. i set it to 10 seconds to see the repeating..
}

You will notice the jsonTimeout = setTimeout(..) and jsonRequest = $.getJSON(..). We store those in variable so we can abort them when we change the current CLASS to avoid excess processing

This is done by adding

    if (jsonTimeout) clearTimeout(jsonTimeout);
    if (jsonRequest) jsonRequest.abort();

to the change handler of the dropdown.

Updated Demo at http://jsfiddle.net/u7UkS/4/

Preface

In an attempt to cover all of your questions I've tried to include demos in all the answers. Unfortunately I'm only one man and I could not create demos for all the answers. If anyone feels that hes has something to contribute please feel free to comment or edit this.

Updates

In response to @DennisSylvian's updated question here are my updates.

Answers

    1. To scroll the overflow you would be better off using:

      $('.table-wrapper')[0].scrollLeft += 50;
      

      DEMO here

    2. If you want to position elements in simple manner using css you can define the parent as position: relative; and then give each element a position: absolute; to "throw" them out into each corner:

      .controller-wrapper { position: relative; } .top-left, .top-right, .bottom-left, .bottom-right { position: absolute; } .top-left { top: 0; left: 0; } .top-right { top: 0; right: 0; } // ...

    Update: DEMO here

    1. You can add any offset you have to the scrolling function:

      var offset = 80; // Or any other calculation
      $('html,body').animate({
          scrollTop: aTag.offset().top + offset
      }, 1);
      
    2. I'm not entirely sure you mean class as in css .class or class as in school class but if it's the latter then you can place an id on each td you would like to scroll to:

      <td id="class1" class="scrollto">Title</td>
      <!-- ... -->
      <td id="class2" class="scrollto">Title</td>
      

      You can then build your list out of these id's using:

      var anchorList = [];
      
      $('.scrollto').each(function(){
      
        anchorList.push( '<option value="'+ this.id +'">'+ this.id +'</option>' );
      
      });
      
      // This is an empty select menu
      $('#anchor-list')
        .append( anchorList.join('') )
        .change(function(){
      
          scrollToAnchor( $(this).val() );
      
        });
      

      This would require a slight change to your scrollToAnchor function:

      // Put this line
      var aTag = $('#' + aid);
      
      // Instead of this one:
      var aTag = $("a[id='" + aid + "']");
      

      DEMO here

  1. This is slightly tricky as the browsers rendering engine does not calculate the columns value based on the contents of the largest cell.

    You would have to either use a plugin (since the code for writing this is much more than this answer can cover), or manually set the width based on the logic of the column data i.e if you have a column that has names in it you can manually set the first td width to the longest name in the list.

    Update: Another option suggested by @sijav is to use:

    table td { white-space: nowrap; }
    
  2. Update:

    You can pull a single page using a drop down and $.get():

    <select id="class-list">
      <option value="1">Class 1</option>
    </select>
    

     

    $('#class-list').change(function(){
      $.get('/server/data/class', { class: $(this).val() }, function(data){
        $('#container').html( data );
      });
    });
    

    With the above example your server side code would render the html and send in the table ready to be inserted into the dom. Since all the table is being created on the fly you would have to use event bubbling (binding the event to an element that is not rendered from the ajax call).

    Example the highlight row button would have to be written like this:

     $('#container').on('click', 'tr', function(){
       var $this = $(this);
    
       $this
         .addClass('highlight')
         .siblings('tr')
         .removeClass('highlight');
     });
    

    The data does not necessarily have to come in JSON format (although it would be more agile if at a future point you would need to do something else with the data).

    You can output your data as HTML instead of JSON from your server code.

    To check if the data is updated or not you could poll for a flag that your server code should output.

    // Poll every minute
    setTimeout(function(){
    
      // Check for changed content
      $.get('/server/data/changed', function( data ){
    
        // Server indicates content has changed get the content and update
        if ( data.flag ){
    
          $.get('/server/data/get', function( data ){
            updateHtml( data );
          });
    
        }
    
      });
    }, 1000 * 60);
    

    The above code is an example of a polling technique for updating your content.

  3. To "remember" the row that was clicked you can use localStorage.

    There are several ways to do this this is one of them:

     // On page ready
     jQuery(function( $ ){
    
       var rowIndex = localStorage.getItem('rowIndex');
    
       if ( rowIndex ) {
    
         $( 'table tr' ).eq( rowIndex ).addClass('highlight');
    
       }
    
       // Save the row to localstorage based on it's index in the table
       var saveRow = function ( index ) {
    
         localStorage.setItem( 'rowIndex', index );
    
       };
    
       // Highlight the row and save it
       $( 'table tr' ).click(function(){
    
         var $this = $(this);
    
         $this
           .addClass('highlight')
           .siblings('tr')
           .removeClass('highlight');
    
         saveRow( $this.index() );
    
       });
    
       // On page exit/reload/change check for highlighted row and "save" it to localstorage
       $(window).on('beforeunload', function(){
    
         saveRow( $('.highlight').index() );
    
       });
    
     });
    

    DEMO here

1) You have to realize that you're not scrolling the page like you would do that with your scroll on a mouse. You're actually manipulating margin-left and this behaviour causes that you give it very large values. Then, it looks like you have told. There's a huge space between table and end of your screen. To solve it, you have to add an if statement that is going to check if you're trying to increase margin-left too much.

 $("a.def").click(function() {
    $("#gradient-style").each(function(){
        var margin =$(this).css("margin-left");

        if(margin > -204)
             $(this).animate({"margin-left":"+=204px"},200);
        else
             $(this).animate({"margin-left":"+=" +(-margin)},200);
    });
});

5) You could use localStorage variable which is built-in JavaScript feature. You can simply define any variable and use it over session. Here's example:

 localStorage.numberOfRow =1;
 console.log(localStorage.numberOfRow);     //1
发布评论

评论列表(0)

  1. 暂无评论