How to call function based on scroll bar click? - php

I am having the Div with scroll bar.When User clicks the scroll bar I need to call the function based on the scroll bar click.How can I make a call?
I am using Jquery in the client and using the PHP in the server side.
I know how to make ajax calls and etc.Only think is I need to make this call when scroll bar is clicked in that div.
Is it possible to make the ID for the scroll bar in that div.

You can bind to the scroll event, it's not fired when the user clicks the scroll-bar but it is fired when the scroll-bar moves for any reason:
//wait for document.ready to fire, meaning the DOM is ready to be manipulated
$(function () {
//bind an event handler to the `scroll` event for your div element
$('#my-scroll-div').on('scroll.test-scroll', function () {
//you can do your AJAX call in here, I would set a flag to only allow it to run once, because the `scroll` event fires A LOT when scrolling occurs
});
});
Note that .on() is new in jQuery 1.7 and in this case is the same as using .bind().
To set a flag like I suggest above:
$(function () {
var AJAX_flag = true;
$('#my-scroll-div').on('scroll.test-scroll', function () {
if (AJAX_flag === true) {
AJAX_flag = false;
$(this).off('scroll.test-scroll');
$.ajax({...});
}
});
});
Update
The best solution to adding event handlers to dynamically created elements is to bind to them before adding them to the DOM:
function scroll_func () {
var AJAX_flag = true;
$(this).on('scroll.test-scroll', function () {
if (AJAX_flag === true) {
AJAX_flag = false;
$(this).off('scroll.test-scroll');//unbind the event handler since we're done with it
$.ajax({...});
}
});
}
$.ajax({
...
success : function (data) {
//note that this selector will have to change to find the proper elements for you, if you are unsure how to select, start by seeing what data is by doing a `console.log(data);`
$(data).find('#my-scroll-div').on('scroll', scroll_func).appendTo('#container-element');
}
});

Related

PHP calling a function before session destory or garabge collection

Im attempting to log the user activity in my database when they login and logout of the site. This works fine, but when they close the page via a tab or browser, there is no way to run the logout query, so according to the records the user never logs out of the site.
Method 1:
I have tried onbeforeunload, but this does not seem to trigger before the page closes.
Method 2:
I would try the method of using an ajax keepalive token sent to the php, but this would need to run every 1 min and could cause high traffic load.
Method 3:
I was hoping an alterantive would be to set the session.gc.maxlifetime to 1 min and add a call to the logout query via a destroy session callback.
Which would be the best method, or is there a better method of achieving this?
Is there a way to trigger a custom function(query) before php destroy session or php garbage collection has taken place?
UPDATE
I have taken the advise of everyone and decided to attempt 'method 1'. So far this is my attempt but its still not working perfectly:
var isClosePage = true;
//detect f5 and backspace page navigation
$(document).on('keypress', function(e)
{
if (e.keyCode == 116)
{
alert('f5');
isClosePage = false;
}
if (e.keyCode == 8)
{
alert('backspace');
isClosePage = false;
}
});
//detect back and forward buttons
$(window).bind('statechange',function()
{
alert('back');
isClosePage = false;
});
//detect page button press
$('html').on('mouseenter', function()
{
console.log('mouse has enetered!');
isClosePage = false;
});
//detect browser buttons press
$('html').on('mouseleave', function()
{
console.log('mouse has left!');
isClosePage = true;
});
//make ajax call (logout) to server if above events not triggered
$(window).on('beforeunload', function(e)
{
if(isClosePage)
{
$.ajax(
{
url:'php/function/active-user.php?logout=ajax',
dataType: 'jsonp',
crossDomain: true,
async: false
});
//return 'some default message';
}
else
{
isClosePage = true;
}
});
Can anyone suggest any improvments to how I can make this work well?
When you speak of Method 1, you're doing it client-side, right?
The interface is window.onbeforeunload, and this is a usage example:
window.onbeforeunload = function(e) {
// call server script to log the user activity to database ...
};
The event window.onbeforeunload IS triggered before page is unloaded (tab/window/browser closed).
I would like to extend MarcoS's answer a little bit. window.onbeforeunload should work but this isn't the preferred way to set a handler for events. Since this is a property other scripts attaching to this event will overwrite your listener and your function will never get called.
The preferred way of registering to this event is as follows:
window.addEventListener('beforeunload', function (evt) {
}, false);
You could also attach a event listener to unload
window.addEventListener('unload', function (evt) {
}, false);
Hope this helps

ie and jquery $.get not working

I am trying to update the content of a div with a $.get call but it is failing in ie(9).
the js is this
function UpdateElementOfParent(box_id, page_ref, template_ref)
{
$.get("get_content.php", { box_id: box_id, page_ref: page_ref, template_ref:template_ref } )
.done(function(data) {
$('#'+box_id).html(data);
});
}
and the get_content.php is this
<?php
include("connect.php");
$page_ref = $_GET['page_ref'];
$template_ref = $_GET['template_ref'];
$box_id = $_GET['box_id'];
$sql = mysql_query("SELECT * FROM site_content WHERE page_ref='$page_ref' AND template_ref='$template_ref' AND box_id='$box_id' AND box_type='text'");
while($row=mysql_fetch_array($sql))
{
echo stripslashes($row['content']);
}
?>
it works fine in firefox/chrome/safari and opera.
the php updates the db but the div ("#"+box_id) doesnt update in ie (only have ie9 at hand so dont know if its just 9 or other versions also)
any clues?
QUICK UPDATE
it seems that ie is holding some data from a previous $.get call in the cache. Basically I have a div on the screen and when the user clicks a button, a layer opens with a textarea that is editable with nicedit.
The textarea is populated with a $.get, then the user clicks save, the layer is hidden and the original div on the parent page is updated with the same $.get call.
In ie, if I change the content, the db is updated but the div is not and when I open the layer, it still shows the old data.
the first $.get call is this
$.get("get_content.php", { box_id: box_id, page_ref: page_ref, template_ref:template_ref } )
.done(function(data) {
document.getElementById("edit_content").value=data;
area1 = new nicEditor({fullPanel : true}).panelInstance("edit_content",{hasPanel : true});
});
the alerted data doesnt show the updated text in IE so its definately something to do with the $.get call
I figured out the problem. Nothing to do with the selector, but with the scope of the parameter variable box_id.
Change your function to:
function UpdateElementOfParent(box_id, page_ref, template_ref) {
myBox = box_id;
$.get("get_content.php", { box_id: box_id, page_ref: page_ref, template_ref:template_ref })
.done(function(data) {
$('#'+myBox).html(data);
});
}
Explanation:
The AJAX callback function does not have access to the local variable in UpdateElementOfParent
This isn't an answer, as the question is incomplete, but I need to post a code comment to assist OP.
As you mentioned that the PHP works just fine, the problem might be that IE doesn't like dynamic selectors in jQuery. Do try these few options:
1) Change $('#'+box_id).html(data); to:
var id = '#'+box_id;
$(id).html(data);
2) Try logging or alert-ing the element out, to see if IE actually got the element right:
var elem = $('#'+box_id);
alert(elem);
elem.html(data);
This would display as [HTMLDivElement] or something similar if the element is there.
3) If all else fails, see if this vanilla JS works in IE, to verify that it isn't a jQuery selector problem.
var elem = document.getElementById(box_id);
alert(elem);
elem.innerHTML = data;
ok problem solved and I knew it was something very obvious.
inside the original $.get function call I have to set the document.ready state
function get_edit_content(box_id,page_ref,template_ref)
{
$(document).ready(function() { <<<<<HERE
if(area1) {
area1.removeInstance('edit_content');
area1 = null;
document.getElementById("edit_content").value="";
}
$.get("get_content.php", { box_id: box_id, page_ref: page_ref, template_ref:template_ref } )
.done(function(data) {
document.getElementById("edit_content").value=data;
document.getElementById("page_ref").value=page_ref;
document.getElementById("template_ref").value=template_ref;
document.getElementById("box_id").value = box_id;
area1 = new nicEditor({fullPanel : true}).panelInstance("edit_content",{hasPanel : true});
});
});
}
thanks for all the input

How to structure javascript when including another php file

I am attempting to build a small web application but I'm not clear how to communicate between different parts of the page. I will use my specific functionality to demonstrate my question.
All of my pages use a generic toolbar. Since this toolbar is used on multiple pages, it is in its own PHP file, which I include using
<?php include("../toolbar.php"); ?>
The toolbar includes a log in button. When clicked, this opens a modal login dialog (in this case the Facebook login dialog). When a user logs in, his or her name is displayed in the toolbar, and the log in button is replaced by a 'logout' button. Since this behavior is the same no matter which page the user is viewing, I created a toolbar.js file to display the log in modal and update the username/button appropriately.
However, on most pages, logging in or out from the toolbar needs to also update the contents of the main page. I can not guarantee that every page that includes toolbar.php will have to do anything when the log in status changes, but most will.
Similarly, the reverse is possible - a certain page might have a 'log in' button outside the toolbar. When this is used, the toolbar needs to update.
What is the best way to handle this?
Current implementation - this might be awful…
In toolbar.js I am basically calling a function, 'userSignedIn', whenever the user logs in (and an equivalent for log out). toolbar.js, implements this itself (it needs to update its button and user name label).
Then, if the main page (lets call it mainPage.php) needs to anything additional, I am re-using this same function to 'tack on' the additional actions. On load of that page, I do the following:
var originalUserSignedIn = userSignedIn;
userSignedIn = function() {
originalUserSignedIn();
customUserSignedIn();
}
customUserSignedIn is a function within mainPage.js, where I perform the additional actions. I have not yet implemented a solution for the opposite (sign in from mainPage.php needs to update toolbar.php).
I guess coming from an objective-C background, I am attempting something analogous to calling 'super' in a method implementation.
One way to do it is to initialize an empty array to hold callback functions and the sign function to call them, before any of the other javascript:
var userSignedInCallbacks = [];
var userSignedIn = function() {
for (var i = 0; i < userSignedInCallbacks.length; i++) {
userSignedInCallbacks[i]();
}
}
Then, toolbar and main page js will both just add their appropriate callbacks to the array:
userSignedInCallbacks.push(function() {
// ...
});
Finally, the login actions in either the toolbar or main page will both just call userSignedIn().
One way you could do this is by using the publisher-subscriber pattern for handling communications between different modules in your page so that every modules is only coupled on an event interface.
I created a very simple example here. It doesn't handle the logout process but you can still see how things could be structured.
HTML
<div id="toolbar">
<button class="login">Login</button>
</div>
<div id="another-section">
<button class="login">Login</button>
</div>
<div id="login-dialog">
<button class="login">Do login!</button>
</div>
JS
//in EventBus.js
var EventBus = {
subscribers: {},
publish: function (eventName) {
var args = Array.prototype.slice.call(arguments, 1),
subscribers = this.subscribers[eventName] || [],
i = 0,
len = subscribers.length,
s;
for (; i < len; i++) {
s = subscribers[i];
s.fn.apply(s.scope, args);
}
},
subscribe: function (eventName, fn, scope) {
var subs = this.subscribers[eventName] = this.subscribers[eventName] || [];
subs.push({ fn: fn, scope: scope });
}
};
//in toolbar.js
function Toolbar(el, eventBus) {
var $el = this.$el = $(el),
$loginButton = $('button.login', $el);
$loginButton.click(function () {
eventBus.publish('userWantsToLogin');
});
eventBus.subscribe('userLoggedIn', function () {
$loginButton.html('Logout');
//change button handlers to handle logout...
});
}
//in another-section.js
function AnotherSection(el, eventBus) {
var $el = this.$el = $(el),
$loginButton = $('button.login', $el);
$loginButton.click(function () {
eventBus.publish('userWantsToLogin');
});
eventBus.subscribe('userLoggedIn', function () {
$loginButton.html('Logout');
//change button handlers to handle logout...
});
}
//in main.js
$(function () {
var $loginDialog = $('#login-dialog');
$loginDialog.dialog({ autoOpen: false});
$('button.login', $loginDialog).click(function () {
EventBus.publish('userLoggedIn');
});
EventBus.subscribe('userWantsToLogin', function () {
$loginDialog.dialog('open');
});
new Toolbar('#toolbar', EventBus);
new AnotherSection('#another-section', EventBus);
});

Re-Initialize jQuery after XMLHttpRequest

I'm using Twitter Bootstrap's Popover feature on a sidebar. The sidebar is fetched and reloads the content every 30 seconds. I'm suing XMLHttpRequest to reload the content of the sidebar by fetching a file called stats.php.
The following code is the "refresh" code which resides in the header of the page.
function onIndexLoad()
{
setInterval(onTimerCallback, 30000);
}
function onTimerCallback()
{
var request = new XMLHttpRequest();
request.onreadystatechange = function()
{
if (request.readyState == 4 && request.status == 200)
{
document.getElementById("stats").style.opacity = 0;
setTimeout(function() {
document.getElementById("stats").innerHTML = request.responseText;
document.getElementById("stats").style.opacity = 100;
}, 1000);
}
}
request.open("GET", "stats.php", true);
request.send();
}
The above code works flawlessly, however, after it reloads the #stats div, the popover no long does what it's supposed to - popup.
The popover code is in the stats.php in a foreach() loop because I have multiple popover scripts I need because there are multiple popovers on the sidebar.
Here's my popover code:
$(document).ready(function() {
$('a[rel=popover_$id]').popover({
placement:'right',
title:'$title',
content: $('#popover_content_$id').html()
});
});
The $id and $title are dynamic as they are pulled from the foreach() loop.
How can I fix it so after the div reloads, the popover function will reinitialize?
$("a[rel=popover_controller_$cid]").on({
mouseenter: function () {
$('a[rel=popover_$id]').popover({
placement:'right',
title:'$title',
content: $('#popover_content_$id').html()
});
}
});
I have also tried:
$("a[rel=popover_controller_$cid]").on("mouseover", function () {
$('a[rel=popover_$id]').popover({
placement:'right',
title:'$title',
content: $('#popover_content_$id').html()
});
});
.live is depreciated. use .on delegation
try something like this:
$('#stats').on("mouseenter", "a[rel=popover_controller_$cid]",function () {
$('a[rel=popover_$id]').popover({
placement:'right',
title:'$title',
content: $('#popover_content_$id').html()
});
});
This delegates the mouseenter event from #stats to a[rel=popover_controller_$cid] and because the event is delegated it will still fire when #stats contents are replaced.
be careful - you will keep initializing popover on each mouseover. that might be bad.
while you are at it - you should use jquery's ajax instead of native xhr. its easier and more cross browser.
$.get('stats.php', function(d){
$('#stats').html(d);
};
--
setInterval(function(){
$.get('stats.php', function(data) {
$('#stats').html(data);
});
}, 30000);

Call prototype(javascript) function on link click?

I am working with AJAX with prototype and PHP. It is working for me but I need some small changes. Following is my running code for AJAX request:
JS/Prototype:
function ajaxRequest(url) {
new Ajax.Request( url, {
method: 'get',
onSuccess: function( transport ) {
// get json response
var json = transport.responseText.evalJSON( true );
alert(json);
},
onFailure: function() {
alert('Error with AJAX request.');
}
});
return false;
}
HTML:
<a href='javascript:ajaxRequest("/testajax/ajaxresponse");'>Testing AJAX</a>
Question:
Now I want to change my link like this:
<a href='/testajax/ajaxresponse' class='AjaxLink'>Testing AJAX</a>
So prototype function should capture click event of class='AjaxLink' links and then get href part of clicked link and proceed. How can I change my above prototype function for such kind of links.
Thanks
If you have Prototype 1.7 then this way is available:
document.on('click', 'a.AjaxLink', ajaxRequest.curry('/testajax/ajaxresponse'));
Otherwise you'll have to rely on good old Event.observe:
$$('a.AjaxLink').invoke('observe', 'click',
ajaxRequest.curry('/testajax/ajaxresponse'));
Just re-read the question and I see you want to use the href attribute. Jan Pfiefer was very close.
document.on('click', 'a.AjaxLink', function(event, element) {
return ajaxRequest(element.href);
});
This wont work. Why do you want such a link? If a link is specified in this way any click on it will follow its href and change location of actual document. Only way to prevent such a behavior then is by adding onclick again or in $(document).ready bind onclick handler, and manualy cancel the event.
UPDATE
However to bind onclick event on all links with AjaxLink class,execute request and cancel the event:
$(document).ready(function(){
$('.AjaxLink').click(
function(e){
ajaxRequest(this.href);
event.preventDefault ? event.preventDefault() : event.returnValue = false;
}
);
});
This will work:
$$('a.AjaxLink').each(function(element) {
element.observe('click', function(e) {
var element = e.element()
Event.stop(e)
alert(element.href)
});
})

Categories