select2 and multiple createSearchChoice - javascript

Is possible to use in select2 the createSearchChoice method to create 2 choices at the same time?
I'm creating an input form for tags, if the tag does not exists I need to create two choices at the same time:
For example when the user types "missingtag" he needs to have two options
Create a public "missingtag" tag
Create a private "missingtag" tag

I can't see why you should not be able to create two tags at the same time. This isnt testet and part of it is c/p from http://ivaynberg.github.io/select2/.
$("#tags").select2({
createSearchChoice: function(term) {
return { data: {
{id:'public-' + term, text:'public-' + term },
{id:'private-' + term, text:'private-' + term}
}
}
});

I resolved modifying the createSearchChoice function in the js file

Related

Multiple tables with individual search inputs in serverSide mode using DataTables

Application is using:
DataTables 1.10.18
jquery 3.2.1
PHP back-end
lodash 4.17.4
The application contains a web page which consists of multiple DataTables. Each of these uses serverSide: true (server-side mode) to obtain the data via an ajax endpoint which returns JSON data.
The tables are initialised as follows:
On page load several <table>'s are rendered. I'm using a jquery .each() to initialise the DataTable for each one:
$.each($('table'), function () {
$(this).DataTable({
processing: true,
serverSide: true,
searching: false,
ajax: {
data: {
table_id: $(this).attr('id')
},
url: '/get-data.json',
},
...
});
Each <table> has an ID. This is passed via ajax in the data: attribute. The endpoint /get-data.json returns data based on the table ID. In other words it knows "which table" the data should be obtained for based on this ID.
I want to be able to do searching on tables, but it must be done server-side. For this reason my initialisation code in (1) sets searching: false because this effectively disables the client-side search facility that DataTables provides (which we can't use in this instance as searching must be done server-side).
The problem I'm facing is how to create search inputs for each table, make an ajax call and update the appropriate table. I want the search to work in realtime after >=3 characters have been entered. Critical to this question is that 1 search input is responsible for searching 1 DataTable - it's not a search feature where the input can update "any/every table on the page" which is a commonly described pattern in other questions. 1 input : searching 1 table in this case.
My plan has been as follows - each table referenced in point (2) has an ID. I need to create unique inputs. So if I have tables with ID's #table1, #table2, #table3 I can easily create:
<input type="text" name="table1_search" id="table1_search">
<input type="text" name="table2_search" id="table2_search">
<input type="text" name="table3_search" id="table3_search">
I then detect if any changes have occurred on inputs:
$('input[type="text"]').bind("keyup change input",
function (e) {
// Ignore tab key for keyup event otherwise it'll fire an ajax request that does nothing useful.
if (e.which !== 9) {
processSearch.call(this);
} else {
e.preventDefault();
}
});
var prev_value = {};
function processSearch() {
var obj = $(this),
search_id = obj.attr('id'), // ID of input
search_value = obj.val(); // Value of input
// There's been no change to the field, ignore.
if (prev_value[search_id] === search_value) {
return;
}
prev_value[search_id] = search_value;
/* Wait until at least 3 characters have been entered, or user has cleared the input */
if (search_value.length >= 3 || (!search_value)) {
debouncedDraw({search_id: search_id, search_value: search_value});
}
}
The above code does what I need in terms of waiting for >=3 characters to be entered. I'm then executing a function called debouncedDraw which passes an object containing search_id and search_value. These refer to the input ID and value respectively, e.g. if I type "foo" into #table1_search then the object is:
{search_id: 'table1_search', search_value: 'foo'}
The debouncedDraw function looks like this. This is using lodash to limit the rate at which the function can fire. The point here is to stop it making needless ajax requests based on a question I asked a few years ago here: DataTables - kill ajax requests when a new one has started:
var debouncedDraw = _.debounce(function (opts) {
console.log(opts);
}, 500);
At the moment this will just console.log the object given above.
I'm unsure of the best way to proceed at this point. I need to re-run /get-data.json via ajax and then update the appropriate table.
I could access the request data and split the search_id based on the underscore to work out which table ID the data is for (e.g. table1_search targets #table1). I then need to write this data back to the appropriate table (#table1 in this case).
I can't help but think I'm going about this in a convoluted way and wondered if DataTables itself has any better ways of supporting this? It seems quite a basic requirement (multiple searchable tables in serverSide mode). But I can't find any posts which refer how to do this specifically.
All the "gotchas" I've experienced over the years is encapsulated in the snippet below. This is the basic template I always use when creating a new datatable. You can create as many datatables on a page as you need using this pattern.
Personally I would use a different ajax url path/route for each table so that table logic is in separate files in the backend... but it is possible to have all the data logic in a single backend file. I modified my usual template to suit that.
<script> //I usually put the script section in the head tag
var table_1; //declare your table var here and initialize as a datatable inside document ready below.
$(document).ready(function() {
table_1 = $('#table_1').DataTable( {
dom: "Bfrtip",
ajax: {
url: "/get-data.json?table=table_1", //add query string var for backend routing
type: "POST" //use POST to not have to deal with url encoding various characters
},
serverSide: true,
searchDelay: 2000, // use this instead of custom debounce
processing: true, // optional visual indicator that a search has been sent to backend
lengthMenu: [ 10, 25, 50, 75, 100 ], // define per page limits. first value will be the default
buttons: [
"pageLength" // per page drop down button. i usually override/extend the default button
],
columns: [ // column definitions of json data fields
{ data: "col_1", title: "ID", width: "1%" }, // width: 1% makes col width as small as possible
{ data: "col_2", title: "Label 2", visible:false }, //visible: false allows you access to field data without displaying to user
{ data: "col_3", title: "Label 3", render: function ( data, type, row ) { //render allows combining of fields into single column
return data + ' <small>('+row.col_2+')</small>'; // data will be col_3 value. row.col_2 is how you reference col_2 value
} },
{ data: "col_4", title: "Label 4", searchable:false }, //searchable: false set this field to not be used in search
],
rowId: 'col_1' //sets the tr row id to the value in this column. useful for DOM and other manipulation later
} );
}
</script>
<table id="table_1" class="table table-striped table-bordered table-sm" style="width:100%"></table>
<!-- If you define title attributes in col definitions above you don't need to create html table headers/footers. Just an empty table tag will do. -->
With this pattern you can utilize the built-in search input that comes with datatables for your use case with server-side processing on all tables.
There's a method behind my madness which I tried to document in the script comments on each line. Let me know if you have a question on something. I'm thinking this is bounty worthy.
For reference, when developing a new app using datatables I basically live on this page https://datatables.net/reference/option/
Edit 1
Inside your existing debounced drawTable function you could do something like this:
function drawTable(id) {
$('#'+id).DataTable().ajax.url( 'get-data.json?table_id='+id+'&foo=bar' ); //update ajax url of existing dt - if necessary
$('#'+id).DataTable().search(search_input_val).draw(); // fire ajax request with value from your custom search input
}
I'm fairly certain you will need to set "searching" to true though for this method to work.
Edit 2
Another way I just thought of, without using dt search. Pass all your data through modified url and load/reload.
$('#'+id).DataTable().ajax.url( 'get-data.json?table_id='+id+'&search=foo' ).load();
You could then get rid of all the debounce stuff if you use a button click listener or an onblur listener on the input field and fire the same command above.
Have you seen this? https://datatables.net/reference/api/%24.fn.dataTable.util.throttle()
I've never used it before, but it looks like a debounce. The example on the page shows it being used for .search()
I've implemented the following but would prefer a better solution as I don't think this is efficient and it definitely isn't elegant!
Taking the code from the question I modified the debounce function as follows:
var debouncedDraw = _.debounce(function (opts) {
// Destroy the existing DataTable.
$('#' + opts.search_region).DataTable().destroy();
// Re-run the drawTable method to get the new DataTable with the search results
drawTable(opts.search_region);
}, 500);
I introduced a function called drawTable which takes the ID of a <table> and runs the DataTables initialisation code. The ajax object was also modified to take into account anything entered into the search keywords input for the given table ID:
function drawTable(id) {
$id = $('#'+id); // Convert string ID to jquery identifier
$id.DataTable({
// DataTable initialisation code as per question
ajax: {
data: {
table_id: id,
keywords: $('input[name="keywords_' + id + '"]').val() // search keywords for table_id
},
url: '/get-data.json',
},
// ... code as per question
});
}
The $.each() was modified so that it detects the ID of each <table> on page load and calls drawTable:
$.each($('table'), function () {
drawTable($(this).attr('id'));
});
This "works" in that it creates each of the required DataTable's on page load, and also handles the search. The search input names were modified to the format: keywords_ plus the ID of the table, e.g. keywords_table1.
I don't think this is efficient because I'm having to call destroy on my DataTable. As per the docs:
This has a very significant performance hit on the page, since a lot of calculations and DOM manipulation is involved, so if you can avoid this, and use the API, that is very strongly encouraged!
However the reason I'm doing this is also as given in the same docs:
DataTables does not allow initialisation options to be altered at any time other than at initialisation time. Any manipulation of the table after initialisation must be done through the API
Well, I'm not using the client-side search feature as I'm having to do searching server-side. So I'm unsure whether manipulating the table via the API would actually help in this instance anyway.
Are there better ways of achieving this?

How can i display content atributes using .ftl? Alfresco

I want to get attributes of a content using an ftl. Does anyone have an example or idea of ​​how to do it. thank you
Content Props
Workflow Form
You are asking to show a content property on a workflow form. The workflow does not have direct access to the content properties. And, there could be many pieces of content in the workflow, so which content are you talking about?
So, the way you have to do this is write some JavaScript in your workflow process that iterates over the documents in your workflow package to gather up the values you want to display on the workflow form, then set those values on one or more process variables.
If you have configured the workflow form in share to display those variables, the values will display on the workflow form.
Get name (or other properties) of content using javascript - Alfresco
var title;
var unitPrice;
Alfresco.util.Ajax.jsonGet(
{
url: Alfresco.constants.PROXY_URI_RELATIVE + "api/metadata?nodeRef=" + nodeRefContext + "&shortQNames=true" ,
successCallback:
{
fn: function(response)
{
if (response.json)
{
title=response.json.properties["cm:title"];
alert(title);
unitPrice=response.json.properties["art:unitPrice"];
alert(unitPrice);
}
},
scope: this
},
failureCallback:
{
fn: function(response)
{
Alfresco.util.PopupManager.displayPrompt(
{
failureMessage: this.msg("message.failure")
});
},
scope: this
}
});
reference link Get filename of workflow with javascript

Select2 not showing results in dropdown with AJAX

I'm working on creating an interface for some system I am working on and I am required to write the Javascript around pre-existing PHP AJAX functions that are used elsewhere in the system (purely as the person who does our DB stuff is too busy to adapt the code to my needs).
Using Select2 I need to make a select field where the user searches for their name in the database and selects the one matching it so it can then be posted to another AJAX function later. I have done this with the following code:
//<select id="sltMyName" style="width: 100%;"></select>
$("#sltMyName").select2({
ajax: {
type: "POST",
url: "includes/php/report_searchPlayers.php",
delay: 250,
data: function (params) {
return {
q: params.term // search term
};
},
processResults: function (data) {
console.log({ results: data.split(",") });
return { results: data.split(",") };
}
},
minimumInputLength: 1
});
This should turn a returned string in the format of name1,name2,name3,name... into the required format for Select2 to display, however, it does not currently work. The dropdown just appears blank.
I've seen some questions referring to a text and id attribute, however, they are all in the context of a JSON string being returned, so I am not sure if they are required here and how to utilise them in this context. Furthermore, I cannot find any of this in the documentation.
Any suggestions? Thanks in advance.
Data returned:
Tommy,Jak_Tommy_Lee_Jones,Tommy_Shelby,Tommy_Balboner,TommyCZ,GA_Tommy,VA_Tommy,Tommy_Skrattar,Tommy_Knocker,Tommy_of_Elektro,Tommy_the_Destroyer,Old_Tommy,tommy_of_house_shelby,TommyDermo,TommyC,TommyCash_CZ,Tommyb69k,SA_Tommy,tommyfaster,Tommy_See,Tommy_de_Destroyer,Tommy_of_Whiteroses,TommyShelby,Templar_Intiate_Tommy,Templar_Initiate_Tommy,tommysuckspp,Tommy_the_Overweight
I think I've figured it out. The main issue is that the data that Select2 wants to use needs to be an array of objects with at least a property named id and a property named text. In the processResults function, just create those objects & then the dropdown will populate with the data from your URL!
I've noticed that it tries to filter the data as i type, but since the url I passed in does not accept the parameters, it just returns the same data each time. Let me know if you need a more robust example.
See my fiddle at https://jsfiddle.net/yp0rp2kw/3/ for a working solution.

pass Algolia id attribute instead of Name Atributre in a post request on Laravel 5.2

Using the Javascript, Vue.js and Typeahead.js way shown by Jeffery Way and Algolia docs to index json objects from the Algolia platform.
Currently when i search for the result i require and hit the submit button, It is passing the name attribute through in the post request.
How is it possible to pass the name and the id attribute or if nescessery just the ID arrtibute would work.
<script>
new Vue({
el: 'body',
data: {
query: '',
users: []
},
ready: function(){
this.client = algoliasearch("MYID", "MYAPI");
this.index = this.client.initIndex('dev_category_list');
$('#typeahead').typeahead(null, {
source: this.index.ttAdapter(),
displayKey: 'name'
});
},
methods: {
search: function(){
if (this.query.length < 3) return;
this.index.search(this.query, function(error, results){
this.users = results.hits;
}.bind(this));
}
}
})
</script>
As a total newcomer the laravel, vuejs and javascript its somewhat difficult to get to grips with the syntax and phrases used when explaining the instructons within the docs so any help would be greatly appreciated.
My indexed objects look like so:
{
"id": "3",
"name": "My Product 3",
"value": "3",
"alternative_name": "Prod 3",
"objectID": "3"
}
Im hoping to pass the value of ID or objectID along with the name attribute in a post request once the user selects the given result from the algolia drop down menu and hits the submit, just the ID would work as mentioned above if its not possible.
Thanks.
--- Update referencing Jerska: ---
Ok so after playing around as a newbie for a little bit i seem to have it working, Im not exactly sure how secure this is or how reliable one would say, Hopefully im not a million miles off from where i need to be. Be good to see what your personal and professional thoughts are.
.on('typeahead:select', function (e, suggestion) {
$('#typeahead').change(function() {
var val = suggestion.id;
$('#st').val(val);
});
I have created a hidden input field and named is 'st' for a demo and on update of the algolia results jquery is using the .change function to append the value to the hidden input fields value. That way the form can be continued and sibmitted as i originally wanted and hoped for, The benefit here is that even if the user is to select a result from algoia drop down menu then continue with the form, If he or she decides they want to go back to the search field and change it, They can do before they submit the form or before any window.location is run, I even thought of using ajax or simply jquery $.post but its working ok the .change
Look forward to hearing your thoughts.
Thanks
If you want to redirect to an item page, the typeahead:select event gives you the selected option :
$('#your-input')
.typeahead(/* ... */)
.on('typeahead:select', function (e, suggestion) {
window.location = suggestion.url;
});
from Algolia redirect to search results
You can access the selected object through the suggestion parameter. You could definitely use something like
window.location = 'YOUR_URL?id=' + suggestion.id + '&name=' + suggestion.name;
This assumes you're using typeahead.js#0.11.
typeahead.js being unmaintained, Algolia recommends to use their own fork of typeahead.js#0.10, autocomplete.js.
Here are the different event names and handlers signatures depending on what library/version you're using:
typeahead.js#0.11: typeahead:select -> function($event, suggestion)
typeahead.js#0.10: typeahead:selected -> function($event, suggestion, datasetName)
autocomplete.js: autocomplete:selected -> function($event, suggestion, datasetName)

Jquery exporting table to csv hidden table cells

I need to be able to export a HTML table to CSV. I found a snippet somewhere; it works but not entirely how I want it to.
In my table (in the fiddle) I have hidden fields, I just use quick n dirty inline styling and inline onclicks to swap between what you see.
What I want with the export is that it selects the table as currently displayed. so only the td's where style="display:table-cell". I know how to do this in normal JS.
document.querySelectorAll('td[style="display:table-cell"])');
but how can I do this using the code I have right now in the exportTableToCSV function?
(sorry but the text in the fiddle is in dutch as its a direct copy of the live version).
The fiddle:
http://jsfiddle.net/5hfcjkdh/
In your grabRow method you can filter out the hidden table cells using jQuery's :visible selector. Below is an example
function grabRow(i, row) {
var $row = $(row);
//for some reason $cols = $row.find('td') || $row.find('th') won't work...
//Added :visisble to ignore hidden ones
var $cols = $row.find('td:visible');
if (!$cols.length) $cols = $row.find('th:visible');
return $cols.map(grabCol)
.get().join(tmpColDelim);
}
Here's how i solved it. Decided to step away from a pure javascript solution to take processing stress off the client and instead handle it server side.
Because i already get the data from the database using a stored procedure i use this to just get the dataset again and convert it into an ViewExportModel so i have a TotalViewExport and a few trimmed variations (reuse most of them) based on a Selected variable i fill a different model.
Added to the excisting show function to update a Selected variable to keep track of the currently selected view.
When the user clicks Export table to excel it calls to the controller of the current page, IE. AlarmReport (so AlarmReportController) and i created the action ExportReports(int? SelectedView);
In addition i added CsvExport as a manager. This takes data results (so c# models/ iqueryables/ lists/ etc). and puts them into a Csv set. using the return type BinaryContent one can export a .csv file with this data.
The action ExportReports calls the stored procedure with the selectedview parameter. The result gets pumped into the correct model. this model is pumped into the CsvExport model as rows.
The filename is made based on the selected view + What object is selected + current date(yyyy-MM-dd). so for example "Total_Dolfinarium_2016-05-13". lets
lastly the action returns the .csv file as download using the BinaryContent Returntype and ExportToBytes from the CsvExport
The export part of this action is programmed like so(shortened to leave some checks out like multiple objects selected etc)(data and objectnames are gathred beforehand):
public ActionResult ExportCsv(CsvExport Data, string ObjectName, string Type){
var FileName = Type + "_" + ObjectName + "_" + DateTime.Now.ToString("yyyy/MM/dd");
return BinaryContent("text/csv", FileName + ".csv", Data.ExportToBytes());
}

Categories

Resources