Skip to content

Commit 5b852b3

Browse files
Add proper paste support
Add paste="expression" to allow custom paste handling. Allow pasting in tagging mode when the tagging function is not defined. In IE use window.clipboardData so jQuery is not required. Fixes angular-ui#910, angular-ui#704, angular-ui#789, angular-ui#848, angular-ui#429
1 parent 4467b82 commit 5b852b3

File tree

3 files changed

+94
-27
lines changed

3 files changed

+94
-27
lines changed

src/uiSelectController.js

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ uis.controller('uiSelectCtrl',
1616
ctrl.searchEnabled = uiSelectConfig.searchEnabled;
1717
ctrl.sortable = uiSelectConfig.sortable;
1818
ctrl.refreshDelay = uiSelectConfig.refreshDelay;
19+
ctrl.paste = uiSelectConfig.paste;
1920

2021
ctrl.removeSelected = false; //If selected item(s) should be removed from dropdown list
2122
ctrl.closeOnSelect = true; //Initialized inside uiSelect directive link function
@@ -295,7 +296,7 @@ uis.controller('uiSelectCtrl',
295296
// create new item on the fly if we don't already have one;
296297
// use tagging function if we have one
297298
if ( ctrl.tagging.fct !== undefined && typeof item === 'string' ) {
298-
item = ctrl.tagging.fct(ctrl.search);
299+
item = ctrl.tagging.fct(item);
299300
if (!item) return;
300301
// if item type is 'string', apply the tagging label
301302
} else if ( typeof item === 'string' ) {
@@ -491,18 +492,36 @@ uis.controller('uiSelectCtrl',
491492

492493
});
493494

494-
// If tagging try to split by tokens and add items
495495
ctrl.searchInput.on('paste', function (e) {
496-
var data = e.originalEvent.clipboardData.getData('text/plain');
497-
if (data && data.length > 0 && ctrl.taggingTokens.isActivated && ctrl.tagging.fct) {
498-
var items = data.split(ctrl.taggingTokens.tokens[0]); // split by first token only
499-
if (items && items.length > 0) {
500-
angular.forEach(items, function (item) {
501-
var newItem = ctrl.tagging.fct(item);
502-
if (newItem) {
503-
ctrl.select(newItem, true);
504-
}
505-
});
496+
var data;
497+
498+
if (window.clipboardData && window.clipboardData.getData) { // IE
499+
data = window.clipboardData.getData('Text');
500+
} else {
501+
data = (e.originalEvent || e).clipboardData.getData('text/plain');
502+
}
503+
504+
// Prepend the current input field text to the paste buffer.
505+
data = ctrl.search + data;
506+
507+
if (data && data.length > 0) {
508+
// If tagging try to split by tokens and add items
509+
if (ctrl.taggingTokens.isActivated) {
510+
var items = data.split(ctrl.taggingTokens.tokens[0]); // split by first token only
511+
if (items && items.length > 0) {
512+
angular.forEach(items, function (item) {
513+
var newItem = ctrl.tagging.fct ? ctrl.tagging.fct(item) : item;
514+
if (newItem) {
515+
ctrl.select(newItem, true);
516+
}
517+
});
518+
ctrl.search = EMPTY_SEARCH;
519+
e.preventDefault();
520+
e.stopPropagation();
521+
}
522+
} else if (ctrl.paste) {
523+
ctrl.paste(data);
524+
ctrl.search = EMPTY_SEARCH;
506525
e.preventDefault();
507526
e.stopPropagation();
508527
}

src/uiSelectDirective.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ uis.directive('uiSelect',
8585
$select.resetSearchInput = resetSearchInput !== undefined ? resetSearchInput : true;
8686
});
8787

88+
attrs.$observe('paste', function() {
89+
$select.paste = scope.$eval(attrs.paste);
90+
});
91+
8892
attrs.$observe('tagging', function() {
8993
if(attrs.tagging !== undefined)
9094
{

test/select.spec.js

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -173,15 +173,23 @@ describe('ui-select tests', function() {
173173
e.keyCode = keyCode;
174174
element.trigger(e);
175175
}
176-
function triggerPaste(element, text) {
176+
function triggerPaste(element, text, isClipboardEvent) {
177177
var e = jQuery.Event("paste");
178-
e.originalEvent = {
178+
if (isClipboardEvent) {
179+
e.clipboardData = {
180+
getData : function() {
181+
return text;
182+
}
183+
};
184+
} else {
185+
e.originalEvent = {
179186
clipboardData : {
180187
getData : function() {
181188
return text;
182189
}
183190
}
184-
};
191+
};
192+
}
185193
element.trigger(e);
186194
}
187195

@@ -2063,20 +2071,39 @@ describe('ui-select tests', function() {
20632071
});
20642072

20652073
it('should allow paste tag from clipboard', function() {
2066-
scope.taggingFunc = function (name) {
2067-
return {
2068-
name: name,
2069-
email: name + '@email.com',
2070-
group: 'Foo',
2071-
age: 12
2072-
};
2073-
};
2074+
scope.taggingFunc = function (name) {
2075+
return {
2076+
name: name,
2077+
email: name + '@email.com',
2078+
group: 'Foo',
2079+
age: 12
2080+
};
2081+
};
2082+
2083+
var el = createUiSelectMultiple({tagging: 'taggingFunc', taggingTokens: ",|ENTER"});
2084+
clickMatch(el);
2085+
triggerPaste(el.find('input'), 'tag1');
2086+
2087+
expect($(el).scope().$select.selected.length).toBe(1);
2088+
expect($(el).scope().$select.selected[0].name).toBe('tag1');
2089+
});
2090+
2091+
it('should allow paste tag from clipboard for generic ClipboardEvent', function() {
2092+
scope.taggingFunc = function (name) {
2093+
return {
2094+
name: name,
2095+
email: name + '@email.com',
2096+
group: 'Foo',
2097+
age: 12
2098+
};
2099+
};
20742100

2075-
var el = createUiSelectMultiple({tagging: 'taggingFunc', taggingTokens: ",|ENTER"});
2076-
clickMatch(el);
2077-
triggerPaste(el.find('input'), 'tag1');
2101+
var el = createUiSelectMultiple({tagging: 'taggingFunc', taggingTokens: ",|ENTER"});
2102+
clickMatch(el);
2103+
triggerPaste(el.find('input'), 'tag1', true);
20782104

2079-
expect($(el).scope().$select.selected.length).toBe(1);
2105+
expect($(el).scope().$select.selected.length).toBe(1);
2106+
expect($(el).scope().$select.selected[0].name).toBe('tag1');
20802107
});
20812108

20822109
it('should allow paste multiple tags', function() {
@@ -2096,6 +2123,23 @@ describe('ui-select tests', function() {
20962123
expect($(el).scope().$select.selected.length).toBe(5);
20972124
});
20982125

2126+
it('should allow paste multiple tags with generic ClipboardEvent', function() {
2127+
scope.taggingFunc = function (name) {
2128+
return {
2129+
name: name,
2130+
email: name + '@email.com',
2131+
group: 'Foo',
2132+
age: 12
2133+
};
2134+
};
2135+
2136+
var el = createUiSelectMultiple({tagging: 'taggingFunc', taggingTokens: ",|ENTER"});
2137+
clickMatch(el);
2138+
triggerPaste(el.find('input'), ',tag1,tag2,tag3,,tag5,', true);
2139+
2140+
expect($(el).scope().$select.selected.length).toBe(5);
2141+
});
2142+
20992143
it('should add an id to the search input field', function () {
21002144
var el = createUiSelectMultiple({inputId: 'inid'});
21012145
var searchEl = $(el).find('input.ui-select-search');

0 commit comments

Comments
 (0)