Sort divs by date / time with JS - javascript

I have a script which creates a lot of divs with the a data-date attribute and has a time format of Tue Aug 16 2016 12:27:21 GMT+0100 (BST)
An example set could be:
<div class="socialBox" data-date="Tue Aug 10 2016 12:30:21 GMT+0100 (BST)" data-type="twitter">
<div class="socialBox" data-date="Tue Aug 14 2016 12:10:21 GMT+0100 (BST)" data-type="facebook">
<div class="socialBox" data-date="Tue Aug 13 2016 15:27:21 GMT+0100 (BST)" data-type="youtube">
<div class="socialBox" data-date="Tue Aug 03 2016 18:27:21 GMT+0100 (BST)" data-type="instagram">
The divs are appended to a blank div from a variety of different functions and then I run the JS to sort the divs and append it to the original blank div again but I can't seem to get it to work.
Here is the script
loadTwitter(twitter);
loadFacebook(facebook);
loadYoutube(youtube);
loadInstagram(instagram);
// DOESN'T WORK YET (THE BELOW)
var board = $("#social-board");
var boards = board.children('.socialBox');
boards.sort(function(a, b) {
var an = $(a).data("date").getTime();
var bn = $(b).data("date").getTime();
if(an > bn) {
return 1;
}
if(an < bn) {
return -1;
}
return 0;
});
boards.detach().appendTo(board);
Could anyone help me out? I'm not sure if its the appending to the div element or the JS sort function itself.

You can do this by:
Detaching them up front and then using .get to get a real array instead of a jQuery object.
Sorting them (which can be a lot simpler)
Appending that array back to #social-board
so:
var boards = board.children('.socialBox').detach().get();
// --------------------------------------^^^^^^^^^^^^^^^
// A bit shorter :-)
boards.sort(function(a, b) {
return new Date($(a).data("date")) - new Date($(b).data("date"));
});
board.append(boards); // <== switched this to append
Live example:
// Wait a sec so we can see the old order...
setTimeout(function() {
// Now sort them
var board = $("#social-board");
var boards = board.children('.socialBox').detach().get();
boards.sort(function(a, b) {
return new Date($(a).data("date")) - new Date($(b).data("date"));
});
board.append(boards);
}, 600);
<div id="social-board">
<div class="socialBox" data-date="2016-08-10T11:30:21.000Z" data-type="twitter">2016-08-10T11:30:21.000Z</div>
<div class="socialBox" data-date="2016-08-03T17:27:21.000Z" data-type="instagram">2016-08-03T17:27:21.000Z</div>
<div class="socialBox" data-date="2016-08-14T11:10:21.000Z" data-type="facebook">2016-08-14T11:10:21.000Z</div>
<div class="socialBox" data-date="2016-08-13T14:27:21.000Z" data-type="youtube">2016-08-13T14:27:21.000Z</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Note: You cannot rely on the JavaScript Date object parsing dates in the string format you've used. Note the ISO format I've used in the snippet instead.
Side note: Unless you're using the features of data, you may want to use attr instead. data is not just an accessor for data-* attributes. It's both more and less than that.

Your idea is right, but your logic is slightly off in your sort function. This is the code I use to sort dates:
var reverse = false; // ascending/descending flag
var board = $("#social-board");
var boards = board.children('.socialBox');
var orderedBoards = boards.slice().sort(function (elem1, elem2) {
var value1 = new Date($(elem1).data("date")).getTime(),
value2 = new Date($(elem2).data("date")).getTime();
if (reverse) {
// descending
return -(value1 > value2) || +(value1 < value2) || (isNaN(value1)) - (isNaN(value2));
}
// ascending
return +(value1 > value2) || -(value1 < value2) || (isNaN(value1)) - (isNaN(value2));
});
board.empty().append(orderedBoards);

I have a solution:
HTML:
<ul class="sort-list">
<li class="sort-item" data-event-date="2018-06-30 22:00">3</li>
<li class="sort-item" data-event-date="2018-06-29 21:00">2</li>
<li class="sort-item" data-event-date="2018-06-27 22:00">1</li>
<li class="sort-item" data-event-date="2018-07-01 22:00">4</li>
<li class="sort-item" data-event-date="2018-07-02 22:00">5</li>
</ul>
<button onclick="chat_order()">
test
</button>
JS:
function chat_order() {
var container = $(".sort-list");
var items = $(".sort-item");
items.each(function() {
// Convert the string in 'data-event-date' attribute to a more
// standardized date format
var BCDate = $(this).attr("data-event-date");
/*console.log(BCDate);
var standardDate = BCDate[1]+" "+BCDate[0]+" "+BCDate[2];*/
var standartDate = new Date(BCDate).getTime();
$(this).attr("data-event-date", standartDate);
console.log(standartDate);
});
items.sort(function(a,b){
a = parseFloat($(a).attr("data-event-date"));
b = parseFloat($(b).attr("data-event-date"));
return a>b ? -1 : a<b ? 1 : 0;
}).each(function(){
container.prepend(this);
});
}
JSFIDDLE: http://jsfiddle.net/2fr0vmhu/294/

Related

Javascript - Show and Add image based on date

I would like to create a landing page where I gradually show our winnings for the advent calendar. For this I have prepared images, which will then be revealed in a DIV.
So until 01 December you will not see any pictures.
On 01 December one sees then picture 01
On 02. December one sees picture 01 & picture 02
and so on
I have found the following code so far. Unfortunately only the DIV with today's date is shown to me. What do I have to do so that the images stay with?
Here is my fiddle: https://jsfiddle.net/bkoenig/m2pzqjrs/14/
<div class="imageClass image1">
1
</div>
<div class="imageClass image2">
2
</div>
<div class="imageClass image3">
3
</div>
var now = new Date().toDateString();
var october1 = new Date("November 22, 2022").toDateString();
var october2 = new Date("November 23, 2022").toDateString();
var october3 = new Date("November 24, 2022").toDateString();
if(now != october1) // today is after Christmas
{
// an id of a div that holds your images?
$('#div_id').hide();
// or a class of images
$('.image1').hide();
}
if(now != october2) // today is after Christmas
{
// an id of a div that holds your images?
$('#div_id').hide();
// or a class of images
$('.image2').hide();
}
if(now != october3) // today is after Christmas
{
// an id of a div that holds your images?
$('#div_id').hide();
// or a class of images
$('.image3').hide();
}
.imageClass {
display: ;
}
I have an example for your problem, hope it helps you
(function () {
const now = new Date();
$("#imageDate img").each(function () {
const el = $(this);
const date = new Date(el.attr('data-date'));
console.log(now, date)
if (date <= now) {
el.show();
}
});
})();
#imageDate img {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="imageDate">
<img src="" data-date="November 22 2022" alt="22/11/2022" />
<img src="" data-date="November 23 2022" alt="23/11/2022" />
<img src="" data-date="November 24 2022" alt="24/11/2022" />
</div>

How to disabled minutes and text (Eastern Standard time) from angular datepicker?

main.html
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<datetimepicker data-ng-model="dateRangeStart" data-datetimepicker-config="{ dropdownSelector: '#dropdownStart', renderOn: 'end-date-changed' }" data-on-set-time="startDateOnSetTime()" data-before-render="startDateBeforeRender($dates)"></datetimepicker>
</ul>
I am using angular directive https://github.com/dalelotts/angular-bootstrap-datetimepicker , if you select date and time with this module it will display Thu Mar 23 2017 15:46:38 GMT-0400 (Eastern Daylight Time) so here is it possible to get rid of 46:38 GMT-0400 (Eastern Daylight Time) this part i just want hours selection ?
Ctrl.js
$scope.dateRangeStart = new Date();
$scope.dateRangeStart.setDate($scope.dateRangeStart.getDate() - 1);
$scope.dateRangeEnd = new Date();
$scope.endDateBeforeRender = endDateBeforeRender
$scope.endDateOnSetTime = endDateOnSetTime
$scope.startDateBeforeRender = startDateBeforeRender
$scope.startDateOnSetTime = startDateOnSetTime
function startDateOnSetTime () {
$scope.$broadcast('start-date-changed');
}
function endDateOnSetTime () {
$scope.$broadcast('end-date-changed');
}
function startDateBeforeRender ($dates) {
if ($scope.dateRangeEnd) {
var activeDate = moment($scope.dateRangeEnd);
$dates.filter(function (date) {
$scope.searchObj.endDate = activeDate._i;
// console.log(activeDate);
return date.localDateValue() >= activeDate.valueOf()
}).forEach(function (date) {
date.selectable = false;
// console.log(date);
})
}
}
You need to set the minView option in the configuration per the docs. It's the lowest denomination of time the date picker should show. Set that to hours or days, however you want it.
Example from above:
data-datetimepicker-config="{ dropdownSelector: '#dropdownStart', renderOn: 'end-date-changed', minView: 'hour' }"
Joshua Wilborn is correct, set the configuration:
data-datetimepicker-config="{ dropdownSelector: '#dropdownStart', renderOn: 'end-date-changed', minView: 'hour' }"
Then you can use the angular-date-time-input directive to format the display of a date in an input box or allow users to enter a valid date with the keyboard.

CLNDR - How to get Today, Tomorrow and Current Month event list and count and print that information to separate div

Hi I'm using CLNDR and trying to get today, tomorrow and this month event list and event count information into separate div, I did try various things but couldn't find a better solution, can anyone, please help me with this. below code is for reference.
doneRendering: function() {
// make a moment object representing today
var target = moment();
var tommorow = target.add(1,'days');
var eventsTommorow =[];
if(this.options.multiDayEvents) {
eventsTommorow = $.makeArray( $(this.options.events).filter( function() {
// filter the dates down to the ones that match.
return ( ( tommorow.isSame(this._clndrStartDateObject, 'day') || tommorow.isAfter(this._clndrStartDateObject, 'day') ) &&
( tommorow.isSame(this._clndrEndDateObject, 'day') || tommorow.isBefore(this._clndrEndDateObject, 'day') ) );
}) );
} else {
eventsTommorow = $.makeArray( $(this.options.events).filter( function() {
// filter the dates down to the ones that match.
return this._clndrDateObject.format('YYYY-MM-DD') == dateString;
}) );
}
if(eventsTommorow.length) {
console.log(eventsTommorow.length);
var newNum = eventsTommorow.length < 10 ? "0" + eventsTommorow.length : eventsTommorow.length;
return $('.td-emp-count.tdTommorow').text(newNum);
}
}
},
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Actually, my problem is I can not filter events and print them into separate div, I tried moment.js validation to get today event. but it didn;t work as expected. but finally I tried a simple method to get today, tomorrow and this month event count and it worked. but the problem is if a recurring event happens, let's say maternity leave start on 24th April to 30th may then I can not get between event counts. because I'm capturing CLNDR date, startDate, endDate there is no way to get between events count. please find the code
doneRendering: function() {
// make a moment object representing today
var _self = this;
function todayCount() {
var totalDate = _.filter(_self.options.events, {
date: moment().format('YYYY-MM-DD')
});
var totalStartDate = _.filter(_self.options.events, {
startDate: moment().format('YYYY-MM-DD')
});
var totalEndDate = _.filter(_self.options.events, {
endDate: moment().format('YYYY-MM-DD')
});
var newNum = (totalDate.length + totalStartDate.length + totalEndDate.length) < 10 ? "0" + (totalDate.length + totalStartDate.length + totalEndDate.length) : (totalDate.length + totalStartDate.length + totalEndDate.length);
return newNum;
}
$('.td-emp-count.tdToday').text(todayCount());
},
This is a simple hack and I'm using underscore.js. but this way I cannot get actual today count, the reason is if a recurring leave happens it cannot get middle leave day as a count
eg:
Sick leave
startDate = 24th April 2016
endDate = 28th April 2016
when I apply my simple hack to this, I can only get 24th April (Monday) as one count and 28th April (Friday) as another count but when I try to print Wednesday leave counts, it cannot get this day as a leave count,
I'm new to underscore.js but I really need to know how to print these variables into underscore.js template,
Within template event count.
I can get the today (actual leave) count by using _.each() method and print them on into day itself like this one
<% _.each(days, function(day) { %>
<div class="<%= day.classes %>" id="<%= day.id %>">
<div class="num"><%= day.day %></div>
<% if (day.events.length) { %>
<div class="eventsTitles">Leave : <strong><%= day.events.length %></strong></div>
<% } %>
<ul class="dayLeaveTypes">
<% _.each(day.events, function(event) { %>
<li title="<%= event.type %>" id="<%= event.type %>" style="color:<%= event.color %>;">●</li>
<% }); %>
</ul>
</div>
<% }); %>
but I need to get this actual count (only specific day today or tomorrow) and print them into separate div, not within the calendar.
this is the whole idea i'm trying to solve. :)

jQuery Javascript Group Years by Decades

I have the below which loops through each div and returns the year that each div represents, but what I'd like to do is group the returned years into arrays of the decades. I'm not quite sure how to do that and was hoping someone could help with this.
<div class="timeline-events timeline-year-1994">This is 1994<div>
<div class="timeline-events timeline-year-1997">This is 1997<div>
<div class="timeline-events timeline-year-2001">This is 2001<div>
<div class="timeline-events timeline-year-2003">This is 2003<div>
<div class="timeline-events timeline-year-2012">This is 2012<div>
$('.timeline-events').each(function(){
console.log(this.className.match(/timeline-year-(\d+)?/)[1]);
});
jsFiddle
You can work out the decade of a year by dividing by ten, flooring it and multiplying the result.
From there on out it's grouping by your decade and merging it into your object:
var groupedByDecade = {};
$('.timeline-events').each(function(){
var year = this.className.match(/timeline-year-(\d+)?/)[1],
decade = Math.floor(year/10)*10;
groupedByDecade[decade] = $.merge(groupedByDecade[decade] || [], [year]);
});
JSFiddle
If i understood your question correctly;
var decades = {};
$('.timeline-events').each(function(){
var year = this.className.match(/timeline-year-(\d+)?/)[1];
var decade = year.substring(0,3) + "0";
if (decades.hasOwnProperty( decade )) {
decades[ decade ].push(year);
} else {
decades[ decade ] = [ year ];
}
});
console.log(JSON.stringify(decades));
this creates an object with "decades" as property name which are of the type array, where the array contains the years.
UPDATED for grouping using underscore.
http://jsfiddle.net/9o39jxLo/1/
var data = [];
var decadedata = new Array();
$(function() {
$('.timeline-events').each(function(){
var year = (this.className.match(/timeline-year-(\d+)?/)[1]);
var decade = year - (year % 10);
data.push({ "decade": decade, "year": year});
});
});
function testdecade(){
var groupedData = _.groupBy(data, function(d){return d.decade});
console.log(groupedData);
}
One approach:
// iterate over each of the '.timeline-events' elements:
$('.timeline-events').each(function() {
// finding first the specific (four-digit) year,
// then getting a substring, for the decade and adding a 0:
var decade = (/timeline\-year\-(\d{4})/).exec(this.className)[1].substring(2, 3) + '0',
// if the previous element to the current element is a decade-grouping element and
// it's the appropriate decade, we use that element; otherwise we create a new one:
decadeDiv = $(this).prev('.decade-' + decade).length ? $(this).prev('.decade-' + decade) : $('<div />', {
'class': 'decade-' + decade
// and insert that element before the current element:
}).insertBefore(this);
// we then append this element to the decade grouping element:
$(this).appendTo(decadeDiv);
});
src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="timeline-events timeline-year-1994">This is 1994
</div>
<div class="timeline-events timeline-year-1997">This is 1997
</div>
<div class="timeline-events timeline-year-2001">This is 2001
</div>
<div class="timeline-events timeline-year-2003">This is 2003
</div>
<div class="timeline-events timeline-year-2012">This is 2012
</div>
In response to the clarification, in the comments to the question, that you'd like a JSON string, I'd suggest (assuming you want the HTML of the elements) the following:
var decadeGroups = {};
$('.timeline-events').map(function () {
var decade = [].filter.call(this.classList, function (cName) {
return cName.indexOf('timeline-year-') === 0;
}).join('').match(/\d{2}$/)[0].replace(/\d$/, '0');
if (decadeGroups[decade]) {
decadeGroups[decade].push(this.outerHTML);
}
else {
decadeGroups[decade] = [this.outerHTML];
}
});
console.log(JSON.stringify(decadeGroups));
// initialising an object:
var decadeGroups = {};
// iterating over the '.timeline-events' elements:
$('.timeline-events').each(function() {
// reducing the array-like classList,
var decade = [].filter.call(this.classList, function(cName) {
// keeping only the class-name that starts with 'timeline-year-':
return cName.indexOf('timeline-year-') === 0;
// turning that into a string with join('')
// matching the last two digits of the year,
// replacing the last digit with a zero:
}).join('').match(/\d{2}$/)[0].replace(/\d$/, '0');
// if the object has a key of the current decade:
if (decadeGroups[decade]) {
// we add the outerHTML of the current element to that array:
decadeGroups[decade].push(this.outerHTML);
} else {
// otherwise we create a new object key, and assign an array
// containing the outerHTML of the current element:
decadeGroups[decade] = [this.outerHTML];
}
});
// logging the JSON-stringified object:
console.log(JSON.stringify(decadeGroups));
src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="timeline-events timeline-year-1994">This is 1994
</div>
<div class="timeline-events timeline-year-1997">This is 1997
</div>
<div class="timeline-events timeline-year-2001">This is 2001
</div>
<div class="timeline-events timeline-year-2003">This is 2003
</div>
<div class="timeline-events timeline-year-2012">This is 2012
</div>
References:
JavaScript:
Array.prototype.filter().
Array.prototype.join().
Element.classList.
Function.prototype.call().
JSON.stringify().
String.indexOf().
String.prototype.match().
jQuery:
appendTo().
each().
insertBefore().
prev().

How to use Javascript to create parent and child element at the same time with variable contents

I have a JSON from PHP assoc array:
Array(
[0] = > Array(
[topicid] = > 17
[entry] = > number 12 this one
[belongdate] = > 2017 - 06 - 12
[edittime] = > 2012 - 06 - 18 05: 22: 21
[User_ID] = > 1
)
[1] = > Array(
[topicid] = > 9
[entry] = > yeah 11 now
[belongdate] = > 2017 - 06 - 12
[edittime] = > 2012 - 06 - 18 05: 22: 02
[User_ID] = > 1
)
)
I don't give you JSON straightly is because I don't know how to print JSON properly.
I need to create parent div and multiple children elements:
<div name='entrydiv' class='entrydiv'>
<h3 name='topich3' class='topich3'>
entryjson[i]['topicid']
</h3>
<p name='entryp' class='entryp'>
entryjson[i]['entry']
</p>
<a name='belongdatea' class='belongdatea' style='display: none;'>
entryjson[i]['belongdate']
</a>
<a name='lastedittimea' class='lastedittimea'>
entryjson[i]['edittime']
</a>
</div>
Note the contents are variable from JSON.
I have checked out this post. But the .append method does't seem to support passing variable to the content. And the .appendTo method does not allow child element(?).
I appreciate your help very mush. Thanks.
Here's one example. To create this DOM structure:
<div name='entrydiv' class='entrydiv'>
<h3 name='topich3' class='topich3'>
entryjson[i]['topicid']
</h3>
</div>
You could use this plain javascript code:
var mainDiv = document.createElement("div");
mainDiv.name = mainDiv.className = "entrydiv";
document.body.appendChild(mainDiv);
var item = document.createElement("h3");
item.name = item.className = "topich3";
item.innerHTML = entryjson[i]['topicid'];
mainDiv.appendChild(item);
You can add code for the other parts and then add a loop to iterate through your JSON to repeat.
If you would like to create the following structure:
<div class="yourClassInHTML">
...
<div>
<img src="thePath"></img>
</div>
...
</div>
then .js code would be:
var element1 = document.createElement("div");
var element2 = document.createElement("img");
img.src = "thePath";
element1.appendChild(element2);
document.getElementsByClassName("yourClassInHTML")[0].appendChild(element1);

Categories