I have a UITextField that I need to select programmatically so when the user taps on a date in a UIDatePicker, it will be sent to that UITextField.
This is the code I have, which does not select the UITextField; I have tried all possible combinations of UIControlEvent, but none of them work. Any other ideas?
// set textField parameters
if([whichTextField isEqualToString:#"oStartTime"]) {
oStartTime.backgroundColor = [UIColor colorWithRed:252.0/255.0 green:255.0/255.0 blue:197.0/255.0 alpha:1.0];
[oStartTime sendActionsForControlEvents: UIControlEventTouchUpInside];
}
else if([whichTextField isEqualToString:#"oFinishTime"]) {
oFinishTime.backgroundColor = [UIColor colorWithRed:252.0/255.0 green:255.0/255.0 blue:197.0/255.0 alpha:1.0];
[oFinishTime sendActionsForControlEvents: UIControlEventTouchUpInside];
}
See the UIResponder instance method becomeFirstResponder.
yourTextField.becomeFirstResponder()
Related
How to get the cursor position(top, left) value in Draft.js. I have already seen this question, but it gives only the line number, but I want the top, left value.
This is working for my needs (NB: not tested on multi-platform/multi-browser, but at least it works great on Chrome/Firefox on Windows). The idea is to consider the caret as a mere window selection, and not as a draftjs selection. Hope it'll help.
function FindCaretPosition() {
let selection = window.getSelection();
let selectionRange = selection.getRangeAt(0).cloneRange();
selectionRange.collapse(false);
//-----
let caretMarker = document.createElement("span");
caretMarker.id = "__caret";
selectionRange.insertNode(caretMarker);
let caretPosition = document.querySelector("#__caret").getBoundingClientRect();
//-----
selectionRange.deleteContents();
return { x: caretPosition.left, y: caretPosition.bottom }
}
editorState.getSelection().getAnchorOffset();
you can get the position of cursor like that
I have a button which creates other buttons based on the class Clip seen below. Those newly created buttons are added to an array and stored in a plist.
class Clip: Encodable, Decodable {
var name: String = ""
var xCoordinate: Int = 100
var yCoordinate: Int = 300
// more parameter will be added later on e.g color, scale etc..
}
Each button can be moved around the view and the new x & y coordinates are stored in a plist.
#objc func handlePan(sender: UIPanGestureRecognizer){
let uIViewSelected = sender.view!
switch sender.state {
case .began, .changed :
moveViewWithPan(view: uIViewSelected, sender: sender)
break
case .ended:
//Finds the position when the button is no longer being dragged
let x = Int(uIViewSelected.center.x)
let y = Int(uIViewSelected.center.y)
//clipArray[0] need to be the corresponding clicked button e.g clipArray[2]
clipArray[0].xCoordinate = x
clipArray[0].yCoordinate = y
saveData()
break
default:
break
}
}
The above works only if I create one button. When more buttons are added, the above lines only change the first clip from the array. I need a way to update the value to the correct button clicked.
How can identify the array position of the click button as I am creating all them programmatically? At the moment I am placing at value 0 of the clipArray.
clipArray[0].xCoordinate = x
clipArray[0].yCoordinate = y
I am not even sure if using a plist is the best way to store the buttons in the first place.
Any help or documentation would be much appreciated.
Thanks
Following from dfd response, I added tags to each button which are created and it solved the issue for now.
let x = Int(uIViewSelected.center.x)
let y = Int(uIViewSelected.center.y)
//clipArray.append(clip)
var tagNo = uIViewSelected.tag
clipArray[tagNo].xCoordinate = x
clipArray[tagNo].yCoordinate = y
I have a table that displays several entries, each has an <input>. The user can dynamically add additional inputs by clicking an "add entry" button. I need to iterate over them before saving and validate each one. I simplified my example to check that the value of each input is greater than 100 (ultimately I will use a pattern-match to validate MAC and IP addresses).
I can probably handle it if I could select all <input>s, but I would really like to select a specific <input> using an index I already have in my scope. I read that angular.element is a way, but I need to select something that was dynamically created, and thus not named something easy like id="myInput". Unless I use an id of "input" and append a unique number with Angular's $index in the id attribute?
Here is my Fiddle that shows what I'm doing. Line 44 is an if() that should check if any <input> is greater than 100. The "Save Row" button validates that the input is greater than 100, but if you edit a line, I need the "Save" button to validate any that the user has edited (by clicking Edit next to it).
tl;dr:
How can I use Angular to select an <input> that has been created dynamically?
I have updated your fiddle in a clean way so that you can maintain the validation in a generic method for both add & edit.
function validateBinding(binding) {
// Have your pattern-match validation here to validate MAC and IP addresses
return binding.ip > 100;
}
Updated fiddle:
https://jsfiddle.net/balasuar/by0tg92m/27/
Also, I have fixed the current issue with editing you have to allow multiple editing without save the first row when clicking the next edit on next row.
The validation of 'save everything' is now cleaner in angular way as below.
$scope.changeEdit = function(binding) {
binding.onEdit = true;
//$scope.editNum = newNum;
$scope.showSave = true;
};
$scope.saveEverything = function() {
var error = false;
angular.forEach($scope.macbindings, function(binding) {
if(binding.onEdit) {
if (validateBinding(binding)) {
binding.onEdit = false;
} else {
error = true;
}
}
});
if (error) {
alert("One/some of the value you are editing need to be greater than 100");
} else {
$scope.showSave = false;
}
}
You can check the updated fiddle for the same,
https://jsfiddle.net/balasuar/by0tg92m/27/
Note: As you are using angular, you can validate the model as above and no need to retrieve and loop the input elements for the validation. Also for your case, validating the model is sufficient.
If you need some advanced validation, you should create a custom
directive. Since, playing around with the elements inside the
controller is not recommended in AngularJS.
You can use a custom class for those inputs you want to validate. Then you can select all those inputs with that class and validate them. See this Fiddle https://jsfiddle.net/lealceldeiro/L38f686s/5/
$scope.saveEverything = function() {
var inputs = document.getElementsByClassName('inputCtrl'); //inputCtrl is the class you use to select those input s you want to validate
$scope.totalInputs = inputs.length;
$scope.invalidCount = 0;
for (var i = 0; i < inputs.length; i++){
if(inputs[i].value.length < 100){
$scope.invalidCount++;
}
}
//do your stuff here
}
On line 46 a get all the inputs with class "classCtrl" and then I go through the input s array in order to check their length.
There you can check if any of them is actually invalid (by length or any other restriction)
recently stakantin ( https://stackoverflow.com/users/1875610/stakantin ) helped me with a question that I have made about change the text of a label with this code:
$label=$this->add('View_HtmlElement')->setElement('h4')->set('Test');
$f=$this->add('Form');
$f->addField('Checkbox','click')->js('click',$label->js()->text('hallo world'));
I'm trying to do this (I cannot figure out how to do it):
I have a label "$label=$this->add('View_HtmlElement')->setElement('h4')->set('100');"
and I have some fields of a form with check boxes. Each check box has a number.
Is it possible when the checkbox is clicked to do operations on that label ?
example:
Label: 100
field1 100 checkbox
field2 200 checkbox
If I click checkbox of field1, then label value is 200 (its original value plus 100 of field1), and so on...
I don't know if I'm very clear buy thanks for any help.
Alejandro
Example:
$f = $this->add('Form');
$l1 = $f->addField('Line','l1')->set(100);
$cb1 = $f->addField('Checkbox','cb1','100');
$l2 = $f->addField('Line','l2')->set(300);
$cb2 = $f->addField('Checkbox','cb2','300');
$cb1->js('change','
if (this.checked) {
$(this).parent().find("label")
.text(parseInt(100) + parseInt('.$l1->js()->val().'));
} else {
$(this).parent().find("label").text(100);
}
');
$cb2->js('change','
if (this.checked) {
$(this).parent().find("label")
.text(parseInt(300) + parseInt('.$l2->js()->val().'));
} else {
$(this).parent().find("label").text("300");
}
');
But but this is not very good way to add javascript. Creating of js function based on my example in .js file is much clearer way.
I have the classic setup of an NSTableView with the columns bound to various keyPaths of the arrangedObjects of an NSArrayController, and the NSArrayController bound to an array of dictionaries.
With this setup, selecting one or multiple rows in the tableview works automatically. The table view and array controller work together and it's easy to query the NSArrayController to get the list of selected objects.
One of my table columns contains NSButtonCells, the checkbox kind. Is there a way to use Cocoa Bindings to bind the checkbox in each row to that row's selection state ? I know that I could add another value to the NSDictionary representing each row, but that would duplicate the selection information that is already available in NSArrayController.
If it is necessary to do that, would also appreciate a quick sketch of your implementation.
Thanks
So, the answer to this is not for the faint of heart. The reason is you are trying to get NSTableView to do something it doesn't naturally want to do.
Start out by using cocoa's native NSTableView multiple selection behavior:
- clicking on a row selects it and deselects other rows
- holding control and clicking on a column toggles the selection state of that row only
Now, add a column of checkboxes. For this row, the rules are different:
- clicking on a checkbox toggles the selection state of that row only
This would be easy if we could capture clicks to the checkboxes and process them ourselves. Now we can, but the problem is that after we process them, they still get forwarded on to the NSTableView, altering the selection in the usual way. [Note: there may be some way to avoid this forwarding - if you know of one, please let me know]
So here's how you can (finally) accomplished this:
- add a "selectedInView" field to each object in the underlying object array. Add an observer to the associated NSArrayController for the keyPath: "selectedObjects". When the selection changes, set the selectedInView field accordingly for each object. Something like this:
if([keyPath isEqualToString:#"selectedObjects"]) {
// For table view checkbox's: keep "selectedInView" of song dictionaries up to date
[_arrayController.arrangedObjects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
BOOL sel = [_arrayController.selectedObjects containsObject:obj];
if([[obj objectForKey:#"selectedInView"] boolValue] != sel)[obj setValue:[NSNumber numberWithBool:sel] forKey:#"selectedInView"];
}];
Now comes the tricky part: the only time the checkboxes malfunction are when there is already a selection present. Here are the types of cases:
Setup: Row's 1,2,3 are selected. Checkbox clicked on row 4.
Result: Checkbox on row four is selected. Row four is selected. Row's 1,2,3 are deselected (because that's what NSTableView does naturally)
To solve this, whenever a checkbox is clicked you need to create a temporary array to remember the current selection, plus or minus the checkbox that just got clicked:
- (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
if([tableColumn.identifier isEqualToString:#"CheckBox"]) {
NSMutableDictionary *song = [_arrayController.arrangedObjects objectAtIndex:row];
if(!_tempSelectedSongs && _arrayController.selectedObjects) _tempSelectedSongs = [[NSMutableArray arrayWithArray:_arrayController.selectedObjects] retain];
if(_tempSelectedSongs) {
if([_tempSelectedSongs containsObject:song]) {
[_tempSelectedSongs removeObject:song];
} else if(![_tempSelectedSongs containsObject:song]) {
[_tempSelectedSongs addObject:song];
}
}
}
}
Now after the tableview has done it's selection processing, we want to set the selection to what it should be. There is a promising looking function that allows you to modify the tableview selection BEFORE it actually does the selecting. You can modify it like so:
- (NSIndexSet *)tableView:(NSTableView *)tableView selectionIndexesForProposedSelection:(NSIndexSet *)proposedSelectionIndexes {
NSMutableIndexSet *newSet = [NSMutableIndexSet indexSet];
if(_tempSelectedSongs) {
NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet];
[_tempSelectedSongs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSUInteger index = [_arrayController.arrangedObjects indexOfObject:obj];
if(index != NSNotFound) [indexSet addIndex:index];
}];
proposedSelectionIndexes = indexSet;
[_tempSelectedSongs release]; _tempSelectedSongs = nil; [_tempSelectedSongsTimer invalidate]; [_tempSelectedSongsTimer release]; _tempSelectedSongsTimer = nil;
}
[proposedSelectionIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
NSProgressIndicator *progress = ((BDDiscreteProgressCell *)[[_arrayController.arrangedObjects objectAtIndex:idx] objectForKey:#"BDCell"]).progress;
if(!progress)
[newSet addIndex:idx];
}];
return newSet;
}
This works great, however there is a problem with the order in which the NSTableView delegate functions are called. Obviously we need the first function - where we setup the temporary array - to be called BEFORE the second function - where we use the information.
For whatever reason, it turns out that when you DE-select a checkbox, this is how things work,
but when you SELECT a checkbox, the opposite occurs. So for this case, you can add some more code to your above keyPath observer:
if([keyPath isEqualToString:#"selectedObjects"]) {
if(_tempSelectedSongs) {
_arrayController.selectedObjects = _tempSelectedSongs;
[_tempSelectedSongs release]; _tempSelectedSongs = nil;
}
// For table view checkbox's: keep "selectedInView" of song dictionaries up to date
[_arrayController.arrangedObjects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
BOOL sel = [_arrayController.selectedObjects containsObject:obj];
if([[obj objectForKey:#"selectedInView"] boolValue] != sel)[obj setValue:[NSNumber numberWithBool:sel] forKey:#"selectedInView"];
}];
}
Edit: turns out there is an additional case: if a single row is selected and it's checkbox is "unclicked," this does not automatically trigger a selectedObjects notification, so you must run a function on a timer to implement the new selection.