Forum Moderators: open

Message Too Old, No Replies

Ajax fragment with infinite scroll applying CSS twice

         

csdude55

2:41 am on Jun 11, 2018 (gmt 0)

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



Still working on a classifieds site, using jQuery.

I have the infinite scroll working correctly, but now I'm trying to set up a toggle between "list view" and "grid view". But instead of refreshing the page, I'm trying to use an Ajax fragment to just refresh the relevant section.

Here's where I started:

// external CSS
#classifiedList { margin-left: 180px }

// PHP
$frag = 'blah blah blah'; // the link of the page we're on

// JavaScript
// usage: onClick="loadFragment('list')"
// or onClick="loadFragment('grid')"
function loadFragment(viewstyle) {
var url = '$frag' + '&viewstyle=' + viewstyle;

$('#classifiedList').load(url + ' #classifiedList');
}


This works, except that where I have margin-left: 180px already set, this doubled it so I have a 360px margin. As I scrolled down and infinite scroll brought in the second iteration of the page, though, the second page was fine... it's just the first page that was doubled.

So I modified the .load to this:

$('#classifiedList').load(url + ' #classifiedList', function() {
$('#classifiedList').css('margin-left', 0);
});


This worked on the first iteration great, but then when infinite scroll loads the second iteration of the page it keeps the margin at 0 instead of using the original 180px!

Then I tried manually setting the style inline from within #classifiedList, which I thought would overwrite the jQuery setting, but that had no impact.

So I'm kind of at a loss... how do I keep it from doubling up on the margin like that?

not2easy

3:29 am on Jun 11, 2018 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



I do not have an answer to your question as asked, and don't know enough about how this script "fits" in the overall page to know whether it would be silly to ask: can the list/views be contained in a sized div that is not part of the content being loaded once, twice or more? I mean if "{ margin-left: 180px }" is not assigned to "#classifiedList" but to a container for "#classifiedList" would that help?

As in
<div class="sized">
#classifiedList
</div>


NickMNS

4:38 am on Jun 11, 2018 (gmt 0)

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



STOP! Whatever you are doing stop...
I'm not sure, because I am basing myself on the tiny snippet of code. But I prefer to warn you just in case.
$('#classifiedList').load(url + ' #classifiedList', function() {

Do not proceed with using the "#" hash method. This is going make your pages uncrawlable by Google. Each additional section of your page should have is its own distinct URL and if possible when a user types the URL the browser should take the user to that page. You can use pushState() to update the URL as new content is loaded.

The URL from your code seems to be www.example.com#classifiedList which in the eyes of Google is the same as www.example.com. You must make the URL something like www.example.com/classifiedList.html.

Before proceeding I urge you to watch this video from Google I/O 2018.
[youtube.com...]

There is one other warning to share (this one I have mentioned before) avoid using document.write() and any commands that use it under the hood such as $().html();. This may in fact be the cause of your apparent bug.
I will not try to explain why, instead see this link
[stackoverflow.com...]

csdude55

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

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



I do not have an answer to your question as asked, and don't know enough about how this script "fits" in the overall page to know whether it would be silly to ask: can the list/views be contained in a sized div that is not part of the content being loaded once, twice or more? I mean if "{ margin-left: 180px }" is not assigned to "#classifiedList" but to a container for "#classifiedList" would that help?

That's a good thought! I tried targeting the DIV that's outside of #classifiedList first, but the problem there is that it contains an AJAX script, and AFAIK you can't load JavaScript within a fragment; it's just not allowed. Which blows, because that would have been the MUCH preferred solution!

There's another ID inside of #classifiedList that I'd tried targeting before, but it broke the infinite scroll (it's part of the section it reads to load). Using your logic, though, I tried putting yet another child ID inside of that one, and yay, it seems to be working! I have a few other bugs to tweak out from it, but I think I'm on the right path, anyway :-)

I've been working on this stupid thing for 3 days now, so thanks for the logic :-D

Do not proceed with using the "#" hash method. This is going make your pages uncrawlable by Google. Each additional section of your page should have is its own distinct URL and if possible when a user types the URL the browser should take the user to that page. You can use pushState() to update the URL as new content is loaded.

Well, I THINK that I'm doing this right, but let me explain the process and see if you agree?

The classifieds page currently uses Page 1 as default, then if you go to classifieds/?s=20 it goes to Page 2 (starting at the 20th record). So s=40 is Page 3, s=60 is Page 4, and so on.

The infinite scroll uses that same logic by looking at a fragment of Page 2 and appending to the ID on Page 1, then the URL still updates to s=20.

So that should still be good with Google, right?

After that, I wouldn't want Google to recognize the same page as 2 pages if the only difference is whether the layout is "list" or "grid", would I? I just want it to see the default. In this case, the # is only a reference to an ID, it's not an anchor. The URL isn't www.example.com#classifiedList, it's www.example.com #classifiedList, where #classifiedList is the ID being fetched.

There is one other warning to share (this one I have mentioned before) avoid using document.write() and any commands that use it under the hood such as $().html();. This may in fact be the cause of your apparent bug.

TBH I've never understood the argument against document.write, and the Stackoverflow conversation didn't really make a lot of sense to me as to what the inherent problem is. But which part of my script is using it? Is it part of the root to $.load?

NickMNS

12:43 pm on Jun 11, 2018 (gmt 0)

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



The classifieds page currently uses Page 1 as default, then if you go to classifieds/?s=20 it goes to Page 2 (starting at the 20th record). So s=40 is Page 3, s=60 is Page 4, and so on.

That looks like it would work.

But which part of my script is using it? Is it part of the root to $.load?

I'm not sure how your page is working exactly. $.load() simply executes a script after the page loads. So it would really depend on the script that is being executed if any. It is not clear to me from what you shared, is it a php script?

Also in researching my answer I noticed that $.load() is deprecated as jQuery1.8.
[api.jquery.com...]

csdude55

6:14 pm on Jun 11, 2018 (gmt 0)

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



I'm not sure how your page is working exactly. $.load() simply executes a script after the page loads. So it would really depend on the script that is being executed if any. It is not clear to me from what you shared, is it a php script?

Also in researching my answer I noticed that $.load() is deprecated as jQuery1.8.

It is a PHP script, yes. But the load event you're looking at isn't the same one that I'm using; they deprecated that one and replaced it with an Ajax shortcut with the same name but different arguments:

[api.jquery.com...]

I haven't looked at the jQuery source so I don't know if it uses document.write to accomplish it.

NickMNS

4:08 am on Jun 12, 2018 (gmt 0)

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



from the link you posted:
jQuery uses the browser's .innerHTML property to parse the retrieved document and insert it into the current document.

.innerHTML use document.write. But I don't think it is causing the problem.
I recommend that you read the section "Script Execution" and the specifics for your use case
$( "#b" ).load( "article.html #target" );
.

I think I know what is causing your problem. Your code snippet shows:
$('#classifiedList').load(url + ' #classifiedList', function() {
$('#classifiedList').css('margin-left', 0);
});


What you are doing is selecting #classifiedList and then inserting a new element into it with an id of #classifiedList. If you look at the example the selected #id and the target #id are different. Try making that change and that should fix it. My guess is that the second instance of #classifiedList is being ignored since id's need to be unique.