CodingForums.com

CodingForums.com (http://www.codingforums.com/index.php)
-   JavaScript programming (http://www.codingforums.com/forumdisplay.php?f=2)
-   -   Display random list items from another page (http://www.codingforums.com/showthread.php?t=286578)

snarf1974 01-28-2013 02:30 PM

Display random list items from another page
 
Hello,

I'm trying to display random <li> from a <ul> on another page.

There are 25 list items on the other page (reports.htm) and I would like 3 to be displayed on the homepage (index.htm) randomly. The list items only have to change on page refresh (F5).

I've tried the following code, BUT this meant copying the 25 list items from reports.htm into index.htm. This only displays 1 list item, and hides the others from the screen (not good for our screen reading audience):

Code:

<script type="text/javascript">

this.randomtip = function(){
        var length = $("#tips li").length;
        var ran = Math.floor(Math.random()*length) + 1;
        $("#tips li:nth-child(" + ran + ")").show();
};

$(document).ready(function(){       
        randomtip();
});

</script>

Any tips/solutions/comments would be greatly appreciated.

Many thanks

sunfighter 01-28-2013 04:56 PM

Code:

<script type="text/javascript">
this.randomtip = function(){
var length = $("#tips li").length;
for($i = 0; $i < 3; $i++)
{
        var ran = Math.floor(Math.random()*length) + 1;
        $("#tips li:nth-child(" + ran + ")").show();
}
};
$(document).ready(function(){
        randomtip();
});
</script>

I didn't check this, but you see what I did right?

Old Pedant 01-28-2013 08:30 PM

I don't understand, in the least, Sunfighter. Your code still depends on having all 25 <li> items on the *current* page. You need to, instead, fetch *only* the requisite number of items from the other page. On top of that, although you try to "show" 3 items, there is no guarantee that you won't end up picking the same random item all 3 times! (Granted, that's unlikely, but it's certainly possible. And picking the same one twice will happen more often than you'd want to see.)

Snarf: There is no way to make this work as you wanted *UNLESS* both pages are present in the browser AT THE SAME TIME. Or unless you are willing to "send" the random item(s) from the one page to the other.

You need to give us more details: Is one of these pages in, for example, an <iframe> on the other of the pages? How do you expect to transfer the data from one page to the next?

rnd me 01-29-2013 05:23 AM

i didn't see this before, but this is a perfect use case for my partial page content fetcher.
it's not setup to do 3 random items, so we'll need a slight modification:

changes in red:

Code:

function getPage(url, from, to, callBack) {
        var cached=sessionStorage[url];
          if(!from){from="body";} // default to grabbing body tag
        if(cached){return elm.innerHTML=cached;} // cache responses for instant re-use re-use
        if(to && to.split){to=document.querySelector(to);} // a string TO turns into an element
        if(!to){to=document.querySelector(from);} // default re-using the source elm as the target elm

        var XHRt = new XMLHttpRequest; // new ajax
        XHRt.responseType='document';  // ajax2 context and onload() event
        XHRt.onload= function() { callBack(XHRt.response.querySelector(from), to);};
        XHRt.open("GET", url, true);
        XHRt.send();
        return XHRt;

}


// to use it with the callback:
$(document).ready(function() {

  getPage("./reports.htm", "ul#tips", "ul#tips", function (elm, dest) {
                var frag = document.createDocumentFragment(),
                items = elm.getElementsByTagName("li");
                dest.innerHTML=""; //clear list

                // grab 3 different items:
                for (var $i = 0; $i < 3; $i++) {
                        frag.appendChild(items[Math.floor(Math.random() * items.length)]);
                }

                // append all 3 to UL on page:
                dest.appendChild(frag);
  });//end getPage()

});//end ready()


snarf1974 01-29-2013 04:31 PM

Old Pedant: I'm working on a local version of this page:
http://www.hse.gov.uk/horizons/index.htm

The box in question is the 'short form reports' box. The other page (http://www.hse.gov.uk/horizons/sfreports.htm) has the 25 reports in an unordered list. The pages are not in iframes.

It would be good to facilitate this using a client-side only script, as we don't have permission to mess around with asp.net on the server.

rnd me: The index.htm and sfreports.htm pages are in a root folder. As sfreports.htm is on the same level as index.htm, Ive done the following:

Code:

  getPage("sfreports.htm", "ul#tips", "ul#tips-index", function (elm, dest) {
Using jQuery 1.7.2

I've tried only putting the <ul> in the index page:

Code:

<ul id="tips-index">

</ul>

And also the following:

Code:

<ul id="tips-index">
<li></li>
<li></li>
<li></li>
</ul>

Unfortunately, still not working. What am I missing?

Thanks to both of you for your help thus far.

snarf1974

sunfighter 01-29-2013 05:47 PM

@Old Pedant This was just a fast code to show how to display three items from a group. Two questions were asked, i answered one; sort of. As I said I didn't check this and didn't think of displaying an item two or three times. If I played with it that scenario might have showed up and been dealt with.

As for getting items from another page. I could do it but it would be complicated and as I said "I didn't check this" cause I had other things to do that day. One would have hoped that snarf1974 would have seen what I did and that it only answered one of his questions.

Anyway I don't want to steal this thread and it looks like rnd me is helping him so I'll just back out of here, hat in hand, eyes downcast, bowing low, smile on my face.

Old Pedant 01-29-2013 08:24 PM

But how will you be *SURE* that a user will have *BOTH PAGES* open in their browser at the same time???

Since both come from the same domain, there is no cross-site scripting issue, but still the one page can only read items from the other page if both are open in the same browser on the same computer at the same time.

Now...

One solution would be to *force* the page you want to grab data from to be in an <iframe> on the page grabbing the data! The <iframe> can be completely invisible, so the user won't even know you are doing this.

Is this a viable path for you??

rnd me 01-30-2013 03:40 AM

Quote:

Originally Posted by Old Pedant (Post 1309566)
But how will you be *SURE* that a user will have *BOTH PAGES* open in their browser at the same time???

Since both come from the same domain, there is no cross-site scripting issue, but still the one page can only read items from the other page if both are open in the same browser on the same computer at the same time.

no, you can usajax to get a page from anywhere on the site or the world w/cors.

@snarf: i'll take a look later, i'm mobile right now.

rnd me 01-30-2013 04:26 AM

the URLs and classnames you provided are a bit out of whack, i suspect local/live drift as the culprit.

nonetheless, the following code ran in chrome's inspector from: http://www.hse.gov.uk/horizons/index.htm .



Code:

function getPage(url, from, to, callBack) {
        var cached=sessionStorage[url];
          if(!from){from="body";} // default to grabbing body tag
        if(cached){return elm.innerHTML=cached;} // cache responses for instant re-use re-use
        if(to && to.split){to=document.querySelector(to);} // a string TO turns into an element
        if(!to){to=document.querySelector(from);} // default re-using the source elm as the target elm

        var XHRt = new XMLHttpRequest; // new ajax
        XHRt.responseType='document';  // ajax2 context and onload() event
        XHRt.onload= function() { callBack(XHRt.response.querySelector(from), to);};
        XHRt.open("GET", url, true);
        XHRt.send();
        return XHRt;

}


// to use it with the callback:
$(document).ready(function() {

  getPage("/horizons/sfreports.htm", "ul.itemThumbBook", ".hse2ColumnRight", function (elm, dest) {
                var frag = document.createDocumentFragment(),
                items = elm.getElementsByTagName("li");
                dest.innerHTML=""; //clear list

                // grab 3 different items:
                for (var $i = 0; $i < 3; $i++) {
                        frag.appendChild(items[Math.floor(Math.random() * items.length)]);
                }

                // append all 3 to UL on page:
                dest.appendChild(frag);
  });//end getPage()

});//end ready()

i didn't see a ul#tips anywhere, so i did the best i could. kinda just threw it into a container at the bottom...

but now that it's operational, you should be able to adjust the css selectors to match the actual markup in use without much fuss. remember that the paths and css selectors have to match up, and that you can't pull the live page from your test rig, you have to pull the local copy, which i observed to be on a different url path than indicated.

the gun is firing. as long as it's pointing in the right place, it will hit the target.

sunfighter 01-30-2013 06:34 PM

I guess you guys got this all sorted, but it seems to me that putting those 25 things into and array and doing an array.sort on it and just picking the first three would be a whole lot easier and less code (and maybe faster ??) without trying to get them from the other page.

Old Pedant 01-30-2013 08:48 PM

Sunfighter: You are, of course, correct. But it was my impression that the 25 items on that other page changed from time to time, presumably because of other external actions. So I assumed that the goal was to pick 3 of the *current* <li>s, from the live page.

RndMe's method is, as usual with his code, quite clever and correct. But I don't know, for example, how many browser support createDocumentFragment().

My own method would be a lot simpler and would work with browsers as far back as MSIE 5.

But I'm not going to bother to show it unless the OP says he wants it.

rnd me 01-30-2013 10:14 PM

Quote:

Originally Posted by sunfighter (Post 1309822)
I guess you guys got this all sorted, but it seems to me that putting those 25 things into and array and doing an array.sort on it and just picking the first three would be a whole lot easier and less code (and maybe faster ??) without trying to get them from the other page.

how is having to publish each content update twice faster than publishing it once?

rnd me 01-30-2013 10:22 PM

Quote:

Originally Posted by Old Pedant (Post 1309849)
RndMe's method is, as usual with his code, quite clever and correct. But I don't know, for example, how many browser support createDocumentFragment().

My own method would be a lot simpler and would work with browsers as far back as MSIE 5.

createDocumentFragment is dom1 thing, been around forever...
it's the ajax2 you should be complaining about ;)

xhr.onload(), querySelectorAll(), and createDocumentFragment() should work in all known browsers to at least a couple versions back.

if you are feeling code-happy, please code an IE6/7 compatible version of the function from the POST A JAVASCRIPT section so that many coders can pickup that extra percent of old user agents with no effort.



as far as making this particular code simpler, i don't really see how that could be done. 6 lines of custom code is not very much for an ajax call, unique (non-repeating) result picking, and cross-browser dom handling. if you know a simpler way of doing all that, please, share your feelings with the group. I'd like to see that code. i don't imagine that mine is the only way or the end-all be-all right way of doing anything. furthermore, it's easier for me to find faults with other's code than my own, so it would be nice if that applied universally, and you can spot some issues i can't...

Old Pedant 01-30-2013 10:33 PM

Well, I *did* say "for example" about createDocumentFragment.

Okay, okay...I'll show my scheme. It's not clever. It's not better. It's just simple. Back later.

But I just noticed this in your code:
Code:

                // grab 3 different items:
                for (var $i = 0; $i < 3; $i++) {
                        frag.appendChild(items[Math.floor(Math.random() * items.length)]);
                }

??? How does that answer my prior objection that you might get the same <li> all 3 times? And you will surely get the same item twice more often than would make the user happy. What am I missing?

rnd me 01-30-2013 11:02 PM

Quote:

Originally Posted by Old Pedant (Post 1309874)
Well, I *did* say "for example" about createDocumentFragment.

Okay, okay...I'll show my scheme. It's not clever. It's not better. It's just simple. Back later.

But I just noticed this in your code:
Code:

                // grab 3 different items:
                for (var $i = 0; $i < 3; $i++) {
                        frag.appendChild(items[Math.floor(Math.random() * items.length)]);
                }

??? How does that answer my prior objection that you might get the same <li> all 3 times? And you will surely get the same item twice more often than would make the user happy. What am I missing?

when you append an element to the fragment, it disappears from the nodeList...

remember, unlike arrays of elements, nodeLists from element.getXXXbyXXX() methods are live.

the other routines i imagined were much more complex, which is why i was curious about what you had in mind.


All times are GMT +1. The time now is 02:37 PM.

Powered by vBulletin®
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.