I am trying to use an "Infinite Ajax Scrolling" Orchard module.
https://gallery.orchardproject.net/List/Modules/Orchard.Module.Orchard.jQuery.Ias
I installed the module through admin interface. I made necessary modifications described on the given link. Also, I had to do an extra modification that is described in the comments.
The infinite scrolling thing is just not functioning. I created about 30 blog posts in order to test it. When I scroll through blog posts through public website, first page og blog posts is loaded and when I scroll to the bottom, nothing happens. Pager is not visible (expected), but no new content is appended to the bottom of the list (not expected).
When I scroll through blog posts using Admin interface and I scroll down sufficiently, Chrome console reports couple of things:
Uncaught Error: Syntax error, unrecognized expression: <!DOCTYPE html>
<html lang="en-US" class="static orchard-blogs">
<head>
<meta charset="utf-8" />
<title>Proba - Manage Infinite Blog</title>
<link href="/OrchardLocal/Modul...<omitted>...l> jquery-1.9.1.js:4421
Sizzle.error jquery-1.9.1.js:4421
tokenize jquery-1.9.1.js:5076
select jquery-1.9.1.js:5460
Sizzle jquery-1.9.1.js:3998
jQuery.fn.extend.find jquery-1.9.1.js:5576
jQuery.fn.jQuery.init jquery-1.9.1.js:196
jQuery jquery-1.9.1.js:62
jQuery.fn.jQuery.init jquery-1.9.1.js:201
jQuery jquery-1.9.1.js:62
(anonymous function) jquery.ias.min.js:210
fire jquery-1.9.1.js:1037
self.fireWith jquery-1.9.1.js:1148
done jquery-1.9.1.js:8074
callback
A moment after:
GET http://localhost:30321/modules/orchard.jquery.ias/styles/images/loader.gif 404 (Not Found) jquery-1.9.1.js:6469
jQuery.extend.buildFragment jquery-1.9.1.js:6469
jQuery.extend.parseHTML jquery-1.9.1.js:531
jQuery.fn.jQuery.init jquery-1.9.1.js:149
jQuery jquery-1.9.1.js:62
get_loader jquery.ias.min.js:266
show_loader jquery.ias.min.js:279
paginate jquery.ias.min.js:167
scroll_handler jquery.ias.min.js:99
jQuery.event.dispatch jquery-1.9.1.js:3074
elemData.handle jquery-1.9.1.js:2750
In the admin interface I checked Blog properties and it seems to be configured fine. All default values are in place for [Container, Item, Pager, NextAnchor], and these values are also present in the html file I'm viewing when reported errors occur.
EDIT (after justrhysism's answer)
After implementing justrhysism's answer, I focused on why infinite scrolling works in the dashboard but not in front-end.
When I opened a list of blog posts in dashboard, I located .pager element.
<ul class="pager">
<li class="first"><span>1</span></li>
<li>2</li>
<li class="last">></li>
</ul>
I opened a list of blogs in front-end, and also located .pager element.
<ul class="pager" shape-id="92" style="display: none;">
<li class="first" shape-id="92"><span shape-id="93">1</span></li>
<li shape-id="92">2</li>
<li shape-id="92">></li>
<li class="last" shape-id="92"></li>
</ul>
Then I inspected javascript in charge for triggering async loading of content.
function paginate(curScrOffset, onCompleteHandler)
{
urlNextPage = $(opts.next).attr("href"); // evaluates to $(".zone-content .pager .last a").attr("href")
...............
}
And found out that the urlNextPage variable always gets set to undefined in front-end view.
Problem
I've come across this before. It's a document parsing error. There is a whitespace character (of some description) at the top of the document which Orchard returns instead of the <! which is expected. Somebody with more knowledge of AJAX and document parsing could better describe this.
Solution
To fix this, find the view Document.cshtml within Orchard's Core (located in src\Orchard.Web\Core\Shapes\Views) and copy it to your Theme's View directory.
In this file, look to Line 10 where <!DOCTYPE html> starts. Above this, remove the line break between the closing brace } and the DOCTYPE declaration.
Before:
}
<!DOCTYPE html>
After:
}<!DOCTYPE html>
This should fix your issue.
The Infinite Ajax Scrolling module for Orchard CMS is on Github
https://github.com/grapto/js.Ias
In response to my last edit where urlNextPage was being set to undefined.
I changed the NextAnchor selector in Blog properties:
From default value of ".zone-content .pager .last a" ----> To ".zone-content .pager a".
Also I went into Orchard.jQuery.Ias module -> Scripts/jquery.ias.min.js
Changed paginate function.
Old:
function paginate(curScrOffset, onCompleteHandler)
{
urlNextPage = $(opts.next).attr("href");
....
New:
function paginate(curScrOffset, onCompleteHandler)
{
if ($(opts.pagination).find(".last span").length)
return; // if span element exists in .last element, that means we are on the last page
urlNextPage = $(opts.next).last().attr("href");
....
It works fine now, both in dashboard and in front-end. This is not a very reliable solution, because I made an assumption that last anchor tag in .pager will always lead to the next page. That assumption is based merely on my observations of module's behavior.
Related
We are replacing the forms for our lists with forms built with SPFx. Building and deploying the form is no issue. The problem is redirecting the form controls to this form (when a user opens an item or clicks new, etc...). Is there a recommended method of accomplishing this? I have been successful using two methods but they both seem volatile and hacky.
The first being replacing the entire form code using SharePoint designer. For instance, the new form code would be
<%# Page language="C#" %>
<html lang="en">
<head>
<script type="text/javascript">
const list = window.location.href;
const site = list.substring(0,list.toLowerCase().indexOf('/lists/'));
window.location.replace(site + "/SitePages/MyListForm.aspx");
</script>
</head>
<body>
</body>
</html>
This works sometimes... Upon saving, the form code seems to regenerate the form code but the redirect still works. However, if I open and save the code again, everything breaks and the list action goes back to default (clicking new would now show the 'New Item' call out instead of directing to the form).
The other method is opening the new/edit/display form in the browser, with ?toolpaneview=2 which allows me to add a script web part to the page (although it doesnt like to save) and add the script redirect in.
<script type="text/javascript">
const list = window.location.href;
const site = list.substring(0,list.toLowerCase().indexOf('/lists/'));
window.location.replace(site + "/SitePages/MyListForm.aspx");
</script>
this seems to be less volatile than the first method, but it still seems hacky. If I delete the original form web part, the form breaks and the list actions again revert to default. Editing the script requires visiting the form with ?contents=1 to delete the script web part and then I have to re-add it again using the toolpaneview method. In order to even save the web part change I have to click "Edit Web Part", which in turn saves it. There is no simple "Save" action which again makes me feel like this method is not intended to be done.
Is there any recommended way to accomplish these redirects? I've found plenty or tutorials online about setting up the list form, but nothing about this essential step.
So every time I use html snippet or boiler plate with <ht + tab or enter
I get this extra opening tag? What gives?
<<!doctype html> <---- whats that additional tag at the beginning?
<html>
......
....
I got emmet installed by the way. Thanks
It's a snippet. You type html (or less), and press tab, it'll inserts all this content:
<!DOCTYPE html>
<html>
<head>
<title>$1</title>
</head>
<body>
$0
</body>
</html>
Note that if you repress tab again, it'll go to $1, and the last one is $0 (by default it's the end of the content).
So, don't type <ht, just ht, tab, and it'll insert everything for you. I really recommend you find yourself a course about Sublime Text, you're going to miss so much otherwise
That is the doctype decleration this is straight out of hte W3School docs:
The declaration must be the very first thing in your HTML
document, before the tag.
The declaration is not an HTML tag; it is an instruction to
the web browser about what version of HTML the page is written in.
In HTML 4.01, the declaration refers to a DTD, because HTML
4.01 was based on SGML. The DTD specifies the rules for the markup language, so that the browsers render the content correctly.
HTML5 is not based on SGML, and therefore does not require a reference
to a DTD.
Tip: Always add the declaration to your HTML documents, so
that the browser knows what type of document to expect.
You can read more about it here: http://www.w3schools.com/tags/tag_doctype.asp
I've got several anchor tags pointing to internal links mainly to scroll to some section titles or to get to the top from a bottom link of the site since some pages can get very long.
All tags like Whatever just scrolled the page to the <a name="whatever"></a> tag as intended until yesterday, but now when clicked they force a page refresh pointing to the root page with just hash, like this localhost/#whatever instead of this localhost/path/to/current/page/#whatever.
1) Is there even the possibility to alter something in the Apache server, browser settings (not touched tough), HTML/JavaScript/CSS code of a page or whatever to force page refreshes when clicking on internal links?
2) If I change the anchor to <a href="path/to/current/page/#whatever> it works, but it's just because a page refresh triggers and then the page is scrolled like normal when interpreting the hash fragment. Also, this way I loose any GET parameters (I can't predict them) which I really need since it's a database website
3) If I alter or remove the <base href="/" /> tag nothing happens, still the internal links worked before with that tag in place
4) I recently updated the .htaccess file and that could potentially be the cause but still routing has no problems and I can't see why any RewriteRule could possibly affect internal links. Also, trying to revert it to previous version didn't help
5) Same behavior applies to both Firefox and Chrome, latest versions
6) I tried to create a test page in the same environment (same .htaccess, same HTML base template) with just a very long <ul> list containing list elements with integers in sequence until 500, then a To 20 at the bottom of the page and it just worked all good... What can force a internal link to redirect?! Please help
I finally solved it! Check here link and here link. The problem was with the <base href="/" /> tag in the <head> section. I solved with a mixture of jQuery and pure JavaScript (jQuery is used only for select anchors and get attribute), here
$("a.local").on("click", function (e) {
e.preventDefault();
document.location.hash = "";
document.location.hash = $(this).attr("href");
});
Please note that I need to set the hash to an empty string before actually setting it to the href of the anchor since document.location.hash = $(this).attr("href"); alone would not trigger automatic scrolling on multiple clicks on the internal anchor (I tried it)
We have code to open dialogs for links on admin pages by calling the javascript function mgnlOpenDialog(), like this,
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
[#assign cms=JspTaglibs["cms-taglib"]]
<html>
<head>
<title>UCP Books</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="${this.request.contextPath}/.resources/admin-css/admin-all.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="${this.request.contextPath}/.magnolia/pages/javascript.js"><!-- --></script>
<script type="text/javascript">
function displayDialog()
{
if ( ! window.focus ) return true;
var path = "${this.path}";
var nodeCollection = null;
var node = "${this.nodeName}";
var paragraph = null;
var repository = "${this.repository}";
var dialogPage = ".magnolia/dialogs/author.html";
mgnlOpenDialog( path, nodeCollection, node, paragraph, repository, dialogPage );
return false;
}
</script>
</head>
<body id="mgnl" class="mgnlBgLight mgnlImportExport">
<h2>
${this.messages.get("module.books.pages.AuthorDetailPage.header")}
<span class="mgnlControlButton" onclick="displayDialog();">
${this.messages.get("module.books.pages.edit")}
</span>
</h2>
<div class="pageFrame">${this.content}</div>
</body>
</html>
Now we are migrating our site from 4.5.12 to 5.3.4, and I noticed that the dialog definitions got updated. Now when I click on the link, there is still the dialog popup, but the popup is blank with the old style "Save" and "Cancel" buttons displaying at the bottom. It seems we need to convert our admin pages to content apps. But to do it that way will require a lot of changes in our code. So I'd like to know if there is an alternative way to replace mgnlOpenDialog() function to invoke the dialogs when I click on the links on the admin pages.
Thanks very much!
Aiping
Yeah this doesn't work any longer. Assuming you needed to open the dialogs explicitly because you had content you were editing in other workspaces then website. Correct?
When migrating custom data to M5, if you had that content in data workspace, you can use migration task to move it from the shared workspace into separate workspace and to also migrate your dialog. Not sure at the moment if it generates also app for you, but if not you can use this script to create one.
Once you have dialog migrated (or created from scratch) and your app created (either via script above or manually) you can just simply open any content in that app for editing and copy url from there. That would be the url you need to call to open dialog for editing from anywhere. It will be something like http://<your host>:<your port>/<contextPath>/.magnolia/admincentral#app:<yourAppName>:detail;/path/to/edited/content:edit
of course, assuming your subapp is called "detail" and your edit action "edit" as suggested in the tutorial or generated by the script.
Good luck,
Jan
Thanks Jan!
This seems a right direction to go by calling the url,
http://<your host>:<your port>/<contextPath>/.magnolia/admincentral#app:<yourAppName>:detail;/path/to/edited/content:edit.
I've configured the detail subapp and added this line to my code,
title
and it works. I'll post more in details later.
Thanks,
Aiping
Jan, I tried your solution as I commented here and it works well, except for one issue. Here I'm pointing to several screenshots to better explain it.
https://plus.google.com/u/0/photos/103180294078685589341/albums/6081701864232931905
On the app_faqSearch_1.png, there is a search form only.
The app_faqSearch_2.png is the page with the search results.
When I click on the "faq0004" link on app_faqSearch_2.png, the app_faqSearch_3.png appears. The code behind the scenes is,
faq0004
The problem is when I close the dialog tab "/FAQ/TOPICS/COMMAS/...", on the app_faqSearch_4.png, the search results are not there anymore since the view got reloaded.
Is there a way to configure to prevent the view from being reloaded if it's already opened, like for this URL in my case, /magnoliaAuthor/.magnolia/admincentral#app:faqSearch:main;
Or is there a way to explicitly open a dialog, instead of an editor, by passing the node path and workspace when click on the link like "faq0004"? Similar way to open the "editMessage" dialog in "contacts" app.
Thanks very much,
Aiping
We have implemented a layout where the main content resides in dynamic sidebars. We defined following layoutTemplate:
<template name="layout">
{{> content}}
{{> leftbar}}
{{> rightbar}}
<nav class="navigation">
{{#if currentUser}}
{{> navigation_logged_in}}
{{else}}
{{> navigation_logged_out}}
{{/if}}
</nav>
</template>
We include e.g. the rightbar template in the layout template.
<template name="rightbar">
<aside class="rightbar">
<button id="closeRightBar" class="close-cross"></button>
{{yield 'rightbar'}}
</aside>
</template>
The rightbar template includes the rightbar yield where we yield the specific content into.
We have implemented following RouteController:
UserShowRouter = RouteController.extend({
before: function() {
var username = this.params.username;
if(App.subs.user) {
App.subs.user.stop();
}
App.subs.user = Meteor.subscribe('user', username);
},
waitOn: function () {
return Meteor.subscribe('user');
},
data: function() {
return Meteor.users.findOne({'profile.username': this.params.username});
},
action: function() {
this.render('profile', {to: 'rightbar'});
}
});
What we wanted to achieve is that for example the profile template is yielded into the rightbar yield and get's updated and re-rendered as the data changes.
The problem is now that the sidebars are dynamically animated, shown and hidden. Now every time the profile template gets re-rendered also the layout template gets re-rendered. Why is that? We thought one of the purposes of yield regions is that the whole site doesn`t need to be re-renderd. Now when the layout gets re-rendered the whole css of the animations are set back to the original values.
We now have tried several different approaches, but none of them seems to be a good and clean solution. Is there a way to keep the layout template from being re-rendered and just keep the yield region and template up-dated? Any suggestions or alternatives would be highly appreciated.
As I understand it, the behavior in which re-rendering of your templates "bubbles up" and causes re-rendering of their parent templates is not particular to iron-router or the way your code is implemented, but is inherent in Spark. Iron-router's {{yield}} pattern does not alter this behavior, as far as I can tell from its documentation.
The good news is that Spark is set to be replaced imminently with a newer, more fine-grained rendering engine, currently codenamed "Spacebars," which should alleviate the concern.
Here is a preview of the new rendering system:
https://github.com/meteor/meteor/wiki/New-Template-Engine-Preview
This talk from a week ago is also excellent at describing the benefits coming through the new rendering engine (while fairly long, an overview is given in the first 5 minutes):
https://www.youtube.com/watch?v=aPf0LMQHIqk
As for your options today, you can:
a) Use the {{#constant}} and {{#isolate}} parameters to try to limit re-rendering.
b) Work from a development branch as described in the link above:
You can play with the current work-in-progress version of the code using the template-engine-preview-4 release tag (run your app with meteor --release template-engine-preview-4), or by checking out the shark branch (it's an internal codename).
c) Best of all if the timeframe of your project allows is to allow the re-rendering to continue until Meteor 1.0 hits and "Spacebars" resides on the main branch - it sounds like this is 1-3 months away.
I think that the reason your layout template gets rerendered is because the data hook you implemented uses a reactive data source. If the current user object changes, the router probably decides to rerender the whole page because there is no simple way to decide which parts exactly depend on your reactive data.
If I'm right, a simple solution to your problem is to create a user helper that will fetch the necessary data only where they're actually needed, e.g.
Template.profile.user = function () {
return Meteor.users.findOne({/*...*/});
}
Then you can use it in your profile template along with the with helper (sic!), i.e.
{{#with user}}
...
{{/with}}
to prevent multiple calls to the Template.profile.user function.
Also, if I were you, I would use the data hook only for data which is required by templates in my layout.