简体   繁体   中英

jQuery Autocomplete style: match parent text input's style

Lots of style-related jquery autocomplete questions (yow), but none that want to "match the parent input's style".

My Background

I'm a java/c++ programmer that has also had quite a bit of experience in JS... within PDF. PDF uses an entirely different object model from HTML, and I'm just starting to get used to it. I'm Quite New to jQuery.

I'd like my JQUI autocomplete control's style to match the corresponding input's style. Border style, font, font size, and so on.

The Question

This is for a form generation app that doesn't really speak CSS (as far as the users are concerned). Each field might have its own font & font size, background color, and so forth. I'd hope not, but Dammit Jim, I'm a programmer not a graphic designer! Not my department.

At any rate, this is programmatically generated HTML (done in Java), so some things that might be simple in hand-rolled markup are out of the question, and some things that would be all-but-impossible are fairly trivial.

Each input field has an ID, so creating the right selector is easy. What to do with that selector is the head-scratching part. Acquiring and parsing the style attribute in script at run time seems like Way Too Much Work. There's got to be a better way.

Ideally, it'd go something like this:

var stylesToCopy = $("#fieldID").???;
$(???).magicallyApplyStyles(stylesToCopy);

Looking at the markup generated by autocomplete (in firebug) I don't see an ID or anything to mark that particular UL as being "attached" to a given input. And I don't see anything added to the input to attach it the other way. Grr.

So what's a guy to do?


Further investigation: autocomplete() returns the selected input, not the autocomplete control itself. Grr.

Hrrm...


Each input might have a different style (all set inline), so I don't think a class-based technique is going to work. That also means I need a selector that can pick out the right UL.

idea

A bit kludgy, but it'd work: Add a div with an ID to the body for each autocomplete, and use that as the appendTo . The selector then becomes "first kid of ID such-n-so". I'm not sure how that will affect the autocomplete's positioning... maybe not at all. They're already in separate branches at different depths in the DOM tree.

$("#such-n-so:first-child").css(someAttr, someVal);

with css and this li'l hack, I've got a working theory... but it seems like "the long way around". Hopefully one of you jQuery gurus can clue me in on something cleaner.

The best thing you can do is apply a class to your autocomplete field, and then apply the same class to your autocomplete control.

So, for example if you have something like:

<input type="text" id="fieldID" class="autocomplete" />
<div id="autocomplete-results"></div>

Then your jquery could do this:

$("#autocomplete-results").attr('class', $("#fieldID").attr('class'));

Of course you could always just modify your HTML to have this:

<div id="autocomplete-results" class="autocomplete"></div>

Then, in your CSS, instead of using #fieldID as your selector, you would use .autocomplete

Finally, if you wanted to just copy certain styles over and didn't want to worry about classes and such, you could use something like this: jQuery CSS plugin that returns computed style of element to pseudo clone that element?

So I think something like this will work.

  1. Use "appendTo" when creating the autocomplete so we can find it with a selector.
  2. "For this list of style attributes, get the style from the input field, and set it into the autocomplete UL.

So the script would look something like:

function addAutoComplete(inputID) {
  var wrapperDiv = document.createElement( "div" );
  var wrapperID = inputID + "__wrapper";
  wrapperDiv.setAttribute( "id", wrapperID );

  var inputSelector = $( "#"+inputID );
  var autoCompSelector = $("#" + wrapperID + ":first-child" );

  inputSelector.autoComplete( {..., appendTo: wrapperID} );

  var attrs = ["font-size", "font-family", "color", "background-color", "border", ...];
  for (var curAttrIdx = 0; curAttrIdx < attrs.length; ++curAttrIdx) {
    var attrVal = inputSelector.css( attrs[ curAttrIdx ] );
    autoCompleteSelector.css( attrs[ curAttrIdx ], attrVal );
  }
}

Close but no cigar. Each <li> under the <ul> has a style class, as does the <a> within the <ul> . Just to make life more exciting, a selector to pick out the links seems like it would be Quite Brittle. A small change in the way Autocomplete works between versions could easily break the selector.

None the less, changing the selector to "#" + wrapperID + ":first-child li a" will work for the current version of jQueryUI (1.8.13 as I write this).


After several hours of experimentation, I came up with something that works. Finally. The list items (and link) don't exist until the autocompleteopen event, so I set the style there instead. Like This:

inputSelector.autocomplete( {source: ["foo", "bar"],
  position: { my : "top", at: "bottom"},
  minLength:minChars,
  appendTo: "#" + wrapperID,
  open: function (event, ui) {
    autoCompApplyEntryStyles(inputID);
  }
});

function autoCompApplyEntryStyles(inputID) {
  var inputSelector = $( "#"+inputID );
  var wrapperID = inputID + "__wrapper";
  var autocompSelector = $("#" + wrapperID + " ul li a");

  if (autocompSelector.size() == 0) {
    return;
  }
  var attrs = ["font-size", "font-family", "font-weight", "font-style", "color", "background-color", "text-align", "text-decoration"];

  for (var curAttrIdx = 0; curAttrIdx < attrs.length; ++curAttrIdx) {
    var attrVal = inputSelector.css( attrs[ curAttrIdx ] );
    autocompSelector.css( attrs[ curAttrIdx ], attrVal );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM