I’ve got a strange problem:
- I’ve got an Ajax datasource
- I want people to be able to create a new option
- It’s all happening in a Chrome Extension. A Chrome extension has access to a JS file which is sandboxed from the internet. But it can get data from the internet by passing messages back and forth with a privileged JS file using some asynchonous message-passing methods that Chrome exposes to extensions.
The problem is that if I:
- Create a new option in the list e.g. “Foobar” and select it
- Create a second option in the list e.g. “Fizzbuzz”
FizzBuzz will never appear in the list. Only Foobar OR a result from the Ajax search will appear. Here’s a video to make the problem more clear:
Code:
Popup.js
// open port to background.js
var custPort = chrome.runtime.connect({name: "customers"});
// we haven't installed the listener on the customer port yet
var custListener = false;
$("#customer").select2({
minimumInputLength: 2,
allowClear: true,
cache: true,
placeholder: "Search for a customer",
ajax: {
delay: 500,
transport: function(params, success, failure) {
if (!custListener) {
custPort.onMessage.addListener(function(msg, sender) {
// this just stuffs the API response into the dropdown.
success(msg.response);
});
// we've now installed the customer listener
custListener = true;
}
custPort.postMessage({q: params.data.q});
},
},
tags: true,
createTag: function (params) {
var term = $.trim(params.term);
if (term === '') {
return null;
}
return {
id: term,
text: term,
newTag: true
}
},
insertTag: function (data, tag) {
// Insert the tag at the end of the results
data.push(tag);
},
templateResult: function (data) {
var term = $("#customer").data("select2").dropdown.$search.val();
var reg = new RegExp(term, 'gi');
var optionText = data.text;
var boldTermText = optionText.replace(reg, function(optionText) {return "<strong>" + optionText + "</strong>"});
var $result = $("<span>" + boldTermText + "</span>");
if (data.newTag) {
$result.prepend("<strong>New Customer: <strong> ");
}
return $result;
}
});
Sandboxed JS file:
chrome.runtime.onConnect.addListener(function(port) {
port.onMessage.addListener(loadXMLDoc);
})
function loadXMLDoc(msg, sender, sendResponse) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onload = function() {
if (xmlhttp.status === 200) {
port.postMessage({
response: JSON.parse(this.responseText)
});
}
}
if (port.name == "customers" && msg.q) {
xmlhttp.open("GET", "http://localhost:8001/app/api/users/?search=" + msg.q, true);
// Go hit endpoint
xmlhttp.send();
}
}
I’ve tried replicating this behavior outside of a Chrome Extension but everything works as normal. Which is to say that I can create different Tags:
Any idea what I might be missing in the first scenario to get Tags working with Ajax?
Thanks in advance!