Forums

Discuss all things Remember The Milk.

Advanced Searches and Smart Lists

zkestenbaum says:
I've always wished that I could have Smart Lists that are more advanced and that reflect dates in the past. Here are searches that can not currently be done (without hardcoding dates that then need to be updated manually in Settings):

- All tasks that were due in the last 7 days
- All tasks that were due so far this week
- All tasks that were due so far this month
- All tasks that were due last month

So, I came up with an alternate solution using javascript bookmarklets. I created a folder called RTM in my bookmarks bar, and under that folder I created one bookmarklet for each search that I want. When I click on any of the bookmarklets, it composes a search string, puts it in the search bar, and submits the search. Boom!

For each of the below bookmarklets, create a new bookmark and put the "javascript" part in the URL or address field.

"Last 7 days"
javascript:function dateToString(date){ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();}; startDateRange = new Date(); startDateRange.setDate(startDateRange.getDate() - 7); searchStr = 'dueAfter:' + dateToString(startDateRange) + ' and dueBefore:tomorrow'; document.getElementById("listFilter").value = searchStr; control.updateListFilter(); startDateRange = null;

"Month to date":
javascript:function dateToString(date){ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();}; startDateRange = new Date(); startDateRange.setDate(0); searchStr = 'dueAfter:' + dateToString(startDateRange) + ' and dueBefore:tomorrow'; document.getElementById("listFilter").value = searchStr; control.updateListFilter(); startDateRange = null;

"Week to date"
javascript:function dateToString(date){ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();}; startDateRange = new Date(); startDateRange.setDate(startDateRange.getDate() - startDateRange.getDay()); searchStr = 'dueAfter:' + dateToString(startDateRange) + ' and dueBefore:tomorrow'; document.getElementById("listFilter").value = searchStr; control.updateListFilter(); startDateRange = null;

"Last month"
javascript:function dateToString(date){ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();}; startDateRange = new Date(); startDateRange.setDate(startDateRange.getDate() - startDateRange.getDay() - 7); endDateRange = new Date(); endDateRange.setDate(endDateRange.getDate() - endDateRange.getDay() + 1); searchStr = 'dueAfter:' + dateToString(startDateRange) + ' and dueBefore:' + dateToString(endDateRange); document.getElementById("listFilter").value = searchStr; control.updateListFilter(); startDateRange = null; endDateRange = null;

"Last week"
javascript:function dateToString(date){ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();}; startDateRange = new Date(); startDateRange.setDate(startDateRange.getDate() - startDateRange.getDay() - 7); endDateRange = new Date(); endDateRange.setDate(endDateRange.getDate() - endDateRange.getDay() + 1); searchStr = 'dueAfter:' + dateToString(startDateRange) + ' and dueBefore:' + dateToString(endDateRange); document.getElementById("listFilter").value = searchStr; control.updateListFilter(); startDateRange = null; endDateRange = null;


Enjoy! And I look forward to seeing what other great searches people come up with.

Zach
Posted at 8:08pm on October 18, 2012
raymond.bergmark Power Poster says:
Wow, using the search box, really good work!

An old problem you probably can solve in a few minutes:
Creating a weekend smartlist, with task due this upcoming weekend (when asking mon-fri), today+tomorrow (when asking sat) or today+yesterday (when asking sun)
Posted 11 years ago
raymond.bergmark Power Poster says:
And of course well worth a Tip of the Week mention - really clever!
Posted 11 years ago
zkestenbaum says:
Thanks rajjan! I did the weekend one below. The only downside to the search box approach is that it only works in the browser, not in the apps. But hey, better than nothing.

"This weekend"
javascript:function dateToString(date){ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();}; startDateRange = new Date(); startDateRange.setDate(startDateRange.getDate() + (4 - ((startDateRange.getDay() + 6) % 7))); endDateRange = new Date(); endDateRange.setDate(startDateRange.getDate() + 3); searchStr = 'dueAfter:' + dateToString(startDateRange) + ' and dueBefore:' + dateToString(endDateRange); document.getElementById("listFilter").value = searchStr; control.updateListFilter(); startDateRange = null; endDateRange = null;
Posted 11 years ago
raymond.bergmark Power Poster says:
Thanks a lot, I've spent too many hours trying to fix this using the normal search operators and now it's done!
Posted 11 years ago
raymond.bergmark Power Poster says:
Found a minor error above, the Last month script is the same as the Last week script, both return Last week tasks.
Had a try at javascript, think this works:

"Last month"
javascript:function dateToString(date){ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();}; startDateRange = new Date(); startDateRange.setDate(0); startDateRange.setDate(0); endDateRange = new Date(); endDateRange.setDate(0); endDateRange.setDate(endDateRange.getDate() + 1); searchStr = 'dueAfter:' + dateToString(startDateRange) + ' and dueBefore:' + dateToString(endDateRange); document.getElementById("listFilter").value = searchStr; control.updateListFilter(); startDateRange = null; endDateRange = null;
Posted 11 years ago
raymond.bergmark Power Poster says:
Another idea: In order to immediately get a list of what you did last week/month, you could add a and status:completed to these javascripts:

"Last week I did this"
javascript:function dateToString(date){ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();}; startDateRange = new Date(); startDateRange.setDate(startDateRange.getDate() - startDateRange.getDay() - 7); endDateRange = new Date(); endDateRange.setDate(endDateRange.getDate() - endDateRange.getDay() + 1); searchStr = 'dueAfter:' + dateToString(startDateRange) + ' and dueBefore:' + dateToString(endDateRange) + ' and status:completed'; document.getElementById("listFilter").value = searchStr; control.updateListFilter(); startDateRange = null; endDateRange = null;

Otherwise, you could just press the Nnn completed link in the details box to get the same result.
Posted 11 years ago
ranbarton Power Poster says:
Whoa - coolest tip on these boards in a long while. Very, very clever.
Posted 11 years ago
raymond.bergmark Power Poster says:
I totally agree (which you probably could guess from the posts above ;-)!

zkestenbaum: I found some minor errors, I hope you don't mind the corrections.

Slight improvments to the scripts above, using completedAfter/Before in order to see what you really did, not only what was due. No need to include the "and status:completed" mentioned above I noticed. I also made a slight modification to the start date, making it the first of the month not the last of the month before. Also, the getDate offsets doesn't work around the end of the month in the original postings , getTime is used here instead.

"Last week I did this" ver 2:
javascript:function dateToString(date){ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();}; startDateRange = new Date(); startDateRange.setDate(startDateRange.getDate() - startDateRange.getDay() - 7); endDateRange = new Date(); endDateRange.setDate(endDateRange.getDate() - endDateRange.getDay() + 1); searchStr = 'completedAfter:' + dateToString(startDateRange) + ' and completedBefore:' + dateToString(endDateRange); document.getElementById("listFilter").value = searchStr; control.updateListFilter(); startDateRange = null; endDateRange = null;

"Last month I did this" ver 2
javascript:function dateToString(date){ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();}; startDateRange = new Date(); startDateRange.setDate(0); startDateRange.setDate(1); endDateRange = new Date(); endDateRange.setDate(1); searchStr = 'completedAfter:' + dateToString(startDateRange) + ' and completedBefore:' + dateToString(endDateRange); document.getElementById("listFilter").value = searchStr; control.updateListFilter(); startDateRange = null; endDateRange = null;

"Last 7 days I did this"
javascript:function dateToString(date){ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();}; startDateRange = new Date(); startDateRange.setTime(startDateRange.getTime() - 7*24*60*60*1000); searchStr = 'completedAfter:' + dateToString(startDateRange) + ' and completedBefore:tomorrow'; document.getElementById("listFilter").value = searchStr; control.updateListFilter(); startDateRange = null;

"Month to date I did this":
javascript:function dateToString(date){ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();}; startDateRange = new Date(); startDateRange.setDate(1); searchStr = 'completedAfter:' + dateToString(startDateRange) + ' and completedBefore:tomorrow'; document.getElementById("listFilter").value = searchStr; control.updateListFilter(); startDateRange = null;

"Week to date I did this"
javascript:function dateToString(date){ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();}; startDateRange = new Date(); startDateRange.setDate(startDateRange.getDate() - startDateRange.getDay()); searchStr = 'completedAfter:' + dateToString(startDateRange) + ' and completedBefore:tomorrow'; document.getElementById("listFilter").value = searchStr; control.updateListFilter(); startDateRange = null;

"This weekend"
javascript:function dateToString(date){ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();}; startDateRange = new Date(); startDateRange.setDate(startDateRange.getDate() + (4 - ((startDateRange.getDay() + 6) % 7))); endDateRange = new Date(); endDateRange.setTime(startDateRange.getTime() + 3*24*60*60*1000); searchStr = 'dueAfter:"' + dateToString(startDateRange) + ' 23:59" and dueBefore:' + dateToString(endDateRange) + ' and not list:¤Z'; document.getElementById("listFilter").value = searchStr; control.updateListFilter(); startDateRange = null; endDateRange = null;

In order to get dates in the 2012-10-29 format instead of 10/29/2012, modify the dateToString like this:
dateToString(date){ return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();};
Posted 11 years ago
raymond.bergmark Power Poster says:
Another idea for those who prefer not to create too many smart lists as they can clutter up the desktop (code borrowed from zkestenbaum, thanks again):

Modify the script below using the normal search operators and save it as a bookmarklet:
javascript:searchStr = 'Modify this part '; document.getElementById("listFilter").value = searchStr; control.updateListFilter();
In this case, the search text will be static, but allows for loads of different saved searches.

If you tend to forget what you've searched for, you could add a dummy NOT-search at the beginning as in:
javascript:searchStr = 'not "Minor tasks" timeEstimate:"<16 min"'; document.getElementById("listFilter").value = searchStr; control.updateListFilter();
Please observe that you have to mix ' and " in javascript in this case.

Tomorrow is Tuesday, I'm curious to find out if this gets the Tip of the Week mention it rightly deserves!
Posted 11 years ago
rebdebgordon says:
Thank is amazing stuff--and while I have never used JavaScript (because it wasn't around the last time I did any programming, in college in the 1980s), this plenty clear.

Now if they would only implement this themselves, since my iPhone is almost the only place I'm looking at RTM these days. A workaround would be to run the search periodically on the desktop and bulk tag the results "dead" or "January 2016" or "last year," allowing me to create a search which includes or excludes items thus tagged. Nice to know at least that I'm not the only one with overdue tasks scattered throughout the past...
Posted 7 years ago
olaf1303 says:
Wow great idea...two thoughts just came up reading these examples of best practice lists:
1) More often than not, it is very helpful to reevaluate projects and tasks after either completing them, postponing them, giving them to someone else and so on.... If I did not miss some options on operators of due and start in rtm its only possible to define backwards in time QUERIES like duewithin:last quarter of year befor today or first half of last year... on update, added, completed....not on due and start....
this can be solution for every reevaluation listing tasks due or started in the past with time windows relative to today ....
looking backward and debriefing in many projects is a must!! And lessons learnt should be part of every major project..... tasking is not only about building a path of futere work from day to day, but on improving your methods by learning from the projects and tasks of yesterday and last week...

2) looks like some smart guys started a library here for solutions just to copy and past, so even people with complete lack of knowledge how to syntax javascripts and apply to rtm objects and controls can profit from these examples.. and maybe learn to write their own with few changes.... thanks and once again: great idea....
Posted 7 years ago
Log in to post a reply.