Forum Moderators: open

Message Too Old, No Replies

Ajax fragments, setting a permanent value

or, maybe, just getting the value of href based on class name

         

csdude55

3:13 am on Jun 12, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Still working on a classifieds site, using jQuery and infinite scroll. I'm having another problem, and I'm hoping you guys can give me some insight on what I might do to fix it.

The infinite scroll uses jQuery's $.load for Ajax fragments:

[api.jquery.com...]

(Note, this is different from the deprecated $.load event)

The first iteration uses the default link, like example.com/classifieds/, and shows the first 20 records. In the original design, the user would click a "Next" button and be taken to example.com/classifieds/?s=20 (where "s" equals the number of records to skip) to see Page 2, s=40 to see Page 3, etc. But now, I'm simply bypassing the "Next" button and using an Ajax fragment to grab the results within the DIV #classifiedList of s=20, and appending it to the same DIV on the default page.

The next page is determined via PHP, using a variable $next_link. It's then coded as:

<a class="nextClassified" href="$next_link" style="display: none">next</a>


The script (in an external JS) looks for $('.nextClassified:last').attr('href'), and loads the fragment based on the result.

And that is all working just fine, it's just some explanation so you'll see where I am.

Now, I'm adding a new mess to the existing mess... I'm setting up a toggle between "list view" and "grid view", and when the user toggles the button it uses a new Ajax fragment to change a child DIV within #classifiedList, named #fragLoad. I'm sending a variable to the $.load of v=list or v=grid, and the fragment reloads and shows the proper output.

This works fine on the first iteration, but the next iteration (when it loads s=20) goes back to the original setting.

I've tried everything I can think of to remember this setting, but nothing is working. I first tried setting a cookie, but since the document header is bypassed it's not loaded until they refresh. I've spent most of today trying to change the href of nextClassified, but since it's hidden I don't think the Javascript is able to find it to change it... and I'm not quite sure changing this will solve the problem, anyway.

Here's the script I'm working with:

// $frag is created via PHP before this script; basically the same as 
// $next_link, but created outside of #classifiedList
function loadFragment(viewstyle) {
var otherlist = 'grid';
if (viewstyle == otherlist) otherlist = 'list';

var url = '$frag' + '&v=' + viewstyle;

$('#fragLoad').load(url + ' #fragLoad');

// setCookie is a separate function I built a long time ago, using document.cookie
setCookie('viewstyle', viewstyle, 1);

// Here's where I'm trying to change v=list or grid
// this throws an error that index can't run on undefined
if ($('a.nextClassified:last').attr('href').index('v=') !== -1) {
$('a.nextClassified:last').attr('href').replace(/v=(list|grid)/, 'v=' + viewstyle);

// Check to see if I make it this far... spoiler, it doesn't
alert('1');
}

// test to see if anything can be read, but both alert "undefined"
// which makes NO sense, because this works fine in the infinite scroll:
// .load($(nextClass + ':last').attr('href') + ' ' + itemID
alert($('.nextClassified:last').attr('href'));
alert($('.nextClassified:last').prop('href'));

// test querySelector instead of jQuery, but "'a.nextClassified:last' is not a valid selector"
// but since I'm in an infinite scroll, I have multiple instances of a.nextClassified
// how else do I only change the last one?
alert(document.querySelector('a.nextClassified:last').getAttribute('href'));
}


Any thoughts on how I can set a variable in the first iteration of the infinite scroll that would be passed along to the second+ iterations?

If you think I'm on the right track, any suggestions on what I'm doing wrong in trying to read and set the href of .nextClassified?

csdude55

7:44 am on Jun 12, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Update: I figured out the issue with changing nextClassified, I had to change that before loading the fragment. Which makes sense, because nextClassified was being changed and it was running before the fragment loaded.

So now:

// $frag is created via PHP before this script; basically the same as 
// $next_link, but created outside of #classifiedList
function loadFragment(viewstyle) {
var otherlist = 'grid';
if (viewstyle == otherlist) otherlist = 'list';

var url = '$frag' + '&v=' + viewstyle;

// Here's where I'm trying to change v=list or grid
alert('1 - ' + $('.nextClassified:last').attr('href'));

if ($('.nextClassified:last').attr('href').indexOf('v=') !== -1) {
$('.nextClassified:last').attr('href').replace(/v=(list|grid)/, 'v=' + viewstyle);

alert('2 - ' + $('.nextClassified:last').attr('href'));

$('#fragLoad').load(url + ' #fragLoad');

// setCookie is a separate function I built a long time ago, using document.cookie
setCookie('viewstyle', viewstyle, 1);
}


But it looks like $('a.nextClassified:last').attr('href').replace(/v=(list|grid)/, 'v=' + viewstyle); isn't working, I end up with the same URL both before and after and there are no errors in the console.

The URL that should be modified is:

https://ww2.example.com/classifieds/for-sale/guns-hunting/?v=grid&data_b=5&s=20


It's 3:40am here so I'm headed to bed, and I'll play with it more tomorrow. But if you guys and gals have any ideas why .replace() isn't working, you might save me another day of wasted efforts :-)

csdude55

4:49 am on Jun 13, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Today was the 5th day straight of trying to figure out this bug, so I officially gave up and just used window.location to reload the page with the GET variable. If anybody has an idea then I'll get notifications on this thread, otherwise I just wasted almost an entire week :'-(

robzilla

6:02 pm on Jun 13, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



The below snippet doesn't actually change the value of the href attribute in the DOM):
$('.nextClassified:last').attr('href').replace(/v=(list|grid)/, 'v=' + viewstyle);

That's essentially like doing this in PHP:
$var = "whatever";
str_replace('what', 'which', $var);

Which doesn't affect $var at all. In your case, replace() doesn't affect the DOM at all.

You'll need to change it to something like this:
$('.nextClassified:last').attr('href', function(i, originalHref) { return originalHref.replace(/v=(list|grid)/, 'v=' + viewstyle); });

The second parameter to attr() changes the value.

csdude55

6:07 pm on Jun 13, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Ahh, I see! Thanks for the tip, @robzilla :-D I'll give that a shot this evening and see what happens!

Steven29

6:47 pm on Jun 13, 2018 (gmt 0)



I think it's also :last-child

robzilla

7:57 pm on Jun 13, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I think it's also :last-child

Wouldn't work since (I think) he's not trying to get the last child of .nextClassified, but rather the last occurrence of .nextClassified, and for that you'd use either :last or .last(). Or .filter(':last'), which is apparently faster than :last, but then again so is .last().

To clarify the snippet I posted earlier, when I didn't have much time:

$('.nextClassified').last().attr('href', function(i, originalHref) { 
return originalHref.replace(/v=(list|grid)/, 'v=' + viewstyle);
}
);

The second parameter (arbitrarily named, I chose originalHref) to the function passed in attr() takes the original value of the attribute you've selected (href), and by returning that with the value of v replaced, we then use that to set the new value of the href attribute.

csdude55

12:24 am on Jun 14, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Well, rob, that did get me past the hurdle, but it's still doing the same thing. It works fine on the first iteration, but if I scroll down so that it gets to the second page (s=20), then scroll back up and toggle it, then the first page toggles but none of the other pages do.

I'm going to have to move on to the next section, though, and maybe come back to this one later... 5 days is just too much time spent on one relatively minor detail :'-(

robzilla

12:06 pm on Jun 14, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Is the switch between list and grid just a simple CSS toggle, or am I misinterpreting that?

I'm a bit confused by the code. Why are you setting the otherlist variable, for example? You don't seem to be using it.

$('#fragLoad').load(url + ' #fragLoad');

And this... why are you tacking the space and #fragLoad anchor onto the URL?

It's difficult to get a firm grasp without seeing all the code.

csdude55

4:19 pm on Jun 14, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Is the switch between list and grid just a simple CSS toggle, or am I misinterpreting that?

I think you're misinterpreting it. The "list" view is drastically different from "grid" view, so when they click the button I use $.load to reload the #classifiedList ID entirely.

Maybe I should revisit it and see if I can change it all with CSS. I think it would be a huge pain, maybe not even possible, but after spending 5 days on it... what's another 2 or 3? LOL

I'm a bit confused by the code. Why are you setting the otherlist variable, for example? You don't seem to be using it.

My mistake, I was trying to only show the relevant parts and so I removed the part of the code that used that, and should have removed those variables, too.

That part wasn't anything major, it was just changing the classes on the buttons:

$('#' + viewstyle + 'Cont').addClass('list_on');
$('#' + otherlist + 'Cont').removeClass('list_on');


$('#fragLoad').load(url + ' #fragLoad');

And this... why are you tacking the space and #fragLoad anchor onto the URL?

That's how you load an Ajax fragment... check this:

[api.jquery.com...]

It's a pretty cool thing to use if you can get it to work right! LOL

It's difficult to get a firm grasp without seeing all the code.

In fact, other than the 2 lines above where I changed the classes on the buttons, the rest is copied verbatim :-) It would be easier if I could just post a link to the page where it's running so you could see how it's messing up, but I don't think we're allowed to do that.

robzilla

9:12 pm on Jun 14, 2018 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



We're not, no, but feel free to send it in a PM. Happy to take a look.

That's how you load an Ajax fragment... check this:

[api.jquery.com...]

It's a pretty cool thing to use if you can get it to work right!

Did not know that. Pretty neat!