I have a problem with pubnub.
I have friends list and I need to change pubnub channel on clicking them, by switching to another friend, to chat with him.
I have global channel variable, and I am changing it on friend click. The problem is, when I switch to another friend and write a message, the message appears in panel is duplicated.
Here is the code I am using.
base = "/";
pubnub = "";
channel ="";
messageListContent = "ul.chat-messages-block";
function handleMessage(message,$index) {
if ( $index != 'me' ) {
var $index = 'left';
} else {
var $index = 'right';
}
var $imageUrl = "";
if ( message.picture != '' && message.picture != null ) {
$imageUrl = message.picture;
if ( (/^http:\/\//.test( $imageUrl ) ) ) {
$imageUrl = $imageUrl;
} else {
$imageUrl = "uploads/user/"+ $imageUrl;
}
} else {
$imageUrl = 'resources/images/user-male.png';
}
var messageEl = jQuery('<li class="'+$index+' clearfix">'+
'<div class="user-img pull-'+$index+'"> <img src="' + $imageUrl +'" alt="'+message.username+'"> </div>'+
'<div class="chat-body clearfix">'+
'<div class="">'+
'<span class="name">'+message.username+'</span><span class="name"></span><span class="badge"><i class="fa fa-clock-o"></i>'+message.chat_date+'</span></div>'+
'<p>'+ message.message + '</p>'+
' </div>'+
'</li>');
jQuery(messageListContent).append(messageEl);
};
jQuery.getJSON( "/chat/read", function( data ) {
var items = [];
if ( data != null && data != "" ){
pubnub = PUBNUB.init({
publish_key: data.publish_key,
subscribe_key: data.subscribe_key,
});
if ( data.messages.length > 0 ) {
var $my_id = data.current_user;
for( var i = 0; i < data.messages.length; i++ ) {
if ( data.messages[i].user_id == $my_id ) {
$index = "me";
} else {
var $index = "";
}
handleMessage(data.messages[i],$index);
}
}
}
});
jQuery(document).ready(function () {
jQuery('#sendMessageButton').click(function (event) {
var message = jQuery('#messageContent').val();
var friend_id = jQuery('li.activeChannel').attr('data-id');
if ( message != '' ) {
jQuery.ajax({
url: base+"chat/sendChat",
type:'POST',
data:{
friend_id: friend_id,
text:message
},
success:function(data){
var data = JSON.parse(data);
//sounds.play( 'chat' );
pubnub.publish({
channel: channel,
message: {
username: data.messages.username,
message: data.messages.message,
user_id: data.messages.friend_id,
current_user: data.messages.user_id,
picture: data.messages.picture,
type:'message',
chat_date: data.messages.chat_date
}
});
},
error: function(err){
jQuery('.errorText').fadeIn();
}
});
jQuery('#messageContent').val("");
}
});
// Also send a message when the user hits the enter button in the text area.
jQuery('#messageContent').bind('keydown', function (event) {
if((event.keyCode || event.charCode) !== 13) return true;
jQuery('#sendMessageButton').click();
return false;
});
jQuery('ul.chat-users li').click(function(){
var friend_id = jQuery(this).attr('data-id');
jQuery('ul.chat-users li').removeClass('activeChannel');
jQuery(this).addClass('activeChannel');
jQuery.ajax({
url: base+"chat/getUsersChat",
type:'POST',
data:{
friend_id: friend_id
},
success:function(data){
var data = JSON.parse(data);
jQuery('.chat-messages ul').html("");
//id = pubnub.uuid();
//channel = 'oo-chat-' + id+friend_id;
channel = 'oo-chat-' + data.channel;
if ( data.messages.length > 0 ) {
var $my_id = data.current_user;
for( var i = 0; i < data.messages.length; i++ ) {
if ( data.messages[i].user_id == $my_id ) {
$index = "me";
} else {
var $index = "";
}
//messageListContent = "ul.activeChannel"+channel;
//console.log(channel);
handleMessage(data.messages[i],$index);
}
}
pubnub.subscribe({
channel: channel,
message: function(message) {
console.log("Pubnub callback", message);
handleMessage(message,"me");
},
connect: function(message) {
console.log("Pubnub is connected", message);
},
//callback:
});
},
error: function(err){
jQuery('.errorText').fadeIn();
}
});
});
});
And here is how it is looking
Any Idea?
I had even tried to unsubscribe the previous channel on friend click, but no result.
What am I doing wrong?
I solved the problem. The problem was in pubnub.js version, it was 3.4, I switched to 3.7.1 and added the following code
jQuery('ul.chat-users li').click(function(){
var friend_id = jQuery(this).attr('data-id');
jQuery('ul.chat-users li').removeClass('activeChannel');
jQuery(this).addClass('activeChannel');
if ( channel != "" ) {
pubnub.unsubscribe({
channel : channel,
});
}
Related
I am using RTCMultiConnection v3.4.4
I want to run WebRTC on localhost. I have chosen XHR-Signaling because I want the project to be completely offline. I do not want it to depend on the internet, since everything is on localhost (to be later deployed on LAN)
I have included XHRConnection.js and set connection.setCustomSocketHandler(XHRConnection). I also did the override connection.openSignalingChannel...
However, when I open/start the room, my video shows but the buttons that was disabled by disableInputButtons() still remains disabled. The chat is not working.
I did a console.log at override connection.openSignalingChannel... to confirm if it ever got called, but it does not.
Please help on how to implement XHR-Signaling on localhost.
Thanks.
Code:
File: Audio+Video+TextChat+FileSharing.html
<!-- Demo version: 2017.08.10 -->
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Audio+Video+TextChat+FileSharing using RTCMultiConnection</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<link rel="shortcut icon" href="./logo.png">
<link rel="stylesheet" href="./stylesheet.css">
<script src="./menu.js"></script>
</head>
<body>
<h1>
Audio+Video+TextChat+FileSharing using RTCMultiConnection
<p class="no-mobile">
Multi-user (many-to-many) video streaming + text chat + file sharing using mesh networking model.
</p>
</h1>
<section class="make-center">
<input type="text" id="room-id" value="abcdef" autocorrect=off autocapitalize=off size=20>
<button id="open-room">Open Room</button><button id="join-room">Join Room</button><button id="open-or-join-room">Auto Open Or Join Room</button>
<br><br>
<input type="text" id="input-text-chat" placeholder="Enter Text Chat" disabled>
<button id="share-file" disabled>Share File</button>
<br><br>
<button id="btn-leave-room" disabled>Leave/or close the room</button>
<div id="room-urls" style="text-align: center;display: none;background: #F1EDED;margin: 15px -10px;border: 1px solid rgb(189, 189, 189);border-left: 0;border-right: 0;"></div>
<div id="chat-container">
<div id="file-container"></div>
<div class="chat-output"></div>
</div>
<div id="videos-container"></div>
</section>
<script src="./RTCMultiConnection.min.js"></script>
<script src="./adapter.js"></script>
<script src="./XHRConnection.js"></script>
<!-- custom layout for HTML5 audio/video elements -->
<link rel="stylesheet" href="./getHTMLMediaElement.css">
<script src="./getHTMLMediaElement.js"></script>
<script src="./FileBufferReader.js"></script>
<script>
// ......................................................
// .......................UI Code........................
// ......................................................
document.getElementById('open-room').onclick = function() {
disableInputButtons();
connection.open( document.getElementById('room-id').value , function() {
showRoomURL(connection.sessionid);
xhr
(
'start-broadcast.php' ,
function( responseText ){ console.log( 'Broadcast started [' + document.getElementById('room-id').value + ']' ) },
JSON.stringify( { name: document.getElementById('room-id').value } )
);
});
};
document.getElementById('join-room').onclick = function() {
disableInputButtons();
connection.join(document.getElementById('room-id').value);
};
document.getElementById('open-or-join-room').onclick = function() {
disableInputButtons();
connection.openOrJoin(document.getElementById('room-id').value, function(isRoomExists, roomid) {
if (!isRoomExists) {
showRoomURL(roomid);
}
});
};
document.getElementById('btn-leave-room').onclick = function() {
this.disabled = true;
if (connection.isInitiator) {
// use this method if you did NOT set "autoCloseEntireSession===true"
// for more info: https://github.com/muaz-khan/RTCMultiConnection#closeentiresession
connection.closeEntireSession(function() {
document.querySelector('h1').innerHTML = 'Entire session has been closed.';
});
} else {
connection.leave();
}
};
// ......................................................
// ................FileSharing/TextChat Code.............
// ......................................................
document.getElementById('share-file').onclick = function() {
var fileSelector = new FileSelector();
fileSelector.selectSingleFile(function(file) {
connection.send(file);
});
};
document.getElementById('input-text-chat').onkeyup = function(e) {
if (e.keyCode != 13) return;
// removing trailing/leading whitespace
this.value = this.value.replace(/^\s+|\s+$/g, '');
if (!this.value.length) return;
connection.send(this.value);
appendDIV(this.value);
this.value = '';
};
var chatContainer = document.querySelector('.chat-output');
function appendDIV(event) {
var div = document.createElement('div');
div.innerHTML = event.data || event;
chatContainer.insertBefore(div, chatContainer.firstChild);
div.tabIndex = 0;
div.focus();
document.getElementById('input-text-chat').focus();
}
// ......................................................
// ..................RTCMultiConnection Code.............
// ......................................................
var connection = new RTCMultiConnection();
connection.setCustomSocketHandler(XHRConnection);
connection.direction = 'one-way';
// by default, socket.io server is assumed to be deployed on your own URL
// connection.socketURL = '/';
connection.trickleIce = false;
// comment-out below line if you do not have your own socket.io server
// connection.socketURL = 'https://rtcmulticonnection.herokuapp.com:443/';
//connection.socketMessageEvent = 'audio-video-file-chat-demo';
connection.enableLogs = true;
connection.enableFileSharing = true; // by default, it is "false".
// this object is used to store "onmessage" callbacks from "openSignalingChannel handler
var onMessageCallbacks = {};
// this object is used to make sure identical messages are not used multiple times
var messagesReceived = {};
// overriding "openSignalingChannel handler
connection.openSignalingChannel = function (config) {
console.log( 'called: openSignalingChannel' );
var channel = config.channel || this.channel;
onMessageCallbacks[channel] = config.onmessage;
// let RTCMultiConnection know that server connection is opened!
if (config.onopen) {
console.log( 'Calling the config.open object' );
setTimeout(config.onopen, 1);
}
else console.log( 'No config.open object' );
// returning an object to RTCMultiConnection
// so it can send data using "send" method
return {
send: function (data) {
data = {
channel: channel,
message: data,
sender: connection.userid
};
// posting data to server
// data is also JSON-ified.
xhr('xhr-signalhandler-post.php', null, JSON.stringify(data));
},
channel: channel
};
};
connection.session = {
audio: true,
video: true,
data: true
};
connection.sdpConstraints.mandatory = {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
};
connection.videosContainer = document.getElementById('videos-container');
connection.onstream = function(event) {
var width = parseInt(connection.videosContainer.clientWidth / 2) - 20;
var mediaElement = getHTMLMediaElement(event.mediaElement, {
title: event.userid,
buttons: ['full-screen'],
width: width,
showOnMouseEnter: false
});
connection.videosContainer.appendChild(mediaElement);
setTimeout(function() {
mediaElement.media.play();
}, 5000);
mediaElement.id = event.streamid;
};
connection.onstreamended = function(event) {
var mediaElement = document.getElementById(event.streamid);
if (mediaElement) {
mediaElement.parentNode.removeChild(mediaElement);
}
};
connection.onmessage = appendDIV;
connection.filesContainer = document.getElementById('file-container');
connection.onopen = function() {
console.log( "com. openend" );
document.getElementById('share-file').disabled = false;
document.getElementById('input-text-chat').disabled = false;
document.getElementById('btn-leave-room').disabled = false;
document.querySelector('h1').innerHTML = 'You are connected with: ' + connection.getAllParticipants().join(', ');
};
connection.onclose = function() {
if (connection.getAllParticipants().length) {
document.querySelector('h1').innerHTML = 'You are still connected with: ' + connection.getAllParticipants().join(', ');
} else {
document.querySelector('h1').innerHTML = 'Seems session has been closed or all participants left.';
}
};
connection.onEntireSessionClosed = function(event) {
document.getElementById('share-file').disabled = true;
document.getElementById('input-text-chat').disabled = true;
document.getElementById('btn-leave-room').disabled = true;
document.getElementById('open-or-join-room').disabled = false;
document.getElementById('open-room').disabled = false;
document.getElementById('join-room').disabled = false;
document.getElementById('room-id').disabled = false;
connection.attachStreams.forEach(function(stream) {
stream.stop();
});
// don't display alert for moderator
if (connection.userid === event.userid) return;
document.querySelector('h1').innerHTML = 'Entire session has been closed by the moderator: ' + event.userid;
};
connection.onUserIdAlreadyTaken = function(useridAlreadyTaken, yourNewUserId) {
// seems room is already opened
connection.join(useridAlreadyTaken);
};
function disableInputButtons() {
document.getElementById('open-or-join-room').disabled = true;
document.getElementById('open-room').disabled = true;
document.getElementById('join-room').disabled = true;
document.getElementById('room-id').disabled = true;
}
// ......................................................
// ......................Handling Room-ID................
// ......................................................
function showRoomURL(roomid) {
var roomHashURL = '#' + roomid;
var roomQueryStringURL = '?roomid=' + roomid;
var html = '<h2>Unique URL for your room:</h2><br>';
html += 'Hash URL: ' + roomHashURL + '';
html += '<br>';
html += 'QueryString URL: ' + roomQueryStringURL + '';
var roomURLsDiv = document.getElementById('room-urls');
roomURLsDiv.innerHTML = html;
roomURLsDiv.style.display = 'block';
}
(function() {
var params = {},
r = /([^&=]+)=?([^&]*)/g;
function d(s) {
return decodeURIComponent(s.replace(/\+/g, ' '));
}
var match, search = window.location.search;
while (match = r.exec(search.substring(1)))
params[d(match[1])] = d(match[2]);
window.params = params;
})();
var roomid = '';
if (localStorage.getItem(connection.socketMessageEvent)) {
roomid = localStorage.getItem(connection.socketMessageEvent);
} else {
roomid = connection.token();
}
document.getElementById('room-id').value = roomid;
document.getElementById('room-id').onkeyup = function() {
localStorage.setItem(connection.socketMessageEvent, this.value);
};
var hashString = location.hash.replace('#', '');
if (hashString.length && hashString.indexOf('comment-') == 0) {
hashString = '';
}
var roomid = params.roomid;
if (!roomid && hashString.length) {
roomid = hashString;
}
if (roomid && roomid.length) {
document.getElementById('room-id').value = roomid;
localStorage.setItem(connection.socketMessageEvent, roomid);
// auto-join-room
(function reCheckRoomPresence() {
connection.checkPresence(roomid, function(isRoomExists) {
if (isRoomExists) {
connection.join(roomid);
return;
}
setTimeout(reCheckRoomPresence, 5000);
});
})();
disableInputButtons();
}
</script>
<footer>
<small id="send-message"></small>
</footer>
<script src="common.js"></script>
</body>
</html>
XHRConnection.js:
function XHRConnection(connection, connectCallback) {
connection.socket = {
send: function(data) {
data = {
message: data,
sender: connection.userid
};
// posting data to server
// data is also JSON-ified.
xhr('xhr-signalhandler-post.php', null, JSON.stringify(data));
}
};
// this object is used to make sure identical messages are not used multiple times
var messagesReceived = {};
function repeatedlyCheck() {
xhr('xhr-signalhandler-get.php', function(data) {
// if server says nothing; wait.
if (data == false) return setTimeout(repeatedlyCheck, 400);
// if already receied same message; skip.
if (messagesReceived[data.ID]) return setTimeout(repeatedlyCheck, 400);
messagesReceived[data.ID] = data.Message;
// "Message" property is JSON-ified in "openSignalingChannel handler
data = JSON.parse(data.Message);
if (data.eventName === connection.socketMessageEvent) {
onMessagesCallback(data.data);
}
if (data.eventName === 'presence') {
data = data.data;
if (data.userid === connection.userid) return;
connection.onUserStatusChanged({
userid: data.userid,
status: data.isOnline === true ? 'online' : 'offline',
extra: connection.peers[data.userid] ? connection.peers[data.userid].extra : {}
});
}
// repeatedly check the database
setTimeout(repeatedlyCheck, 1);
});
}
repeatedlyCheck();
setTimeout
(
function() {
if (connection.enableLogs) {
console.info('XHR connection opened');
}
connection.socket.emit('presence', {
userid: connection.userid,
isOnline: true
});
if( connectCallback ) {
console.log( 'Calling connectCallback...' );
connectCallback(connection.socket);
console.log( 'Done' );
}
},
2000
);
connection.socket.emit = function(eventName, data, callback) {
if (eventName === 'changed-uuid') return;
if (data.message && data.message.shiftedModerationControl) return;
connection.socket.send({
eventName: eventName,
data: data
});
if (callback) {
callback();
}
};
var mPeer = connection.multiPeersHandler;
function onMessagesCallback(message) {
if (message.remoteUserId != connection.userid) return;
if (connection.peers[message.sender] && connection.peers[message.sender].extra != message.extra) {
connection.peers[message.sender].extra = message.extra;
connection.onExtraDataUpdated({
userid: message.sender,
extra: message.extra
});
}
if (message.message.streamSyncNeeded && connection.peers[message.sender]) {
var stream = connection.streamEvents[message.message.streamid];
if (!stream || !stream.stream) {
return;
}
var action = message.message.action;
if (action === 'ended' || action === 'stream-removed') {
connection.onstreamended(stream);
return;
}
var type = message.message.type != 'both' ? message.message.type : null;
stream.stream[action](type);
return;
}
if (message.message === 'connectWithAllParticipants') {
if (connection.broadcasters.indexOf(message.sender) === -1) {
connection.broadcasters.push(message.sender);
}
mPeer.onNegotiationNeeded({
allParticipants: connection.getAllParticipants(message.sender)
}, message.sender);
return;
}
if (message.message === 'removeFromBroadcastersList') {
if (connection.broadcasters.indexOf(message.sender) !== -1) {
delete connection.broadcasters[connection.broadcasters.indexOf(message.sender)];
connection.broadcasters = removeNullEntries(connection.broadcasters);
}
return;
}
if (message.message === 'dropPeerConnection') {
connection.deletePeer(message.sender);
return;
}
if (message.message.allParticipants) {
if (message.message.allParticipants.indexOf(message.sender) === -1) {
message.message.allParticipants.push(message.sender);
}
message.message.allParticipants.forEach(function(participant) {
mPeer[!connection.peers[participant] ? 'createNewPeer' : 'renegotiatePeer'](participant, {
localPeerSdpConstraints: {
OfferToReceiveAudio: connection.sdpConstraints.mandatory.OfferToReceiveAudio,
OfferToReceiveVideo: connection.sdpConstraints.mandatory.OfferToReceiveVideo
},
remotePeerSdpConstraints: {
OfferToReceiveAudio: connection.session.oneway ? !!connection.session.audio : connection.sdpConstraints.mandatory.OfferToReceiveAudio,
OfferToReceiveVideo: connection.session.oneway ? !!connection.session.video || !!connection.session.screen : connection.sdpConstraints.mandatory.OfferToReceiveVideo
},
isOneWay: !!connection.session.oneway || connection.direction === 'one-way',
isDataOnly: isData(connection.session)
});
});
return;
}
if (message.message.newParticipant) {
if (message.message.newParticipant == connection.userid) return;
if (!!connection.peers[message.message.newParticipant]) return;
mPeer.createNewPeer(message.message.newParticipant, message.message.userPreferences || {
localPeerSdpConstraints: {
OfferToReceiveAudio: connection.sdpConstraints.mandatory.OfferToReceiveAudio,
OfferToReceiveVideo: connection.sdpConstraints.mandatory.OfferToReceiveVideo
},
remotePeerSdpConstraints: {
OfferToReceiveAudio: connection.session.oneway ? !!connection.session.audio : connection.sdpConstraints.mandatory.OfferToReceiveAudio,
OfferToReceiveVideo: connection.session.oneway ? !!connection.session.video || !!connection.session.screen : connection.sdpConstraints.mandatory.OfferToReceiveVideo
},
isOneWay: !!connection.session.oneway || connection.direction === 'one-way',
isDataOnly: isData(connection.session)
});
return;
}
if (message.message.readyForOffer || message.message.addMeAsBroadcaster) {
connection.addNewBroadcaster(message.sender);
}
if (message.message.newParticipationRequest && message.sender !== connection.userid) {
if (connection.peers[message.sender]) {
connection.deletePeer(message.sender);
}
var userPreferences = {
extra: message.extra || {},
localPeerSdpConstraints: message.message.remotePeerSdpConstraints || {
OfferToReceiveAudio: connection.sdpConstraints.mandatory.OfferToReceiveAudio,
OfferToReceiveVideo: connection.sdpConstraints.mandatory.OfferToReceiveVideo
},
remotePeerSdpConstraints: message.message.localPeerSdpConstraints || {
OfferToReceiveAudio: connection.session.oneway ? !!connection.session.audio : connection.sdpConstraints.mandatory.OfferToReceiveAudio,
OfferToReceiveVideo: connection.session.oneway ? !!connection.session.video || !!connection.session.screen : connection.sdpConstraints.mandatory.OfferToReceiveVideo
},
isOneWay: typeof message.message.isOneWay !== 'undefined' ? message.message.isOneWay : !!connection.session.oneway || connection.direction === 'one-way',
isDataOnly: typeof message.message.isDataOnly !== 'undefined' ? message.message.isDataOnly : isData(connection.session),
dontGetRemoteStream: typeof message.message.isOneWay !== 'undefined' ? message.message.isOneWay : !!connection.session.oneway || connection.direction === 'one-way',
dontAttachLocalStream: !!message.message.dontGetRemoteStream,
connectionDescription: message,
successCallback: function() {
// if its oneway----- todo: THIS SEEMS NOT IMPORTANT.
if (typeof message.message.isOneWay !== 'undefined' ? message.message.isOneWay : !!connection.session.oneway || connection.direction === 'one-way') {
connection.addNewBroadcaster(message.sender, userPreferences);
}
if (!!connection.session.oneway || connection.direction === 'one-way' || isData(connection.session)) {
connection.addNewBroadcaster(message.sender, userPreferences);
}
}
};
connection.onNewParticipant(message.sender, userPreferences);
return;
}
if (message.message.shiftedModerationControl) {
connection.onShiftedModerationControl(message.sender, message.message.broadcasters);
return;
}
if (message.message.changedUUID) {
if (connection.peers[message.message.oldUUID]) {
connection.peers[message.message.newUUID] = connection.peers[message.message.oldUUID];
delete connection.peers[message.message.oldUUID];
}
}
if (message.message.userLeft) {
mPeer.onUserLeft(message.sender);
if (!!message.message.autoCloseEntireSession) {
connection.leave();
}
return;
}
mPeer.addNegotiatedMessage(message.message, message.sender);
}
window.addEventListener('beforeunload', function() {
connection.socket.emit('presence', {
userid: connection.userid,
isOnline: false
});
}, false);
}
// a simple function to make XMLHttpRequests
function xhr( url, callback, data ) {
// if( data ) console.log('[' + url + '] sending: ' + JSON.stringify( data ) );
if (!window.XMLHttpRequest || !window.JSON){
console.log( 'No JSON and/or XMLHttpRequest support' );
return;
}
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (callback && request.readyState == 4 && request.status == 200) {
// server MUST return JSON text
if( request.responseText != 'false' )
console.log('Logging non-false data [from ' + url + ']: ' + request.responseText + "[...data POST'ed: " + JSON.stringify( data ) + "]" );
callback(JSON.parse(request.responseText));
}
};
request.open( 'POST', url );
var formData = new FormData();
// you're passing "message" parameter
formData.append( 'message', data );
request.send(formData);
}
start-broadcast.php:
<?php
require( "connection.inc.php" );
if( isset( $_POST['message'] ) )
{
$data = json_decode( $_POST['message'] , true );
// Now, if someone initiates WebRTC session; you should make an XHR request to create a record in the room-table; and
// set "Owner-id" equals to that user's "user-id".
//{"message":{"eventName":"presence","data":{"userid":"winey","isOnline":true}},"sender":"winey"}
$query = " INSERT INTO active_broadcasts ( name ) VALUES ( '{$data['name']}' ) ";
if( $mysqli->query( $query ) )
{
$transport = json_encode( false );
exit( $transport );
}
else
exit( $mysqli->error );
}
else
exit( 'No data sent' );
?>
xhr-signalhandler-post.php:
<?php
require( "connection.inc.php" );
$response = array();
//{"message":{"eventName":"presence","data":{"userid":"winey","isOnline":true}},"sender":"winey"}
// var_dump( $_POST );
// exit;
if( isset( $_POST['message'] ) )
{
$query = " INSERT INTO webrtc-messages ( name ) VALUES ( '{$_POST['name']}' ) ";
if( $mysqli->query( $query ) )
{
$transport = json_encode( false );
exit( $transport );
}
else
exit( $mysqli->error );
// Now, if someone else joins the room; you can update above record; and append his "user-id" in the "Participants-id" column.
}
if( #$_POST["message"] = "undefined" )
$response = false;
$transport = json_encode( $response );
exit( $transport );
?>
xhr-signalhandler-get.php:
<?php
require( "connection.inc.php" );
$response = array();
// var_dump( $_POST );
if( isset( $_POST['message'] ) )
{
$query = "SELECT id , message , channel , `sender-id` FROM `webrtc-messages` ";
if( $mysqli->connect_errno )
exit ( "Failed to connect to MySQL: " . $mysqli->connect_error );
if( $res = $mysqli->query( $query ) )
{
if( $res->num_rows > 0 )
{
while( $value = mysqli_fetch_assoc( $res ) )
{
//
}
}
}
else
{
echo "<center class='text-danger'>Server error</center>";
exit( $mysqli->error );
}
}
if( #$_POST["message"] = "undefined" )
$response = false;
$transport = json_encode( $response );
exit( $transport );
?>
I've never played with WebRTC nor RTCMultiConnection but I think I understand where your problem comes from.
As you're using XHR, there is no direct connection between your client (web browser) and your server. So, there is no way for the server to push information to the client thus, the openSignalingChannel override will never be triggered.
The trick is to call a function on a regular basis to check the server status (aka. long polling).
If you check the documentation of RTCMultiConnection about the openSignalingChannel override ( http://www.rtcmulticonnection.org/docs/openSignalingChannel/#xhr-signaling ), you'll notice the use of repeatedlyCheck();. I think this is the missing piece of your puzzle.
Hope it helps.
I'm facing a very strange issue where I'm able to make asynchronous HTTP call in my local Cent-OS environment but as soon as I push my code to demo server somehow the HTTP calls are not executed asynchronously.
Below is the function that I'm trying to execute,
$scope.getResults = function(){
$http({
url: /getResults,
method: 'POST',
data: data,
headers: {'async': true}
})
.then(function (response) {
var contactId = response.data.contactId[0];
$scope.loadProfileInfo(contactId);
var requestId = response.data.requestId;
$scope.getTotalCount(requestId);
}
});
};
$scope.loadProfileInfo = function(id){
$http({
url: /getProfileInfo,
method: 'POST',
data: {contactId: id},
headers: {'async': true})
.then(function (response) {
//perform operations
});
};
$scope.getTotalCount = function(id){
$http({
url: /getTotalCount,
method: 'POST',
data: {some: data},
headers: {'async': true})
.then(function (response) {
//perform operations
});
};
When I call the function getResults() it loads the results and calls the function loadProfileInfo() which loads the profile information as expected.
Now the issue is the function getTotalCount takes a lot longer to execute and until it does not return the response no other HTTP calls are processed even if they are very small.
I'm using Laravel PHP framework.
Real Code
Reference:
pageChangeHandler() = getResults()
getCount() = getTotalCount()
showProfileAction() = loadProfileInfo()
$scope.pageChangeHandler = function(num) {
$scope.checkMoreResults = false;
console.log("pageChangeHandler begins");
//removing cached values from previous results
$("#analyticsResults").text("...");
$scope.showTitleLevelGraph(['','','','',''], [0,0,0,0,0]);
$scope.showScoreGraph([0,0,0,0,0,0]);
$scope.showGenderGraph([0,0,0]);
$scope.showCompanySizeGraph([0,0,0,0]);
$scope.analyticsFlag = false;
$("#loading-bar").show();
$("#loading-spinner").show();
if ($window.Math.ceil(num*50)>50000){
sweetAlert("Oops", "Seeking is limited to 50,000 results. Please narrow your search or contact a Customer Support rep at 866-535-3960 if you are interested in larger quantities of data.", "error");
} else {
$('body').css('cursor', 'progress');
// if downloadList exists, save it so it can be added to after reloading.
if ($scope.downloadList.length>0) {
$scope.storedSelectedContacts = angular.copy($scope.downloadList);
$scope.storedLiUrl = angular.copy($scope.liUrl);
$scope.storedCompanyName = angular.copy($scope.companyName);
$scope.storedCompLink = angular.copy($scope.compLink);
}
$scope.selectedPage = num;
//$scope.showProfile = false;
//$scope.profileData = null;
if (num > 1 || null!==$scope.shortCode) {
// use code
var data = {'code': $scope.shortCode};
} else {
$scope.shortCode = null;
var data = angular.copy($scope.wizardData);
console.debug(data+" "+JSON.stringify(data));
try{
if (data.state.length > 0) {
for (var x = 0; x < data.state.length; x++) {
data.tbl_company_State[x] = data.state[x].value;
}
data.state = null; // null it out to prevent issues in LV controller
}
}catch(e){
}
}
//console.debug(data);
if ($scope.searchFast == true){
var url = $scope.baseUrl + "/search/fast?page=" + num;
} else {
var url = $scope.baseUrl + "/search/wizard?page=" + num;
console.log("wizard: "+num);
var newsearch = true;
}
console.log("Real data: "+JSON.stringify(data));
$http({
url: url,
method: 'POST',
data: data,
headers: {'async': true}
})
.success(function (response) {
(function() {
setTimeout(function() {
// code-here
//response = response.data;
console.log("Search results: "+JSON.stringify(response));
$('body').css('cursor', 'auto');
//console.debug(response);
if (response.error){
if (response.error == 1000000) {
sweetAlert("Oops", "Your search returned more than 1 million results. Please narrow your search or contact a Customer Support rep at 866-535-3960 if you are interested in larger quantities of data.", "error");
$scope.totalResults = '1000000+';
} else {
sweetAlert("Oops", response.error, "error");
$scope.totalResults = '0';
}
} else {
if (response.data) {
//loading the profile of the first result from the fast load
$scope.selectedAll = false;
$scope.searchResults = response.data;
$scope.totalResults = response.total;
$scope.resultStart = $window.Math.ceil((response.per_page * response.current_page) - response.per_page + 1);
$scope.resultEnd = $window.Math.ceil(response.per_page * response.current_page);
if ($scope.resultEnd > $scope.totalResults) {
$scope.resultEnd = angular.copy($scope.totalResults);
}
$scope.resultsPerPage = response.per_page;
$scope.pageSize = $scope.resultsPerPage;
$scope.lastPage = response.last_page;
$scope.currentPage = response.current_page;
if (response.code) {
$scope.shortCode = response.code;
$scope.disableRange = false;
}
$scope.shareUrl = $scope.baseUrl + '/search/code/' + $scope.shortCode;
console.log();
if (response.data.length > 0) {
if ($scope.currentPage > 1 && $scope.passedCode!='') {
$scope.passedCode=''
}
if ($scope.currentPage == 1 && ($scope.searchFast==true || $scope.searchFast==null)) {
//------Edit Jeet kapadia---//
if($scope.newSearchFlag == false){
$scope.showResults = true;
//loading the profile of the first result from the fast load
$scope.firstContactId = response.data[0].ContactID;
console.log("1 Profile loaded");
$scope.showProfileAction($scope.firstContactId);
}
}*/
//-----End Jeet Kapadia-----//
}
if(newsearch == true && $scope.newSearchFlag == true){
//console.log(response.data[0]);
//$scope.newSaveSelectSearch();
$scope.showResults = false;
newsearch = "false";
}
angular.forEach($scope.searchResults, function (item) {
item.Selected = false;
if (arrayObjectIndexOf($scope.storedSelectedContacts, item.ContactID)>-1 || arrayObjectIndexOf($scope.downloadList, item.ContactID)>-1) {
item.Selected = true;
}
});
$scope.buildDownloadList();
if (response.more){
$scope.totalResults = 'Loading...';
$scope.searchFast=false;
$scope.disableRange = true;
$scope.checkMoreResults = true;
$scope.pageChangeHandler(1);
}else{
$scope.getCount();
//reloading the profile of the first result if the contact changes after all
//the records have been loaded
if($scope.firstContactId != response.data[0].ContactID){
console.log("2 Profile loaded: "+$scope.firstContactId+" "+response.data[0].ContactID);
$scope.showProfileAction(response.data[0].ContactID);
}
//fetching all results to perform analytics on
console.log("short code: "+$scope.shortCode);
//globalAnalyticsInterval = $interval(function () {
}
} else {
sweetAlert("Oops", "Your search returned 0 results. Please widen your search parameters a bit.", "error");
}
}
}
}, 500)
})()
});
}
};
$scope.getCount = function(){
var data = angular.copy($scope.wizardData);
console.debug(data+" "+JSON.stringify(data));
try{
if (data.state.length > 0) {
for (var x = 0; x < data.state.length; x++) {
data.tbl_company_State[x] = data.state[x].value;
}
data.state = null; // null it out to prevent issues in LV controller
}
}catch(e){
}
var url = $scope.baseUrl + "/search/getCount";
$http.post(url, data)
.success(function (response) {
//response = response.data;
$scope.lastPage = response.last_page;
$scope.totalResults = response.total;
console.log("Count: "+JSON.stringify(response));
});
};
$scope.showProfileAction = function(id) {
$scope.liTimeoutFlag = false;
$scope.liResponseFlag = false;
$scope.storedContactId = id;
console.log("showProfileAction: "+id);
$scope.showProfile = false;
$scope.profileData = null;
$("#qualityScoreText").text("Verifying");
$scope.socialScoreFlag = false;
$scope.emailScoreFlag = false;
$("#profileInfo").addClass("visibilityHidden");
try{
$scope.canceller.resolve();
}catch(err){
//console.log("showProfileAction: "+err.message);
}
$scope.userNoteContactId = id;
//getting user notes for the contact
$scope.getUserNoteComment(id);
//console.debug(id);
if (id > 0) {
$scope.idContactSelected = id;
var url = $scope.baseUrl + "/search/contact/" + id;
$('body').css('cursor', 'progress');
$('#profilePanel').css('background-color: #ccc');
$http.get(url)
.then(function (response) {
response = response.data;
$('body').css('cursor', 'auto');
$('#profilePanel').css('background-color: #fff');
if (response.error) {
sweetAlert("Oops", "Contact info could not be loaded.", "error");
} else {
if (response.id) {
if ($scope.mapMarker!==null) {
$scope.mapMarker.setMap(null);
}
$timeout(function(){
$scope.showProfile = true;
}, 100)
$scope.profileData = response;
$("#profileInfo").removeClass("visibilityHidden");
$scope.lat = parseFloat($scope.profileData.Latitude).toFixed(6);
$scope.lon = parseFloat($scope.profileData.Longitude).toFixed(6);
$scope.mapOptions = {
zoom: 14,
center: new google.maps.LatLng($scope.lat, $scope.lon),
// Style for Google Maps
styles: [{"featureType":"landscape","stylers":[{"saturation":-100},{"lightness":65},{"visibility":"on"}]},{"featureType":"poi","stylers":[{"saturation":-100},{"lightness":51},{"visibility":"simplified"}]},{"featureType":"road.highway","stylers":[{"saturation":-100},{"visibility":"simplified"}]},{"featureType":"road.arterial","stylers":[{"saturation":-100},{"lightness":30},{"visibility":"on"}]},{"featureType":"road.local","stylers":[{"saturation":-100},{"lightness":40},{"visibility":"on"}]},{"featureType":"transit","stylers":[{"saturation":-100},{"visibility":"simplified"}]},{"featureType":"administrative.province","stylers":[{"visibility":"off"}]},{"featureType":"water","elementType":"labels","stylers":[{"visibility":"on"},{"lightness":-25},{"saturation":-100}]},{"featureType":"water","elementType":"geometry","stylers":[{"hue":"#ffff00"},{"lightness":-25},{"saturation":-97}]}],
mapTypeId: google.maps.MapTypeId.ROADMAP
};
$scope.mapMarker = new google.maps.Marker({
map: $scope.myMap,
position: $scope.mapOptions.center
});
for(var key in $scope.profileData) {
//console.log(key+" "+$scope.profileData[key]);
}
//verifying the email address of the loaded profile
var emailUrl = $location.protocol() + '://'+ $location.host() + '/contact/verify/' + id;
$http.post(emailUrl)
.then(function (result) {
var singleVerificationKey = result.data.verification_key;
var emailStatus = result.data.status;
var singleEmailResult = result.data.result;
console.log("single email call: "+JSON.stringify(result)+" "+emailStatus);
if($scope.storedContactId == result.data.contactid){
if(emailStatus == "0"){ //when something goes wrong while verifying the email
$("#qualityScoreEmail").html("<i class='fa fa-question' style='font-size:15px' popover-placement='right' popover-trigger='mouseenter' popover='The email for this contact is UNKNOWN.'></i> Email");
}else if(emailStatus == "2"){ //when the email is verified in last 24 hours
if((singleEmailResult == 'pass')){ //success
$("#qualityScoreEmail").html("<i class='fa fa-check' style='font-size:15px' popover-placement='right' popover-trigger='mouseenter' popover='The email for this contact IS up to date.'></i> Email");
}else if((singleEmailResult == 'fail')){ //failed
$("#qualityScoreEmail").html("<i class='fa fa-remove' style='font-size:15px' popover-placement='right' popover-trigger='mouseenter' popover='The email for this contact is NOT up to date.'></i> Email");
}else if((singleEmailResult == 'unknown')){ // unknown
$("#qualityScoreEmail").html("<i class='fa fa-question' style='font-size:15px' popover-placement='right' popover-trigger='mouseenter' popover='The email for this contact is UNKNOWN.'></i> Email");
}
}else if(emailStatus == "1"){
console.log("single email key: "+singleVerificationKey);
//instantiate a Pusher object with our Credential's key
var pusher = new Pusher('2703a05dc7f552e2a2d5', {
encrypted: true
});
//Subscribe to the channel we specified in our Laravel Event
var channel = pusher.subscribe(singleVerificationKey);
//Bind a function to a Event (the full Laravel class)
channel.bind('EmailSingleVerification', $scope.singleEmailVerification);
}
}else{
console.log("single email creation information from previous request");
}
});
// //verifying the social information of the loaded profile
var liUrl = $scope.baseUrl + '/socialVerifyBatch';
var contactIdArr = [id];
var postData = {'id': contactIdArr, 'background': false};
$http.post(liUrl, postData)
.then(function (result) {
setTimeout(function () {
console.log("Timeout: start");
$scope.liTimeoutFlag = true;
if(($scope.storedContactId == result.data.contactid) && (!$scope.liResponseFlag)){
console.log("Timeout: making unknown");
$("#qualityScoreSocial").html("<i class='fa fa-question' style='font-size:15px' popover-placement='right' popover-trigger='mouseenter' popover='The social record for this contact is UNKNOWN'></i> Social");
$scope.animateScore($scope.profileData.Quality_Score, $scope.profileData.Quality_Score-1, 1000);
console.log("here 1");
var url = $scope.baseUrl + '/contact/verifySocial/' + $scope.storedContactId + "/6";
$http.post(url)
.then(function (result) {
console.log("Timeout: Update quality score: "+JSON.stringify(result));
}
);
}
}, 20000);
console.log("single li: "+JSON.stringify(result)+" "+$scope.storedContactId+" "+result.data.contactid);
if($scope.storedContactId == result.data.contactid){
//if the social information was verified in last 24 hours
if(result.data.status == "exist"){
if(result.data.passed == 1){ //success
$("#qualityScoreSocial").html("<i class='fa fa-check' style='font-size:15px' popover-placement='right' popover-trigger='mouseenter' popover='The social record for this contact IS up to date.'></i> Social");
}else if(result.data.failed == 1){ //failed
$("#qualityScoreSocial").html("<i class='fa fa-remove' style='font-size:15px' popover-placement='right' popover-trigger='mouseenter' popover='The social record for this contact is NOT up to date.'></i> Social");
}else if(result.data.unknown == 1){ // unknown
$("#qualityScoreSocial").html("<i class='fa fa-question' style='font-size:15px' popover-placement='right' popover-trigger='mouseenter' popover='The social record for this contact is UNKNOWN'></i> Social");
}
}else if(result.data.status == "done"){
var uniqueString = result.data.download_key;
console.log("karthik key: "+uniqueString);
//instantiate a Pusher object with our Credential's key
var pusher = new Pusher('2703a05dc7f552e2a2d5', {
encrypted: true
});
//Subscribe to the channel we specified in our Laravel Event
var channel = pusher.subscribe(uniqueString);
//Bind a function to a Event (the full Laravel class)
channel.bind('SocialBulkVerification', $scope.singleSocialVerification);
console.log("end karthik key");
}
}else{
console.log("single social creation information from previous request");
}
});
}
}
});
} else {
}
}
Any help is appreciated. Thanks in advance.
I'm having a problem locating where my problem is. I'm using PubNub for realtime messaging and the example project is using ECC (elliptical curve cryptography) encrypted messaging.
Every thing in the file works(animation, channel presence, etc.) except for sending the message. Every time I hit send I get this message:
Here is my chat-app.js file:
(function() {
if (typeof(user) === 'undefined') {
return;
}
var output = document.getElementById('output'),
input = document.getElementById('input'),
picture = document.getElementById('picture'),
presence = document.getElementById('presence'),
action = document.getElementById('action'),
send = document.getElementById('send');
var channel = 'fun';
var keysCache = {};
var pubnub = PUBNUB.init({
subscribe_key: 'sub-c-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
publish_key: 'pub-c-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
uuid: user.name,
auth_key: user.gtoken,
ssl: true
});
function displayOutput(message) {
if(!message) return;
if(typeof(message.text) === 'undefined') return;
var html = '';
if ('userid' in message && message.userid in keysCache) {
var signature = message.signature;
delete message.signature;
var result = ecc.verify(keysCache[message.userid].publicKey, signature, JSON.stringify(message));
if(result) {
html = '<p><img src="'+ keysCache[message.userid].picture +'" class="avatar"><strong>' + keysCache[message.userid].name + '</strong><br><span>' + message.text + '</span></p>';
} else {
html = '<p><img src="images/troll.png" class="avatar"><strong></strong><br><em>A troll tried to spoof '+ keysCache[message.userid].name +' (but failed).</em></p>';
}
output.innerHTML = html + output.innerHTML;
} else {
var xhr = new XMLHttpRequest();
xhr.open('GET', '/user/' + message.userid, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
var res = JSON.parse(xhr.responseText);
keysCache[message.userid] = {
'publicKey': res.publicKey,
'name': res.name,
'artist': res.artist,
'picture': res.picture,
'id': res.id
}
displayOutput(message);
}
};
xhr.send(null);
}
}
function getHistory() {
pubnub.history({
channel: channel,
count: 30,
callback: function(messages) {
messages[0].forEach(function(m){
displayOutput(m);
});
}
});
}
pubnub.subscribe({
channel: channel,
restore: true,
connect: getHistory,
disconnect: function(res){
console.log('disconnect called');
},
reconnect: function(res){
console.log('reconnecting to pubnub');
},
callback: function(m) {
displayOutput(m);
},
presence: function(m){
if(m.occupancy === 1) {
presence.textContent = m.occupancy + ' person online';
} else {
presence.textContent = m.occupancy + ' people online';
}
if((m.action === 'join') || (m.action === 'timeout') || (m.action === 'leave')){
var status = (m.action === 'join') ? 'joined' : 'left';
action.textContent = m.uuid + ' ' + status +' room';
action.classList.add(m.action);
action.classList.add('poof');
action.addEventListener('animationend', function(){action.className='';}, false);
}
}
});
function post() {
var safeText = input.value.replace(/\&/g, '&').replace( /</g, '<').replace(/>/g, '>');
var message = { text: safeText, userid: user.id };
var signature = ecc.sign(user.eccKey, JSON.stringify(message));
message['signature'] = signature;
pubnub.publish({
channel: channel,
message: message
});
input.value = '';
}
input.addEventListener('keyup', function(e) {
if(input.value === '') return;
(e.keyCode || e.charCode) === 13 && post();
}, false);
send.addEventListener('click', function(e) {
if(input.value === '') return;
post();
}, false);
})();
This error is coming from my ecc.js file
Uncaught TypeError: Cannot read property 'r' of undefined
However, I'm assuming the error is in the chat-app.js file because I didn't touch the ecc.js file. I got it from the project -- https://github.com/pubnub/auth-chat-demo
More info on ECC can be found here: https://github.com/jpillora/eccjs
According to your description, it looks like this line is giving you the error:
var signature = ecc.sign(user.eccKey, JSON.stringify(message));
So I am guessing you are not properly passing user.eccKey?
Do you have all the user data from oAuth (or any login auth)? or is the eccKey generated correctly upon the user sign-up?
Also, try include the non-minified version of ecc.js so you can track where the error is coming from more easily.
https://raw.githubusercontent.com/jpillora/eccjs/gh-pages/dist/0.3/ecc.js
I need to send ajax requests with checkbox values (on each click/check). I have three lists with checkboxes, each list filters the data returend from php (with mysql AND condition):
$('body').on('click', '.click, :checkbox, .pag_link', function() {
var self = this;
// radio buttons
if ($('#res_prop').is(':checked')) {
var use = $('#res_prop').val();
}
else if ($('#com_prop').is(':checked')) {
var use = $('#com_prop').val();
}
else {
$('p.error').show();
die();
}
//checkboxes from each list have the same class, is this ok?
if ($(self).is(':checkbox')) {
$(self).on('change', function() {
if ($(self).prop('class') == 'filter1' || $('.filter1').is(':checked')) {
if ($('.filter1').is(':checked'))
var type = $(self).val(); // maybe should be an array
else var type = null;
} else var type = null;
if ($(self).prop('class') == 'filter2' || $('.filter2').is(':checked')) {
if ($('.filter2').is(':checked'))
var status = $(self).val(); // maybe should be an array
else var status = null;
} else var status = null;
if ($(self).prop('class') == 'filter3' || $('.filter3').is(':checked')) {
if ($('.filter3').is(':checked'))
var bhk = $(self).val(); // maybe should be an array
else var bhk = null;
} else var bhk = null;
});
}
else {
var type = status = bhk = null;
}
if ($(self).is('.pag_link')) {
if ($(self).text() == '«')
var page = (parseInt($('.active').text()) - 1);
else if ($(self).text() == '»')
var page = (parseInt($('.active').text()) + 1);
else
var page = parseInt($(self).text());
}
else {
var page = 1;
}
$.ajax({
method: 'POST',
url: '/search',
data: {
'do': getUrlParameter('do'),
'use': use,
'type': type,
'status': status,
'bhk': bhk,
'city': $('select[name="city"]').val(),
'zone': $('select[name="zone"]').val(),
'page': page
}
}).done(function(data) {
if ($( '#search' ).is(':visible'))
$( '#search' ).hide();
if ($(self).is(':checkbox')) {
alert('should work');
var new_content = $(data).find( '#scroll-to-list' );
$( '#scroll-to-list' ).replaceWith( new_content );
}
else {
var new_content = $(data).find( '#search-filters, #scroll-to-list' );
$( '#results' ).html( new_content );
$( 'html, body' ).animate({
scrollTop: $( '#scroll-to-list' ).offset().top
}, 1000);
}
});
});
I'm looking on each click/check to do the ajax request and print the new results (relying on server is performance-wise?). If checked, the variable gets the value and is sent, if unchecked the variable gets null. The search.php script handles the mysql Select query (with ifs adding the AND conditions to the query).
I just have 1 example in the db but the checkboxes script is not working (or the mysql select query is not including the and condition, i think the problem is in the jquery, the php script is fine).
$use = isset( $_POST['use'] ) ? (int) $_POST['use'] : ''; // int AJAX
$filter_type = isset( $_POST['type'] ) ? (int) $_POST['type'] : ''; // int AJAX
$filter_status = isset( $_POST['status'] ) ? (int) $_POST['status'] : ''; // int AJAX
$filter_bhk = isset( $_POST['bhk'] ) ? (int) $_POST['bhk'] : ''; // int AJAX
$filter_city = isset( $_POST['city'] ) ? (int) $_POST['city'] : 0; // int AJAX
$filter_zone = isset( $_POST['zone'] ) ? (int) $_POST['zone'] : 0; // int AJAX
$page_number = isset( $_POST['page'] ) ? (int) $_POST['page'] : ''; // int AJAX
if ($filter_type != NULL || $filter_type != '') {
$filter_type = 'AND t2.type = ' . $filter_type;
} else $filter_type = NULL;
if ($filter_status != NULL || $filter_status != '') {
$filter_status = 'AND t2.status = ' . $filter_status;
} else $filter_status = NULL;
if ($filter_bhk != NULL || $filter_bhk != '') {
$filter_bhk = 'AND t2.bhk = ' . $filter_bhk;
} else $filter_bhk = NULL;
if ($filter_city > 0) {
$filter_city = 'AND t2.city = ' . $filter_city;
$filter_zone = NULL;
if ($filter_zone > 0) {
$filter_zone = 'AND t2.zone = ' . $filter_zone;
}
} else $filter_city = $filter_zone = NULL;
if ($stmt = $mysqli->prepare(' SELECT t1.id, t2.*
FROM ' . $table . ' t1 // not from get/post
INNER JOIN property t2 ON t2.id = t1.id
WHERE t2.use = ?
' . $filter_type
. $filter_status
. $filter_bhk
. $filter_city
. $filter_zone . '
LIMIT ?, ?')) {
$stmt->bind_param('iii', $use, $start, $limit);
$stmt->execute();
I just found this JQuery method .serialize()... and it changed my life :)
$('body').on('click', '.click, :checkbox, .pag_link', function() {
var self = this;
if (!$(':radio').is(':checked')) {
$('p.error').show();
die();
}
var data = $('input, select').serializeArray(),
mode = getUrlParameter('do'),
page = 1;
if ($(self).is('.pag_link')) {
if ($(self).text() == '«')
page = (parseInt($('.active').text()) - 1);
else if ($(self).text() == '»')
page = (parseInt($('.active').text()) + 1);
else
page = parseInt($(self).text());
}
data.push({ name : 'do', value : mode});
data.push({ name : 'page', value : page});
alert($.param(data));
$.ajax({
method: 'POST',
url: '/search',
data: $.param(data)
}).done(function (data) {
if ($( '#search' ).is(':visible'))
$( '#search' ).hide();
if ($(self).is(':checkbox')) {
var new_content = $(data).find( '#scroll-to-list' );
$( '#scroll-to-list' ).replaceWith( new_content );
}
else {
var new_content = $(data).find( '#search-filters, #scroll-to-list' );
$( '#results' ).html( new_content );
$( 'html, body' ).animate({
scrollTop: $( '#scroll-to-list' ).offset().top
}, 1000);
}
});
});
Hope it helps someone.
I am using magento 1.8.1 and I am working on sms integration. I am trying to trigger a api url after clicking on placed order button. But as I new on magento I don't know where I put that url. After finding, I get these code of button
<div class="clear"></div>
<button style="float:left" onclick="oscPlaceOrder(this);"
id="onestepcheckout-button-place-order" type="button"
title="<?php echo $this->__('Place Order') ?>"
class="btn-proceed-checkout onestepcheckout-btn-checkout onestepcheckout-place">
<span>
<span><?php echo $this->__('Place order now') ?></span>
</span>
</button>
</div>
now here is one function oscPlaceOrder:
function oscPlaceOrder(element) {
var validator = new Validation('one-step-checkout-form');
var form = $('one-step-checkout-form');
if (validator.validate()) {
if (($('p_method_hosted_pro') && $('p_method_hosted_pro').checked) || ($('p_method_payflow_advanced') && $('p_method_payflow_advanced').checked)) {
$('onestepcheckout-place-order-loading').show();
$('onestepcheckout-button-place-order').removeClassName('onestepcheckout-btn-checkout');
$('onestepcheckout-button-place-order').addClassName('place-order-loader');
$('ajaxcart-load-ajax').show();
checkAjax('<?php echo $this->getUrl('onestepcheckout/index/saveOrderPro', array('_secure' => true)); ?>');
} else {
if (checkpayment()) {
element.disabled = true;
var already_placing_order = true;
disable_payment();
$('onestepcheckout-place-order-loading').show();
$('onestepcheckout-button-place-order').removeClassName('onestepcheckout-btn-checkout');
$('onestepcheckout-button-place-order').addClassName('place-order-loader');
//$('one-step-checkout-form').submit();
var options = document.getElementsByName('payment[method]');
for (var i = 0; i < options.length; i++) {
if ($(options[i].id).checked) {
if (options[i].id.indexOf("tco") != -1) {
var params = Form.serialize('one-step-checkout-form');
var request = new Ajax.Request(
'<?php echo $this->getCheckoutUrl() . 'isAjax/tco'; ?>',
{
method: 'post',
onComplete: this.onComplete,
onSuccess: function(transport) {
if (transport.status == 200) {
if (transport.responseText.isJSON) {
var response = JSON.parse(transport.responseText);
$('onestepcheckout-place-order-loading').style.display = 'none';
$('checkout-' + response.update_section.name + '-load').update(response.update_section.html);
$('onestepcheckout-button-place-order').removeAttribute('onclick');
$('onestepcheckout-button-place-order').observe('click', formsubmit());
$('onestepcheckout-button-place-order').disabled = false;
}
}
},
onFailure: '', //checkout.ajaxFailure.bind(checkout),
parameters: params
});
} else if (options[i].id.indexOf("wirecard") != -1) {
var params = Form.serialize('one-step-checkout-form');
var request = new Ajax.Request(
'<?php echo $this->getCheckoutUrl() . 'isAjax/wirecard'; ?>',
{
method: 'post',
onComplete: this.onComplete,
onSuccess: function(transport) {
var response = JSON.parse(transport.responseText);
if (response.url) {
window.location.href = response.url;
} else {
var payment_method = $RF(form, 'payment[method]');
var wireparams = {'paymentMethod': payment_method};
url = '<?php echo Mage::getBaseUrl() . 'wirecard_checkout_page/processing/wirecard_checkout_pagecheckout/'; ?>';
var wirerequest = new Ajax.Request(
qmoreIsIframe,
{
method: 'get',
parameters: wireparams,
onSuccess: function(innerTransport) {
if (innerTransport && innerTransport.responseText) {
try {
var innerResponse = eval('(' + innerTransport.responseText + ')');
}
catch (e) {
innerResponse = {};
}
if (innerResponse.isIframe)
{
toggleQMoreIFrame();
$('qmore-iframe').src = url;
} else {
window.location.href = url;
}
}
},
onFailure: ''
});
}
},
onFailure: '', //checkout.ajaxFailure.bind(checkout),
parameters: params
});
} else {
if(isUseAmazon() == false){
$('one-step-checkout-form').submit();
}
else{
<?php
if(Mage::helper('core')->isModuleEnabled('Amazon_Payments')){
$helperAmz = new Amazon_Payments_Helper_Data();
if(isset($helperAmz))
$checkoutUrl = $helperAmz->getCheckoutUrl(false);
}
?>
window.location.href = "<?php if(isset($checkoutUrl)) echo $checkoutUrl;?>";
}
}
break;
}
}
}
}
}
}
function checkAjax(url) {
var form = $('one-step-checkout-form');
var payment_method = $RF(form, 'payment[method]');
var shipping_method = $RF(form, 'shipping_method');
var parameters = {
payment: payment_method,
shipping_method: shipping_method
}
get_billing_data(parameters);
get_shipping_data(parameters);
if ($('giftmessage-type') && $('giftmessage-type').value != '') {
parameters[$('giftmessage-type').name] = $('giftmessage-type').value;
}
if ($('create_account_checkbox_id') && $('create_account_checkbox_id').checked) {
parameters['create_account_checkbox'] = 1;
}
if ($('gift-message-whole-from') && $('gift-message-whole-from').value != '') {
parameters[$('gift-message-whole-from').name] = $('gift-message-whole-from').value;
}
if ($('gift-message-whole-to') && $('gift-message-whole-to').value != '') {
parameters[$('gift-message-whole-to').name] = $('gift-message-whole-to').value;
}
if ($('gift-message-whole-message') && $('gift-message-whole-message').value != '') {
parameters[$('gift-message-whole-message').name] = $('gift-message-whole-message').value;
}
if ($('billing-address-select') && $('billing-address-select').value != '') {
parameters[$('billing-address-select').name] = $('billing-address-select').value;
}
if ($('shipping-address-select') && $('shipping-address-select').value != '') {
parameters[$('shipping-address-select').name] = $('shipping-address-select').value;
}
new Ajax.Request(url, {
method: 'post',
evalJS: 'force',
onSuccess: function(transport) {
// alert(JSON.parse(transport.responseText).url);
if (JSON.parse(transport.responseText).url == 'null' || JSON.parse(transport.responseText).url == null) {
$('ajaxcart-loading').style.display = 'block';
$('ajaxcart-loading').style.top = '15%';
$('ajaxcart-loading').style.left = '40%';
$('ajaxcart-loading').style.width = '551px';
$('ajaxcart-loading').style.height = '400px';
$('ajaxcart-loading').style.overflow = 'hidden';
$('ajaxcart-loading').style.padding = '5px';
$('ajaxcart-loading').innerHTML = JSON.parse(transport.responseText).html;
$('iframe-warning').style.textAlign = 'left';
}
else
{
window.location.href = JSON.parse(transport.responseText).url;
}
},
onFailure: function(transport) {
},
parameters: parameters
});
}
I think I have to put the url in this function, but where and how, I don't understand. So please help me
You can always use the getOrderPlaceRedirectUrl() In your payment module Model and return your url to redirect customer to external page.
An other alternative could be to use the authorize() and trig a curl to the external url.