Two single clicks to rename something in html? - angularjs

In OS X, if I do a single click on a file or folder to highlight it, and then do another single click on the filename, the filename becomes an editable input box that I can change the filename in that box. Now I found xeditable http://vitalets.github.io/angular-xeditable/#overview very useful. I'm wondering in html, or Angularjs, is there such two single click event? Thanks.

Yes its a ng-dblclick used the same as ng-click
here's and example:
<button ng-dblclick="count = count + 1" ng-init="count=0">
Increment (on double click)
</button>
count: {{count}}

Solved the problem by the following code:
app.controller('QueryItemCtrl', function ($scope) {
$scope.rename = function () {
$scope.lastClickTime = $scope.lastClickTime || 0;
var now = new Date().getTime();
var delta = now - $scope.lastClickTime;
$scope.lastClickTime = now;
if (delta > 500 && delta < 1000) {
$scope.textBtnForm.$show();
}
};
})
In the html, data-ng-click="rename()".

Related

angular file upload in ng-repeat with preview input bind

I'm working on an angular 1.6 based image upload with ng-repeat, note the input is not multi, but there are multiple ng-repeated inputs, I have the image preview working as well as adding lines / removing lines, the only thing that seems to not be working is if I remove an item the file inputs do not update (I have code that does properly update the previews). Here is what I am working with:
<div ng-repeat="item in data.items track by $index">
<input ng-model="item.fileinput" type="file" name="image_{{$index}}" id="image_{{$index}}" onchange="angular.element(this).scope().imageChoose(this)"/><i ng-click="removeEvent($index)" class="fa fa-trash fa-lg"></i>
<img ng-if="!item.thumb" class="preview-image-small" ng-src="/images/general/placeholder.jpg"</img>
<img ng-if="item.thumb" class="preview-image-small" ng-src="{{item.thumb}}"</img>
</div>
Then in my controller I handle the imageChoose as follows:
$scope.imageChoose = function (data) {
var id = data.id.split("_");
id = id[id.length-1];
var elem = document.getElementById(data.id);
if (typeof (FileReader) != "undefined") {
var reader = new FileReader();
reader.onload = function (e) {
$scope.$apply(function() {
$scope.data.data.items[id].thumb = e.target.result;
});
};
reader.readAsDataURL(elem.files[0]);
} else {
alert("This browser does not support FileReader.");
}
};
This properly sets the image previews and when I run a remove on a line they re-order correctly due to the ng-src of event.thumb. The problem is the actual file input does not bind or update, here is the code for removing a line:
$scope.removeEvent = function (index) {
$scope.data.items.splice(index, 1);
};
I'm hoping there is a relatively simple way to bind the input or handle the remove so that the inputs stay correct. Thanks in advance for any ideas.
Your removeEvent method is not working because of using track by $index together with ng-repeat. This is a known side effect. Try removing it/using different track by expressions.

AngularJS Get text selection and append html to start and end of selection

Have little dilemma here. I'm building text editor in angular js. The problem that I have is, when user selects part of text within a paragraph or heading I need to change styling of that part of text to bold / italic etc.
So basically I need to wrap selected text in <strong></strong> or <em></em>.
Plunker
I have a directive
editorApp.directive('watchSelection', function() {
return function(scope, elem) {
elem.on('mouseup', function() {
scope.startPosition = elem[0].selectionStart;
scope.endPosition = elem[0].selectionEnd;
// scope.selected = elem[0].value.substring(start, end);
scope.$apply();
});
};
});
That gets text selection its startposition and endposition. On button click I need to wrap that selection in specific tags, which I'm hoping to accomplish with this function:
$scope.boldText = function(startPosition, endPosition) {
$scope.start = startPosition;
$scope.end = endPosition;
var htmlStart = angular.element('<strong>');
var htmlEnd = angular.element('</strong>');
$scope.start.append(htmlStart);
$scope.end.append(htmlEnd);
};
I relatively new to angular and I might have taken a bigger bite than I can handle :)
Issue is I can't get selection to wrap inside them tags.
You don't need to watch anything.
$scope.boldText = function() {
document.execCommand('bold');
};
This will bold the selected text.

ng img crop - cropping existing images

ng-img-crop is an awesome directive however I am having trouble adapting it to my scenario. My issue is that when a user has an image I would like to give them the option to resize the image if they would like to.
So here is the code I am attempting to use:
js:
vm.userImageOriginal = vm.editUser.image_pkey ? 'api/file/' + vm.editUser.image_pkey : null;
html:
<img-crop image="profileVM.userImageOriginal" result-image="profileVM.userImageNew"
area-type="square" result-image-size="300" on-change="profileVM.imageCropped = true;"></img-crop>
So I two issues:
1) I only want to upload the new image if the user has indeed changed the cropping. I tried setting a flag in on-change but it looks like on-change gets executed on initialization as well. Is there any way to know if the user has actually cropped?
2) Is there any way to set the position of the square/circle. In my scenario, if there is an existing user image, I would like to set the cropping square to the dimensions of the current image (i.e. the border of the image).
Thanks in advance.
Solved like this:
Add the following attribute to ng-img-crop directive in html:
on-load-done="profileVM.addCroppingWatcher()"
Here is the function:
function addCroppingWatcher(){
if (croppingWatcher)
return;
$window.setTimeout(function(){
croppingWatcher = $scope.$watch(
function(){ return vm.userImageNew; },
function(newVal, oldVal){
if (oldVal && oldVal != newVal) {
vm.imageCropped = true;
croppingWatcher();
}
}
);
}, 0);
}

How can I get the click count

In an anchor tag I would like call one of two different events based on if the user clicked once or twice. However if I implement ng-click and ng-dblclick, both are activated.
Is there any way to route to the appropriate listener based on click count?
You can use a combination of ng-click and $timeout to count the number of times the function has been executed. the code could look like something like this;
<a ng-click="clicked()" />
$scope.clickCount = 0;
var timeoutHandler = null;
$scope.clicked = function()
{
if (timeoutHandler != null)
$timeout.cancel( timeoutHandler );
$scope.clickCount++;
timeoutHandler = $timeout(function()
{
//now you know the number of clicks.
//set the click count to zero for future clicks
$scope.clickCount = 0;
}, 500)
}

Caret position in textarea with AngularJS

I am asking myself if I am doing it right. The problem I have is that I want to preserve caret position after AngularJS update textarea value.
HTML looks like this:
<div ng-controlle="editorController">
<button ng-click="addSomeTextAtTheEnd()">Add some text at the end</button>
<textarea id="editor" ng-model="editor"></textarea>
</div>
My controller looks like this:
app.controller("editorController", function($scope, $timeout, $window) {
$scope.editor = "";
$scope.addSomeTextAtTheEnd = function() {
$timeout(function() {
$scope.editor = $scope.editor + " Period!";
}, 5000);
}
$scope.$watch("editor", function editorListener() {
var editor = $window.document.getElementById("editor");
var start = editor.selectionStart;
var end = editor.selectionEnd;
$scope.$evalAsync(function() {
editor.selectionStart = start;
editor.selectionEnd = end;
});
});
});
Let say I start typing some text in textarea. Then I hit the button which will soon add " Period!" at the end of $scope.editor value. During the 5 seconds timeout I make focus on textarea again and write some more text. After 5 seconds my textarea value is updated.
I am watching for $scope.editor value. The editorListener will be executed on every $digest cycle. In this cycle also happens two-way data binding. I need to correct caret position right after data binding. Is $scope.$evalAsync(...) the right place where should I do this or not?
Here is a directive I use to manipulate the caret position; however, like I stated in a comment, there is an issue with IE.
Below is something that may help you plan this out. One thing I noticed in your question is that you mention a condition where the user may re-focus the input box to type additional text, which I would believe resets the timeout; would this condition be true?
Instead of using a button to add text, would you rather just add it without? Like running the addSomeTextAtTheEnd function whenever a user un-focuses from the input box?
If you have to use the button, and a user re-focuses on the input box and types more into, you should cancel your button timeout.
Like:
myVar = setTimeout(function(){ alert("Hello"); }, 3000);
// Then clear the timeout in your $watch if there is any change to the input.
clearTimeout(myVar);
If you do it this way, perhaps you will not even need to know the cursor position as the addSomeTextAtTheEnd function timeout will just reset on any input change before the 5 second timeout. If the 5 second timeout occurs then the addSomeTextAtTheEnd will run and "append text to the end" like it's supposed to do. Please give more information and I will update this as needed.
app.directive('filterElement', ['$filter', function($filter){
return {
restrict:'A', // Declares an Attributes Directive.
require: '?ngModel', // ? checks for parent scope if one exists.
link: function( scope, elem, attrs, ngModel ){
if( !ngModel ){ return }
var conditional = attrs.rsFilterElement.conditional ? attrs.rsFilterElement.conditional : null;
scope.$watch(attrs.ngModel, function(value){
if( value == undefined || !attrs.rsFilterElement ){ return }
// Initialize the following values
// These values are used to set the cursor of the input.
var initialCursorPosition = elem[0].selectionStart
var initialValueLength = elem[0].value.length
var difference = false
// Sets ngModelView and ngViewValue
ngModel.$setViewValue($filter( attrs.rsFilterElement )( value, conditional ));
attrs.$$element[0].value = $filter( attrs.rsFilterElement )( value, conditional );
if(elem[0].value.length > initialValueLength){ difference = true }
if(elem[0].value.length < initialValueLength){ initialCursorPosition = initialCursorPosition - 1 }
elem[0].selectionStart = difference ? elem[0].selectionStart : initialCursorPosition
elem[0].selectionEnd = difference ? elem[0].selectionEnd : initialCursorPosition
});
} // end link
} // end return
}]);

Resources