I have a little problem with typescript and jquery. And yes, I'm using Angular2.
My code looks like this:
Here I'm including JQuery so I can use it in ts
let $ = require('/node_modules/jquery/dist/jquery.js');
On another part I'm defining a function like this
public goBack() {
console.log("HUHU");
this.router.navigateByUrl('/dash/' + this.projectId);
}
So far so good... now it's the part using JQuery which doesn't work:
$(document).ready(function() {
$('.modal').modal('show');
});
$(document).keyup(function (e) {
if (e.which == 27 && $('body').hasClass('modal-open')) {
this.goBack();
}
});
$(document).click(function (e) {
if (e.target === $('.modal')[0] && $('body').hasClass('modal-open')) {
this.goBack();
}
});
What I'm doing here? I'm actualyl opening a bootstrap modal (popup) in the first part using $('.modal').modal('show'); and that's even working.
But the two other parts, keyup and click even handling are working too BUT I can't use this.goBack(). In this two parts I want to catch the events for:
Clicking ESC and closing the modal
Clicking out of the modal (grey zoned) to close it
As I said, the modal is closing but URL is not changing, changing by calling this.goBack()
And ideas out there?
Thanks in advance!
Yadbo
Change
$(document).keyup(function (e) {
and
$(document).click(function (e) {
to
$(document).keyup((e)=> {
and
$(document).click((e)=> {
if you use function your this will not refer to your component but to the instance of the click and keyup events.
The arrow notation is the short version of creating a js closure:
var self = this;
$(document).keyup(function (e) {
if (e.which == 27 && $('body').hasClass('modal-open')) {
self.goBack();
}
});
Suggested reading: How to access the correct `this` inside a callback?
Related
I made a simple plunkr here http://plnkr.co/edit/zNb65ErYH5HXgAQPOSM0?p=preview
I created a little datepicker I would like this to close itself when you focus out of it (focusout of datepicker) if I put blur on input I'm unable to use the datepicker, if I put focusout event on datepicker it doesn't works
I also tried:
angular.element(theCalendar).bind('blur', function () {
$scope.hideCalendar();
});
but it doesn't work.
Any clue?
this is because you are removing the item before you get a chance to do anything, here is a working example:
http://plnkr.co/edit/mDfV9NLAQCP4l7wHdlfi?p=preview
just add a timeout:
thisInput.bind('blur', function () {
$timeout(function(){
$scope.hideCalendar();
}, 200);
});
have you considered using existing datepickers? like angularUI or angular-strap: http://mgcrea.github.io/angular-strap/##datepickers
Update:
Not a complete solution, but should get you quite closer:
angular.element($document[0].body).bind('click', function(e){
console.log(angular.element(e.target), e.target.nodeName)
var classNamed = angular.element(e.target).attr('class');
var inThing = (classNamed.indexOf('datepicker-calendar') > -1);
if (inThing || e.target.nodeName === "INPUT") {
console.log('in');
} else {
console.log('out');
$timeout(function(){
$scope.hideCalendar();
}, 200);
}
});
http://plnkr.co/edit/EbQl5xsCnG837rAEhBZh?p=preview
What you want to do then is to listen for a click on the page, and if the click is outside of the calendar, then close it, otherwise do nothing. The above only takes into account that you are clicking on something that has a class name which includes datepicker-calendar, you will need to adjust it so that clicking within the calendar doesn't close it as well.
How about closing on mouseout?
You need to cancel the close if you move to another div in the calendar though:
//get the calendar as element
theCalendar = element[0].children[1];
// hide the calendar on mouseout
var closeCalendarTimeout = null;
angular.element(theCalendar).bind('mouseout', function () {
if ( closeCalendarTimeout !== null )
$timeout.cancel(closeCalendarTimeout);
closeCalendarTimeout = $timeout(function () {
$scope.hideCalendar();
},250)
});
angular.element(theCalendar).bind('mouseover', function () {
if ( closeCalendarTimeout === null ) return
$timeout.cancel(closeCalendarTimeout);
closeCalendarTimeout = null;
});
EDIT
Adding a tabindex attribute to a div causes it to fire focus and blur events.
, htmlTemplate = '<div class="datepicker-calendar" tabindex="0">' +
angular.element(theCalendar).bind('blur', function () {
$scope.hideCalendar();
});
So, i know it probably is not the best practice or the best way to do this, but at the end i fixed and got what i need using this:
thisInput.bind('focus click', function bindingFunction() {
isMouseOnInput = true;
$scope.showCalendar();
angular.element(theCalendar).triggerHandler('focus');
});
thisInput.bind('blur focusout', function bindingFunction() {
isMouseOnInput = false;
});
angular.element(theCalendar).bind('mouseenter', function () {
isMouseOn = true;
});
angular.element(theCalendar).bind('mouseleave', function () {
isMouseOn = false;
});
angular.element($window).bind('click', function () {
if (!isMouseOn && !isMouseOnInput) {
$scope.hideCalendar();
}
});
I setted up some boolean vars to check where mouse is when you click the page and it works like a charm if you have some better solution that works , please let me know, but this actually fixed all.
I accept this as the answer but i thank all the guys on this page!
The User should be able to change the Name and then confirm the change. I'm not able to archive it with this code as when I click confirm, it returns like before.
What am I missing?
Any better way to put this together (which I'm sure there's one) ?
Please check the demo where you can also see the changeElementTypefunction
http://jsfiddle.net/dLk6E/
js:
$('.replace').on('click', function () {
$("h2").changeElementType("textarea");
$('.replace').hide();
$('.confirm').show();
//Confermation of the change
$('.confirm').bind('click', function () {
$('.replace').show();
$('.confirm').hide();
$("textarea").changeElementType("h2");
});
if ($('textarea:visible')) {
$(document).keypress(function (e) {
if (e.which == 13) {
alert('You pressed enter!');
$("textarea").changeElementType("h2");
$('.replace').css('opacity', '1');
}
});
}
});
Here are your updated code and working fiddle http://jsfiddle.net/dLk6E/
(function($) {
$.fn.changeElementType = function(newType) {
var attrs = {};
$.each(this[0].attributes, function(idx, attr) {
attrs[attr.nodeName] = attr.nodeValue;
});
this.replaceWith(function() {
return $("<" + newType + "/>", attrs).append($(this).contents());
});
}
})(jQuery);
$('.replace').on('click', function (){
$("h2").changeElementType("textarea");
$('.replace').hide();
$('.confirm').show();
//Confermation of the change
$('.confirm').on('click', function(){
$('.replace').show();
$('.confirm').hide();
// you are missing this
$('.replaceble').html($("textarea").val());
$("textarea").changeElementType("h2");
});
if ($('textarea:visible')){
$(document).keypress(function(e) {
if(e.which == 13) {
alert('You pressed enter!');
$("textarea").changeElementType("h2");
$('.replace').css('opacity','1');
}
});
}
});
updated
jsfiddle.net/dLk6E/1
I think your code is right but you need to use the value you're entering when replacing it. So the confirmation binding would be something like this (fetching it, and then using it to update the textarea before "transforming" it into an h2 tag.
$('.confirm').bind('click', function(){
var valueEntered = $('textarea').val();
$('.replace').show();
$('.confirm').hide();
$("textarea").html(valueEntered).changeElementType("h2");
});
You could be using .on for this as well as of jQuery 1.7 is prefered to .bind.
Another thing I would suggest is whenever you struggle with something like this just put in google (or whatever...) exactly what you want, in this case "jquery get value of input" will get asw first result the jquery documentation
This way you won't forget it ;)
Update: Maybe a small detail but in the binding I use it would be more efficient to just hit $('textarea') once, so it would be something like this. Something that you may keep in mind (not really an issue here), better to store in a variable than hit the DOM several times.
$('.confirm').on('click', function(){
var $textarea = $('textarea');
$('.replace').show();
$('.confirm').hide();
$textarea.html($textarea.val()).changeElementType("h2");
});
jsfiddle
I want click event to be distinguished between the click on modal dialog with the click of the background of modal dialog for some purpose.
Please help !
Thanks a ton in advance.
I can't find any built in function to obtain what you want; the only "hacky" way I found is to check the click/keyup event of the document and if the modal is opened call your callback.
Code:
$(document).keyup(function (e) {
if (e.which == 27 && $('body').hasClass('modal-open')) {
console.log('esc')
}
})
$(document).click(function (e) {
if (e.target === $('.modal-scrollable')[0] && $('body').hasClass('modal-open')) {
console.log('click')
}
})
Demo: http://jsfiddle.net/4zzKz/
I've gotten hundreds of aids from this site. thanks. This is my first question.
Which object is a modal window (alert popup) into the Dom. How can i refer it? How can i know if open or closed? Something like this: if (alertPopup is open) {..code...}
My code is this (i use jQuery):
<script type="text/javascript">
$(document).ready(function(){
var myButton = $('#mybutton')
myButton.click(function(){
if ($('#myinput').val() == '') {
alert('input Empty!');
} else {
// More code.
}
});
$(document).keyup(function(e){
if (e.keyCode == 13) myButton.trigger('click');
})
});
</script>
<body>
<input id="myinput" />
<button id="mybutton">Show alert</button>
</body>
The purpose of the code is trigger up the event 'click' on the button whith key 'enter'. It works, but when i close the popup, again with key 'enter', the popup comes again an again. I need to disable event 'click' of my button or unbind the trigger action when the popup is displayed.
I would't like to make my own modal windows.
thanks in advance.
You can move the handler to its own function and programmatically bind/unbind it to the event:
$(document).ready(function(){
var myButton = $('#mybutton')
console.log('whee');
myButton.click(clickHandler);
$(document).keyup(function(e){
if (e.keyCode == 13) myButton.trigger('click');
})
});
function clickHandler(){
$('#mybutton').unbind('click', clickHandler)
if ($('#myinput').val() == '') {
alert('input Empty!');
} else {
// More code.
}
}
However, it looks more like you're trying to deal with enter buttons in a form submission style. I'd recommend wrapping this whole thing in a form and dealing with it as such.
See http://jsfiddle.net/ruBY4/ for a cleaner form-based solution.
I have a span element that I want to become editable upon double-click. (That is, the user can edit the text and it will save when s/he clicks outside.)
The effect I want to emulate is similar to when I double-click CSS properties in the Google Chrome Developer Tools. (See picture.)
Now tested, and does work (at least Firefox 8 and Chromium 14 on Ubuntu 11.04):
$('span').bind('dblclick',
function(){
$(this).attr('contentEditable',true);
});
JS Fiddle demo.
Edited in response to Randomblue's comment (below):
...how do I detect when the user clicks outside the span, so that I can set attr('contentEditable', false)
Just append the blur() method:
$('span').bind('dblclick', function() {
$(this).attr('contentEditable', true);
}).blur(
function() {
$(this).attr('contentEditable', false);
});
JS Fiddle demo.
If you want a solution that works in ALL modern browsers, here's a nifty little jQuery plugin I made that emulates the functionality you described:
SIMPLY DROP THIS BLOCK INTO YOUR CODE-BASE:
//plugin to make any element text editable
//http://stackoverflow.com/a/13866517/2343
$.fn.extend({
editable: function() {
var that = this,
$edittextbox = $('<input type="text"></input>').css('min-width', that.width()),
submitChanges = function() {
that.html($edittextbox.val());
that.show();
that.trigger('editsubmit', [that.html()]);
$(document).unbind('click', submitChanges);
$edittextbox.detach();
},
tempVal;
$edittextbox.click(function(event) {
event.stopPropagation();
});
that.dblclick(function(e) {
tempVal = that.html();
$edittextbox.val(tempVal).insertBefore(that).bind('keypress', function(e) {
if ($(this).val() !== '') {
var code = (e.keyCode ? e.keyCode : e.which);
if (code == 13) {
submitChanges();
}
}
});
that.hide();
$(document).click(submitChanges);
});
return that;
}
});
Now you can make any element editable simply by calling .editable() on a jQuery selector object, like so:
$('#YOURELEMENT').editable();
To get the changes after the user submits them, bind to the "editsubmit" event, like so:
$('#YOURELEMENT').editable().bind('editsubmit', function(event, val) {});
//The val param is the content that's being submitted.
Here's a fiddle demo: http://jsfiddle.net/adamb/Hbww2/
The above works: I've tested it in this jsfiddle: http://jsfiddle.net/nXXkw/
Also, to remove the editability when user clicks off of the element, include:
$('span').bind('blur',function(){
$(this).attr('contentEditable',false);
});
I found this nice jQuery plugin: "X-editable In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery" http://vitalets.github.com/x-editable/
I found many answers to be out of date on this topic, but adamb's was the easiest solution for me, thank you.
However, his solution was bugged to fire multiple times due to not removing the keypress event along with the element.
Here's the updated plugin using $.on() instead of $.bind() and with the keypress event handler being removed when the element is created again.
$.fn.extend({
editable: function() {
var that = this,
$edittextbox = $('<input type="text"></input>').css('min-width', that.width()),
submitChanges = function() {
that.html($edittextbox.val());
that.show();
that.trigger('editsubmit', [that.html()]);
$(document).off('click', submitChanges);
$edittextbox.detach();
},
tempVal;
$edittextbox.click(function(event) {
event.stopPropagation();
});
that.dblclick(function(e) {
tempVal = that.html();
$edittextbox.val(tempVal).insertBefore(that).off("keypress").on('keypress', function(e) {
if ($(this).val() !== '') {
var code = (e.keyCode ? e.keyCode : e.which);
if (code == 13) {
submitChanges();
}
}
});
that.hide();
$(document).one("click", submitChanges);
});
return that;
}
});
http://jsfiddle.net/Hbww2/142/