Cakephp 2.1 and Jquery UI autocomplete - ajax

Mission:
Implement autocomplete of departments(saved in departments table) in employee form field called department.
A user enters a few spellings of department name
That brings up list of the names matching departments
The user select one and that's it.
Platforms
CakePhp 2.1
Jquery UI Autocomplete(part of Jquery UI library version 1.8.18)
Database Model
Emplyee (id, first_name,last_name,department_id)
department(id,name)
so in my add.ctp file ajax call is something like
$( "#auto_complete" ).autocomplete({
source: function( request, response ) {
$.ajax({
url: "/employees/showDepartment",
dataType: "json",
data: {
featureClass: "P",
style: "full",
maxRows: 12,
name_startsWith: request.term
},
success: function( data ) {
alert("success--");
response( $.map( data, function( item ) {
//alert(item);
return {
label: item.name,
value: item.id
}
}));
}
});
},
minLength: 2,
select: function( event, ui ) {
log( ui.item ?
"Selected: " + ui.item.label :
"Nothing selected, input was " + this.value);
},
open: function() {
$( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" );
},
close: function() {
$( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" );
}
});
i have a action in my EmployeeController called show_depatment()
public function getAddress() {
$this->autoRender = false;// I do not want to make view against this action.
$this->log($this->params->query['name_startsWith'] , 'debug');
$str = $this->params->query['name_startsWith'];
$this->log($str, 'debug');
$this->layout = 'ajax';
$departments = $this->Employee->Department->find('all', array( 'recursive' => -1,
'conditions'=>array('Department.name LIKE'=>$str.'%'),
'fields'=>array('name', 'id')));
//$this->set('departments',$departments);
$this->log($departments, 'debug');
echo json_encode($departments);
}
I dont want show_department action to have any view so i have made $this->autoRender = false;
but it is not working as expected.
when i debug the response using firebug in response and HTLM section it shows
[{"Department":{"name":"Accounting","id":"4"}}] // when i type "acc" in input field
Question
How to make it to display in form field.
echo json_encode($departments); is it right method of sending response in json format?
when i alert in sucess part of ajax call (alert(item);) it gives error as "undefined"

i'm friend of fat Model and skinny Controller so my Controller action looks like this
public function getAddress()
{
if($this->RequestHandler->isAjax()) {
Configure::write('debug', 0);
$this->layout = 'ajax';
$this->autoRender = false;
echo json_encode($this->Employee->Department->getAddress($this->params['url']['term']));
exit;
}
}
and my Department model method:
public function getAddress($str)
{
$rs = array();
$search = $this->find('all', array(
'recursive' => -1,
'conditions'=>array('Department.name LIKE'=>$str.'%'),
'fields'=>array('name', 'id')
));
if (!empty($search))
{
//the jquery ui autocomplete requires object with label/value so we need to traverse the query results and create required array
foreach ($search as $key => $val)
{
$rs[] = array('label' => $val['Department']['name'],
'value' => $val['Department']['id']);
}
}
return $rs;
}
and finaly my view entry is like this:
$( "#auto_complete" ).autocomplete({
minLength: 2,
source: function( request, response ) {
var term = request.term;
if ( term in cache ) {
response( cache[ term ] );
return;
}
lastXhr = $.getJSON( "/employees/showDepartment", request, function( data, status, xhr ) {
cache[ term ] = data;
if ( xhr === lastXhr ) {
response( data );
}
});
}
});
hope this helps.

Related

How add the Woocommerce notices(without reload) when using add to cart with ajax?

I try to make the add to cart buttons and notices on the productpages(and everywhere else) work with ajax. But the notices (e.g. You cannot add that amount to the cart - we have X in stock and you already have Y in your cart.) don't work.
How do I make it work?
This is what I have right now:
JS for AJAX Add to Cart handling
/**
* JS for AJAX Add to Cart handling
*/
function ace_product_page_ajax_add_to_cart_js() {
?><script type="text/javascript" charset="UTF-8">
jQuery(function($) {
$('form.cart').on('submit', function(e) {
e.preventDefault();
var form = $(this);
form.block({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 } });
var formData = new FormData(form.context);
formData.append('add-to-cart', form.find('[name=add-to-cart]').val() );
// Ajax action.
$.ajax({
url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'ace_add_to_cart' ),
data: formData,
type: 'POST',
processData: false,
contentType: false,
complete: function( response ) {
response = response.responseJSON;
if ( ! response ) {
return;
}
if ( response.error && response.product_url ) {
window.location = response.product_url;
return;
}
// Redirect to cart option
if ( wc_add_to_cart_params.cart_redirect_after_add === 'yes' ) {
window.location = wc_add_to_cart_params.cart_url;
return;
}
var $thisbutton = form.find('.single_add_to_cart_button'); //
var $thisbutton = null; // don't want the 'View cart' button
// Trigger event so themes can refresh other areas.
$( document.body ).trigger( 'added_to_cart', [ response.fragments, response.cart_hash, $thisbutton ] );
// Remove existing notices
$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
// Add new notices
form.closest('.product').before(response.fragments.notices_html)
form.unblock();
}
});
});
});
</script><?php
}
add_action( 'wp_footer', 'ace_product_page_ajax_add_to_cart_js' );
Add to cart handler:
/**
* Add to cart handler
*/
function ace_ajax_add_to_cart_handler() {
WC_Form_Handler::add_to_cart_action();
WC_AJAX::get_refreshed_fragments();
}
add_action( 'wc_ajax_ace_add_to_cart', 'ace_ajax_add_to_cart_handler' );
add_action( 'wc_ajax_nopriv_ace_add_to_cart', 'ace_ajax_add_to_cart_handler' );
// Remove WC Core add to cart handler to prevent double-add
remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 );
Add fragments for notices:
/**
* Add fragments for notices
*/
function ace_ajax_add_to_cart_add_fragments( $fragments ) {
$all_notices = WC()->session->get( 'wc_notices', array() );
$notice_types = apply_filters( 'woocommerce_notice_types', array( 'error', 'success', 'notice' ) );
ob_start();
foreach ( $notice_types as $notice_type ) {
if ( wc_notice_count( $notice_type ) > 0 ) {
wc_get_template( "notices/{$notice_type}.php", array(
'messages' => array_filter( $all_notices[ $notice_type ] ),
) );
}
}
$fragments['notices_html'] = ob_get_clean();
wc_clear_notices();
return $fragments;
}
add_filter( 'woocommerce_add_to_cart_fragments', 'ace_ajax_add_to_cart_add_fragments' );
Try replacing in last snippet 'messages' => array_filter( ... with 'notices' => array_filter( ... and it should work.

Istotope ajax content load

I'm stuck implementing load next set of posts in WordPress with isotope masonry layout.
It's just not triggered for appended elements and I can't figure out why.
If someone could point me in right direction I would appreciate.
jQuery AJAX function
function load_content( args ) {
$container = $('#container-async');
$status = $('.status');
$.ajax({
url: ajax_url,
data: {
action: 'do_load_posts',
nonce: nonce,
args: args
},
type: 'post',
dataType: 'json',
success: function( data, textStatus, XMLHttpRequest ) {
$items = data.posts;
if ( args.action === 'filter') {
/**
* Replace items
*/
$container.imagesLoaded( function() {
$container.isotope({
itemSelector: '.grid-item',
percentPosition: true,
masonry: {
columnWidth: '.grid-sizer'
}
});
$container.html( $items ).isotope( 'appended', $items, function() {
console.log('inserted');
});
});
}
else {
/**
* Append items
*/
$container.imagesLoaded( function() {
$container.isotope({
itemSelector: '.grid-item',
percentPosition: true,
masonry: {
columnWidth: '.grid-sizer'
}
});
$container.append( $items ).isotope( 'appended', $items, function() {
console.log('appended');
});
});
}
},
error: function( MLHttpRequest, textStatus, errorThrown ) {
$status.toggleClass('active');
}
});
}
WordPress AJAX:
function ajax_do_load_posts() {
// Verify nonce
if( !isset( $_POST['nonce'] ) || !wp_verify_nonce( $_POST['nonce'], 'nonce' ) )
die('Permission denied');
$response = [
'status' => 500,
'posts' => 0,
];
$filter = $_POST['args'];
$type = get_post_type_object( $filter['type'] );
$args = [
'post_type' => sanitize_text_field($filter['type']),
'paged' => intval($filter['page']),
'posts_per_page' => $filter['qty'],
];
$qry = new WP_Query($args);
if ($qry->have_posts()) :
ob_start();
while($qry->have_posts()) : $qry->the_post(); ?>
<div class="grid-item col-xs-12 col-sm-6 col-md-4 col-lg-3">
<?php get_template_part('templates/loop', 'card' ); ?>
</div>
<?php endwhile;
$response = [
'status' => 200,
'posts' => ob_get_clean(),
];
endif;
wp_reset_query();
wp_reset_postdata();
die(json_encode($response));
}
add_action('wp_ajax_do_load_posts', 'ajax_do_load_posts');
add_action('wp_ajax_nopriv_do_load_posts', 'ajax_do_load_posts');
Items are inserted or appended into container but masonry is triggered only on items that are already there on page load.
I have googled around and tried various solutions but none of them work, neither with isotope or masonry jquery plugin.
I was able to fix my issue, and kind of looks like the problem is because I was using jQuery default append/insert methods.
I have switched to isotope methods and now things look fine.
So basically instead of
$container.html( $items ).isotope( 'appended', $items, function() {
console.log('inserted');
});
I am now using:
$grid.isotope('insert', jQuery($items));
It looks logical actually that isotope cannot know items are appended if I don't use isotopes append/insert method. And notice that I also wrapped $items inside jQuery.
Anyhow my working JS for same PHP function is:
function load_content( args ) {
$container = $('#container-async');
$status = $('.status');
$.ajax({
url: ajax_url,
data: {
action: 'do_load_posts',
nonce: nonce,
args: args
},
type: 'post',
dataType: 'json',
success: function( data, textStatus, XMLHttpRequest ) {
$items = data.posts;
var $grid = $('.masonry').imagesLoaded( function() {
$grid.isotope({
itemSelector: '.grid-item',
percentPosition: true,
masonry: {
columnWidth: '.grid-sizer'
}
});
if ( args.action === 'filter') {
$grid.isotope('remove', $('.grid-item'));
}
$grid.isotope('insert', jQuery($items));
});
$grid.on( 'layoutComplete', function( event, laidOutItems ) {
$container.removeClass(data.action);
});
},
error: function( MLHttpRequest, textStatus, errorThrown ) {
$status.toggleClass('active');
}
});
}

how to pass a variable with the help of ajax jquery into a function directly, which is on another page

how to pass a variable with the help of ajax jquery into a function directly, which is on another page
function show_data2(str1) {
xml2http = new XMLHttpRequest();
xml2http.onreadystatechange = function () {
if (xml2http.readyState === 4 && xml2http.status === 200) {
document.getElementById("show_data_sal").innerHTML = xml2http.responseText;
}
};
xml2http.open("POST", "functions.php?r=" + str1, true);
xml2http.send(str1);
};
functions.php
class querydb
{
function useHere()
{
...I want to use that variable 'r' here.
}
}
If you are using jQuery, this will be the easiest way to send post data via ajax:
var jqxhr = $.ajax( {
method: "POST",
url: "functions.php",
data: { r: "some value", s: "another value" }
})
.done(function() {
alert( "success" );
})
.fail(function() {
alert( "error" );
})
.always(function() {
alert( "complete" );
});
function.php
class querydb
{
function useHere()
{
// We're sending our post data as json so we'll need php to decode it for us to use.
$foo = json_decode($_POST[], true);
// you can now access your variables like an array
$bar = $foo['r'];
}
}
Just be sure to clean anything from post before you do anything with it to prevent any malicious parameters coming through

checking if the success data is empty in ajax method of jquery

I have two select boxes in my form.when a user select an option of first select box the options of second select box will be shown by jquery ajax.My problem is that some options of first select box has no record in database and when they selected the second select box should not be shown.I need to check if the data is empty .I treid this code but nothing happens
view:
<script type='text/javascript'>
$(document).ready(function(){
$('#subsec').hide();
$('section').change(){
var sec_id=$(this).val();
var url='article_controler/get_options/'+sec_id;
$.ajax({
url:url,
type:'post',
success:function(resp){
if(!resp)
$('#subsec').hide();
else
$('#subsec').show();
$('$subsec').html(resp)
})
}
});
</script>
you can try this
$.ajax({
url:url,
type:'post',
success:function(resp){
if(resp == "" || resp == null){
$('#subsec').hide();
}
else {
$('#subsec').show();
$('#subsec').html(resp);
}
})
}
});
I have added inline comments to help you out
class Article_Controller extends CI_Controller
{
public function get_options()
{
$option = $this->input->post('option'); // validate this
//Get a list of Sub options from your model
$model = ''; //your own implementation here
//If no model data returned, send a 404 status header
//and bail
if(!$model){
return $this->output->set_status_header(404);
}
$responce = array(
'suboptions' => $model // array of suboptions the model returned
);
// Ideally Abstract all the Ajax stuff to
// its own controller to keep things Dry
return $this->output
->set_status_header(200)
->set_content_type('application/json')
->set_output(json_encode($responce));
}
}
-
//Global URL variable or put it in <base href>
var URL = "<?php echo site_url();?>";
(function($){
var myForm = {
init : function(){
//initialize myForm object properties here
this.Form = $("form#myFormID");
this.selectChange = this.Form.find("select#mySelectBoxI");
this.newSelect = this.Form.find("select#secondaryselectboxId");
//hide second select with CSS by default
//Bind the Change event to our object(myForm) method
this.selectChange.on('change', $.proxy(this.ChangedEvent, this));
},
ChangedEvent : function(event){ // gets the change event
//Grab the currentTarget(option[i]) value from the event received
//You may also need to pass the CSRF Token
this.buildAjaxRequest({'option' : event.currentTarget.value});
},
buildAjaxRequest : function( data ){
var config = {
cache : false,
url : URL + 'article_controller/get_options',
method : 'POST',
data : data, //'option' : event.currentTarget.value
dataType : 'json'
};
this.makeAjaxRequest(config).then(
$.proxy(this.ResponceHandler, this),
$.proxy(this.ErrorHandler, this)
);
},
makeAjaxRequest : function( config ){
return $.ajax( config ).promise();
},
ResponceHandler : function( data ){
$.each(data.suboptions, function(i, v){
this.newSelect.append('<option value="'.data[i].'">'.data[v].'</option>');');
});
this.newSelect.show();
},
ErrorHandler : function(xhr, statusText, exception){
switch(xhr.status)
{
case 404: //remember the 404 from the controller
alert(xhr.statusText); //handle your own way here
break;
}
},
}
myForm.init();
}(jQuery));
Hi pls try this,
<script type='text/javascript'>
$(document).ready(function(){
$('#subsec').hide();
$('#firstSelectBoxId').change("selectboxMethod");
});
function selectboxMethod(){
var sec_id=$("#firstSelectBoxId").val();
alert("Selected from first select"+sec_id);
if(sec_id != null){
var url='article_controler/get_options/'+sec_id;
$.ajax({
url:url,
type:'post',
success:function(resp){
$('#subsec').show();
$('#subsec').html(resp);
}
});
}else{
$("#subsec").hide();
}
}
</script>

Jquery mobile autocomplete implementation with local json

I am trying to implement the jquery mobile autocomplete functionality, because i have a list of around 3000 items.
I have a json that has this structure:
[{"v1":" abcd","v2":"http://www.url.nl","v3":0487,"v4":"street12","v5":"H"},
{"v1":" qq","v2":"http://www.url.nl","v3":0297,"v4":"street14","v5":"A"},
{"v1":" zz","v2":"http://www.url.nl","v3":0117,"v4":"street55","v5":"A"}]
I am using this example: http://jquerymobile.com/demos/1.3.0-rc.1/docs/demos/widgets/autocomplete/autocomplete-remote.html
but i can not get this to work with my json file.
$( document ).on( "pageinit", "#myPage", function() {
$( "#autocomplete" ).on( "listviewbeforefilter", function ( e, data ) {
var $ul = $( this ),
$input = $( data.input ),
value = $input.val(),
html = "";
$ul.html( "" );
if ( value && value.length > 2 ) {
$ul.html( "<li><div class='ui-loader'><span class='ui-icon ui-icon-loading'></span></div></li>" );
$ul.listview( "refresh" );
$.ajax({
url: "http://gd.geobytes.com/AutoCompleteCity",
dataType: "jsonp",
crossDomain: true,
data: {
q: $input.val()
}
})
.then( function ( response ) {
$.each( response, function ( i, val ) {
html += "<li>" + val + "</li>";
});
$ul.html( html );
$ul.listview( "refresh" );
$ul.trigger( "updatelayout");
});
}
});
});
I have the feeling that it has to with the ajax call and my json file, but I haven't found the solution yet.

Resources