I've been searching for a way to take the user to a random page when they press a button with JavaScript/jQuery. Everything I've seen has all the pages in an array, and then uses a script to randomly choose an index.
Would it be possible to do something like this without adding all the pages into an array. I don't want to sit there and add every page/image in the directory to a large array and then have the script run, I just want it to go through the appache directory list and grab something by itself.
Can this be done? I know we're supposed to include code we have so far, but this is more of a conceptual question.
Use ajax to get your link:
$.ajax({
method: "GET",
url: "/getRandomLink", // I don't know which server side language you're using, I presume its PHP
dataType: "text", // text will be enought if it only returns a link
success: function(link) {
window.location.href = link;
}
});
Then put this inside an event of your choice. Nice and easy.
UPDATE
The return of your service must be a string with the link. I'm suposing you're using PHP, so will be something like:
<?php
$randomLink = "";// Code to get the random link here
echo $randomLink; // e.g.: http://www.google.com/
?>
Something needs to provide the list of files for your script to randomly choose from. That's going to be either a pregenerated array or an ajax request.
These would work:
Apache directory listing as json
how to get file listing using jquery ajax
...but for your purposes it would make more sense for your server side script to just return a single randomly selected file, instead of using bandwidth for the whole list only for the client to discard all but one.
Edit to reflect the comment given by the OP. Pardon the jQuery.
Assuming the directory index you've got is a standard Apache Auto-Index page:
//jQuery doc.ready, because I'm too lazy to do something better ;)
$(function () {
var links = [];
$.ajax(
{
//url: location.pathname, // Use current page
url: '/directoryname/', //directory index of your choice
success: saveAjaxedLinks
}
);
function saveAjaxedLinks (data, e) {
// Scrape anchors off of page.
// Note -- there might be other anchors on the page
// that you don't want to pick up, say the "up a directory level" anchors.
// you can filter those out if you want, but you'll have to determine the criteria for doing so.
var directory = $('a', data);
//Get anchor nodes and store them.
links = directory.get();
//Assign event listener to button after the data is ready.
$('button#yourbuttonid').on( 'click', onclickGetRandomPage );
//uncomment to do action immediately.
//onclickGetRandomPage();
}
function onclickGetRandomPage (e) {
if ( !!e && !!e.preventDefault ) {
e.preventDefault();
}
//if no links on the index, do nothing.
if ( !links.length ) return;
//Get the a random index from the links.
var rnd = Math.floor( Math.random()*links.length);
for (var i = 0, len = links.length; i < len; i++ ) {
// Make sure there's an actual href inside the random link.
// Also, check to make sure the links arent just hashes. Not necessary if you're just using an apache auto-index.
// If there are certain types of links you don't want (eg. directory roots), you can filter them out here.
if ( !!links[rnd].href && links[rnd].href.replace( links[rnd].hash, '' ) !== (location.href.replace( location.hash, '' ) ) ) {
//console.log(links[rnd].href); //Log out the links if you're just testing
window.location.href = links[rnd].href;
break;
} else {
//That link was no good, get a different one.
rnd = Math.floor( Math.random()*links.length );
}
}
}
});
Related
I found this article by the plugin author: https://contactform7.com/redirecting-to-another-url-after-submissions/ but the problem is that it redirects to a URL that is known beforehand. I need to know the URL as a response from the server, because the redirect URL will depend on the submitted values.
I can log the event:
document.addEventListener('wpcf7mailsent', function(event) {
console.log(event);
}, false);
But I am not at all sure how much of the data is provided by the server and how much by the client script. I tried altering the submission like this:
add_action('wpcf7_posted_data', 'alter_input');
function alter_input($data) {
$data['your-message'] = 'Something totally different here.';
}
But my alteration seems to have no effect on what data the event object contains. I have trouble finding where exactly the response (if any) is formulated and what filters or actions apply.
EDIT: I reworded the question; too many answers and comments get stuck into the why, which is irrelevant, or try to suggest "other approaches", which isn't what I asked, instead of just sticking to the how.
you may try this :
document.addEventListener( 'wpcf7submit', function( event ) {
var inputs = event.detail.inputs;
for ( var i = 0; i < inputs.length; i++ ) {
if ( 'name-of-the-field' == inputs[i].name ) {
//make your test on inputs[i].value and rediret
}
}
}, false );
They say
The simplest way is utilizing Contact Form 7’s custom DOM event to run
JavaScript. The following is an example of script that redirects you to another
URL when the wpcf7mailsent event occurs:
<script>
document.addEventListener( 'wpcf7mailsent', function( event ) {
location = 'http://example.com/';
}, false );
</script>
but they don't offer any access to the server response.
The only solution would require you to add in the server response under the onSentOk a javascript string (a serialized object) which will be evaluated line by line.
They say in scripts.js:
if ( data.onSentOk ) {
$.each( data.onSentOk, function( i, n ) { eval( n ) } );
}
so in rest-api.php instead of:
if ( ! empty( $result['scripts_on_sent_ok'] ) ) {
$response['onSentOk'] = $result['scripts_on_sent_ok'];
}
you have to add your url logic, something like:
$response['onSentOk'] = array('top.location.href="' . $cutomUrl .'";');
But again, this plugin wasn't designed to do anything with the server response ;)
Update
Another solution, since you may not have access to plugin files, is to make a second ajax request, this time to one script that is yours:
document.addEventListener('wpcf7mailsent', function(event) {
$.ajax({
url: 'your_scrit.php',
data: sameData,
success: function(response){
// do your redirect
}
});
}, false);
I had the same issue and none of the answers above were helpful. Actually this is feasible, you may follow the below code (add it to functions.php):
add_filter( 'wpcf7_ajax_json_echo', 'filter_wpcf7_ajax_json_echo', 10, 2 );
function filter_wpcf7_ajax_json_echo( $items, $result ) {
$items['foo'] = 'bar';
return $items;
};
You will then be able to access the new element with the below javascript code:
document.addEventListener( 'wpcf7mailsent', function( event ) {
console.log( event.detail.apiResponse.foo );
}, false );
By the way, you may want to use the event wpcf7mailsent over wpcf7submit as suggested in some answers as wpcf7mailsent will fire only if the form is successfully submitted (eg. all required fields are filled properly) which is not the case of wpcf7submit.
Well, I managed to find what I was looking for. The AJAX request to the server returns actually only three variables, eg:
{
into:"#wpcf7-f19-p59-o1",
message:"An error occurred. Please try again later.",
status:"mail_failed"
}
So no luck there. There is no hook or filter to modify the response serverside, to add more variables. And even if there was a way, the clientside javascript is not coded in such a way that it would be easy to overwrite singular methods to achieve the functionality that I want. It would require an ugly copy pasta of hundreds of lines to change just a couple little things.
Thus my verdict is that this is not doable, at least not for now, unless the plugin author decides to make some changes that could accommodate this kind of functionality, wink wink. I'll just implement a form processing action myself. That'll be less work.
Lets take a look here: http://www.pepco.pl/sklepy
When you click one particular shop, there appears window with opening hours and address. In site source I can see that there is javascript function. Is it possible to get all those data using javascript function without having to click on every shop? I need this for informational purposes.
When you click on a shop, there s a Ajax call which request the specific informations.
Try to use this url for your purposes.
var count = 244,
$output = $('#output');
for (var i = 0; i < count; i++) {
$.ajax({
url: 'http://www.pepco.pl/web/ajax/sites.city.php?param='+i+'&date_format=Y-m-d',
})
.done(function(data) {
$output.append($("<div class='item'>"+data+"</div>"));
})
.fail(function() {
$output.append($("<div class='item'>error</div>"));
});
}
Because of crossdomain policy you cant use this from any other page. A curl solution could work
I'm trying to put together a script that will add to the concept of load, and extend it outward in a fashion that load can be called to multiple pages, in search of instances of a div.
For example, consider the code below:
<div class="loadStuffHere">
</div>
$('.loadStuffHere').load('/wiki.htm .posts');
So, the code above works just fine, but I'm not sure how to get it to search more than one page at a time.
The second page I would need to search in this case would be: /wiki.htm?b=1&pageindex=2. After the script searches the first page, then it would need to search the second. After the second page is searched, then the script would need to first auto increment the number 2, and change it to a three, and search that page, and then continue to do so, until it hits a page that doesn't exist, and then return false and end it's execution. So the search and load process would consist of this:
/wiki.htm
/wiki.htm?b=1&pageindex=2
/wiki.htm?b=1&pageindex=3
/wiki.htm?b=1&pageindex=4
/wiki.htm?b=1&pageindex=5
/wiki.htm?b=1&pageindex=6
And it would continue in that manor, until it hits a page that doesn't exist yet, as this is a pagination system.
Is this something that can be done, and if so, what would it look like?
Any help is very appreciated!
P.s. If you are thinking I'm likely attempting something that would be easier achieved with some server side coding, you are right. I don't have access to it however, regretfully.
You could do something like:
function loadWikiPosts(page_index) {
if (page_index != null) { url += '?b=1&pageIndex='+page_index; }
else { page_index = 1; /* for next time if this one fails */ }
url += ' .posts'; // to grab just the posts
// Send the AJAX request
$('.loadStuffHere').load(url, function(response, status, request) {
if (status == "error") { console.log(response); throw "Load returned an error"; }
if ($('.loadStuffHere').find('.posts').length == 0) {
page_index++;
loadWikiPosts(page_index);
}
});
}
try {
loadWikiPosts();
} catch (exception) {
// do something w/the exception message
}
Create an array with all your results, using the following code:
JavaScript/jQuery
var linkArray=["/wiki.htm",
"/wiki.htm?b=1&pageindex=2",
"/wiki.htm?b=1&pageindex=3",
"/wiki.htm?b=1&pageindex=4",
"/wiki.htm?b=1&pageindex=5",
"/wiki.htm?b=1&pageindex=6"];
for (var i in linkArray)
{
var content = "";
$('.loadStuffHere').append($(content).load(linkArray[i]+' .posts'));
}
The code above was not tested.
I have two HTML pages that work in a parent-child relationship in this way:
The first one has a button which does two things: First it requests data from the database via an AJAX call. Second it directs the user to the next page with the requested data, which will be handled by JavaScript to populate the second page.
I can already obtain the data via an ajax call and put it in a JSON array:
$.ajax({
type: "POST",
url: get_data_from_database_url,
async:false,
data: params,
success: function(json)
{
json_send_my_data(json);
}
});
function json_send_my_data(json)
{
//pass the json object to the other page and load it
}
I assume that on the second page, a "document ready" JavaScript function can easily handle the capture of the passed JSON object with all the data. The best way to test that it works is for me to use alert("My data: " + json.my_data.first_name); within the document ready function to see if the JSON object has been properly passed.
I simply don't know a trusted true way to do this. I have read the forums and I know the basics of using window.location.url to load the second page, but passing the data is another story altogether.
session cookie may solve your problem.
On the second page you can print directly within the cookies with Server-Script tag or site document.cookie
And in the following section converting Cookies in Json again
How about?
Warning: This will only work for single-page-templates, where each pseudo-page has it's own HTML document.
You can pass data between pages by using the $.mobile.changePage() function manually instead of letting jQuery Mobile call it for your links:
$(document).delegate('.ui-page', 'pageinit', function () {
$(this).find('a').bind('click', function () {
$.mobile.changePage(this.href, {
reloadPage : true,
type : 'post',
data : { myKey : 'myVal' }
});
return false;
});
});
Here is the documentation for this: http://jquerymobile.com/demos/1.1.1/docs/api/methods.html
You can simply store your data in a variable for the next page as well. This is possible because jQuery Mobile pages exist in the same DOM since they are brought into the DOM via AJAX. Here is an answer I posted about this not too long ago: jQuery Moblie: passing parameters and dynamically load the content of a page
Disclaimer: This is terrible, but here goes:
First, you will need this function (I coded this a while back). Details here: http://refactor.blog.com/2012/07/13/porting-javas-getparametermap-functionality-to-pure-javascript/
It converts request parameters to a json representation.
function getParameterMap () {
if (window.location.href.indexOf('?') === (-1)) {
return {};
}
var qparts = window.location.href.split('?')[1].split('&'),
qmap = {};
qparts.map(function (part) {
var kvPair = part.split('='),
key = decodeURIComponent(kvPair[0]),
value = kvPair[1];
//handle params that lack a value: e.g. &delayed=
qmap[key] = (!value) ? '' : decodeURIComponent(value);
});
return qmap;
}
Next, inside your success handler function:
success: function(json) {
//please really convert the server response to a json
//I don't see you instructing jQuery to do that yet!
//handleAs: 'json'
var qstring = '?';
for(key in json) {
qstring += '&' + key + '=' + json[key];
qstring = qstring.substr(1); //removing the first redundant &
}
var urlTarget = 'abc.html';
var urlTargetWithParams = urlTarget + qstring;
//will go to abc.html?key1=value1&key2=value2&key2=value2...
window.location.href = urlTargetWithParams;
}
On the next page, call getParameterMap.
var jsonRebuilt = getParameterMap();
//use jsonRebuilt
Hope this helps (some extra statements are there to make things very obvious). (And remember, this is most likely a wrong way of doing it, as people have pointed out).
Here is my post about communicating between two html pages, it is pure javascript and it uses cookies:
Javascript communication between browser tabs/windows
you could reuse the code there to send messages from one page to another.
The code uses polling to get the data, you could set the polling time for your needs.
You have two options I think.
1) Use cookies - But they have size limitations.
2) Use HTML5 web storage.
The next most secure, reliable and feasible way is to use server side code.
Background
I'm writing an asynchronous comment system for my website, after reading plenty of tutorials on how to accomplish this I started building one from scratch. The comments are pulled using a JSON request and displayed using Javascript (jQuery). When the user adds a new comment it goes through the hoops and finally is sent via AJAX to the backend where it's added to the database. In the success section of the AJAX request I had the script empty the comments, then repull the new list (including the new post) and redisplay them.
Problem
While that was all nice, since it's making the page much shorter, then much longer it messes up where the user is viewing the page. I wanted to have it readjust the page back down to the end of the comment list (where the add comment form is). It also re-enables the add button, which was disabled when the clicked it to prevent impatient people from spamming.
$('#commentList').empty();
getComments('blog', $('input#blogId').val());
window.location = "#addComment";
$('#comAdd').removeAttr('disabled');
While this worked all well and good in theory, it seemed that the browser was getting ahead of itself and processing the window.location before the getComments function was done. So I read a little more and googled it and it seemed people were saying (for similar problems) to use callback functions, so I came up with this:
$('#commentList').empty();
getComments('blog', $('input#blogId').val(), function() {
window.location = "#addComment";
$('#comAdd').removeAttr('disabled');
});
This generates no javascript errors according to FireFox, but nothing within the callback function is working, it's not re-enabling the button nor changing the window.location.
Any ideas? Better ways to go about it? Do I have a glaring typo that I can't seem to see?
Thanks!
Update
I was under the impression the callback functions were a standard thing you could use.
function getComments(type, id)
{
$.getJSON("/ajax/"+type+"/comments?jsoncallback=&id="+id, function(data) {
for (var x = 0; x < data.length; x++)
{
var div = $("<div>").addClass("comment").appendTo("#commentList");
var fieldset = $("<fieldset>");
var legend = $("<legend>").addClass("commentHeader");
if ( data[x].url == "" )
{
legend.text((x+1) + ' - ' + data[x].name);
}
else
{
$("<a>").attr({href: data[x].url}).text((x+1) + ' - ' + data[x].name).appendTo(legend);
}
legend.appendTo(fieldset);
$("<div>").addClass("date").text(data[x].timestamp).appendTo(fieldset);
$("<p>").addClass("comment").text(data[x].content).appendTo(fieldset);
fieldset.appendTo(div);
}
});
}
This is called on document ready. Pulling all the comments and displaying them inside the #commentList div. When the user submits his/her comment it performs an AJAX request to a PHP script that adds the new comment to the database, upon success of this I have this:
$('#commentList').empty();
getComments('blog', $('input#blogId').val());
window.location = "#addComment";
$('#comAdd').removeAttr('disabled');
Deletes all the comments from the page.
Uses JSON to request the comments again (including the users new one).
Moves the page to the #addComment anchor, which is where their new comment would be displayed.
Re-enables the add comment button.
The problem is that the browser does the window.location line before the getComments function is done rendering all the comments, so as the page grows the user isn't looking anywhere near their new comment.
I expect here the problem is your getComments() function (for which more detail is required). You're supplying a third argument being a callback but does the function actually use a callback? What is it doing?
Certain jQuery functions provide callbacks but this isn't an automatic feature. If you're waiting for a user to type a comment you need to trigger the relevant event when they click "Done" or whatever they do.
Ok, try this:
function get_comments(type, id, callback) {
$.getJSON("/ajax/"+type+"/comments?jsoncallback=&id="+id, function(data) {
for (var x = 0; x < data.length; x++) {
var div = $("<div>").addClass("comment").appendTo("#commentList");
var fieldset = $("<fieldset>");
var legend = $("<legend>").addClass("commentHeader");
if ( data[x].url == "" ) {
legend.text((x+1) + ' - ' + data[x].name);
} else {
$("<a>").attr({href: data[x].url}).text((x+1) + ' - ' + data[x].name).appendTo(legend);
}
legend.appendTo(fieldset);
$("<div>").addClass("date").text(data[x].timestamp).appendTo(fieldset);
$("<p>").addClass("comment").text(data[x].content).appendTo(fieldset);
fieldset.appendTo(div);
if (typeof callback != 'undefined') {
callback();
}
}
});
}
Note: the difference here is that a third argument is supplied to get_comments() which is a callback that'll be called at the end of your $.getJSON() callback. That'll give you the proper ordering you want.
I might also suggest not constructing the HTML like that but including it in your page and hiding/unhiding it as necessary. It tends to be much more performant that dynamic HTML and have less issues (eg new HTML, unless you use $().live() will not have relevant event handlers).
Edit: Made the callback optional as per the comments. With the above code you can call the function without or without the callback.
Simple. Re-enable the button and go to the anchor after you receive the request and process the information. Like so:
function getComments(type, id)
{
// ADDED
$('#commentList').empty();
$.getJSON("/ajax/"+type+"/comments?jsoncallback=&id="+id, function(data) {
for (var x = 0; x < data.length; x++)
{
var div = $("<div>").addClass("comment").appendTo("#commentList");
var fieldset = $("<fieldset>");
var legend = $("<legend>").addClass("commentHeader");
if ( data[x].url == "" )
{
legend.text((x+1) + ' - ' + data[x].name);
}
else
{
$("<a>").attr({href: data[x].url}).text((x+1) + ' - ' + data[x].name).appendTo(legend);
}
legend.appendTo(fieldset);
$("<div>").addClass("date").text(data[x].timestamp).appendTo(fieldset);
$("<p>").addClass("comment").text(data[x].content).appendTo(fieldset);
fieldset.appendTo(div);
}
// ADDED
window.location = "#addComment";
$('#comAdd').removeAttr('disabled');
});
}
Personal opinion: rather than fetching all comments, why not fetch comments from a certain date? When you load the page, include a server time in the response. The Javascript uses this to query behind the scenes (to automatically check for new comments). The JSON response includes a new server time, which is used in the next response.
How would you handle deleted comments? Easy: have a deleted_on column in your database table, query it, and spit that out in the JSON response along with new posts.
Suggestion: instead of #addcomment, ID comments by timestamp.