This isn't a duplicate question by any means and I have tried a lot finding solutions.So, please read it before down voting.
Background:
This application is like a note-taking web app where you can post/delete your notes.
Each item in the list has an id which is needed when making a delete call.
In my application, I have to delete individual items from a list which is generated by looping over a JSON response (by a REST API) using PHP.The JSON response can be obtained after successful login.
Question:
To implement delete functionality I have to send id of each of the items as a parameter to the rest api delete call.
So, for this I have to generate dynamic links of the form :
http://localhost/myfolder/api/notes/:id
which should be passed to the delete.php function (Which I have implemented in CURL).
I searched for possible ways :
Using a PHP function: It seems to be complex, however if there is some way to invoke a PHP function (the delete code using CURL) on click of a link (Which I found not possible as per some answers ?) this could be a great solution.
Using Javascript: I have to call a function upon click of link that sets a variable $_SESSION["id"] to the current item["id"] and then goes to delete.php where I use the $_SESSION variable to first set up the link and then use the CURL code.
I tried basic implementation using the second approach but I have hit a roadblock in this issue. It would be great if you could tell with a bit of code which approach should be followed or any other way to do this ?
This functionality is present in twitter/facebook and almost every such service, how do they implement this, the basic approach should be the same, right: Generate dynamic links and pass them to a php script on click ?
Basic Javasript approach :
<script>
<script>
var el = document.getElementById('del1');
el.onclick = del1;
function del() {
// I have to set $_SESSION here
return false;
}
</script>
echo "<a href=\"delete.php\" title=\"Delete\" id=\"del1\">";
//Here, I have to pass the item["id"] to the javascript function.
I had tried some other ways but I have modified the code a lot so, I can't post them. Thanks for your help.
Regarding #2, you can't access the user's session from Javascript, so that will not work.
My preferred way (if using jquery) is to put the id in a data attribute of the delete button (or the block as a whole). Then in the delete onclick function do something like
<div class="block" data-itemid="<?=$item['id']?>">
...
<div class="delete_button">Delete</div>
</div>
...
$('.delete_button').on('click',function(event) {
block = $(event).target.parent('.block');
itemid = block.data('itemid');
$.post('delete.php',[itemid: itemid]...);
});
Related
I have a website entirely coded with PHP. Let's consider the simple example in which a PHP script generates HTML/CSS code from data about a list of fruits, fetched in a MySQL data base :
<?php
function displayFruit( $fruit ) {
echo('<div>');
echo('<span class="fruit-color">Coulor : '.$fruit['color'].'</span>');
...
// display some other parameters of the fruit, with maybe some complex styles, etc.
...
echo('</div>');
}
// Get infos from dabase
$fruits = getAllFruitsFromDatabase();
// Display infos
foreach( $fruits as $fruit ) {
displayFruit( $fruit );
}
?>
Now, I want to add interactivity and to allow the user to filter according to some fruits characteristics (color, etc.) so that only the corresponding fruits are displayed.
So I add some controls and link them to Javascript AJAX queries. These queries will return the same type of data (even though not the same format) as what getAllFruitsFromDatabase() returned, and I want this data to be displayed the same way displayFruit() displayed it.
However, the issue here is that the display/styling process will now have to occur on the client side and not anymore on the server side.
Is there a technical way to factorize the PHP code (the one of displayFruit() ) and the Javascript code that will have to be used, so that there only exists one place where the HTML display code is written (and not once in PHP, and once again in JS) ?
What you describe is a very common problem for interactive web apps and there is not really one 'correct' solution for it. : )
It really depends on what you want in terms of PHP-vs-JS balance, but here are two possible solutions that avoid duplication of the HTML rendering code:
1. Always create the mark-up in Javascript, even on the initial page load
This works well if you want the bulk of your code to be on the client-side. In this solution, you wouldn't have a displayFruit($fruit) function in PHP, but you'd have the equivalent in your Javascript. You would render your page 'frame' on page load, and then do your AJAX call on the document-ready event.
2. Always create the mark-up in PHP, even on the filter-AJAX calls
This is perhaps a more balanced approach and has the advantage that you could design your code such that it's possible to run even if the client has Javascript disabled.
One way to do this is to pass an optional parameter to your page rendering function (in the PHP code) that will make it render only the data part, e.g. something like this:
function renderPage($filters = false, $dataOnly = false)
{
if (!$dataOnly) {
// Output the top of the page
}
// Output the data
// If $filters is not false, the getFruitsFromDatabase call will return filtered data
$fruits = getFruitsFromDatabase($filters);
foreach( $fruits as $fruit ) {
displayFruit($fruit);
}
if (!$dataOnly) {
// Output the bottom of the page
}
}
When your PHP script is called via AJAX, you pass your filters to the first argument of the renderPage function and true to the second argument.
Note on front-end frameworks:
exussum and Michael Chaney have mentioned Javascript frameworks. While I haven't used any of those myself, they look fantastic!
So If you're ready to invest time in re-writing your display logic in JS, then go for it. However, if you don't have much time and would like to re-use as much of your original PHP code as possible, then I would go for solution number 2. The decision probably also depends on the size and design of your existing code.
EDIT: had forgotten to add a $filters argument to the example function
EDIT 2: comment on front-end frameworks mentioned by others in comments
Well i wanna create an Ajax Drag and Drop Shopping cart using only javascript and ajax. Currently i'm using the example in this page as a stepping stone. Right now it's only with local jquery and it works fine but i want to make the cart work with ajax calls. Note that i do not want to use a server side language( like php, rubby, asp etc), only html and javascript.
My initial thought was that at the $(".basket").droppable i should add an ajax call to another html page containing the "server logic" in javascript, execute in that file all the necessary steps( like reading the get variables (product name, product id and quantity), set a cookie and then return an ok response back. When the server got the "ok" response it should "reload" the cart div with the updated info stored inside the cookie.
If this was with php i would know how to do it. The problem is that as far as i know, you can execute javascript once it reaches the DOM, but how can you execute that js from inside the page that isbeing called upon ? ( thanks to Amadan for the correction)
I've thought about loading the script using $.getScript( "ajax/test.js", function( data, textStatus, jqxhr ).. but the problem with that is that the url GET variables i want to pass to the "server script" do not exist in that page.
I havent implemented all the functionality yet as i am stuck in how to first achieve javascript execution inside an ajax target page.
Below is a very basic form of my logic so far
// read GET variables
var product = getQueryVariable("product");
var id = getQueryVariable("id");
var quantity= getQueryVariable("quantity");
//To DO
//--- here eill go all the logic regarding cookie handling
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
alert('Query Variable ' + variable + ' not found');
}
Any help regarding this matter will be appreciated.
Note: Logic in simple words:
1)have an html page with products+cart
2)Have an "addtocart.html" with the "Cart Server Logic"( being the target of the ajax call when an item is dropped into the product.)
If you have some other idea on this, please enlighten me :)
thanks in advance
Foot Note-1:
if i try loading the scipt using
$("#response").load("ajax/addtocart.html?"+ $.param({
product: product,
id: id,
quantity:quantity
})
);
i get the alert about not being able to find the url parameters( something that i thing is normal as because the content is being loaded into the initial page, from which the request is started, there are no get parameters in the url in the first place)
The problem is that as far as i know, you cannot execute javascript contained in the target of an ajax call, as that page never reaches the browser interpreter.
This is either incorrect or misleading. The browser will execute any JavaScript that enters DOM. Thus, you can use $.load to load content and execute code at the same time. Alternately, you can use hacked JSONP to both execute code and also provide content as a JSON document.
EDIT: Yes, you can't get to the AJAX parameters from JavaScript. Why do you want to? Do you have a good reason for it, or is it an XY problem?
The way I'd do it is this:
$('#response').load(url, data, function() {
onAddedToCart(product, id, quantity);
});
and wrap your JS code in your HTML into the onAddedToCart function.
Depending on what exactly you're doing, it could be simplified even further, but this should be enough to cover your use case.
I am not sure if I worded my question correctly. I'm not actually sure how to go about this at all.
I have a site load.html. Here I can use a textbox to enter an ID, for example 123, and the page will display some information (retrieved via a Javascript function that calls AJAX from the Flask server).
I also have a site, account.html. Here it displays all the IDs associated with an account.
I want to make it so if you click the ID in account.html, it will go to load.html and show the information required.
Basically, after I press the link, I need to change the URL to load.html, then call the Javascript function to display the information associated with the ID.
My original thoughts were to use variable routes in Flask, like #app.route('/load/<int:id>') instead of simply #app.route('/load')
But all /load does is show load.html, not actually load the information. That is done in the Javascript function I talked about earlier.
I'm not sure how to go about doing this. Any ideas?
If I need to explain more, please let me know. Thanks!
To make this more clear, I can go to load.html and call the Javascript function from the web console and it works fine. I'm just not sure how to do this with variable routes in Flask (is that the right way?) since showing the information depends on some Javascript to parse the data returned by Flask.
Flask code loading load.html
#app.route('/load')
def load():
return render_template('load.html')
Flask code returning information
#app.route('/retrieve')
def retrieve():
return jsonify({
'in':in(),
'sb':sb(),
'td':td()
})
/retrieve just returns a data structure from the database that is then parsed by the Javascript and output into the HTML. Now that I think about it, I suppose the variable route has to be in retrieve? Right now I'm using AJAX to send an ID over, should I change that to /retrieve/<int:id>? But how exactly would I retrieve the information, from, example, /retrieve/5? In AJAX I can just have data under the success method, but not for a simple web address.
Suppose if you are passing the data into retrieve from the browser url as
www.example.com/retrieve?Data=5
you can get the data value like
dataValue = request.args.get('Data')
You can specify param in url like /retrieve/<page>
It can use several ways in flask.
One way is
#app.route('/retrieve/', defaults={'page': 0})
#app.route('/retrieve/<page>')
def retrieve():
if page:
#Do page stuff here
return jsonify({
'in':in(),
'sb':sb(),
'td':td()})
Another way is
#app.route('/retrieve/<page>')
def retrieve(page=0):
if page:
#Do your page stuff hear
return jsonify({
'in':in(),
'sb':sb(),
'td':td()
})
Note: You can specify converter also like <int:page>
I have a script that loads the code dynamically. It is kind of a search engine. When I press a search button, the action gets triggered and a new page opens with many parameters.
I want to override one of the parameters generated with the script in the new URL. JS code is quite big and hard to read, but I have found the important part in the Firebug DOM editor.
This is the pattern of the URL generated when you perform the search:
http://www.example.com/...?ParameterOne=123&ParameterTwo=Two&ThisParameter=Sth&ParameterFour=Four...
What I want to edit is "ThisParameter" and change its value. This is the part edited in the DOM that does what I want:
Foobar = {
_options: [],
...
var options = {"ParameterOne":123,"ParameterTwo":"Two","ThisParameter":"ABC","ParameterFour":Four,...}
...
And this is the output of "ThisParameter" when you choose "Copy path" in Firebug's DOM tab:
_options[0].ThisParameter
I am wondering it this is possible at all. What makes me think that it is, is the fact that I can change this parameter in Firebug and it works perfectly. So, if Firebug can edit it, there should be a way to influence it with another script.
Looking forward to any suggestions, thank you in advance!
Since you cannot edit the dynamic script you have the following options:
You have to try to give the script the correct input and hope it uses your value.
Add a script to the results page which will read the url and arguments, change it and redirect, as we discussed here. (If you put everything in functions it should not conflict with the dynamic script if the functions are uniquely named.)
You could try adding something like this jQuery code to the page with the search button:
$('input[name=search_button_name]').click(function(e) {
e.preventDefault();
var form_search = $('#search_form_id');
$('<input>').attr({
type: 'hidden',
name: 'ThisParameter',
value: 'SomethingElse'
}).appendTo(form_search);
f.submit();
});
You can override any js function and method, or wrap you code around it. The easiest thing would be to look at the code you get and once it gets loaded, you re-declare a method with your own functionality.
I you are trying to replace a parameter in a specific jquery request, you can even wrap around the jquerys ajax method:
var jquery_ajax = $.ajax
$.ajax = function(options){
// parse only a specific occurence
if(options.url.indexOf("example.com") > -1) {
// change the url/params object - depending on where the parameter is
options.params.ThisParameter = "My Custom value"
}
// call the original jquery ajax function
jquery_ajax(options);
}
But it would be a lot cleaner to override the method that builds the ajax request rather than the ajax request itself.
I would investigate further on the scope of the variable options (var options), is it global? i.e. if you type 'options' in the Firebug console, does it display its properties?
If so, you could then access it via your own script and change is value, e.g.
options.ThisParameter = 'my-own-value';
You might hook your script to the click event of the search button.
I hope this helps, it could be more specific maybe if you have some sample code somewhere.
I have a view where ill have 3 divs:
Div 1: List of Brands with checkboxs.
Div 2: List of Categories with checkboxs.
Div 3: List of Items.
This last div will be refreshed with the all the items according to what is selected in the first two divs. At beginning it shows all the items, after we select some of the brands and/or categories and press refresh i'll want to refresh the div 3.
In Javascript I can get which of the categories/brands are selected and my biggest doubt is on how to refresh the last div...
Heres what I was trying:
function refresh() {
var brands= /*<code where i get all the brands selected (this will be a js array)>*/
var categories = /*<code where i get all the categories selected (this will be a js array)>*/
<?php echo $ajax->remoteFunction(array('url' => array('controller' => 'items',
'action' => 'men', brands, categories),
'update' => 'itemsContent')); ?>
}
My problems are:
- How do I pass the js vars into the php method?
- How do I receive an js array in a cakephp action? Because brands and categories will be used to filter the query that produce results for the div 3...
You won't be able to use the $ajax helper here, since it just outputs a static script which can't be changed/influenced at "run-time" in the browser. It just wasn't made for something more complex than it is.
So, you'll have to roll your own JS, which shouldn't be that hard though. All you need is:
a Cake action that outputs a list of items based on the data it receives (shouldn't be hard)
a bit of JS that figures out which brands and categories are selected (which you already have)
another bit of JS that packages that data and sends it to the Cake action
another bit of JS that updates the site with the list of items you received back
I'd take a look at jQuery's AJAX functions to accomplish #3. If you POST the data in a format like this, it's very easily accessible in $this->data in Cake:
{
'data[ModelName][categories]' : categories,
'data[ModelName][brands]' : brands
}
Regarding your question:
"How do I pass the js vars into the php method?"
You don't. PHP runs on the server and is already finished by the time the Javascript runs in the browser. The only "communication" between JS and PHP is via standard HTTP GET and POST requests, and there it doesn't matter whether the request comes from a standard browser or JS or Flash or whatnot.
The $ajax helper just has a bunch of pre-fabricated Javascript snippets it can put into your page, but your JS will not be able to "talk to" the $ajax helper in any way.
I had a similar scenario to yours, and I found a few methods on the Javascript helper that are applicable. I used codeBlock() to wrap a chunk of javascript, and event() to wire up the click event, but I'm not sure how much clearer this is than just writing the raw Javascript.
I found the AJAX section of the CakePHP manual to be really helpful for getting the basic set up. Then I took the generated Javascript and made it more dynamic.
In this example, I'm calling the add_topic action whenever the user clicks the link. Every time it gets called, I increment the topicIndex variable and pass it as a parameter in the AJAX call. The AJAX call returns a few rows that are inserted in the table above the link that the user clicked.
<tr id="add_topic_row"><td colspan="3">
<a id="add_topic_link" href="javascript:void(0);">New Topic
<?php echo $html->image('icons/add32.png');?></a></td></tr>
</table>
</fieldset>
<?php
echo $form->end('Submit');
$addTopicUrl = $html->url(array('action' => 'add_topic')) . '/';
$script = <<<EOS
var topicIndex = $index;
var addTopicUrl = '$addTopicUrl';
addTopic = function()
{
new Ajax.Updater(
'add_topic_row',
addTopicUrl + topicIndex,
{
asynchronous:true,
evalScripts:true,
insertion:Insertion.Before,
requestHeaders:['X-Update', 'add_topic']
});
topicIndex++;
}
EOS;
echo $javascript->codeBlock($script);
echo $javascript->event('add_topic_link', 'click', 'addTopic();')
?>