Open datepicker only if condition is true? - javascript

I'm using a datepicker in my To Do List table that the user can use to select a certain date. I'm using it to select a certain "completed date" and I only want the datepicker to open if the To Do is marked 100% complete. Right now the datepicker will open if the To Do isn't marked 100%. Does anyone know how to add a conditional saying
if (todos[i].progress != 100) { *dont open datepicker* }
I've tried adding this to my event function but it does not work as I had hoped.
HTML: The last td element is for the datepicker.
tr class="rowTable dropdown-button" data-id="%todoID%" data-activates="todo_dropdown" data-context="true" data-type="edit-%canedit%" data-canedit="%canedit%" data-constrainwidth="false">
<td class="tableData">
<div class="checkbox" data-complete="%notTrue%" data-show="hidden">
<div class="todo_checkbox"></div>
</div>
</td>
<td class="tableData">%todoTitle%</td>
<td class="tableData">%resources%</td>
<td class="%isOverdue% tableData">%duedate%</td>
<td class="tableData">%percentcomplete%</td>
<td class="completedCalendar tableData"><input value="%dateCompleted%" class="datepicker picker_input" data-id="%todoID%" id="todo_completeddate" style="border:none" readonly="readonly"/></td>
JavaScript:
$('.datepicker').on('change', function (e) {
var $targ = $(e.currentTarget);
var todoID = $targ.parents(".rowTable").data("id");
var todos = currentItems;
for (var i = 0; i < todos.length; i++) {
if (todoID == todos[i].id) {
if (todos[i].progress == 100) {
var dateSet = $('.datepicker[data-id=' + todoID + ']').val();
todos[i].completed_date = dateSet;
}
}
}
})

You should try using
beforeShow: function(input, inst) {
// check condition here
}

You can check your condition on change much like you're currently doing in your on change for the datePicker. This could be a change within the form, table, etc. Within that OnChange, you can check the condition and access the datepicker and hide it or show it like this
$(".datepicker").hide();
$(".datepicker").show();

I think in your case you should disable/hide the date field when data are loaded from server.
You can also use beforeShow event of datepicker widget. But you'll not able to block opening datepicker window. You can hide calendar just after it is shown. Notice you have to use setTimeout in beforeShow otherwise it won't work.
beforeShow: function(input, inst) {
setTimeout(function() {
if (condition) {
$(".foo").datepicker("widget").hide();
}
}, 0);
}
See here for example

Related

How to allow selecting and copying text on a clickable div container? [duplicate]

I've got this problem where I need to show and hide divs when clicking on a table cell. However, I also want people to be able to select text and copy it within the cell without hiding the information.
Totally open to changing the design if necessary. :)
Here's a fiddle which demonstrates the issue
http://jsfiddle.net/k61u66ek/1/
Here's the HTML code in the fiddle:
<table border=1>
<tr>
<td>
Information
</td>
<td onClick="toggleInfo()">
<div id="information" style="display:none">
More information that I want to select without hiding
</div>
<div id="clicktoshow">
Click to show info
</div>
</td>
</tr>
</table>
Here's the javascript:
function toggleInfo() {
$("#clicktoshow").toggle();
$("#information").toggle();
}
Any suggestion/advise is much appreciated!
/Patrik
One option is to check the type of the Selection object returned by window.getSelection:
function toggleInfo() {
var selection = window.getSelection();
if(selection.type != "Range") {
$("#clicktoshow").toggle();
$("#information").toggle();
}
}
http://jsfiddle.net/k61u66ek/4/
Update
If the browser you're targeting doesn't expose a type property on the Selection object then you can test against the length of the selected value instead:
function toggleInfo() {
var selection = window.getSelection();
if(selection.toString().length === 0) {
$("#clicktoshow").toggle();
$("#information").toggle();
}
}
http://jsfiddle.net/k61u66ek/9/
which can in turn be reduced down to a bool check on toString:
if(!selection.toString()) {
http://jsfiddle.net/k61u66ek/10/
You could check if there is a selection made in the click event handler:
window.getSelection().toString();
TLDR
Demo: http://jsfiddle.net/5472ja38/
Code (cancels click event when text highlighted/selected):
document.getElementById('information').addEventListener('click', (e) => {
const cellText = document.getSelection();
if (cellText.type === 'Range') e.stopPropagation();
})
Explanation
document.getSelection().type checks on the document object level if any of the text has been highlighted. If so, the type property is equal to 'Range' stop the event propagation which will cancel the click toggle button change.
Taken from MDN
A DOMString describing the type of the current selection. Possible
values are:
None: No selection has currently been made.
Caret: The selection is
collapsed (i.e. the caret is placed on some text, but no range has
been selected).
Range: A range has been selected.
You can use mouseup, mousedown and mousemove events to achieve this:
DEMO
var isDragging = false;
$("#clickshow")
.mousedown(function() {
isDragging = false;
})
.mousemove(function() {
isDragging = true;
})
.mouseup(function() {
var wasDragging = isDragging;
isDragging = false;
if (!wasDragging) {
$("#information").toggle();
$("#clicktoshow").toggle();
}
});
SOURCE
You can check if the 'information' div is toggled :
function toggleInfo() {
if(document.getElementById('information').style.display == 'none'){
$("#clicktoshow").toggle();
$("#information").toggle();
} else {
// do nothing
}
}
Check this Fiddle
Another way to go is to use the isCollapsed property of the selection. As per MDN, it returns true if the start and end of a selection are the same (which is true of a click):
document.getElementById('information').addEventListener('click', (e) => {
if (!window.getSelection().isCollapsed) {
return;
}
// do something here
});

How to get the date of the selected <td> in a calendar

I need an idea and maybe a solution to get the date from the <td>s which are selected by mouse.
Heres my code, to select (until now its only a function to change the class) the TD:
$(function () {
var isMouseDown = false,
isHighlighted;
$("#schichtplan td")
.mousedown(function () {
isMouseDown = true;
$(this).toggleClass("highlight");
isHighlighted = $(this).hasClass("highlight");
return false; // prevent text selection
})
.mouseover(function () {
if (isMouseDown) {
$(this).toggleClass("highlight", isHighlighted);
}
});
$(document)
.mouseup(function () {
isMouseDown = false;
});
});
A screenshot from the calendar:
Screenshot
This is, how the days are displayed:
echo "<td class=\"td kal_standard_tag\"> - </td>";
The "-" is displayed, because at this day is no entry for this user.
Maybe I could add something like this and read it out with jQuery?
timestamp=\"".$timestamp_tag."\"
My target: After selecting the days, the user has to use rightclick and a Dialog shows up where the user can add some informations and save it to a database.
But I dont know how to get the selected days... :(
Does anyone have an idea and maybe a solution for that?
The best practice to do such things is to add a data attribute. So you would add a timestamp or datestamp as you said. E.g.: <td data-timestamp="1231232131"> and then get it with jQuery in an event with $(this).data('timestamp').

jQuery UI Datepicker, move from one Calendar to the next?

I'm looking for a way of moving from one Calendar to the next once the user has selected a date e.g:
User picks dateFrom
Automatically close dateFrom calendar and show dateTo version
I feel like I'm close to a solution but the dateTo calendar pops up and then disappears instantly, I'm hooking into the onSelect function of the calendar and when the inst is the dateFrom calendar, then i call .focus() on the dateTo text box e.g:
$('.datepicker > input').datepicker({
// snip.....
onSelect: function (dateText, inst) {
var type = $('#' + inst.id).data('calendar');
if (type === 'date-from') {
$('.js-hook--date-to').focus();
}
}
});
Markup:
<div class="large-2 columns">
<div class="datepicker">
<asp:TextBox ID="txtDateFrom" runat="server" placeholder="CHECK IN" data-calendar="date-from" />
</div>
</div>
<div class="large-2 columns">
<div class="datepicker">
<asp:TextBox ID="txtDateTo" runat="server" CssClass="js-hook--date-to" placeholder="CHECK OUT" data-calendar="date-to" />
</div>
</div>
This causes the next Calendar to pop up but it then disappears, is there an easy way to achieve this?
Edit*
I've also tried using .datepicker("show"); with no success.
2nd Edit*
jsFiddle to demonstrate
Use a short delay before triggering the focus.
onSelect: function(dateText, inst) {
var type = $('#' + inst.id).data('calendar');
if (type === 'date-from') {
setTimeout(function() {
$('.js-hook--date-to').focus();
}, 50)
}
}
As mentioned in comments the plugin only uses one container for all instances.
I think what is happening is since the first instance hasn't quite closed and cleaned up when you trigger the focus, the new instance is getting hidden from event in first
I arbitrarily set the delay and didn't play with it much to see what is best.
DEMO
I managed to do this using onClose and checking if a date was selected with getDate:
onClose: function (dateText, inst) {
var picker = $('#' + inst.id);
var type = picker.data('calendar');
var date = picker.datepicker('getDate');
if (type === 'date-from' && date !== null) {
$('.js-hook--date-to').focus();
}
}

How to uncheck a checkBox but stop any event from getting fired?

I have a onclick function attached to check Box (which selectes or Unselects all dependent checkBoxes),I am using AngularJs. So For a checkBox say X ,there are more dependant chekcboxes say A ,B ,C. So when all of the get checked X get checked automatically. And when even one of the get unchekced X get unchekced. But I need to stop "Unselecting checkBox event" from getting fired.
Is there any way possible to do that?
<span style="float: right">
<input id="SelectAllRecords" type="checkbox" ng-model="toSelectAllEmployees"
ng-click="selectAndAddAllEmployees($event)">{{selectAllLabel}} {{totalRecord()}}
</span>
$scope.$watch('toSelectAllEmployees',function() {
// toSelectAllEmployees is an ng-model for select all Emp
if($scope.toSelectAllEmployees!=null && $scope.toSelectAllEmployees!=undefined) {
$scope.selectAllOrUnselectAll();
}
});
$scope.selectAllOrUnselectAll = function() {
if($scope.toSelectAllEmployees!=null && $scope.toSelectAllEmployees!=undefined) {
if($scope.toSelectAllEmployees==true) {
$('.allEmployees').attr("checked", true);
} else {
$(".allEmployees").attr('checked',false);
if($rootScope.fromMovingPage!=2 && $rootScope.fromMovingPage!=3) {
// as we have now unchecked all employees hence we need to do matching and selected employee list size 0
$scope.matchingAndSelectedEmployeesList.length = 0;
}
}
}
}
in the onclick event, providing you pass an event var like
function(e) {
}
you may type:
function(e) {
e.preventDefault();
}
I believe this is what you are asking.

Onblur triggering everywhere

Update
It appears that the input is locked until I input a well formatted email address and then and only then is the element able to be unlock/unfocus. That is just weird, because if I can't focus any other element then how can the unfocus event get trigger when the current element is still focus. Do you suppose it has to do with something on the server side then?
So I have this piece of code that has an input html generated by the server so I can not directly do the onblur=function() in the tag. Instead I use the onclick event of the td to bind an event handler to the input.
<td id="emailInput" class="label" onclick="emailValidation(event);">
#Html.EditorFor(model => Model.EmailAddress, new { Class = "ignore"})
</td>
<td id="emailValidate" style="display: none">
<label>Please enter a valid email address</label>
</td>
in the Javascript file I bind the event handler like so:
function emailValidation(e) {
$(e.target).on("blur", function () {
console.log("what target e is");
console.log(e.target);
var inputVal = $(e.target).val();
var re = /[A-z0-9]*[\.?[\w+]+[A-z0-9]+#[A-z0-9][\.?[\w+]+\.[A-z][A-z][A-z]/;
if (!re.test(inputVal)) {
$(e.target).focus();
$("#emailValidate").css("display", "inline-block");
} else {
$("#emailValidate").css("display", "none");
}
});
}
I check the dev console and e.target is the input element I want. What is happening is that the onblur event in being trigger after it has been appended and the input is unfocus even though the input element is no longer focus, and I am just clicking random area in the screen. Am I mis-understanding something? Is there a better definition that I can get than the w3school, the developer.mozilla, and this weird one
EDIT
I was trying to create a JSfiddle (w/o server stuff) to demonstrate and it worked fine so upon closer inspection I see the the input element is not being unfocus. It does not matter where I click the cursor remains in the text area, and no other element can be focus now.
Edit 2
As requested the JSFiddle, but it works here but not on the one with server side stuff
Here is a working fiddle:
http://jsfiddle.net/Mn5E4/1/
$("#emailMe").on("blur", function () {
var inputVal = $(this).val();
var re = /[A-z0-9]*[\.?[\w+]+[A-z0-9]+#[A-z0-9][\.?[\w+]+\.[A-z][A-z][A-z]/;
if (!re.test(inputVal)) {
$("#emailMe").focus();
$("#emailValidate").css("display", "inline-block");
} else {
$("#emailValidate").css("display", "none");
}
});
You don't need to bother with using the click event to attach the handler since you know the id of the input you want to bind to.
Edit: Note that this is a fork of your jsFiddle. Based on the code in your question, I would expect the id of the desired input element to be "EmailAddress", in which case you would replace $("#emailMe") with $("#EmailAddress").
Edit2: You can take out any guesswork by doing this:
<td id="emailInput" class="label">
#Html.EditorFor(model => Model.EmailAddress, new { #class = "ignore validateEmail"})
</td>
<td id="emailValidate" style="display: none">
<label>Please enter a valid email address</label>
</td>
<script type='text/javascript'>
$(".validateEmail").on("blur", function () {
var inputVal = $(this).val();
var re = /[A-z0-9]*[\.?[\w+]+[A-z0-9]+#[A-z0-9][\.?[\w+]+\.[A-z][A-z][A-z]/;
if (!re.test(inputVal)) {
$(".validateEmail").focus();
$("#emailValidate").css("display", "inline-block");
} else {
$("#emailValidate").css("display", "none");
}
});
</script>
Note that I passed another class into the EditorFor helper and changed how the class attribute was named to use # to escape the lower case name "class".
Please try this aproach:
<td id="emailInput" class="label" onclick="emailValidation(event);">
#Html.EditorFor(model => Model.EmailAddress, new { Class = "ignore"})
</td>
$("#emailInput").on('focusin', "input", function (e) {
var inputobj = $(this);
var inputVal = inputobj.val();
var re = /[A-z0-9]*[\.?[\w+]+[A-z0-9]+#[A-z0-9][\.?[\w+]+\.[A-z][A-z][A-z]/;
if (!re.test(inputVal)) {
inputobj.focus();
$("#emailValidate").css("display", "inline-block");
} else {
$("#emailValidate").css("display", "none");
}
})
Note: Not tested
You should use $(this)
var inputVal = $(this).val();

Categories

Resources