Page load on scrolling - ajax

I am developing a website and I want to load the data dynamically on scrolling the page,When the scroll bar reaches the bottom of the page I want to load more data from the database using AJAX.
In my web page there is a iframe in which i want to append the new data.Like flipkart.com website. Where on scrolling the page new products are loaded.
Could anyone help me in this regard?
Thanks in advance.
I have tried many times but no luck what i'm getting is only once the GetActivity() is being called,that too when i scroll down its not calling GetActivity(),but when i scroll up from that point it calls javascript function GetActivity()And on repeating this it is not working
here is the code which i used as given by Greg :please look into this and help.
<html>
<head>
<script type="text/javascript" src="jQuery-1.4.1-min.js"></script>
<script type="text/javascript">
$(window).scroll(function() {
var bottom = getBottom(window),
$reset = $("#activity_reset");
if (bottom == $(this).scrollTop() && $reset.val() == 0) {
$reset.val(1);
$("#activity_loading").show();
if ($("#activity_full").val() == 0) {
setTimeout("GetActivity();", 100);
}
}
});
function getBottom(e) {
height = $(document).height();
windowheight = $(e).height();
return height - windowheight;
}
function GetActivity()
{
alert("got it!");
$('div.tt').html('1');
$('div.ttt').html('1');
}
function setting()
{
$('div.tt').html('0');
$('div.ttt').html('0');
}
</script>
</head>
<body onload="return setting()" >
<pre>
<!--here i have used some junk texts so that a scroll bar appears in the browser-->
</pre>
<div style="display:none" id="activity_full" class="ttt"></div>
<div style="display:none" id="activity_reset" class="tt"></div>
</body>
</html>

This will monitor the page and load the function GetActivity() when you scroll down to the bottom of the page; you can put your ajax call in there and edit this accordingly to display the data you wish to have appear on the page.
$(window).scroll(function() {
var bottom = getBottom(window),
$reset = $("#activity_reset");
if (bottom == $(this).scrollTop() && $reset.val() == 0) {
$reset.val(1);
$("#activity_loading").show();
if ($("#activity_full").val() == 0) {
setTimeout("GetActivity();", 1000);
}
}
});
function getBottom(e) {
height = $(document).height();
windowheight = $(e).height();
return height - windowheight;
}
function GetActivity() {
/* ajax call in here */
}
When the window is scrolled the .scroll(function()) is triggered; the getBottom(window) function then calculates the document height and the screen height and subtracts them to see if the user's window has reached the bottom of the screen. $("#activity_reset") is then stored to an identifier for later use.
Once the action is fired your reset value is set to one so that the ajax isn't fired more than once at a time. The loading bar is displayed and a timeout is then set for the GetActivity() function.
$("#activity_reset") -> Should be a hidden div on the page that holds a value of either 1 or 0; it should be initialized as 0 and when the users browser hits the bottom of the page your ajax call is fired and once it is done being loaded you should then set the value back to 0 to allow loading again.
$("#activity_show") -> Should be a hidden div on the page that contains a loading image, or simply text saying that something is loading (not necessary but certainly helps for user experience).
$("#activity_full") -> Is another hidden div that is used to identify when your div is full and should not load anymore content. It should be initialized to 0 and when you have loaded as many items as can fit on the page you can set it to 1 (likely in your GetActivity() function) to prevent any further loading.
Further Explaining:
Inside of your GetActivity() function change the following:
$('div.tt').html('1');
//returns <div class="tt">1</div>
to
$('div.tt').val(1);
//returns <div class="tt" value="1"></div>
Your code is setting the html of the div to be 1, when what you actually want is for the value attribute to be equal to 1 since that is what the script is checking for in the comparison. I also noticed that you are also setting $('div.ttt') to be 1 as well, but this will stop the script from loading any further. This one should only be set to one once a condition has been met and you would no longer like any items to load.
$num = 6; //number of items per page
if($num == 6)
$('div.ttt').val(1);
Hope that clears things up; let me know.

Related

Load a Page Content without page refresh in Codeigniter/Bootstrap

I have created a Admin Panel in the header part with bootstrap , when i click on any nav bar option (ul->li->a) the whole page jerk and reload i want to load it smoothly with the hllp of ajax i.e, without page refresh.
How can i acheive that i have tried various material supplied in the net but it wont help.
I have limited knowledge in ajax.
Please help
Usually I think you've used jQuery. It's would be simplest. https://jquery.com
You'll need to have a back-end that should returns only part of your page (that needs to be loaded). Or use (not recommended) $.load
http://api.jquery.com/load/
If you have the back-end that returns part of your page:
var $container = $('#container'); // It's a block that will be used for content displaying
// Renderring content
function renderPage(response) {
// Wrapped content hidden by default
var $content = $('<div style="display: none">' + response + '</div>');
// Then clear current content
$container.find('*').remove();
// Then append our response and fade it to display
$content.appendTo($container).stop(true, true).fadeIn(300);
}
// Loading page
function loadPage(url, params) {
$.get(url, (params||{}), renderPage);
}
// Adding handler
function go(e) {
loadPage($(e).attr('href'));
return false;
}
And then in your items:
<ul>
<li>Page</li>
</ul>

CKEDITOR - how to add permanent onclick event?

I am looking for a way to make the CKEDITOR wysiwyg content interactive. This means for example adding some onclick events to the specific elements. I can do something like this:
CKEDITOR.instances['editor1'].document.getById('someid').setAttribute('onclick','alert("blabla")');
After processing this action it works nice. But consequently if I change the mode to source-mode and then return to wysiwyg-mode, the javascript won't run. The onclick action is still visible in the source-mode, but is not rendered inside the textarea element.
However, it is interesting, that this works fine everytime:
CKEDITOR.instances['editor1'].document.getById('id1').setAttribute('style','cursor: pointer;');
And it is also not rendered inside the textarea element! How is it possible? What is the best way to work with onclick and onmouse events of CKEDITOR content elements?
I tried manually write this by the source-mode:
<html>
<head>
<title></title>
</head>
<body>
<p>
This is some <strong id="id1" onclick="alert('blabla');" style="cursor: pointer;">sample text</strong>. You are using CKEditor.</p>
</body>
</html>
And the Javascript (onclick action) does not work. Any ideas?
Thanks a lot!
My final solution:
editor.on('contentDom', function() {
var elements = editor.document.getElementsByTag('span');
for (var i = 0, c = elements.count(); i < c; i++) {
var e = new CKEDITOR.dom.element(elements.$.item(i));
if (hasSemanticAttribute(e)) {
// leve tlacitko mysi - obsluha
e.on('click', function() {
if (this.getAttribute('class') === marked) {
if (editor.document.$.getElementsByClassName(marked_unique).length > 0) {
this.removeAttribute('class');
} else {
this.setAttribute('class', marked_unique);
}
} else if (this.getAttribute('class') === marked_unique) {
this.removeAttribute('class');
} else {
this.setAttribute('class', marked);
}
});
}
}
});
Filtering (only CKEditor >=4.1)
This attribute is removed because CKEditor does not allow it. This filtering system is called Advanced Content Filter and you can read about it here:
http://ckeditor.com/blog/Upgrading-to-CKEditor-4.1
http://ckeditor.com/blog/CKEditor-4.1-Released
Advanced Content Filter guide
In short - you need to configure editor to allow onclick attributes on some elements. For example:
CKEDITOR.replace( 'editor1', {
extraAllowedContent: 'strong[onclick]'
} );
Read more here: config.extraAllowedContent.
on* attributes inside CKEditor
CKEditor encodes on* attributes when loading content so they are not breaking editing features. For example, onmouseout becomes data-cke-pa-onmouseout inside editor and then, when getting data from editor, this attributes is decoded.
There's no configuration option for this, because it wouldn't make sense.
Note: As you're setting attribute for element inside editor's editable element, you should set it to the protected format:
element.setAttribute( 'data-cke-pa-onclick', 'alert("blabla")' );
Clickable elements in CKEditor
If you want to observe click events in editor, then this is the correct solution:
editor.on( 'contentDom', function() {
var element = editor.document.getById( 'foo' );
editor.editable().attachListener( element, 'click', function( evt ) {
// ...
// Get the event target (needed for events delegation).
evt.data.getTarget();
} );
} );
Check the documentation for editor#contentDom event which is very important in such cases.

How to reduce Tumblr photoset posts size and keep the original ph-set layout?

I want to reduce them to a maximum 200px width and keep the same layout with the 10px spacing the photos have. Also I don't want to style the posts to be that wide and use overflow:hidden that will only cut off the photosets.
jQuery Solution
For this solution you will need the latest version of jQuery and the jQuery plugin imagesLoaded included in the head of the theme before the following:
<script type="text/javascript">
$(document).ready(function() {
$('iframe.photoset').each(function() {
var i = this;
$(i).attr("onload", "ps_resize(this)");
var s = $(i).attr("src");
s = s.replace(/\/500\//, "/200/");
$(i).attr("src", s);
});
});
function ps_resize(i) {
$(i).contents().find("body").imagesLoaded(function() {
$(i).attr("width", 200);
$(i).attr("height", $(this).height());
});
return false;
}
</script>
What Solution Does
When the DOM is ready, find all the photoset iFrames
For each iFrame...
set the "onload" attribute to your frame resizing function
get the frame's source url, change the size (e.g. 500) to 200
set the frame's source url (this will cause it to reload with a smaller photoset)
In the resizing function...
wait for the images to load
set the frame width to 200
set the frame height to the new height of the photoset
Additional Code for Infinite Scroll
If you are using the Infinite Scroll jQuery Plugin, you will need to additionally include this in your success callback function:
...
$(newElements).find('iframe.photoset').each(function() {
var i = this;
$(i).attr("onload", "ps_resize(this)");
var s = $(i).attr("src");
s = s.replace(/\/500\//, "/200/");
$(i).attr("src", s);
});
...
Obviously, if you're using Infinite Scroll, I would suggest defining a function that is called on each iFrame on both the initial load and the scroll so you don't have repeated code to maintain.

jQuery .on() event doesn't work for dynamically added element

I'm making a project where a whole div with buttons is being inserted dynamically when user click a button, and inside that div there's a button, which when the user click on it, it does something else, like alerting something for example.
The problem is when i press on that button in the dynamically added div, nothing happens. The event doesn't fire at all.
I tried to add that div inside the HTML and try again, the event worked. So i guess it's because the div is dynamically added.
The added div has a class mainTaskWrapper, and the button has a class checkButton.
The event is attached using .on() at the end of script.js file below.
Here's my code :
helper_main_task.js : (that's the object that adds the div, you don't have to read it, as i think it's all about that div being dynamically added, but i'll put it in case you needed to)
var MainUtil = {
tasksArr : [],
catArr : ["all"],
add : function(){
var MTLabel = $("#mainTaskInput").val(), //task label
MTCategory = $("#mainCatInput").val(), //task category
MTPriority = $("#prioritySlider").slider("value"), //task priority
MTContents = $('<div class="wholeTask">\
<div class="mainTaskWrapper clearfix">\
<div class="mainMarker"></div>\
<label class="mainTaskLabel"></label>\
<div class="holder"></div>\
<div class="subTrigger"></div>\
<div class="checkButton"></div>\
<div class="optTrigger"></div>\
<div class="addSubButton"></div>\
<div class="mainOptions">\
<ul>\
<li id="mainInfo">Details</li>\
<li id="mainEdit">Edit</li>\
<li id="mainDelete">Delete</li>\
</ul>\
</div>\
</div>\
</div>');
this.tasksArr.push(MTLabel);
//setting label
MTContents.find(".mainTaskLabel").text(MTLabel);
//setting category
if(MTCategory == ""){
MTCategory = "uncategorized";
}
MTContents.attr('data-cat', MTCategory);
if(this.catArr.indexOf(MTCategory) == -1){
this.catArr.push(MTCategory);
$("#categories ul").append("<li>" + MTCategory +"</li>");
}
$("#mainCatInput").autocomplete("option", "source",this.catArr);
//setting priority marker color
if(MTPriority == 2){
MTContents.find(".mainMarker").css("background-color", "red");
} else if(MTPriority == 1){
MTContents.find(".mainMarker").css("background-color", "black");
} else if(MTPriority == 0){
MTContents.find(".mainMarker").css("background-color", "blue");
}
MTContents.hide();
$("#tasksWrapper").prepend(MTContents);
MTContents.slideDown(100);
$("#tasksWrapper").sortable({
axis: "y",
scroll: "true",
scrollSpeed : 10,
scrollSensitivity: 10,
handle: $(".holder")
});
}
};
script.js : (the file where the .on() function resides at the bottom)
$(function(){
$("#addMain, #mainCatInput").on('click keypress', function(evt){
if(evt.type == "click" || evt.type =="keypress"){
if((evt.type =="click" && evt.target.id == "addMain") ||
(evt.which == 13 && evt.target.id=="mainCatInput")){
MainUtil.add();
}
}
});
//Here's the event i'm talking about :
$("div.mainTaskWrapper").on('click', '.checkButton' , function(){
alert("test text");
});
});
It does not look like div.mainTaskWrapper exist.
From the documentation (yes, it is actually bold):
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on(). To ensure the elements are present and can be selected, perform event binding inside a document ready handler for elements that are in the HTML markup on the page.
[...]
By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers.
You might want to bind it to #tasksWrapper instead:
$("#tasksWrapper").on('click', '.checkButton' , function(){
alert("test text");
});
You need to specify a selector with on (as a parameter) to make it behave like the old delegate method. If you don't do that, the event will only be linked to the elements that currenly match div.mainTaskWrapper (which do not exists yet). You need to either re-assign the event after you added the new elements, or add the event to an element that already exists, like #tasksWrapper or the document itself.
See 'Direct and delegate events' on this page.
I know this is an old post but might be useful for anyone else who comes across...
You could try:
jQuery('body')on.('DOMNodeInserted', '#yourdynamicallyaddeddiv', function () {
//Your button click event
});
Here's a quick example - https://jsfiddle.net/8b0e2auu/

prototype js: rotating div display using $$ for dynamic divs

I'm wondering why the following code doesn't work, where "banner" is the css class of each of four different divs. The resulting page displays all images for one second, and then they all vanish.
<script type="text/javascript">
var bannerArray = new Array();
bannerArray = $$(".banner");
bannerArray.each(function (b) {
b.hide();
});
bannerArray.each(function (b) {
b.show();
Element.hide.delay(1, b.id);
});
</script>
delay doesn't delay all code execution. It only delays the invocation of a specific function; the rest of your code gets executed right away, while the delay is counting down in the background. So you're setting a "hide timer" for each element at the same time. Since they all have the same 1-second delay, they all fire 1 second after being set.
Try this instead
(function() { // wrap everything in a function to avoid polluting the global namespace
var banners = $$('.banner'); // no need to create an empty array first
banners.invoke('hide'); // no need to use each
function showNextBanner() {
banners.last().hide(); // hide previous banner
banners.first().show(); // show next banner
banners.push(banners.shift()); // first element moves to become last element
showNextBanner.delay(1); // set a timeout to show the next banner
}
showNextBanner(); // start the banner rotation/looping
}());
Here's a demo

Resources