Skip to content

Commit

Permalink
For #5
Browse files Browse the repository at this point in the history
  • Loading branch information
andrechalom committed Nov 28, 2017
1 parent 36f4215 commit 9ffb8d6
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 3 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Register provider and facade on your config/app.php file. This is necessary for

The jQuery code required by this package is in the file multiselect.js. If you use Laravel Mix, you can include it
in your mix.js. Otherwise, copy it to your public folder and source it directly in the app layout.
Remember to do it after you include jquery.
Remember to do it after you include jQuery.

Example:

Expand Down Expand Up @@ -152,6 +152,11 @@ of the `span` function (strict mode).
) !!}
```

(4) You can also use an autocomplete input instead of a select element! To do so, import
[devbridge's Autocomplete plugin](https://github.com/devbridge/jQuery-Autocomplete), replace the calls to
`Multiselect::select()` to `Multiselect::autocomplete()`, and include a `Multiselect::scripts()` call after
jQuery is loaded.

## Change log

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
Expand Down
46 changes: 44 additions & 2 deletions resources/assets/js/multiselect.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ $(document).ready(function(){
// The elements are tied by the NAME, CLASS AND ID attributes, use them as
// span: ID specialist-span
// select: ID specialist-ms CLASS .multiselect
// inputs: ID specialists[] NAME specialist[] CLASS .multiselector
$(".multiselect").change(function()
// inputs: ID specialist[] NAME specialist[] CLASS .multiselector
$("select.multiselect").change(function()
{
var $name = $(this).attr('id');
$name = $name.substring(0, $name.length-3);
Expand All @@ -20,4 +20,46 @@ $(document).ready(function(){
$(this).find('option:selected').text() + '</span>');
}
});
// chainable custom autocomplete with some global defaults
$.fn.lmsAutocomplete = function(url, params) {
// forces the tied-together names (input, span, hidden inputs)
var name = $(this).attr('id');
name = name.substring(0, name.length-3);
// provides some default parameters
var autocomplete_params = {
serviceUrl: url,
onSelect: function (suggestion) {
var $span = $("#" + name + "-span");
if ( $(this).val() === "") {
return;
}
if ($span.find('input[value=' + suggestion.data + ']').length == 0) {
$span.append('<span class="multiselector" onclick="$(this).remove();">' +
'<input type="hidden" name="' + name + '[]" value="' +
suggestion.data + '" /> ' +
suggestion.value + '</span>');
}
},
minChars: 3,
onSearchStart: function() {
$(".minispinner").remove();
$(this).after("<div class='spinner minispinner'></div>");
},
onSearchComplete: function() {
$(".minispinner").remove();
}
};
// Merges the received params
if (typeof params === "object") {
// this is probably intended:
if (typeof params.noSuggestionNotice !== "undefined") {
params.showNoSuggestionNotice = true;
}
autocomplete_params = Object.assign(autocomplete_params, params);
}
if (!$.fn.devbridgeAutocomplete) {
throw 'Library laravel-multiselect is using autocomplete, but devbridgeAutocomplete is not available!';
}
return this.devbridgeAutocomplete(autocomplete_params);
};
});
59 changes: 59 additions & 0 deletions src/Multiselect.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,65 @@ protected function option($display, $value, array $attributes = [])
return $this->toHtmlString('<option' . $this->attributes($options) . '>' . e($display) . '</option>');
}

/**
* Create the multi-select autocomplete field and optionally the already selected span field.
* This method interface mimicks LaravelCollective\html select method.
*
* @param string $name The name of the select element. Will be used by the JS to add hidden inputs
* @param array $list A Laravel collection or list of key => values
* @param array $selected A laravel collection or list of keys
* @param array $inputAttributes
* @param array $spanAttributes
* @param boolean $inputOnly
*
* @return \Illuminate\Support\HtmlString
*/
public function autocomplete(
$name,
$list = [],
$selected = [],
array $inputAttributes = [],
array $spanAttributes = [],
$inputOnly = false
) {
// Forces the ID attribute
$inputAttributes['id'] = $name . "-ms";
if (!isset($inputAttributes['class'])) {
$inputAttributes['class'] = "multiselect";
}

// We will concatenate the span html unless $selectOnly is passed as false
$spanHtml = $inputOnly ? "" : $this->span($name, $list, $selected, $spanAttributes);

$inputAttributes = $this->attributes($inputAttributes);

return $this->toHtmlString($spanHtml . "<input type=\"text\"{$inputAttributes}>");
}

/**
* Create the javaScript scripts required for the multi-select autocomplete plugin.
* Notice that this should be called *after* jQuery has been imported
*
* @param string $name The name of the select element.
* @param string $url The URL to be used for getting the autocomplete responses
* @param array $params Further parameters to be passed to devbridgeAutocomplete
*
* @return \Illuminate\Support\HtmlString
*/
public function scripts(
$name,
$url,
array $params = []
) {
$inputName = $name . "-ms";

return $this->toHtmlString(
'<script>$("' . $inputName. '").lmsAutocomplete("' .
$url . '", ' .
json_encode($params, true) .
');</script>');
}

/**
* Create the multi-select select box field and optionally the already selected span field.
* This method interface mimicks LaravelCollective\html select method.
Expand Down
27 changes: 27 additions & 0 deletions tests/MultiselectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,31 @@ public function testSelectWithPlaceholder()
$element = $select->select('name', [], [], ['placeholder' => 'placeholder-text'], [], [], true)->toHtml();
$this->assertSame('<select id="name-ms" class="multiselect"><option value="">placeholder-text</option></select>', $element);
}

/////////////////////////////////////////////////
// Tests for generating the autocomplete input //
/////////////////////////////////////////////////
public function testInputEmpty()
{
$select = new Multiselect();
$element = $select->autocomplete('name', [], [], [], [], true)->toHtml();
$this->assertSame('<input type="text" id="name-ms" class="multiselect">', $element);
}

///////////////////////////////////////////////////
// Tests for generating the autocomplete scripts //
///////////////////////////////////////////////////
public function testScriptsSimple()
{
$select = new Multiselect();
$element = $select->scripts('name', 'http://url/', [])->toHtml();
$this->assertSame('<script>$("name-ms").lmsAutocomplete("http://url/", []);</script>', $element);
}

public function testScriptsParams()
{
$select = new Multiselect();
$element = $select->scripts('name', 'http://url/', ['minChars' => 5, 'showNoSuggestionNotice' => true])->toHtml();
$this->assertSame('<script>$("name-ms").lmsAutocomplete("http://url/", {"minChars":5,"showNoSuggestionNotice":true});</script>', $element);
}
}

0 comments on commit 9ffb8d6

Please sign in to comment.