I have a form that is a drop down select list.
I also have an action, that looks for the request parameter:
indexAction:
if($this->getRequest()->isXmlHttpRequest())
{
$this->setLayout('layout');
}
$param = $this->getRequestParameter('type');
if($param == 'video')
{
isicsBreadcrumbs::getInstance()->addItem('All Videos', '#homepage');
$pager = new sfPropelPager('Item', 15);
$pager->setPage($request->getParameter('page', 1));
$pager->setPeerMethod('doSelectLatestVideo');
$pager->init();
$this->pager = $pager;
}
elseif($param == 'photo')
{
isicsBreadcrumbs::getInstance()->addItem('All Photos', '#homepage');
$pager = new sfPropelPager('Item', 15);
$pager->setPage($request->getParameter('page', 1));
$pager->setPeerMethod('doSelectLatestPhoto');
$pager->init();
$this->pager = $pager;
}
}
Now this works fine when the url is: example.com?type=video - it loads the video content
The problem is, I'm wanting to update the content using AJAX and because I'm doing it via AJAX, I'm struggling to get the requestParamater, since it is no longer in mu URL;
ajax function:
$("#filter-form-newsroom .submit").live('click', function(e){
$("#search-results").html(ajax_loading);
var content_type = $("#filter-form-newsroom #type").val();
$.ajax(
{
url: "",
type: "GET",
data: "?type=" + content_type,
success: function(data){
var $response=$(data);
var filtered_response = $response.find('.post');
$("#search-results").html(filtered_response).hide().fadeIn("fast");
}
});
e.preventDefault();
});
This function checks the parameter in my select list and is supposed to filter by the requestParamter, but it isn't working.
Any ideas?
Thanks
Rather than putting ?type=" into the data property, put it in the url. Wouldn't that result in the same request you get when you type the URL yourself?
Related
I am using Codeigniter 4 with csrf active.
I have tried to make Search form with the table will load without loading on page.
It is success on first attempt, but another response--which is token_value get undefined. And if I tried to search for the second time it get error 403 Forbidden.
Here is my jquery looks like:
$("#btnSearch").click(function(){
$.post("vendor/search",
{
"searchByCode":$("input[name='searchByCode']").val(),
"<?= csrf_token() ?>" : "<?= csrf_hash() ?>"
},
function(data, status){
alert(data.token_value);
$("#table_vendors").html(data);
});
});
and this is my related Controller looks like
public function search()
{
$result = $this->vendors;
if ($this->request->getPost('searchByCode')) {
$result->like('code', $this->request->getPost('searchByCode'));
};
$data = [
'vendors' => $result->paginate(10, 'vendors'),
'page' => $result->pager,
'token_value' => csrf_hash()
];
return view('vendors/_vendors', $data);
}
This is what happen when I click search for a second time.
I wish I could do re-search with my code above without refreshing page.
Try this in your JS:
// Courtesy of W3Schools :o)
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i = 0; i <ca.length; i++) {
var c = ca[i];
while (c.charAt(0)==' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length,c.length);
}
}
return "";
}
function resetCSRF(){
$('input[name="csrf_cookie_name"]').val(getCookie('csrf_cookie_name'));
}
Assuming your cookie name is csrf_cookie_name then call resetCSRF() after each form submit. This code will get the latest Cookie value and set it in the form and should allow you to resubmit without refreshing.
I'm working on a webapplication in Symfony2. At the moment I have several pages that include a search form where you can search for specific entities that belong to that page.
For example; I have a client page with an overview of client information. Here you can search for clients with a name like your search value. Thats no rocket science I guess.
At the front page I want to somehow search all my entities at once. I was thinking about combining the searches I already have, or maybe there is a function in Symfony that allows this?
Here's some of my code for the search(es) I have so far:
Live search action for clients:
public function liveSearchAction(Request $request)
{
$string = $this->getRequest()->request->get('sQuery');
$clients = $this->getDoctrine()
->getRepository('clientsBundle:client')
->findByLetters($string);
$response = new JsonResponse(array('clients' => $clients));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
The repository function findByLetters:
public function findByLetters($string){
$query = $this->getEntityManager()
->createQuery(
'SELECT c FROM clientsBundle:client c
WHERE c.name LIKE :string'
)->setParameter('string', '%'.$string.'%');
$result = $query->getArrayResult();
return $result;
}
The AJAX call for returning searchresults
(function($, Handlebars, window, document, undefined) {
var that = this;
var oXHR;
var source = $("#searchResult").html();
var template = Handlebars.compile(source);
var action = $('#quickSearch').data('action');
var route = $('#quickSearch').data('route');
Handlebars.registerHelper('url', function(options) {
console.log(this, options);
return new Handlebars.SafeString(
Routing.generate(route, {'id': this.id})
);
});
$('#quickSearch').on('input',function() {
var $this = $(this);
var searchText = $this.val();
console.log('searching for: ' + searchText);
if (typeof oXHR !== 'undefined') {
oXHR.abort();
}
oXHR = $.ajax({
type: "POST",
url: action,
dataType: "json",
data: {
sQuery : searchText
},
success: function(response)
{
var html = template(response);
// console.log(html);
$('#list .list-group').html(html);
},
error: function(failresponse)
{
console.log( failresponse );
}
});
});
}).call(window.Test = window.Test || {}, jQuery, Handlebars, window, document);
As you might have noticed, the return of the AJAX call gets handled by handlebars.
Admittedly, there are similar questions lying around on Stack Overflow, but it seems none quite meet my requirements.
Here is what I'm looking to do:
Upload an entire form of data, one piece of which is a single file
Work with Codeigniter's file upload library
Up until here, all is well. The data gets in my database as I need it. But I'd also like to submit my form via an AJAX post:
Using the native HTML5 File API, not flash or an iframe solution
Preferably interfacing with the low-level .ajax() jQuery method
I think I could imagine how to do this by auto-uploading the file when the field's value changes using pure javascript, but I'd rather do it all in one fell swoop on for submit in jQuery. I'm thinking it's not possible to do via query strings as I need to pass the entire file object, but I'm a little lost on what to do at this point.
Can this be achieved?
It's not too hard. Firstly, take a look at FileReader Interface.
So, when the form is submitted, catch the submission process and
var file = document.getElementById('fileBox').files[0]; //Files[0] = 1st file
var reader = new FileReader();
reader.readAsText(file, 'UTF-8');
reader.onload = shipOff;
//reader.onloadstart = ...
//reader.onprogress = ... <-- Allows you to update a progress bar.
//reader.onabort = ...
//reader.onerror = ...
//reader.onloadend = ...
function shipOff(event) {
var result = event.target.result;
var fileName = document.getElementById('fileBox').files[0].name; //Should be 'picture.jpg'
$.post('/myscript.php', { data: result, name: fileName }, continueSubmission);
}
Then, on the server side (i.e. myscript.php):
$data = $_POST['data'];
$fileName = $_POST['name'];
$serverFile = time().$fileName;
$fp = fopen('/uploads/'.$serverFile,'w'); //Prepends timestamp to prevent overwriting
fwrite($fp, $data);
fclose($fp);
$returnData = array( "serverFile" => $serverFile );
echo json_encode($returnData);
Or something like it. I may be mistaken (and if I am, please, correct me), but this should store the file as something like 1287916771myPicture.jpg in /uploads/ on your server, and respond with a JSON variable (to a continueSubmission() function) containing the fileName on the server.
Check out fwrite() and jQuery.post().
On the above page it details how to use readAsBinaryString(), readAsDataUrl(), and readAsArrayBuffer() for your other needs (e.g. images, videos, etc).
With jQuery (and without FormData API) you can use something like this:
function readFile(file){
var loader = new FileReader();
var def = $.Deferred(), promise = def.promise();
//--- provide classic deferred interface
loader.onload = function (e) { def.resolve(e.target.result); };
loader.onprogress = loader.onloadstart = function (e) { def.notify(e); };
loader.onerror = loader.onabort = function (e) { def.reject(e); };
promise.abort = function () { return loader.abort.apply(loader, arguments); };
loader.readAsBinaryString(file);
return promise;
}
function upload(url, data){
var def = $.Deferred(), promise = def.promise();
var mul = buildMultipart(data);
var req = $.ajax({
url: url,
data: mul.data,
processData: false,
type: "post",
async: true,
contentType: "multipart/form-data; boundary="+mul.bound,
xhr: function() {
var xhr = jQuery.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener('progress', function(event) {
var percent = 0;
var position = event.loaded || event.position; /*event.position is deprecated*/
var total = event.total;
if (event.lengthComputable) {
percent = Math.ceil(position / total * 100);
def.notify(percent);
}
}, false);
}
return xhr;
}
});
req.done(function(){ def.resolve.apply(def, arguments); })
.fail(function(){ def.reject.apply(def, arguments); });
promise.abort = function(){ return req.abort.apply(req, arguments); }
return promise;
}
var buildMultipart = function(data){
var key, crunks = [], bound = false;
while (!bound) {
bound = $.md5 ? $.md5(new Date().valueOf()) : (new Date().valueOf());
for (key in data) if (~data[key].indexOf(bound)) { bound = false; continue; }
}
for (var key = 0, l = data.length; key < l; key++){
if (typeof(data[key].value) !== "string") {
crunks.push("--"+bound+"\r\n"+
"Content-Disposition: form-data; name=\""+data[key].name+"\"; filename=\""+data[key].value[1]+"\"\r\n"+
"Content-Type: application/octet-stream\r\n"+
"Content-Transfer-Encoding: binary\r\n\r\n"+
data[key].value[0]);
}else{
crunks.push("--"+bound+"\r\n"+
"Content-Disposition: form-data; name=\""+data[key].name+"\"\r\n\r\n"+
data[key].value);
}
}
return {
bound: bound,
data: crunks.join("\r\n")+"\r\n--"+bound+"--"
};
};
//----------
//---------- On submit form:
var form = $("form");
var $file = form.find("#file");
readFile($file[0].files[0]).done(function(fileData){
var formData = form.find(":input:not('#file')").serializeArray();
formData.file = [fileData, $file[0].files[0].name];
upload(form.attr("action"), formData).done(function(){ alert("successfully uploaded!"); });
});
With FormData API you just have to add all fields of your form to FormData object and send it via $.ajax({ url: url, data: formData, processData: false, contentType: false, type:"POST"})
I am currently using jquery to get JSON data via ajax from a codeigniter backend / mySQL database, which works fine. The problem I'm having is that, along with the data that gets returned to the jquery function, I also need to run a PHP loop for some data in another table. Currently what I'm doing is waiting for an ajax success from the first function, then making another ajax call to the second function - but I know there is a way to do it with just one function, I'm just not sure how. Here are the two database queries:
function get_selected_member($member = null){
if($member != NULL){
$this->db->where('id', $member); //conditions
}
$query = $this->db->get('members'); //db name
if($query->result()){
$member_result = $query->row();
return $member_result;
}
}
AND
function get_all_groups(){
$query = $this->db->get('groups');
$result = $query->result();
return $result;
}
and then in the javascript function, what I'm doing is saying:
var post_url = "/index.php/control_form/get_selected_member/" + selected_member_id;
$('#chosen_member').empty();
$.ajax({
type: "POST",
url: post_url,
success: function(member)
{
//Add all the member data and...
var post_url2 = "/index.php/control_form/get_all_groups/";
$.ajax({
type: "POST",
url: post_url2,
success: function(group)
{
//Create a dropdown of all the groups
}
});
}
});
In PHP you can combine both in one then echo it to ajax as json variable. So in php you will need a change like following
function get_member_with_group($member = null){
$data['member'] = $this->get_selected_member($member);
$data['group'] = $this->get_all_groups();
echo json_encode($data);
}
Then in javascript something like below..
var post_url = "/index.php/control_form/get_member_with_group/" + selected_member_id;
$('#chosen_member').empty();
$.getJSON(post_url, function(response){
var member = response.member;
//do with member
var group = response.group;
// do with group
});
Hope this will help you :)
I am a bit stuck with my website, currently on the new section of my site(among others) the user rolls over a thumbnail and gets the articles abstract displayed below it, and then when they click on said thumbnail the article appears on the left of the page,
The ajax works by pulling the href from the link that surronds the thumbnail image and using that as the url for the method call, the problem is that the click version will also be using the same function call, I cannot work out how to show the different content depening on what even happends, currently I have this as my code,
<?php
if(isset($content)) {
foreach($category_name as $k => $v) {
echo "<h2 class='$v[category_name]'><a href='#'>$v[category_name]</a></h2>";
echo "<div class='$v[category_name]'>";
}
$replace = array(".", "png", "gif", "jpg");
$count = 0;
foreach($content as $k=>$v) {
$count ++;
$image_name = str_replace($replace, "", $v['image_name']);
echo "<a class='contentlink' href='index.php/home/get_content_abstract/$v[content_id]'>";
echo "<img src='/media/uploads/".strtolower($v['category_name'])."/".$image_name."_thumb.png' alt='This is the picture' />";
echo "</a>";
}
echo "</div>";
//die(var_dump($content));
}
?>
<script>
$("a.contentlink").mouseover(function(){
var url = $(this).attr("href");
$.ajax ({
url: url,
type: "POST",
success : function (html) {
$('#abstract').html(html);
}
});
});
$("a.contentlink").click(function(ev) {
ev.preventDefault();
$('#main_menu').hide();
var url = $(this).attr("href");
$.ajax({
url:url,
type: "POST",
success : function (html) {
// alert(html)
$('#left-content').html(html);
}
})
});
</script>
The method that gets called is,
public function get_content_abstract() {
$this->load->model('content_model');
if($query = $this->content_model->get_content_by_id($this->uri->segment(3))) {
$data['abstract'] = $query;
}
$this->load->view('template/abstract', $data);
}
This is called by the ajax following the link /get_content_abstract/3, where 3 or any other number is the articles ID.
How can I sort so that I can use this function again, but only show that body content of the article instead of the abstract if the link is clicked and mouseovered?
You can pass a call type variable and check for it in your php code. Notice I added data to your ajax calls.
$("a.contentlink").mouseover(function(){
var url = $(this).attr("href");
$.ajax ({
url: url,
type: "POST",
data: "calltype=abstract",
success : function (html) {
$('#abstract').html(html);
}
});
});
$("a.contentlink").click(function(ev) {
ev.preventDefault();
$('#main_menu').hide();
var url = $(this).attr("href");
$.ajax({
url:url,
type: "POST",
data: "calltype=full",
success : function (html) {
// alert(html)
$('#left-content').html(html);
}
})
pass a GET variable in the url of the ajax call.
You just pass an variable to the handler via GET or POST that tells the handler which content to show. As your AJAX calls are simple, you can simplify the calls and use load(). If you can't use $_GET or $_POST, just append the data in the URL:
$("a.contentlink").mouseover(function() {
// URL becomes index.php/home/get_content_abstract/3/abstract
$('#abstract').load($(this).attr("href")+'/abstract');
});
$("a.contentlink").click(function(ev) {
$('#main_menu').hide();
// URL becomes index.php/home/get_content_abstract/3/full
$('#left-content').load($(this).attr("href")+'/full');
return false;
});
And in PHP, you can use something like this:
public function get_content_abstract() {
$this->load->model('content_model');
if($this->uri->segment(4) == 'full') {
// Load full content
} else {
// Load abstract
}
$this->load->view('template/abstract', $data);
}