jQuery Sortable Placeholder Height Issue

Today I searched jQuery Sortable Placeholder Height Issue because when I dragged my sortable list the placeholder was shrinking to have a 0 height. It was tough tell where exactly I was moving it to. I needed to get this working or it would drive me crazy. So I tried a couple things before I found a solution. I made sure that there was a height on the element and in my jQuery call I used the options placeholder: ‘ui-state-highlight’ and forcePlaceholderSize:true, none of these things worked. Then I found that you could set the height of the placeholder on the start event of your sortable like this.

$( ".selector" ).sortable({
   placeholder: 'ui-state-highlight',
   start: function(event, ui) {
        ui.placeholder.height(ui.item.height());
   }
});

Once I added this code and refreshed, it a beautiful site to see a jQuery sortable placeholder work.

jQuery UI Combobox Widget Improved

Today I searched for a JQuery UI Combobox. I found a custom widget on the jQuery UI site. By default it populates the combobox off of a select element. I was really wanting to load this off of a Ajax call instead, but only load the top 50 from the DB if they were to click on the arrow to browse. I made some modifications to the Combobox code to allow for the ‘source’ callback which is implemented on their current autocomplete. I also implemented the ‘select’ callback and ‘delay’ property.

I also have it setup to be able to combobox off of a text element if desired, instead of the select.

This widget should go into a js file and be included on the page

(function( $ ) {
		$.widget( "ui.combobox", {
			_create: function() {
				var self = this,
					select = this.element.hide(),
					selected = select.children( ":selected" ),
					value = select.is('input:text') ?
								select.val() :
									selected.val() ?  selected.text() : "";
				var input = this.input = $( "
" )
					.insertAfter( select )
					.val( value )
					.autocomplete({
						delay: self.options.delay ? self.options.delay : 0,
						minLength:  self.options.minLength ? self.options.minLength : 0,
						source: function( request, response ) {
							if (!self.options.source) {
								var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
								response( select.children( "option" ).map(function() {
									var text = $( this ).text();
									if ( this.value && ( !request.term || matcher.test(text) ) )
										return {
											label: text.replace(
												new RegExp(
													"(?![^&;]+;)(?!<[^<>]*)(" +
													$.ui.autocomplete.escapeRegex(request.term) +
													")(?![^<>]*>)(?![^&;]+;)", "gi"
												), "$1" ),
											value: text,
											option: this
										};
								}) );
							} else {
								self.options.source(request, response);
							}
						},
						select: function( event, ui ) {
							if (!self.options.select) {
								ui.item.option.selected = true;
								self._trigger( "selected", event, {
									item: ui.item.option
								});
							} else {
								self.options.select(event, ui);
							}
						},
						change: function( event, ui ) {
							if ( !ui.item ) {
								var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
									valid = false;
								select.children( "option" ).each(function() {
									if ( $( this ).text().match( matcher ) ) {
										this.selected = valid = true;
										return false;
									}
								});
								if ( !valid ) {
									// remove invalid value, as it didn't match anything
									$( this ).val( "" );
									select.val( "" );
									input.data( "autocomplete" ).term = "";
									return false;
								}
							}
						}
					})
					.addClass( "ui-widget ui-widget-content ui-corner-left" );

				input.data( "autocomplete" )._renderItem = function( ul, item ) {
					return $( "
  • " ) .data( "item.autocomplete", item ) .append( "" + item.label + "" ) .appendTo( ul ); }; this.button = $( "" ) .attr( "tabIndex", -1 ) .attr( "title", "Show All Items" ) .insertAfter( input ) .button({ icons: { primary: "ui-icon-triangle-1-s" }, text: false }) .removeClass( "ui-corner-all" ) .addClass( "ui-corner-right ui-button-icon" ) .click(function() { // close if already visible if ( input.autocomplete( "widget" ).is( ":visible" ) ) { input.autocomplete( "close" ); return; } // work around a bug (likely same cause as #5265) $( this ).blur(); // pass empty string as value to search for, displaying all results input.autocomplete( "search", "" ); input.focus(); }).find('.ui-button-text').removeClass('ui-button-text'); //added the remove ui-button-text to remove the padding //and make it the same size as our input //see button in Message Center -> New Message for reference }, destroy: function() { this.input.remove(); this.button.remove(); this.element.show(); $.Widget.prototype.destroy.call( this ); } }); })( jQuery );

    Here is an example usage of the widget:

    $('#myTextField').combobox({
    		source: function(req,add) {
                          $.ajax({
                            url: "test.html",
                           dataType:"json",
                           success: function(data, textStatus, XMLHttpRequest){
                             add(data);
                           }
                       });
    
    		},
    		select: function(event, ui) {
                                  //call back when the user selects an item on the list
    	                        alert('Item id selected [' + ui.item.id + ']');
    		},
    		delay: 500
    		});
    

    Here is an example of json structure that the add() method takes above

    [{"id":"1","label":"Option1"},{"id":"2","label":"Option2"},{"id":"3","label":"Option3"}]
    

    This mod does not break the traditional means of creating the combobox off of a select element

    $( "#MySelectElement" ).combobox();
    

    Make AJAX Call To A Different Domain Using PHP & JQuery

    Today I Searched how to make an AJAX call to a URL on a different domain. My first attempt failed with a security error. I dug into the problem a bit and found out that PHP can be used as a proxy to fetch the web content.

    AJAX Calls PHP Script On Your Domain -> PHP Script Fetches Content From Remote Domain -> PHP Script Returns The Remote Data Back To The AJAX Call

    Below is a sample PHP script that I found and tweaked.

    // Set your return content type
    header('Content-type: text/html');
    
    // Website url to open
    $daurl = 'http://www.otherdomain.com/index.php?sku=' . $_GET["sku"];
    
    // Get that website's content
    $handle = fopen($daurl, "r");
    
    // If there is something, read and return
    if ($handle) {
        while (!feof($handle)) {
            $buffer = fgets($handle, 4096);
            echo $buffer;
        }
        fclose($handle);
    }
    

    Below is the AJAX call to load the content into a div using JQuery

    $("#loadremotecontent").load('getprice.php?sku=322000');
    

    The script could be further modified to pass in the entire URL as a parameter so it could be more generic. I would love to hear about other cross domain AJAX options if anyone has any other suggestions.

    jQuery getJSON() async false

    Today I searched jQuery getJSON() async false because I needed my jQuery Ajax call to be synchronous. It turns out that getJSON is just an Ajax shortcut in jQuery that can not have any extra parameters passed to it according to a post at Stackoverflow.com and then confirmed in the jQuery doc . So I had to turn my call back to normal jQuery.ajax().

    //before
    $.getJSON(url, data, function(json){
                                    //success code
                               });
    
    //after
    $.ajax({
      url: url,
      dataType: 'json',
      data: data,
      async: false,
      success: function(json){
                      //success code
                   }
    });
    

    As you can see the shortcut code is well, shorter, but not as flexible as the basic ajax function. Shortcuts are nice but shouldn’t be leaned on for heavy lifting.

    Go back to top