I'm trying to use Select2 and load remote data (ajax) in Aurelia. So I create a custom attribute called Select2 and follow the options in the documentation.
But, I faced an issue when I scroll to the end of the drop down a "loading more results" message appears but doesn't load more data or call the API (using the same API in the Select2 documentation to make sure I'm not missing anything).
import { customAttribute, inject , bindable, bindingMode} from 'aurelia-framework';
import 'jquery';
import 'select2';
#customAttribute('select2')
#inject(Element)
export class Select2CustomAttribute {
element;
constructor(element) {
this.element = element;
}
attached() {
var self=this;
$(this.element).select2(
{
// closeOnSelect: false,
allowClear: true,
ajax: {
url: "https://api.github.com/search/repositories",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function (data, params) {
// parse the results into the format expected by Select2
// since we are using custom formatting functions we do not need to
// alter the remote JSON data, except to indicate that infinite
// scrolling can be used
params.page = params.page || 1;
return {
results: data.items,
pagination: {
more: (params.page * 30) < data.total_count
}
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; },
minimumInputLength:0,
templateResult: function( repo )
{
if (repo.loading) return repo.text;
var markup = "<div class='select2-result-repository clearfix'>" +
"<div class='select2-result-repository__avatar'><img src='" + repo.owner.avatar_url + "' /></div>" +
"<div class='select2-result-repository__meta'>" +
"<div class='select2-result-repository__title'>" + repo.full_name + "</div>";
if (repo.description) {
markup += "<div class='select2-result-repository__description'>" + repo.description + "</div>";
}
markup += "<div class='select2-result-repository__statistics'>" +
"<div class='select2-result-repository__forks'><i class='fa fa-flash'></i> " + repo.forks_count + " Forks</div>" +
"<div class='select2-result-repository__stargazers'><i class='fa fa-star'></i> " + repo.stargazers_count + " Stars</div>" +
"<div class='select2-result-repository__watchers'><i class='fa fa-eye'></i> " + repo.watchers_count + " Watchers</div>" +
"</div>" +
"</div></div>";
return markup;
},
templateSelection: function (repo) { return repo.full_name || repo.text; } ,
}
).on('change', evt => {
if (!evt.originalEvent) {
try{
this.element.dispatchEvent(new Event('change'));
}catch(e){
// IE 11+
try{
let evt = document.createEvent('HTMLEvents');
evt.initEvent('change', false, true);
this.element.dispatchEvent(evt);
}catch(e){
console.log(e);
}
}
}
});
}
}
I copied your code in to a gist.run and it worked fine: https://gist.run/?id=5b560eac6deff0f1b0896c30a3f12f79
The only difference is I'm loading jQuery and select2 from a CDN and not from the bundle. You can see a GIF of it working for me here: http://imgur.com/a/6uSs6
Related
My html like this :
<input id="appdate" type="text" class="required" placeholder="Select Date">
My javascript like this :
...
$(document).ready(function () {
...
$('#appdate').change(function () {
console.log('when the retrieveSchedule function is called, this is not executed')
var date = $('#appdate').val();
...
});
});
appointment = function () {
function retrieveSchedule({ id, url }) {
...
$.ajax({
url: url,
type: 'GET',
data: '',
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (result) {
...
var $input = $('#appdate').pickadate({
disable: _disableDate,
formatSubmit: 'yyyy-mm-dd',
min: someDate,
max: new Date((someDate.getFullYear() + 1), (someDate.getMonth() - 1), someDate.getDate()),
selectMonths: true,
selectYears: true,
close: 'Ok',
autoClose: false,
closeOnSelect: false, // Close upon selecting a date,
onClose: function () { $('.picker__input').removeClass('picker__input--target'); $('.picker').blur(); },
onRender: function () {
$('#appdate_root .picker__day-display').append('<div class="cal-notif"></div>');
var loadingcal = '<div class="cal-loading preloader-background">' +
'<div class="preloader-wrapper big active center">' +
'<div class="spinner-layer spinner-blue-only">' +
'<div class="circle-clipper left">' +
'<div class="circle"></div>' +
'</div>' +
'<div class="gap-patch">' +
'<div class="circle"></div>' +
'</div>' +
'<div class="circle-clipper right">' +
'<div class="circle"></div>' +
'</div>' +
'</div>' +
'</div>' +
'</div>';
$('#appdate_root .picker__calendar-container').append(loadingcal);
}
});
// Use the picker object directly.
var picker = $input.pickadate('picker');
picker.clear();
if (picker.get('start')) {
var getdisable = picker.get('disable');
picker.set('enable', [1, 2, 3, 4, 5, 6, 7]);
picker.set('disable', _disableDate);
getdisable = picker.get('disable');
picker.render();
} else { console.log('false picker'); }
},
error: function (result) {
...
}
}).done(function () {
...
});
}
return { retrieveSchedule: retrieveSchedule }
}();
I don't display all my scripts. I only show the details of the problem I am having
When the above js file is run, it will first call the retrieveSchedule function. If ajax is successful, it will create a pickdate and display it in the input text with id = appdate
My problem is that when pickdate is successfully displayed in the input text with id = appdate, it also runs this script in $('#appdate').change(function({. I want the statement inside $('#appdate').change(function({ is not run. So it only runs when selecting pickdate. Not display pickdate
How do I make the conditions?
How about create checking variable like this
var appdateCreated = false;
$('#appdate').change(function () {
if(appdateCreated) {
console.log('when the retrieveSchedule function is called, this is not executed')
} else {
appdateCreated = true
}
});
I am able to display out all the details including the button. However, the main problem is that the when I click the button, nothing happens. It says that BtnRemoveAdmin() is not defined when I inspect for errors. However, I have function BtnRemoveAdmin()?? I have tried to move the function to htmlstring. Nothing works. I am not sure what went wrong.
(function () {
$(document).ready(function () {
showadmin();
});
function showadmin() {
var url = serverURL() + "/showadmin.php";
var userid = "userid";
var employeename = "employeename";
var role ="role";
var JSONObject = {
"userid": userid,
"employeename": employeename,
"role": role,
};
$.ajax({
url: url,
type: 'GET',
data: JSONObject,
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function (arr) {
_getAdminResult(arr);
},
error: function () {
alert("fail");
}
});
}
function _getAdminResult(arr) {
for (var i = 0; i < arr.length; i++) {
htmlstring = '<div class="grid-container">' +
'<div>' + arr[i].userid + '</div>' +
'<div>' + arr[i].employeename + '</div>' +
'<div>' + arr[i].role + '</div>' +
'<div>' + '<button onclick="BtnRemoveAdmin()">Remove</button>' + // 'BtnRemoveAdmin' is not defined
'</div>' ;
$("#name").append(htmlstring);
}
function BtnRemoveAdmin() {
var data = event.data;
removeadmin(data.id);
}
}
function removeadmin(userid) {
window.location = "removeadmin.php?userid=" + userid;
}
})();
All your code is defined inside an IIFE.
That includes BtnRemoveAdmin.
When you generate your JavaScript as a string, it is evaled in a different scope.
BtnRemoveAdmin does not exist in that scope.
Don't generate your HTML by mashing strings together.
Use DOM instead.
function _getAdminResult(arr) {
var gridcontainers = [];
for (var i = 0; i < arr.length; i++) {
var gridcontainer = $("<div />").addClass("grid-container");
gridcontainer.append($("<div />").text(arr[i].userid));
gridcontainer.append($("<div />").text(arr[i].employeename));
gridcontainer.append($("<div />").text(arr[i].role));
gridcontainer.append($("<div />").append(
$("<button />")
.on("click", BtnRemoveAdmin)
.text("Remove")
));
gridcontainers.push(gridcontainer);
}
$("#name").append(gridcontainers);
}
I use JQuery, and sometimes I get the same problem with plain JS functions not being called.
So I create JQuery functions :
$.fn.extend({
btnRemoveAdmin: function() {
...//Do what you want here
}
});
To call it use :
<button onclick="$().btnRemoveAdmin();"></button>
Hope it helps you !
I'm trying to build a string depending on an image whether it exists or not, if it exists then build an image tag if it doesn't then create an empty div tag with a class .no-image how can I accomplish this - could some give me some help
$('#search_movies').select2({
ajax: {
url: "http://localhost:8000/admin/tmdb/search",
dataType: 'json',
delay: 250,
type: 'POST',
results: function (data, page) {
console.log(data);
return { results: data.d };
},
data: function (params) {
return {
q: params.term, // search term
// page: params.page
};
},
processResults: function (data, params) {
// parse the results into the format expected by Select2
// since we are using custom formatting functions we do not need to
// alter the remote JSON data, except to indicate that infinite
// scrolling can be used
//params.page = params.page || 1;
console.log(data)
return {
results: data.items,
// pagination: {
// more: (params.page * 30) < data.total_count
// }
};
},
cache: false
},
escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatRepo, // omitted for brevity, see the source of this page
templateSelection: formatRepoSelection // omitted for brevity, see the source of this page
});
function formatRepo(repo) {
if (repo.loading) return repo.text;
var markup = '<div data-id="' + repo.id + '" class="option clearfix">';
markup += '<div class="option-image"><img alt="" src="' + repo.image + '"></div>';
markup += '<div class="option-content">';
markup += '<h4>' + repo.title + '</h4>';
markup += '<h4>' + repo.release_date + '</h4>';
markup += '<h4>' + repo.popularity + '</h4>';
markup += '</div>';
markup += '</div>';
return markup;
}
function formatRepoSelection (repo) {
return repo.title || repo.text;
}
Instead of making formatRepo return the markup, make it pass the markup to a callback function like.
function formatRepo(repo, markupCallback) {
function imageExists(url, callback) {
var img = new Image();
img.onload = function() { callback(true); };
img.onerror = function() { callback(false); };
img.src = url;
}
imageExists(repo.image, function(exists) {
var markup = '';
if(exists) {
markup += '<img src="' + repo.image + '">';
} else {
markup += '<div class="no-image"></div>';
}
// pass markup to markupCallback
markupCallback(markup);
});
}
// and then use it like
formatRepo(myRepo, function(markup){
// use markup here
});
I am coding a simple RSS feed using jquery and a feed from wired. Everything is working great, but for some reason the result is including a NaN after the description. I cannot figure out what it is trying to pull, and since it is not wrapped in any tags, it follows a paragraph as such:
<p></p> NaN </div>
I cannot use css to hide it, and i dont want to limit the description length as some are longer than others and setting an arbitrary character limit may allow it to display anyways on shorter descriptions.
xml feed: http://www.wired.com/category/business/feed/
script:
(function ($) {
$.fn.FeedEk = function (opt) {
var def = $.extend({
FeedUrl: "http://www.wired.com/category/business/feed/",
MaxCount: 5,
ShowDesc: true,
ShowPubDate: true,
TitleLinkTarget: "_blank",
}, opt);
var id = $(this).attr("id");
var i;
$("#" + id).empty().append('<img src="loader.gif" />');
$.ajax({
url: "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=" + def.MaxCount + "&output=json&q=" + encodeURIComponent(def.FeedUrl) + "&hl=en&callback=?",
dataType: "json",
success: function (data) {
$("#" + id).empty();
var s = "";
$.each(data.responseData.feed.entries, function (e, item) {
s += '<li><div class="itemTitle"><a href="' + item.link + '" target="' + def.TitleLinkTarget + '" >' + item.title + "</a></div>";
if (def.ShowPubDate) {
i = new Date(item.publishedDate);
s += '<div class="itemDate">' + i.toLocaleDateString() + "</div>";
}
if (def.ShowDesc) {
if (def.DescCharacterLimit > 0 && item.content.length > def.DescCharacterLimit) {
var StringStartAfterImage = item.content.indexOf('>',item.content.indexOf('< img')) + 1;
s += '<div class="itemContent">' + item.content.substr(0, def.DescCharacterLimit + StringStartAfterImage) + "..";
}
else {
s += '<div class="itemContent">' + item.content;
}
s += + "</div>";
}
});
$("#" + id).append('<ul class="feedEkList">' + s + "</ul>");
}
});
};
})(jQuery);
$(document).ready(function() {
$('#home-news').FeedEk({
FeedUrl: 'http://www.wired.com/category/business/feed/',
MaxCount: 5,
ShowDesc: true,
ShowPubDate: true,
});
});
html:
<div class="newsCenter">
<div class="news">
<div id="home-news"> </div>
</div>
</div>
any help is much appreciated! Thank you!
i solved this by removing code after the else statement and closing the div in the else statement, i do not need the data that is not generating so this solution works for me.
I'm trying to use typeahead's matcher function to check if my search returns no results. If it returns no results i want to append a div on the end of the search bar. However the matcher function is causing my highlighter to break and return random results. Does anyone know if there is a way to accomplish this without using the matcher function or how use it properly in this instance? I think i might be taking the wrong approach.
$('.shop_search').typeahead({
source: function (query, process) {
map = {};
$.each(data, function (i, data) {
map[data.text] = {
address: data.text2,
name: data.text,
post: data.post
};
shops.push(data.text);
});
process(shops);
shops = [];
},
minLength: 3,
matcher: function (item) {
if (item.indexOf(this.query) == -1) {
$(".dropdown-menu").append($('<li><button class="btn" >Advanced Search</button></li>'));
return true;
}
},
highlighter: function (item) {
var p = map[item];
var itm = ''
+ "<div class='typeahead_primary'>" + p.name + "</div>"
+ "<div class='typeahead_secondary'>" + p.address + </div>"
+ "</div>"
+ "</div>";
return itm;
},
});
Seems to me that you forgot a "
+ "<div class='typeahead_secondary'>" + p.address + </div>"
should be
+ "<div class='typeahead_secondary'>" + p.address + "</div>"