Skip to content

Commit 17aac66

Browse files
authored
Merge pull request #8 from silverstripe-superchargers/dev/ss4-upgrade
Upgrade module to SS4
2 parents 24d99ca + 771be8c commit 17aac66

File tree

6 files changed

+107
-64
lines changed

6 files changed

+107
-64
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ Uses a plugin for Chosen.js (which is used by SS), [Image-Select](https://github
55

66
![Working screenshot](https://github.com/Copperis/DropdownImageField/raw/master/docs/img/ss.png)
77

8+
## Requirements
9+
10+
SilverStripe 4.0+
11+
812
## Usage
913

1014
Example:

_config/config.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
Name: dropdownimagefield
3+
---
4+
5+
SilverStripe\Admin\LeftAndMain:
6+
extra_requirements_javascript:
7+
- 'copperis/dropdownimagefield: javascript/Polyfill.js'
8+
- 'copperis/dropdownimagefield: javascript/ImageSelect.jquery.js'
9+
extra_requirements_css:
10+
- 'copperis/dropdownimagefield: css/ImageSelect.css'

code/DropdownImageField.php

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
<?php
22

3+
namespace Copperis\DropdownImageField;
4+
5+
use SilverStripe\Forms\DropdownField;
6+
use SilverStripe\View\Requirements;
7+
use SilverStripe\View\ArrayData;
8+
use SilverStripe\ORM\ArrayList;
9+
use SilverStripe\Forms\FormField;
10+
311
class DropdownImageField extends DropdownField {
412

513
protected $keyField, $labelField, $imageField;
@@ -18,21 +26,15 @@ public function __construct($name, $title, $sourceObject, $keyField = 'ID', $lab
1826
public function Field($properties = array()) {
1927

2028
$dirName = basename(dirname(dirname(__FILE__)));
21-
;
22-
23-
Requirements::javascript($dirName . '/javascript/Polyfill.js');
24-
Requirements::javascript($dirName . '/javascript/ImageSelect.jquery.js');
25-
Requirements::css($dirName . '/css/ImageSelect.css');
26-
2729
$source = $this->getSource();
2830
$options = array();
2931
if ($source) {
3032
if (is_object($source) && $this->hasEmptyDefault) {
31-
$options[] = new ArrayData(array(
33+
$options[] = new ArrayData([
3234
'Value' => '',
3335
'Title' => $this->emptyString,
3436
'Image' => ''
35-
));
37+
]);
3638
}
3739

3840
foreach ($source as $item) {
@@ -64,17 +66,19 @@ public function Field($properties = array()) {
6466
$disabled = 'disabled';
6567
}
6668

67-
$options[] = new ArrayData(array(
69+
$options[] = new ArrayData([
6870
'Title' => $title,
6971
'Value' => $value,
7072
'Image' => $image,
7173
'Selected' => $selected,
7274
'Disabled' => $disabled,
73-
));
75+
]);
7476
}
7577
}
7678

77-
$properties = array_merge($properties, array('Options' => new ArrayList($options)));
79+
$properties = array_merge($properties, [
80+
'Options' => new ArrayList($options)
81+
]);
7882

7983
return FormField::Field($properties);
8084
}
@@ -90,7 +94,7 @@ public function getSourceAsArray() {
9094
if (is_array($source)) {
9195
return $source;
9296
}
93-
97+
9498
return $source->map($this->keyField, $this->labelField)->toArray();
9599
}
96100

composer.json

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
{
22
"name": "copperis/dropdownimagefield",
33
"description": "Dropdown field with image support for SilverStripe CMS",
4-
"type": "silverstripe-module",
4+
"type": "silverstripe-vendormodule",
55
"keywords": ["silverstripe", "dropdown", "image", "field"],
66
"license": "MIT",
77
"support": {
88
"issues": "http://github.com/Copperis/DropdownImageField/issues"
99
},
1010
"require": {
11-
"silverstripe/framework": "~3.1",
12-
"silverstripe/cms": "~3.1"
13-
}
11+
"silverstripe/framework": "^4",
12+
"silverstripe/cms": "^4"
13+
},
14+
"extra": {
15+
"expose": [
16+
"css",
17+
"javascript"
18+
]
19+
}
1420
}

javascript/ImageSelect.jquery.js

Lines changed: 67 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
// Store the original 'chosen' method
1919
var fn_chosen = $.fn.chosen;
2020

21-
$.fn.extend({
21+
$.fn.extend({
2222
// summery:
2323
// Extend the original 'chosen' method to support images
2424

@@ -28,22 +28,32 @@
2828

2929
var html_template = options.html_template || fn_template;
3030

31+
var self = this;
32+
3133
// Attach Ready event before continue with chose
3234
this.each(function(input_field) {
3335

3436
$this = $(this);
3537

36-
$this.on("liszt:ready", function change(e, chosen){
37-
38+
$this.on("chosen:ready", function change(e, chosen){
3839
chosen = chosen.chosen;
3940

41+
// The change event handler used further down doesn't pass in the chosen object so we need to store this for later.
42+
self.chosen = chosen;
43+
44+
// The ready event is being triggered twice so ensure we only handle it once
45+
if (self.readyEventTriggered) {
46+
return;
47+
} else {
48+
self.readyEventTriggered = true;
49+
}
50+
4051
var form_field = chosen.form_field;
4152

4253
var options = form_field.options;
43-
var spans = $(chosen.container).find('.chzn-choices span');
44-
54+
var spans = $(chosen.container).find('.chosen-choices span');
4555

46-
if(options && options.length){
56+
if(options && options.length){
4757

4858
for(var i = 0 ; i < options.length; i++){
4959

@@ -53,36 +63,32 @@
5363
var text = $(option).text();
5464

5565
if(selected && img_src){
56-
57-
var template = html_template.replace('{url}',img_src);
58-
59-
if(spans.length){
60-
for (var j = 0; j < spans.length; j++)
61-
if(text == $(spans[j]).text()){
62-
$(spans[j]).prepend(template.replace('{class_name}','chose-image'));
63-
}
66+
var template = html_template.replace('{url}',img_src);
67+
if(spans.length){
68+
for (var j = 0; j < spans.length; j++)
69+
if(text === $(spans[j]).text()){
70+
$(spans[j]).prepend(template.replace('{class_name}','chose-image'));
71+
}
6472
} else {
65-
$(chosen.container).find('.chzn-single span').prepend(template.replace('{class_name}','chose-image-small'));
73+
$(chosen.container).find('.chosen-single span').prepend(template.replace('{class_name}','chose-image-small'));
6674
}
6775
}
6876

6977
}
7078
}
7179

72-
});
80+
});
7381
});
7482

7583
// original behavior - use function.apply to preserve context
7684
var ret = fn_chosen.apply(this, arguments);
7785

7886
this.each(function(input_field) {
7987

80-
var $this, chosen;
88+
var $this;
8189

8290
$this = $(this);
8391

84-
chosen = $this.data('chosen');
85-
8692
$this.on("change", function change(evt,selected){
8793
// summery
8894
// This function is triggered when the chosen instance has changed,
@@ -91,35 +97,40 @@
9197
// selected: Object
9298
// Contains the value of the selected
9399
//
100+
101+
var chosen = self.chosen;
94102
var options = chosen.form_field.options;
95103

96-
if(selected != undefined && selected.selected != undefined && options && options.length){
104+
if(selected !== undefined && selected.selected !== undefined && options && options.length){
97105

98106
for(var i = 0 ; i < options.length; i++){
99107
var option = options[i];
100108
var value = ($(option).attr('value')) ? $(option).attr('value') : $(option).text();
101109
var img_src = $(option).attr('data-img-src');
102110

103-
if(img_src != undefined && selected.selected == value){
111+
if(img_src !== undefined && selected.selected === value){
104112
var template = html_template.replace('{url}',img_src);
105113

106114
// For multiple selection
107-
span = $(chosen.container).find('.chzn-choices span').last()
115+
span = $(chosen.container).find('.chosen-choices span').last()
108116
span.find('img').remove()
109117
span.prepend(template.replace('{class_name}','chose-image'));
110118

111119
// For single select
112-
span = $(chosen.container).find('.chzn-single span')
120+
span = $(chosen.container).find('.chosen-single span')
113121
span.find('img').remove()
114122
span.prepend(template.replace('{class_name}','chose-image-small'));
115123
}
116124
}
117125
}
118126
});
119127

120-
$this.on("liszt:hiding_dropdown", function(e, _c){
121-
122-
var options = chosen.form_field.options;
128+
$this.on("chosen:hiding_dropdown", function(e, chosen){
129+
if (!chosen) {
130+
return;
131+
}
132+
chosen = chosen.chosen;
133+
var options = chosen.form_field; //.options;
123134

124135
var selected = $(chosen.form_field).find(':selected');
125136

@@ -132,17 +143,17 @@
132143
var template = html_template.replace('{url}',img_src);
133144

134145
// For multiple selection
135-
span = $(chosen.container).find('.chzn-choices span').last()
146+
span = $(chosen.container).find('.chosen-choices span').last()
136147
span.find('img').remove()
137148
span.prepend(template.replace('{class_name}','chose-image'));
138149

139150
// For single select
140-
span = $(chosen.container).find('.chzn-single span')
151+
span = $(chosen.container).find('.chosen-single span')
141152
span.find('img').remove()
142153
span.prepend(template.replace('{class_name}','chose-image-small'));
143154
})
144155

145-
$this.on("liszt:showing_dropdown", function showing_dropdown(evt, _chosen){
156+
$this.on("chosen:showing_dropdown", function showing_dropdown(evt, _chosen){
146157
// summery
147158
// This function is triggered when the chosen instance dropdown list becomes visible
148159
// For Chose custom events: http://forwebonly.com/jquery-chosen-custom-events-and-how-to-use-them/
@@ -151,28 +162,36 @@
151162
// The event object
152163
// _chosen: Object {chosen:Chosen}
153164
// Contains the current instance of Chosen class
154-
var lis = $(chosen.container).find('.chzn-drop ul li')
155-
var options = $(chosen.form_field).find('optgroup, option:not(:empty)');
156-
157-
// SS uses a modified Chosen.js and after the 'showing_dropdown' event the
158-
// values get immediatelly reset, also removing the images. Solved it with setTimeout.
159-
setTimeout(function(lis, options){
160-
for(var i = 0; i < lis.length; i++){
161-
var li = lis[i];
162-
var option = options[i];
163-
var img_src = $(option).attr('data-img-src');
164165

165-
if(typeof img_src != 'undefined' && img_src != ''){
166-
var template = html_template.replace('{url}',img_src);
167-
$(li).prepend(template.replace('{class_name}','chose-image-list'));
168-
}
166+
// Ensure images have not already been processed (occurs because this dropdown event seems to be
167+
// triggered twice.
168+
var hasImage = $(_chosen.chosen.container).find('.chosen-drop ul li img');
169+
if (hasImage.length > 0) {
170+
return;
171+
}
172+
173+
var lis = $(_chosen.chosen.container).find('.chosen-drop ul li')
174+
var options = $(_chosen.chosen.form_field).find('optgroup, option:not(:empty)');
175+
176+
for(var i = 0; i < lis.length; i++){
177+
var li = lis[i];
178+
var option = options[i];
179+
var img_src = $(option).attr('data-img-src');
180+
181+
if(typeof img_src !== 'undefined' && img_src !== ''){
182+
var template = html_template.replace('{url}',img_src);
183+
$(li).prepend(template.replace('{class_name}','chose-image-list'));
169184
}
170-
}, 1, lis, options);
185+
}
171186
});
172-
});
173-
$this.trigger('liszt:hiding_dropdown');
187+
});
188+
189+
if (typeof $this !== 'undefined') {
190+
$this.trigger('chosen:hiding_dropdown');
191+
}
192+
174193
return ret;
175194
}
176-
});
195+
});
177196

178-
})(jQuery);
197+
})(jQuery);
File renamed without changes.

0 commit comments

Comments
 (0)