var scrollIntoView = function(el) {
if (!el || !el.length) return;
var h = window.innerHeight - $("section#things").position().top,
eh = el.height();
var p = el.position().top,
b = $(window).scrollTop();
if (p + eh > b + h || p < b) {
$("html,body").stop().animate({
scrollTop: Math.floor(p + eh - h / 2) + "px"
}, 400);
}
};
var implodeTextList = function(list) {
var startTag = "<b>",
endTag = "</b>";
if (typeof list[0] != "string") return list;
if (list.length == 1) return startTag + list[0] + endTag;
var tempList = list.slice();
var last = startTag + tempList.pop() + endTag;
return startTag + tempList.join(endTag + ", " + startTag) + endTag + " and " + last;
};
var isTouchDevice = (function() {
var android = navigator.userAgent.indexOf('Android') != -1;
return android || !! ('createTouch' in document);
//return typeof Touch == "object";
})();
var isIPad = navigator.userAgent.match(/iPad/i) != null;
var Thinkery = (function() {
var username, tag, data, originalData, singlePage, currentQuery = false;
if (typeof jQuery.prompt != 'undefined') jQuery.prompt.setDefaults({
persistent: false,
opacity: 0.7,
show: "fadeIn",
overlayspeed: "fast",
promptspeed: "fast",
top: "25%"
});
// impromptu for mobile devices
if (typeof jQuery.prompt != 'undefined' && isTouchDevice) jQuery.prompt.setDefaults({
persistent: false,
opacity: 0.7,
show: "show",
overlayspeed: "fast",
promptspeed: "fast",
top: "5%"
});
var updateTimeLeft = function(timeLeft) {
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
function timeLeft(secs, shortDate) {
if (typeof shortDate == "undefined") shortDate = true;
var ago = false;
if (secs < 0) {
secs = -secs;
ago = true;
}
var x, s, t = [];
if (secs >= 3456000) { // 40 days
s = new Date(new Date() - secs * 1000);
return months[s.getMonth()] + " " + s.getDate() + ", " + s.getFullYear();
}
if (secs >= 86400) {
s = Math.floor(secs / 86400);
x = s + " d" + (shortDate ? "" : "ay");
if (!shortDate && s > 1) x += "s";
t.push(x);
secs -= s * 86400;
}
if (secs >= 3600) {
s = Math.floor(secs / 3600);
x = s + " h" + (shortDate ? "r" : "our");
if (s > 1) x += "s";
t.push(x);
secs -= s * 3600;
}
if (secs >= 60) {
s = Math.floor(secs / 60);
x = s + " min" + (shortDate ? "" : "ute");
if (s > 1) x += "s";
t.push(x);
secs -= s * 60;
}
if (t.length == 0) {
if (!secs) {
t.push("just before");
ago = false;
} else t.push(parseInt(secs, 10) + "s");
}
var ret = "";
s = "";
for (var i = Math.min(1, t.length - 1); i >= 0; i--) {
ret = t[i] + s + ret;
s = (shortDate || s) ? ", " : " and ";
}
return ret + (ago ? " ago" : "");
}
$("span.dateTime").each(function() {
var $this = $(this);
var t = $this.attr("data-t").split(",");
var time = new Date;
time.setUTCHours(parseInt(t[3], 10));
time.setUTCMinutes(parseInt(t[4], 10));
time.setUTCSeconds(parseInt(t[5], 10));
time.setUTCMonth(0);
time.setUTCFullYear(t[0]);
time.setUTCDate(parseInt(t[2], 10));
time.setUTCMonth(parseInt(t[1], 10) - 1);
var diff = (time.getTime() - new Date) / 1000;
$this.text(timeLeft(diff, !$this.hasClass("long")));
});
};
setInterval(updateTimeLeft, 30000);
var lastTag = false;
var loadTag = function(_tag, initialLoad, nonEmpty) {
if (typeof initialLoad == "undefined") initialLoad = false;
if (!Thinkery.mainListUrl) return false;
if (_tag == lastTag) return false;
lastTag = _tag;
var tagUrlPart = _tag ? "tag=" + encodeURIComponent(_tag) : "";
$.getJSON(Thinkery.mainListUrl + tagUrlPart, function(r) {
if (initialLoad && data.length == 0) {
location.href = "/" + username;
return;
}
var tags = $("nav#menu ul li").removeClass("active");
if (typeof _tag == "undefined" || !_tag) {
if (typeof history.pushState == "function") history.pushState({
tag: ""
}, username, "/" + username);
tags.filter("li:contains(All)").addClass("active");
tag = false;
} else {
_tag = String(_tag);
if (typeof history.pushState == "function") history.pushState({
tag: _tag
}, username + " - " + _tag, "/" + username + "/" + _tag);
tags.filter("li[data-tag='" + _tag.replace("'", "\\'") + "']").addClass("active");
tag = _tag;
}
_gaq.push(['_trackPageview', '/' + username + "/" + tag]);
originalData = data = r;
$("section#things ul").show(function() {
var searchAdd = $("#searchadd");
if (nonEmpty == true) {
} else if (searchAdd.val() != "") {
searchAdd.val("").keyup();
}
$("button.ir").addClass("search").removeClass("add");
$("sub.results, sub.hint").addClass("hidden");
updateList();
$("section#things ul li:first").addClass("active");
$("section#things ul").fadeIn();
if ($("#bulkControls").is(":visible")) showBulk();
});
retrieveThings();
registerLazyLoad();
updateFlyout(0, false, true);
});
return false;
};
var retrieveQueue = 0,
retrieveTimeout = false;
// update items that have not been retrieved
var retrieveThings = function() {
if (retrieveTimeout) {
clearTimeout(retrieveTimeout);
if (retrieveQueue > 3) {
retrieveTimeout = setTimeout(retrieveThings, 3000);
return;
}
}
var l = data.length;
for (var i = 0; i < l; i++) {
if (data[i].retrieved) continue;
if (retrieveQueue > 3) {
retrieveTimeout = setTimeout(retrieveThings, 3000);
break;
}
retrieveQueue += 1;
data[i].thinking = true;
updateList(i);
$.ajax({
url: "/retrieve.php",
type: "post",
data: {
id: data[i]._id
},
success: function(r) {
retrieveQueue -= 1;
if (typeof r._id == "undefined") return false;
for (var i = 0, l = data.length; i < l; i++) {
if (data[i]._id != r._id) continue;
data[i] = r;
if ($("section#things li.active").index() == i) updateFlyout(i);
updateList(i);
break;
}
},
error: function() {
retrieveQueue -= 1;
}
});
}
};
/* Check if more things can be loaded */
var checkMore = function() {
var l = $('section#things li:not(.no-thing)').length;
var s = $('#searchadd');
var num = parseInt($('#menu li.active .num').text(), 10);
if (isNaN(num)) num = 0;
if (!l || l >= num || (s.length !== 0 && s.val() !== '')) {
$('.loadmore').addClass('inactive').find('a').text('');
return false;
}
$('.loadmore').removeClass('inactive').find('a').text('Show more ↓');
return true;
};
/* init Lazy Loading */
var registerLazyLoad = function(initLoad) {
if (typeof initLoad == 'undefined') initLoad = false;
//page init
$('section#things').data('page', 0);
checkMore();
$(window).unbind('scroll').bind('scroll', function() {
if ($(window).scrollTop() != $(document).height() - $(window).height()) return;
setTimeout(function() {
if ($(window).scrollTop() != $(document).height() - $(window).height()) return;
loadThings(initLoad);
}, 300);
});
$('.loadmore a').unbind('click').live('click', function(e) {
e.preventDefault();
loadThings(initLoad);
});
};
/* load more things */
var loadThings = function(noargs) {
if (!checkMore()) return;
//show loader, increment page count
$('section#things, .loadmore').addClass('loading');
$('section#things').data('page', parseInt($('section#things').data('page'), 10) + 1);
if (typeof noargs !== 'undefined' && noargs) {
var _data = {
'page': 0
};
} else {
var tag = $('#menu ul li.active').attr('data-tag');
var page = $('section#things').data('page');
var _data = {
'page': page
};
if (typeof tag !== 'undefined' && tag !== '') {
$.extend(_data, {
'tag': encodeURIComponent(tag)
});
}
if (document.URL.split("?")[1] == 'archived') {
$.extend(_data, {
'archived': true
});
}
if ($('#search h4 a').text() !== "") {
$.extend(_data, {
'username': $('#search h4 a').text()
});
}
}
var url, _type = "get";
if (currentQuery) {
url = '/search.php';
_type = "post";
} else if (typeof Thinkery.mainListUrl == "undefined") {
url = '/mainlist.php';
} else {
url = Thinkery.mainListUrl;
}
$.ajax({
url: url,
dataType: 'json',
data: _data,
type: _type,
success: function(r) {
if (r == '') {
$('.loadmore').addClass('inactive').find('a').text('');
} else {
updateData(r);
retrieveThings();
}
$('section#things, .loadmore').removeClass('loading');
}
});
};
var reloadSidebar = function(full) {
if (typeof full == "undefined") full = false;
var sidebarUrl = "/sidebar.php?username=" + encodeURIComponent(username);
if (tag) sidebarUrl += "&tag=" + encodeURIComponent(tag);
if (location.search == "?archived") sidebarUrl += "&archived";
if (full) sidebarUrl += "&full";
var favorites = $("#edittags").hasClass("active");
$("nav#menu").load(sidebarUrl + " nav#menu>*", function() {
if ($("#bulkControls").is(":visible")) {
$('#toggleBulk').addClass("active");
}
if (favorites) {
$("#edittags").click();
}
$(window).trigger('reloadSidebar');
});
};
var updateData = function(d) {
if (!d) {
$('.loadmore').addClass('inactive').find('a').text('');
return;
}
for (i = 0, l = d.length; i < l; i++) {
data.push(d[i]);
}
originalData = data;
updateList();
};
var getPrivacyIcon = function(tmp) {
return '<span class="icn grey ' + getPrivacyClass(tmp) + ' tip ' + (tmp.canEdit ? 'canEdit' : '') + ' title="' + getPrivacyTitle(tmp) + '"></span>';
};
var getPrivacyTitle = function(tmp, html) {
if (typeof html == "undefined") html = false;
var privacyTitle = "Private: only you can see it";
if (!tmp["private"]) {
privacyTitle = "Public: everybody can see it";
if (tmp.shared) {
privacyTitle += '; also shared between ' + implodeTextList(tmp.shared);
}
} else if (tmp.shared) {
privacyTitle = 'Shared between ' + implodeTextList(tmp.shared);
}
if (!html) privacyTitle = privacyTitle.replace(/</g, "<").replace(/>/g, ">");
return privacyTitle;
};
var getPrivacyIconText = function(tmp) {
var friends = tmp.shared ? tmp.shared.length - 1 : 0;
var privacyIconText = "Private";
if (!tmp["private"]) {
privacyIconText = "Public" + (friends > 0 ? " + " + friends + ' Friend' + (friends == 1 ? "" : "s") : "");
} else if (tmp.shared) {
privacyIconText = friends + ' Friend' + (friends == 1 ? "" : "s");
}
return privacyIconText;
};
var getPrivacyClass = function(tmp) {
var privacyClass = "private";
if (!tmp["private"]) {
privacyClass = "public";
} else if (tmp.shared) {
privacyClass = "shared";
}
return privacyClass;
};
var updateList = function(i) {
bulkedit = $("#bulkControls").is(":visible");
var listItem;
if (typeof i != "undefined") {
var tmp = data[i];
listItem = $("section#things li").eq(i);
if (tmp.archived) {
listItem.addClass("archived");
} else {
listItem.removeClass("archived");
}
var allClasses = listItem[0].className.split(" ");
for (var o = 0, l = allClasses.length; o < l; o++) {
if (allClasses[o].substr(0, 6) == "thing-") listItem.removeClass(allClasses[o]);
}
for (var o = 0, l = tmp.classNames.length; o < l; o++) {
listItem.addClass(tmp.classNames[o]);
}
$("article", listItem).html(tmp.htmlTitle + ((typeof tmp.thinking != "undefined" && tmp.thinking) ? '<img src="/img/loading.gif" class="loader" /> <span class="smaller grey">thinking...</span>' : "")).highlight(currentQuery);
$("span.tags", listItem).html(tmp.tags);
var p = $("span.public, span.private, span.shared", listItem);
var privacyClass = getPrivacyClass(tmp);
p.removeClass("private public shared").addClass(privacyClass).attr("title", getPrivacyTitle(tmp, true)).tipTip();
if (privacyClass == "private") $("div.privacy", listItem).hide();
else $("div.privacy", listItem).show();
var bulk = $("input.bulk", listItem);
bulk.attr("checked", typeof tmp.checked != "undefined" && tmp.checked);
if (tmp.canEdit && bulkedit) {
bulk.show();
} else {
bulk.hide();
}
return;
}
var actions, active;
if (typeof i == "undefined" && $('section#things li.active').length != 0) {
active = $("section#things li.active").index();
}
if (data.length == 0) {
$("section#things ul").text("").append($("ul#noThingTemplate li").clone());
return;
}
var list = $("section#things ul"),
html = "",
oldFirstId = $("section#flyout input.id").val(),
firstId = false,
tmp, l;
for (j = 0, l = data.length; j < l; j++) {
tmp = data[j];
listItem = "<li class=\"thing-list-item";
if (tmp.archived) listItem += ' archived';
if (tmp.classNames) listItem += ' ' + tmp.classNames.join(" ");
if (tmp.todoStatus) listItem += ' checked';
listItem += '">';
if (tmp.canEdit) listItem += '<span class="drag"></span>';
var privacyIcon = getPrivacyIcon(tmp);
listItem += '<div class="privacy"' + ((!tmp.shared || !tmp.shared.length) && tmp["private"] ? ' style="display: none"' : '') + '>' + privacyIcon + "</div>";
listItem += '<input type="checkbox" name="bulk[]" value="' + tmp._id + '" class="bulk" ' + (typeof tmp.checked != "undefined" && tmp.checked ? ' checked="checked"' : '') + ' />';
listItem += '<input type="checkbox" class="todo" ' + (typeof tmp.todoStatus != "undefined" && tmp.todoStatus ? ' checked="checked"' : '') + ' />';
listItem += '<article>' + tmp.htmlTitle + ((typeof tmp.thinking != "undefined" && tmp.thinking) ? '<img src="/img/loading.gif" class="loader" /> <span class="smaller grey">thinking...</span>' : "") + "</article>";
actions = "";
actions += privacyIcon;
if (tmp.canEdit) {
actions += "<a href=\"\" class=\"icn edit tip\" title=\"Edit\"> </a>" + "<a href=\"\" class=\"icn archive tip\" title=\"" + (tmp.archived ? "Unarchive" : "Move to archive") + "\"> </a>" + "<a href=\"\" class=\"icn delete tip\" title=\"Delete\"> </a>";
}
listItem += "<sub class=\"meta\">" + "<span class=\"tags\">" + tmp.tags + "</span> <span data-t=\"" + tmp.date + "\" class=\"info grey dateTime\">just before</span>" + "<span class=\"actions\">" + actions + "</span>" + "</sub>";
listItem += "</li>";
html += listItem;
}
list.html(html);
//check if element and/or edit-mode is active
if (typeof i == 'undefined') i = active;
if (typeof i != "undefined") {
if ($('section#flyout .content.edit').is(":hidden")) {
updateFlyout(i);
}
$('section#things li').eq(i).addClass('active');
}
$("section#things li article").highlight(currentQuery);
$("section#things li span.tags").highlight(currentQuery);
checkMore();
if (typeof data[0] == "undefined") {
$("section#flyout .content").hide();
}
/*else if (oldFirstId) {
updateFlyout(0, false, false);
}*/
updateTimeLeft();
$(window).trigger('things-list-updated', data);
};
var updatePublicPrivate = function(i) {
var content = $("section#flyout div.content.display");
var active = $("section#things li").eq(i).hasClass("active");
var a = $("nav#sharing ul.dropdown>li>a>span"),
pp = $("span.publicprivate", content),
permalink = $("a.permalink", content);
var tmp = data[i];
if (active) {
if (tmp.canEdit) $("nav#sharing").show();
else $("nav#sharing").hide();
$("nav#sharing ul ul a").removeClass("active");
}
var friends = tmp.shared ? tmp.shared.length - 1 : 0;
var text = getPrivacyIconText(tmp);
var privacyClass = getPrivacyClass(tmp);
pp.text(text).removeClass("private public shared").addClass(privacyClass).attr("title", getPrivacyTitle(tmp, true)).tipTip();
permalink.attr("title", privacyClass == "private" ? "Private Permalink" : "Public Permalink: use this URL to share it with shared").tipTip();
if (active) {
a.text(text).removeClass("private public shared").addClass(privacyClass);
$("nav#sharing ul ul a." + privacyClass).addClass("active");
}
};
var updateFlyout = function(i, showEdit, fade) {
if (typeof showEdit == "undefined") showEdit = false;
if (typeof data[i] == "undefined") return false;
if (typeof fade == "undefined") fade = true;
var tmp = data[i];
$("section#things li").eq(i).addClass("active").siblings().removeClass("active");
var content = $("section#flyout div.content.display");
var edit = $("section#flyout div.content.edit");
var show = showEdit ? edit : content;
var showIt = function() {
if (tmp.url) {
$("h1.linked a", content).html(tmp.htmlTitle).attr("href", tmp.url).highlight(currentQuery);
$("h1.linked", content).show();
$("h1.unlinked", content).hide();
} else {
$("h1.unlinked", content).html(tmp.htmlTitle).show().highlight(currentQuery);
$("h1.linked", content).hide();
}
$("div.embed", content).html(tmp.html).highlight(currentQuery);
$("span.tags", content).html(tmp.tags).highlight(currentQuery);
$("span.dateTime", show).attr("data-t", tmp.date);
if (tmp.htmlNote && $.trim(String(tmp.htmlNote).replace("<br>", "")).length) {
$("details", content).html(tmp.htmlNote).show().highlight(currentQuery);
$("a.icn.edit.note", content).hide();
} else {
$("details", content).hide();
$("a.icn.edit.note", content).show();
}
$("a.icn.archive", content).text(tmp.archived ? "Unarchive" : "Archive").attr("title", tmp.archived ? "Unarchive" : "Move to archive");
$("a.permalink", content).attr("href", tmp.permalink);
if (tmp.canEdit) $("nav.actions").show();
else $("nav.actions").hide();
updatePublicPrivate(i);
$("input.title", edit).val(tmp.title);
$("input.url", edit).val(tmp.url ? tmp.url : "");
$("input.tags", edit).val(tmp.textTags);
$("input.id", edit).val(tmp._id);
$("textarea.note", edit).val(tmp.note ? tmp.note : "");
$("select[name=private]", edit).eq(0).attr("selectedIndex", tmp["private"] ? 0 : 1);
updateTimeLeft();
var afterShow = function() {
if (showEdit) {
var editor = $("textarea.note", edit).cleditor({
width: "99%",
height: "12%",
controls: "bold italic underline strikethrough | bullets numbering | link unlink | style highlight | undo redo | source",
styles: [
["Paragraph", "<p>"],
["Header 1", "<h1>"],
["Header 2", "<h2>"],
["Header 3", "<h3>"],
["Header 4", "<h4>"],
["Header 5", "<h5>"],
["Header 6", "<h6>"]
]
})[0].updateFrame().focus();
var resizeEditor = function() {
var d = $("div.cleditorMain");
var p = d.offset();
d.height(Math.max(200, $(window).height() - p.top - 135));
editor.refresh();
};
resizeEditor();
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
$(window).scrollTop($(window).scrollTop() - 50);
}
//$('#flyout .content.edit').scrollTop(0);
$(window).unbind("resize").resize(resizeEditor);
$("input.title", edit).focus();
}
};
if (fade) {
show.fadeIn(20, afterShow);
} else {
show.show();
afterShow();
}
};
if (fade) {
$(content).add(edit).filter(":visible").fadeOut(10, showIt);
} else {
$(content).add(edit).filter(":visible").hide();
showIt();
}
};
var showBulk = function() {
var bulkControls = $("#bulkControls").show();
var c = 0;
var unarchive = bulkControls.find("button[name=unarchive]"),
archive = bulkControls.find("button[name=archive]"),
publ = bulkControls.find("button[name=public]"),
priv = bulkControls.find("button[name=private]");
if ($("section#things li.archived").length) { // has things that are archived
unarchive.parent().show(); // so offer the unarchive button
c++;
} else {
unarchive.parent().hide();
}
if ($("section#things li:not(.archived)").length) { // has things that are not archived
archive.parent().show(); // so offer the archive button
c++;
} else {
archive.parent().hide();
}
if ($("section#things li span.private").length) { // has things that are private
publ.parent().show(); // so offer the public button
c++;
} else {
publ.parent().hide();
}
if ($("section#things li span.public").length) { // has things that are public
priv.parent().show(); // so offer the private button
c++;
} else {
priv.parent().hide();
}
if (c > 3) {
publ.text("public");
priv.text("private");
} else {
publ.text("make public");
priv.text("make private");
}
if (c > 2) {
$("#closeBulk").text("[x]");
} else {
$("#closeBulk").text("[x] close");
}
$("section#things li").addClass("bulkedit");
$("#toggleAllChecked").attr("checked", false);
$('#toggleBulk').addClass("active");
};
var hideBulk = function() {
$("#bulkControls").hide();
$("section#things li").removeClass("bulkedit");
$('#toggleBulk').removeClass("active");
};
var tags = {};
return {
registerLazyLoad: registerLazyLoad,
loadTag: loadTag,
loadThings: loadThings,
updateList: updateList,
reloadSidebar: reloadSidebar,
findThingById: function(_id) {
for (var i = 0, l = data.length; i < l; i++) {
if (data[i]._id == _id) return data[i];
}
return false;
},
saveThing: function(thing, cb, err) {
$.post("/save.php", thing, function(r) {
if (!r || !r._id) {
if (err) err();
return;
}
for (var i = 0, l = data.length; i < l; i++) {
if (data[i]._id != r._id) continue;
data[i] = r;
updateFlyout(i);
updatePublicPrivate(i);
updateList(i);
}
if (cb) cb();
});
},
load: function(_username, _data, _singlePage, _tags) {
for (var k in _tags) {
_tags[k]['q'] = k.toLowerCase();
tags[k] = _tags[k];
}
Thinkery.tags = tags;
username = _username;
originalData = data = _data;
singlePage = typeof _singlePage == "boolean" ? _singlePage : false;
$('#main').attr('username', username);
retrieveThings();
$("nav#menu ul li a").live("click", function(e) {
if (!Thinkery.mainListUrl) return true;
var li = $(e.target).closest("li");
if (li.closest("nav#filter").length) return true;
var _tag = li.data("tag");
if (!li.data("all") && (typeof _tag == "undefined" || !_tag)) {
if (!tag) return true;
location.href = "/" + username + "/" + tag + (e.target.search == "?archived" ? "?archived" : "");
return false;
}
if (li.hasClass("smart")) _tag = "smart:" + _tag;
loadTag(_tag);
return false;
});
$("nav#menu ul li span.settings, nav#menu #addsmartfolder").live("click", function(e) {
$.prompt($("#smartfolderTemplate").html(), {
buttons: {
"Save": true,
"Cancel": false
},
classes: 'share',
loaded: function(v) {
var buttons = $("button", "#jqi table");
function firstRemoveButton() {
var rows = $("tr", "#jqi table");
var firstRemove = rows.find("button.remove");
if (rows.length == 1) firstRemove.attr("disabled", true);
else firstRemove.attr("disabled", false);
}
firstRemoveButton();
buttons.live("click", function(r) {
var button = $(r.target);
if (button.hasClass("add")) {
$("#jqi table").append($("#smartfolderTemplate tr").clone());
} else if (button.hasClass("remove")) {
button.closest("tr").remove();
}
firstRemoveButton();
});
}
});
return false;
});
$("a[data-tag]").live("click", function(e) {
if (!Thinkery.mainListUrl) return true;
var _tag = $(e.target).data("tag");
if (typeof _tag == "undefined" || !_tag) return true;
loadTag(_tag);
return false;
});
$('nav#menu .moretags a').live("click", function(e) {
var $this = $(this);
var expanded = !$this.hasClass('expanded');
var p = $this.parent();
var loaded = p.hasClass('loaded');
if (expanded) {
$this.html("Fewer tags ↑");
this.className = "expanded";
if (!loaded) {
$this.html("<img src='/img/loading.gif' />");
reloadSidebar(true);
} else {
$("ul#nonFavoriteTags li").show();
}
} else {
$this.html("All tags ↓");
this.className = "collapsed";
$("ul#nonFavoriteTags li:gt(9)").hide();
}
$('nav#menu').css("position", expanded ? "absolute" : "fixed");
return false;
});
$("section#things li").live("click", function(e) {
if (e.shiftKey) {
var i = $("section#things li.active").index();
var j = $(this).index();
if (j < i) {
var k = j;
j = i;
i = k;
}
var bulks = $("section#things li input.bulk");
if ($("#bulkControls").is(":hidden")) bulks.attr("checked", false);
for (; i <= j; i++) {
data[i].checked = true;
bulks.eq(i).attr("checked", true);
}
showBulk();
return false;
}
updateFlyout($(this).index());
});
$("section#things li input.todo").live("click", function(e) {
var li = $(this).closest("li");
var i = li.index();
data[i].todoStatus = this.checked;
if (this.checked) li.addClass("checked");
else li.removeClass("checked");
$.post("/save.php", {
id: data[i]._id,
"todo": this.checked ? "checked" : "not-checked"
});
});
$("section#things li input.bulk").live("click", function(e) {
data[$(this).closest("li").index()].checked = this.checked;
});
if (isTouchDevice) {
var touchStartThing = false,
touchStartTag = false,
touchMoves = 0;
$("section#things li").live("touchstart", function(e) {
touchStartThing = $(this).index();
touchMoves = 3;
});
$("section#things li").live("touchmove", function(e) {
if (--touchMoves > 0) return;
touchStartThing = false;
});
$("section#things li").live("touchend", function(e) {
if (touchStartThing === false) return;
if (isIPad) {
updateFlyout($(this).index());
} else {
location.href = data[$(this).index()].permalink;
}
});
$("a[data-tag]").live("touchstart touchmove", function(e) {
touchStartThing = false;
});
$("a[data-tag]").live("touchend", function(e) {
e.preventDefault();
if (!Thinkery.mainListUrl) return true;
touchStartThing = false;
var _tag = $(e.target).data("tag");
if (typeof _tag == "undefined" || !_tag) return true;
loadTag(_tag);
return false;
});
}
$("section#things li a.edit").live("click", function(e) {
e.preventDefault();
updateFlyout($(this).closest("li").index(), /* edit */ true);
return false;
});
$('section#flyout .content .icn.edit').live("click", function(e) {
e.preventDefault();
$("section#things li.active a.edit").click();
return false;
});
$('section#flyout .content.edit nav.actions button.cancel').live("click", function() {
if (isTouchDevice) return location.reload();
$('section#flyout .content.display').show();
$('section#flyout .content.edit').hide();
$('section#flyout').css("position", "fixed");
return false;
});
var updatePrivacy = function(r) {
for (var i = 0, l = data.length; i < l; i++) {
if (data[i]._id != r._id) continue;
data[i] = r;
updateFlyout(i);
updateList(i);
updatePublicPrivate(i);
break;
}
};
$('section#flyout .meta .publicprivate, section#things li span.private, section#things li span.public, section#things li span.shared').live('click', function(e) {
var i = $(this).closest("section#flyout").length ? $("section#things li.active").index() : $(this).closest("li").index();
if (!data[i].canEdit) return false;
var newPrivate = !data[i]["private"];
var id = data[i]._id;
$("#tiptip_holder").hide();
$.post("/save.php", {
id: id,
"private": newPrivate ? "private" : "public"
}, updatePrivacy);
});
$('nav#sharing li').live('click', function(e) {
var $this = $(this);
if ($this.hasClass("dir")) return false;
var i = $("section#things li.active").index();
if (!data[i].canEdit) return false;
var newPrivate = true;
var id = data[i]._id;
switch ($this.text()) {
case "Public":
newPrivate = false;
case "Private":
$.post("/save.php", {
id: id,
"private": newPrivate ? "private" : "public"
}, updatePrivacy);
break;
case "Friends":
$.prompt($('#shareTagPopup').html(), {
buttons: {},
classes: 'share',
loaded: function(v) {
var buttons = $("button", "#jqi");
$("input[name=users]:visible").focus().keyup(function(e) {
if (e.altKey || e.metaKey || e.ctrlKey) return true;
var keyCode = (e == null) ? event.keyCode : e.which;
switch (keyCode) {
case 13:
// buttons.eq(0).click();
return false;
}
});
buttons.eq(0).click(function() {
var users = $("input[name=users]:visible").val();
$.post("/share.php", {
id: id,
users: users,
allowChange: $("input[name=allowChange]:visible").is(":checked")
}, function(v) {
$.prompt.close();
if (typeof v.thing != "undefined") {
data[i] = v.thing;
updateFlyout(i);
updateList(i);
updatePublicPrivate(i);
}
$.prompt("Now these users can view this item: " + v.users.join(", "));
});
return false;
});
buttons.eq(1).click(function() {
$.prompt.close();
return false;
});
}
});
break;
}
return false;
});
$('section#flyout .content.edit nav.actions button.save').live("click", function() {
var edit = $("section#flyout .content.edit");
var title = edit.find("input.title").val();
if ($.trim(title).length == 0) {
$.prompt("The title can't be empty.");
return false;
}
var id = edit.find("input.id").val();
var tags = $.trim(edit.find("input.tags").val());
$.post("/save.php", {
id: id,
title: title,
tags: tags,
url: edit.find("input.url").val(),
note: edit.find("textarea.note").val(),
"private": edit.find("select[name=private]").val()
}, function(r) {
if (isTouchDevice) return location.reload();
for (var i = 0, l = data.length; i < l; i++) {
if (data[i]._id != id) continue;
data[i] = r;
updateFlyout(i);
updateList(i);
reloadSidebar();
break;
}
});
$('section#flyout').css("position", "fixed");
return false;
});
$("section#flyout a.delete, section#things li a.delete, section#flyout a.archive, section#things li a.archive").live("click", function() {
var question, buttons, del = $(this).hasClass("delete");
var i = $(this).closest("section#flyout").length ? $("section#things li.active").index() : $(this).closest("li").index();
if (del) {
question = "<h1 class='border'>Delete</h1>Really delete <i>" + data[i].title + "</i>?";
buttons = {
"Yes, delete it": true,
"Cancel": false
};
} else {
if (data[i].archived) {
question = "<h1 class='border'>Unarchive</h1>Really unarchive <i>" + data[i].title + "</i>?";
buttons = {
"Yes, unarchive it": true,
"Cancel": false
};
} else {
question = "<h1 class='border'>Archive</h1>Really archive <i>" + data[i].title + "</i>?";
buttons = {
"Yes, archive it": true,
"Cancel": false
};
}
}
$.prompt(question, {
buttons: buttons,
classes: del ? "delete" : "archive",
callback: function(buttonClicked) {
if (!buttonClicked || typeof data[i] == "undefined") return false;
$.post(del ? "/delete.php" : (data[i].archived ? "/archive.php?unarchive" : "/archive.php"), {
id: data[i]._id
}, function(r) {
if (singlePage) {
if (del) { // item doesn't exist anymore, go to all things
location.href = "/" + username;
return;
}
data[i].archived = !data[i].archived;
} else {
if (!del && data[i].archived) {
data[i].archived = false;
} else {
data.splice(i, 1);
}
}
reloadSidebar();
updateList();
if ($("section#things li").length == 0) {
$("section#things ul").append("<li>No Things found.</li>");
$("section#flyout div.content.display").css("visibility", "hidden");
} else {
var el = $("section#things li").eq(i).click();
scrollIntoView(el);
}
});
}
});
return false;
});
var lastQuery, lastAjax, lastTimeout = null,
beforeQuery = null,
tmpQuery, ajaxQueryOld, ajaxQueryCurrent;
var autocompleteDiv = $('#tag-autocomplete');
var slStart = null;
var searchAdd = $('#searchadd').bind('focus focusin mouseenter', function() {
return true;
if (check_tag_autocomplete()) {
// beforeQuery = null;
searchAdd.keyup();
}
});
var searchField = $('#search').bind('mouseleave click', function(e) {
return true;
autocompleteDiv.empty().hide();
});
var searchInput = $('#search-input');
var btns = {
bir: $("button.ir"),
hint: $("sub.hint"),
results: $("sub.results")
};
function tag_autocomplete_render(tagName) {
$("<li>" + tagName + " <span class=\"grey flr\">" + tags[tagName].count + "</span></li>").attr('data-tag', tagName).appendTo(autocompleteDiv).click(function() {
searchAdd.trigger('tag-autocomplete', tagName);
});
}
function check_tag_autocomplete() {
slStart = searchAdd.get(0).selectionStart || slStart;
var sval = searchAdd.val();
if (sval[sval.length - 1] == " ") return false;
if (!slStart) {
var tmp = $.trim(sval).split(" ");
} else {
var tmp = $.trim(sval);
tmp = tmp.substr(0, slStart + 1);
if (tmp[tmp.length - 1] == " ") return false;
tmp = tmp.split(" ");
tmp.reverse();
for (var i = 0, l = tmp.length; i < l; i++) {
if (tmp[i][0] == "#") {
return tmp[i];
} else {
return false;
}
}
tmp.reverse();
}
tmp.reverse();
for (var i = 0, l = tmp.length; i < l; i++) {
if (tmp[i][0] == "#") {
return tmp[i];
}
}
return false;
}
searchAdd.bind('tag-autocomplete', function(evt, tagName) {
if (!tagName || typeof tagName == "undefined") return;
// var d = check_tag_autocomplete();
var tmp = $.trim(searchAdd.val()).split(" ");
tmp.reverse();
for (var i = 0, l = tmp.length; i < l; i++) {
if (tmp[i][0] == "#") {
tmp[i] = '#' + tagName + " ";
break;
}
}
tmp.reverse();
searchAdd.val(tmp.join(" ")).data('tag.added', true);
autocompleteDiv.empty().hide();
beforeQuery = null;
searchAdd.focus().keyup();
btns.bir.addClass("searchadd").removeClass("add");
btns.hint.addClass("hidden");
btns.results.removeClass("hidden");
}).bind('stop', function() {
if (lastAjax) lastAjax.abort();
clearTimeout(lastTimeout);
searchField.removeClass('searching');
}).keyup(function() {
lastQuery = this.value;
if ($.trim(this.value) == "") {
searchAdd.trigger('stop');
btns.bir.addClass("search").removeClass("add").removeClass("searchadd");
btns.hint.addClass("hidden");
btns.results.addClass("hidden");
data = originalData;
currentQuery = false;
updateList();
autocompleteDiv.hide();
return true;
}
if (beforeQuery == lastQuery) return;
tmpQuery = beforeQuery;
beforeQuery = lastQuery;
// vorherigen ajax request abbrechen wenn neue suche angefangen wird
searchAdd.trigger('stop');
lastTimeout = setTimeout(function() {
searchAdd.focus();
var d = check_tag_autocomplete();
if (d && d[0] == "#" && searchAdd.data('tag.added') !== true) {
// tags autocomplete
if (!autocompleteDiv.size()) {
autocompleteDiv = $('<ul id="tag-autocomplete" class="tag-autocomplete search">').appendTo("#container");
}
autocompleteDiv.empty().hide();
d = d.toLowerCase();
var k, q = d.substr(1),
ql = q.length,
qk;
for (k in tags) {
qk = tags[k].q;
if (qk.substr(0, ql) == q && k != q) {
tag_autocomplete_render(k);
}
}
if (autocompleteDiv.find('li:first').addClass('active').size()) {
autocompleteDiv.show();
// beforeQuery = null;
return;
} else {
autocompleteDiv.hide();
}
} else {
autocompleteDiv.hide();
}
searchAdd.data('tag.added', false);
//if( $trim(tmpQuery) == $.trim(beforeQuery) ) {
//}
ajaxQueryCurrent = $.trim(lastQuery);
if (ajaxQueryOld == ajaxQueryCurrent) return;
searchAdd.trigger('stop');
searchField.addClass('searching');
lastAjax = $.post("/search.php", {
q: lastQuery
}, function(r) {
ajaxQueryOld = ajaxQueryCurrent;
// if (lastQuery != r.q) return;
data = r.result;
currentQuery = r.q;
if (data.length == 0) {
btns.bir.addClass("add").removeClass("search").removeClass("searchadd");
btns.hint.removeClass("hidden");
btns.results.addClass("hidden");
} else {
btns.bir.addClass("searchadd").removeClass("add");
btns.hint.addClass("hidden");
btns.results.removeClass("hidden").text('Search results for "' + (lastQuery.length > 40 ? "..." + lastQuery.substr(lastQuery.length - 20) : lastQuery) + '":');
}
updateList();
retrieveThings();
searchField.removeClass('searching');
ajaxQueryOld = ajaxQueryCurrent;
});
}, 100);
});
$("#toggleBulk").live("click", function(e) {
var bulkControls = $("#bulkControls");
if (bulkControls.is(":visible")) {
hideBulk();
} else {
showBulk();
}
return false;
});
$("#closeBulk").click(function() {
hideBulk();
return false;
});
$("#toggleAllChecked").click(function(e) {
var ch = this.checked;
$("section#things li input.bulk").each(function(i) {
if (e.shiftKey) this.checked = !this.checked;
else this.checked = ch;
data[i].checked = this.checked;
});
});
$("button.bulk").click(function() {
var checked = $("section#things li:has(input.bulk:checked)");
var el = this;
var formSubmit = function(r) {
if (r == "error" || typeof(r) == "string") {
$.prompt("An error was reported from the server, please try again." /* + r */ );
return;
}
var ids = {};
for (var i = 0, l = r.length; i < l; i++) {
ids[r[i]._id] = r[i];
}
var activeIndex = $("section#things li.active").index();
var updateWholeList = false;
for (var i = data.length - 1; i >= 0; i--) {
var j = data[i]._id;
if (typeof ids[j] == "undefined") continue;
if (typeof ids[j].deleted != "undefined" && ids[j].deleted) {
data.splice(i, 1);
updateWholeList = true;
continue;
}
data[i] = ids[j];
data[i].checked = true;
updateList(i);
if (activeIndex == i) {
updatePublicPrivate(i);
updateFlyout(i);
}
}
if (updateWholeList) {
updateList();
}
if (!(el.name == "public" || el.name == "private")) {
reloadSidebar();
}
if (data.length) {
showBulk();
} else {
if (tag != "") loadTag("");
hideBulk();
}
};
var sendForm = function() {
var form = $("form[name=bulk]");
$.post(form.attr("action"), form.serialize() + "&" + el.name + "=" + encodeURIComponent(el.value), formSubmit);
};
switch (this.name) {
case "add-tag":
if (checked.length == 0) {
action = "add a tag to";
break;
}
$.prompt('<h1 class="border">Add which tag?</h1><input type="text" name="add-tag" data-only-one="1" /><div class="status"></div>', {
buttons: {
"Add tag": true,
"Cancel": false
},
callback: function(buttonClicked, message, fields) {
if (!buttonClicked) return;
el.value = fields["add-tag"];
sendForm();
},
loaded: function(v) {
$("input[name=add-tag]:visible").focus().keyup(function(e) {
if (e.altKey || e.metaKey || e.ctrlKey) return true;
var keyCode = (e == null) ? event.keyCode : e.which;
switch (keyCode) {
case 13:
$(this).closest("#jqi").find("button").eq(0).click();
}
});
},
submit: function(buttonClicked) {
if (!buttonClicked) return true;
var input = $("input[name=add-tag]:visible");
if ($.trim(input.val()) == "") {
input.closest("#jqi").find("div.status").addClass("error").html("Please enter a tag.");
input.focus();
return false;
}
return true;
}
});
return false;
case "remove-tag":
if (checked.length == 0) {
action = "remove a tag from";
break;
}
$.prompt('<h1 class="border">Remove which tag?</h1><input type="text" name="remove-tag" data-only-one="1" /><div class="status"></div>', {
buttons: {
"Remove tag": true,
"Cancel": false
},
callback: function(buttonClicked, message, fields) {
if (!buttonClicked) return;
el.value = fields["remove-tag"];
sendForm();
},
loaded: function(v) {
$("input[name=remove-tag]:visible").focus().keyup(function(e) {
if (e.altKey || e.metaKey || e.ctrlKey) return true;
var keyCode = (e == null) ? event.keyCode : e.which;
var jqi = $(this).closest("#jqi");
switch (keyCode) {
case 13:
jqi.find("button").eq(0).click();
return;
}
var affected = checked.find("span.tags a[data-tag=\"" + $.trim(this.value).replace('"', '\\"') + "\"]").length;
if (!affected) {
$("div.status", jqi).removeClass("ok").addClass("error").text("None of your selected things have that tag.");
} else {
$("div.status", jqi).removeClass("error").addClass("ok").text(affected + " selected thing" + (affected == 1 ? " has" : "s have") + " this tag.");
}
});
},
submit: function(buttonClicked) {
if (!buttonClicked) return true;
var input = $("input[name=remove-tag]:visible");
input.val($.trim(input.val()));
if ($.trim(input.val()) == "") {
input.closest("#jqi").find("div.status").addClass("error").html("Please enter a tag.");
input.focus();
return false;
}
var affected = checked.find("span.tags a[data-tag=\"" + input.val().replace('"', '\\"') + "\"]").length;
if (!affected) return false;
return true;
}
});
return false;
case "delete":
if (checked.length == 0) {
action = "delete";
return false;
}
var t = checked.length + " thing" + (checked.length == 1 ? "" : "s");
var buttons = {};
buttons["Yes, delete " + t] = true;
buttons["Cancel"] = false;
$.prompt("<h1 class='Delete'></h1>This will delete " + t + ". This cannot be undone. Are you sure?", {
buttons: buttons,
classes: "delete",
callback: function(buttonClicked) {
if (!buttonClicked) return;
sendForm();
}
});
return false;
case "public":
action = "publish";
break;
case "private":
action = "make private";
break;
case "archive":
action = "archive";
break;
}
if (checked.length == 0) {
$.prompt("You haven't marked any things to " + action + ".");
return false;
}
sendForm();
return false;
});
},
showBulk: showBulk,
hideBulk: hideBulk,
tag: function(t) {
tag = t;
}
};
})();
var waiting = {},
timeout = {},
last = {};
var showStatus = function(t, status, req, container) {
if (typeof status == "undefined") status = "ok";
if (timeout[t]) clearTimeout(timeout[t]);
if (typeof req == "undefined" || waiting[t] == req) {
container.find("div.loading img").hide();
} else {
return;
}
var div = $("div.status", container).text(status).removeClass("untouched");
if (status == "ok") {
div.addClass("ok").removeClass("error");
} else if (status == "") {
div.removeClass("error").removeClass("ok");
} else {
div.addClass("error").removeClass("ok");
}
};
var checkField = function(inputField, name) {
if (timeout[name]) clearTimeout(timeout[name]);
var container = $(inputField).closest("div");
timeout[name] = setTimeout(function() {
container.find("div.loading img").show();
$("div.status", container).text("");
}, 100);
if (typeof waiting[name] == "undefined") waiting[name] = 1;
else waiting[name] += 1;
if ($.trim(inputField.value) != inputField.value) inputField.value = $.trim(inputField.value);
var post = {
js: 1,
req: waiting[name]
};
post[name] = inputField.value;
$.post(container.closest("form").attr("action"), post, function(t) {
var i = t.indexOf(":");
var status = t.substr(i + 1);
var req = t.substr(0, i);
showStatus(name, status, req, container);
});
};
$(document).ready(function() {
$(".toggle").live("click", function() {
$(this).toggleClass("closed").next().slideToggle("slow");
});
var searchInput = $('#search-input input');
var placeholder = $("#search-input #placeholder");
if (!isTouchDevice) {
placeholder.click(function() {
$(this).hide();
searchInput.focus();
return false;
});
}
if (isIPad) {
$('#search-input').css("marginLeft", "40px");
searchInput.css("width", "80%");
}
var makeFavoriteTag = function(e) {
var el = $(e.target);
var li = el.closest("li");
var tag = li.data("tag");
if (li.closest("ul").is("#favoriteTags")) {
li.appendTo("ul#nonFavoriteTags");
$.post("/favorite-tag.php", {
remove: tag
});
} else {
li.appendTo("ul#favoriteTags");
$.post("/favorite-tag.php", {
add: tag
});
}
var ul = $("ul#favoriteTags");
ul.children().length ? ul.show() : ul.hide();
};
$("#edittags").live("click", function() {
var lis = $("nav#menu ul li");
if ($("nav#menu ul li.edit").length) {
$(this).text("Tag settings");
$(this).removeClass("active");
lis.removeClass("edit");
return false;
}
$(this).text("Save settings");
$(this).addClass("active");
lis.addClass("edit");
if (lis.find("div.fav").length) return false; // just display them
lis.each(function() {
if (!$(this).data("tag")) return true;
$("<div>").addClass("fav").click(makeFavoriteTag).prependTo(this);
});
return false;
});
var hidePlaceholderHelper = function(e) {
if (e.altKey || e.metaKey || e.ctrlKey) return true;
var keyCode = (e == null) ? event.keyCode : e.which;
switch (keyCode) {
case 38:
// up
case 40:
// down
this.blur();
//if (keyCode == 40) {
// el = $("section#things li.active").next().click();
// scrollIntoView(el);
//}
return true;
}
if ($.trim(this.value) == "") {
if (!isTouchDevice && placeholder.is(":hidden")) {
placeholder.show();
}
return true;
}
if (placeholder.is(":visible")) {
placeholder.hide();
}
return true;
};
var getUrlParameter = function(name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(location.href);
if (!results) return false;
return results[1];
};
searchInput.focus(hidePlaceholderHelper).keyup(hidePlaceholderHelper);
if (getUrlParameter("from") != "bookmarklet") searchInput.focus();
else hidePlaceholderHelper({
which: 0
});
searchInput.closest("form").submit(function() {
if ($.trim(searchInput.val()).length == 0) return false;
});
var hover = {
"section#things ul li": {
"": {
"-webkit-transition": "background 250ms linear",
"-moz-transition": "background 250ms linear",
"-o-transition": "background 250ms linear",
transition: "background 250ms linear",
cursor: "pointer"
},
".actions": {
"-thinkery-timeout": 400,
display: "inline-block",
margin: 0
},
".actions a": {
border: 0,
margin: "0 0.5em 0 0",
"padding-top": "0.25em",
display: "inline-block"
},
".drag": {
"-thinkery-timeout": 400,
display: "block"
}
}
};
var hoverTimeouts = {};
if (isTouchDevice) { // apply some hovers on touch device
for (var selector in hover) {
for (subselector in hover[selector]) {
if (!hover[selector][subselector]['-thinkery-mobile']) continue;
$(this).find(subselector).css(hover[selector][subselector]).addClass("hover");
}
}
} else {
for (var selector in hover) {
$(selector).live("mouseenter", function() {
var t = $(this);
for (subselector in hover[selector]) {
if (hover[selector][subselector]["-thinkery-timeout"]) {
(function(selector, subselector) {
hoverTimeouts[selector + subselector] = setTimeout(function() {
if (subselector != "") {
t.find(subselector).css(hover[selector][subselector]).end();
} else t.css(hover[selector][subselector]);
}, hover[selector][subselector]["-thinkery-timeout"]);
})(selector, subselector);
} else {
if (subselector != "") t.find(subselector).css(hover[selector][subselector]).addClass("hover").end();
else t.css(hover[selector][subselector]).addClass("hover");
}
}
});
$(selector).live("mouseleave", function() {
for (var subselector in hover[selector]) {
var css = {};
for (var c in hover[selector][subselector]) {
if (c.indexOf("transition") > 0) css[c] = hover[selector][subselector];
else css[c] = "";
}
if (hoverTimeouts[selector + subselector]) clearTimeout(hoverTimeouts[selector + subselector]);
if (subselector != "") $(this).find(subselector).css(css).removeClass("hover").end();
else $(this).css(css).removeClass("hover");
}
});
}
}
Thinkery.registerLazyLoad();
$(document).keydown(function(e) {
if (e.altKey || e.metaKey || e.ctrlKey) return true;
var target = $(e.target);
var keyCode = (e == null) ? event.keyCode : e.which;
var autocompleteDiv = $('#tag-autocomplete');
var el;
switch (keyCode) {
case 27:
// escape
var display = $('section#flyout .content.display');
if (display.is(":hidden")) {
display.show();
$('section#flyout .content.edit').hide();
}
if ($("#jqi").is(":visible")) {
$.prompt.close();
return false;
}
if ($("#bulkControls").is(":visible")) {
Thinkery.hideBulk();
return false;
}
if (!autocompleteDiv.is(':hidden')) {
autocompleteDiv.empty().hide();
}
if (searchInput.val() != "") searchInput.trigger('stop').val("").keyup();
return false;
}
if (autocompleteDiv.size() != 0 && !autocompleteDiv.is(':hidden') && $("#searchadd").data('tag.added') !== true && autocompleteDiv.find('li').size() !== 0) {
switch (keyCode) {
case 13:
// enter
case 9:
// tab
// load tag
var t = autocompleteDiv.find("li.active").attr('data-tag');
if (t && autocompleteDiv.find("li.active").size()) {
searchInput.trigger('tag-autocomplete', t);
return false;
}
case 38:
// up
// top
if (autocompleteDiv.find("li.active").index() == 0) {
searchInput.focus();
return true;
}
if (autocompleteDiv.find("li").size() == 1) {
var t = autocompleteDiv.find("li").attr('data-tag');
searchInput.trigger('tag-autocomplete', t);
return false;
}
autocompleteDiv.find('li.active').removeClass('active').prev().addClass('active');
return false;
case 40:
// down
if (autocompleteDiv.find("li").size() == 1) {
var t = autocompleteDiv.find("li").attr('data-tag');
searchInput.trigger('tag-autocomplete', t);
return false;
}
if (autocompleteDiv.find('li.active').next().size()) {
autocompleteDiv.find('li.active').removeClass('active').next().addClass('active');
}
return false;
}
// return;
}
if (target.is("input,select,textarea,button") && target.is(":visible")) {
return true;
}
switch (keyCode) {
case 9:
// tab
// searchInput.keyup();
return false;
case 13:
// enter
if ($.trim(searchInput.val()).length > 0) {
searchInput.trigger('stop');
return true;
}
var link = $("div.embed a");
if (!link.length) {
link = $("section#flyout div.content.edit input.url").val();
if (link) {
location.href = link;
return false;
}
}
location.href = link.eq(0).attr("href");
return false;
case 38:
// up
if ($("section#things li.active").index() == 0) {
searchInput.focus();
return true;
}
el = $("section#things li.active").prev().click();
scrollIntoView(el);
return false;
case 40:
// down
el = $("section#things li.active").next().click();
scrollIntoView(el);
return false;
}
var keyPressed = String.fromCharCode(keyCode);
keyPressed = e.shiftKey ? keyPressed.toUpperCase() : keyPressed.toLowerCase();
switch (keyPressed) {
case "e":
$("section#things li.active a.edit").click();
return false;
case "a":
$("section#things li.active a.archive").click();
return false;
case "b":
$('#toggleBulk').click();
return false;
case "m":
$("section#things li.active input.bulk").click();
return false;
case "d":
$("section#things li.active a.delete").click();
return false;
case "s":
$("#searchadd").focus();
return false;
}
return true;
});
$("a.login").live("click", function() {
$.prompt.close();
$.prompt($('#loginPopup').html(), {
buttons: {},
classes: 'login',
loaded: function(v) {
$("input[name=username]:visible").focus();
}
});
return false;
});
$("div#notifications a.clear").live("click", function(e) {
$(e.target).siblings().remove();
$("a.notifications").closest("li").remove();
$.post("/notifications.php", {
clear: 1
});
return false;
});
if (!isTouchDevice) { // don't use tooltips on mobile device
$(".tip").tipTip({
delay: 100,
edgeOffset: 5
});
}
$('div.expandable').expander({
slicePoint: 500,
// default is 100
expandText: '[More]',
// default is 'read more...'
collapseTimer: 0,
// re-collapses after 5 seconds; default is 0, so no re-collapsing
userCollapseText: '[Less]' // default is '[collapse expanded text]'
});
$("ul.dropdown li.dir").live("click", function(e) {
var $this = $(e.target);
if ($this.closest("li.open").length) return true;
$this.closest("li").addClass("open");
return false;
});
$("body").live('click touchend', function(e) {
if ($(e.target).closest("li.open").length > 0) return true; // click within the dropdown: ok
var openDropdown = $("ul.dropdown li.open");
if (openDropdown.length == 0) return true;
openDropdown.removeClass("open");
return false;
});
/*
* @group Tag Autocompleter fuer Edit, Bulk Edit/Remove Forms
*/
;
(function() {
var slStart;
function check_tag_autocomplete(inp) {
try {
slStart = inp.get(0).selectionStart || slStart;
} catch (err) {}
var sval = inp.val();
if (sval[sval.length - 1] == " ") return false;
if (!slStart) {
var tmp = $.trim(sval).split(" ");
} else {
var tmp = $.trim(sval);
tmp = tmp.substr(0, slStart + 1);
if (tmp[tmp.length - 1] == " ") return false;
tmp = tmp.split(" ");
tmp.reverse();
if (tmp.length) return tmp[0];
}
tmp.reverse();
if (tmp.length) return tmp[0];
return false;
}
function tag_autocomplete_render(tagName, autocompleteUL, inp) {
$("<li>" + tagName + " <span class=\"grey flr\">" + Thinkery.tags[tagName].count + "</span></li>").attr('data-tag', tagName).appendTo(autocompleteUL).click(function() {
inp.trigger('tag-autocomplete', tagName);
});
}
$('input.tags,input[name=add-tag],input[name=remove-tag]').live('tag-autocompleter', function(e) {
var that = $(this),
autoTag = check_tag_autocomplete(that),
autocompleteUL = that.next('.tag-autocomplete');
var oldv = that.data('oldv');
if (oldv != that.val()) {
that.data('oldv', that.val());
if (autoTag) {
if (!autocompleteUL.size()) {
autocompleteUL = $('<ul class="tag-autocomplete edit">').insertAfter(that);
autocompleteUL.parents('#jqibox,form,#container').bind('mousedown', function(e) {
if (e.target && $(e.target).parent('.tag-autocomplete').size()) {
return false;
}
autocompleteUL.hide();
});
}
autocompleteUL.empty().hide();
var ql = autoTag.length,
k, qk;
var tags = ("|" + that.val().split(" ").join("|") + "|").toLowerCase();
autoTag = autoTag.toLowerCase();
for (k in Thinkery.tags) {
qk = Thinkery.tags[k].q;
if (qk.substr(0, ql) == autoTag && autoTag !== qk && tags.indexOf("|" + qk + "|") == -1) {
tag_autocomplete_render(k, autocompleteUL, that);
}
}
if (autocompleteUL.find('li').size()) {
autocompleteUL.find('li:first').addClass('active');
autocompleteUL.show();
} else {
autocompleteUL.hide();
}
} else {
autocompleteUL.hide();
}
}
}).live('tag-autocomplete', function(e, tagName) {
var that = $(this),
tmp = $.trim(that.val()).split(" "),
onlyone = that.attr('data-only-one') ? true : false,
autocompleteUL = that.next('.tag-autocomplete');
//slStart = this.selectionStart || slStart;
//if( slStart > -1 ) {
//}
if (onlyone) {
that.val(tagName);
} else {
tmp.reverse();
for (var i = 0, l = tmp.length; i < l; i++) {
tmp[i] = tagName + " ";
break;
}
tmp.reverse();
that.val(tmp.join(" "));
}
autocompleteUL.empty().hide();
that.focus();
}).live('keyup', function() {
var that = $(this);
that.trigger('tag-autocompleter');
}).live('keydown', function(e) {
if (!e) return;
var keyCode = e.which,
that = $(this),
keyPressed = String.fromCharCode(keyCode),
autocompleteUL = that.next('.tag-autocomplete');
that.trigger('tag-autocompleter');
switch (keyCode) {
case 9:
// tab
// case 13: // enter
if (autocompleteUL.find('li.active').size()) {
autocompleteUL.find('li.active').trigger('click');
return false;
}
return true;
break;
case 38:
// up
if (autocompleteUL.find('li.active').prev().size()) {
autocompleteUL.find('li.active').removeClass('active').prev().addClass('active');
} else {
autocompleteUL.find('li.active').trigger('click');
}
if (autocompleteUL.find('li.active').size()) return false;
return true;
break;
case 40:
// down
if (autocompleteUL.find('li.active').next().size()) {
autocompleteUL.find('li.active').removeClass('active').next().addClass('active');
} else {
autocompleteUL.find('li.active').trigger('click');
}
if (autocompleteUL.find('li.active').size()) return false;
return true;
break;
}
});
})(); /* @end */
/* @group dragAndDrop for Things in Sidebar tags */
;
(function() {
var menu = $('#menu'),
dragOptions = {
opacity: 0.7,
zIndex: 600,
helper: 'clone',
// scope: 'tags',
appendTo: 'body',
handle: '.drag',
cursorAt: {
left: 50
},
start: function() {
menu.addClass('drag-drop-enabled');
},
stop: function() {
menu.removeClass('drag-drop-enabled');
}
},
dropOptions = {
accept: '.thing-list-item',
activeClass: 'ui-state-highlight',
hoverClass: 'drophover',
tolerance: 'pointer',
// scope: 'tags',
drop: function(event, ui) {
var drag = ui.draggable;
if (!drag.size()) return;
var id = drag.find('.bulk').val(),
tag = $(this).attr('data-tag');
var thing = Thinkery.findThingById(id);
if (!thing) {
// error
return;
}
if (!tag) {
// prompt new tag window
$.prompt('<h1 class="border">Add which tag?</h1><input type="text" name="add-tag" data-only-one="1" /><div class="status"></div>', {
buttons: {
"Add tag": true,
"Cancel": false
},
callback: function(buttonClicked, message, fields) {
if (!buttonClicked) return;
Thinkery.saveThing({
id: thing._id,
title: thing.title,
tags: $.trim(thing.textTags + " " + fields["add-tag"])
}, function() {
Thinkery.reloadSidebar();
});
return;
},
loaded: function(v) {
$("input[name=add-tag]:visible").focus().keyup(function(e) {
if (e.altKey || e.metaKey || e.ctrlKey) return true;
var keyCode = (e == null) ? event.keyCode : e.which;
switch (keyCode) {
case 13:
$(this).closest("#jqi").find("button").eq(0).click();
}
});
},
submit: function(buttonClicked) {
if (!buttonClicked) return true;
var input = $("input[name=add-tag]:visible");
if ($.trim(input.val()) == "") {
input.closest("#jqi").find("div.status").addClass("error").html("Please enter a tag.");
input.focus();
return false;
}
return true;
}
});
return;
}
Thinkery.saveThing({
id: thing._id,
title: thing.title,
tags: $.trim(thing.textTags + " " + tag)
});
}
};
$(window).bind('things-list-updated', function(event, data) {
$('#things .thing-list-item').draggable(dragOptions);
});
$(window).bind('reloadSidebar', function(event, data) {
$("#nonFavoriteTags li,#favoriteTags li,#menu .create-new-tag").droppable(dropOptions);
});
$('#things .thing-list-item').draggable(dragOptions);
$("#nonFavoriteTags li,#favoriteTags li,#menu .create-new-tag").droppable(dropOptions);
/*
$('#things .thing-list-item').live( 'mousedown', function( e ){
e.preventDefault();
console.log( e );
} ).live( 'mouseup mousleave', function(){
} )
*/
})(); /* @end */
});
var scrollIntoView = function(el) {
if (!el || !el.length) return;
var h = window.innerHeight - $("section#things").position().top, eh = el.height();
var p = el.position().top, b = $(window).scrollTop();
if (p + eh > b + h || p < b) {
$("html,body").stop().animate({scrollTop: Math.floor(p + eh - h / 2) + "px"}, 400);
}
};
var implodeTextList = function(list) {
var startTag = "<b>", endTag = "</b>";
if (typeof list[0] != "string") return list;
if (list.length == 1) return startTag + list[0] + endTag;
var tempList = list.slice();
var last = startTag + tempList.pop() + endTag;
return startTag + tempList.join(endTag + ", " + startTag) + endTag + " and " + last;
};
var isTouchDevice = (function() {
var android = navigator.userAgent.indexOf('Android') != -1;
return android || !!('createTouch' in document);
//return typeof Touch == "object";
})();
var isIPad = navigator.userAgent.match(/iPad/i) != null;
var Thinkery = (function() {
var username, tag, data, originalData, singlePage, currentQuery = false;
if (typeof jQuery.prompt != 'undefined') jQuery.prompt.setDefaults({
persistent: false,
opacity: 0.7,
show: "fadeIn",
overlayspeed: "fast",
promptspeed: "fast",
top: "25%"
});
// impromptu for mobile devices
if (typeof jQuery.prompt != 'undefined' && isTouchDevice) jQuery.prompt.setDefaults({
persistent: false,
opacity: 0.7,
show: "show",
overlayspeed: "fast",
promptspeed: "fast",
top: "5%"
});
var updateTimeLeft = function(timeLeft) {
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
function timeLeft(secs, shortDate) {
if (typeof shortDate == "undefined") shortDate = true;
var ago = false;
if (secs < 0) {
secs = -secs;
ago = true;
}
var x, s, t = [];
if (secs >= 3456000) { // 40 days
s = new Date(new Date() - secs * 1000);
return months[s.getMonth()] + " " + s.getDate() + ", " + s.getFullYear();
}
if (secs >= 86400) {
s = Math.floor(secs / 86400);
x = s + " d" + (shortDate ? "" : "ay");
if (!shortDate && s > 1) x += "s";
t.push(x);
secs -= s * 86400;
}
if (secs >= 3600) {
s = Math.floor(secs / 3600);
x = s + " h" + (shortDate ? "r" : "our");
if (s > 1) x += "s";
t.push(x);
secs -= s * 3600;
}
if (secs >= 60) {
s = Math.floor(secs / 60);
x = s + " min" + (shortDate ? "" : "ute");
if (s > 1) x += "s";
t.push(x);
secs -= s * 60;
}
if (t.length == 0) {
if (!secs) {
t.push("just before");
ago = false;
}
else t.push(parseInt(secs, 10) + "s");
}
var ret = "";
s = "";
for (var i = Math.min(1, t.length - 1); i >= 0; i--) {
ret = t[i] + s + ret;
s = (shortDate || s) ? ", " : " and ";
}
return ret + (ago ? " ago" : "");
}
$("span.dateTime").each(function() {
var $this = $(this);
var t = $this.attr("data-t").split(",");
var time = new Date;
time.setUTCHours(parseInt(t[3], 10));
time.setUTCMinutes(parseInt(t[4], 10));
time.setUTCSeconds(parseInt(t[5], 10));
time.setUTCMonth(0);
time.setUTCFullYear(t[0]);
time.setUTCDate(parseInt(t[2], 10));
time.setUTCMonth(parseInt(t[1], 10) - 1);
var diff = (time.getTime() - new Date) / 1000;
$this.text(timeLeft(diff, !$this.hasClass("long")));
});
};
setInterval(updateTimeLeft, 30000);
var lastTag = false;
var loadTag = function(_tag, initialLoad, nonEmpty ) {
if (typeof initialLoad == "undefined") initialLoad = false;
if (!Thinkery.mainListUrl) return false;
if (_tag == lastTag) return false;
lastTag = _tag;
var tagUrlPart = _tag ? "tag=" + encodeURIComponent(_tag) : "";
$.getJSON(Thinkery.mainListUrl + tagUrlPart, function(r) {
if (initialLoad && data.length == 0) {
location.href = "/" + username;
return;
}
var tags = $("nav#menu ul li").removeClass("active");
if (typeof _tag == "undefined" || !_tag ) {
if (typeof history.pushState == "function") history.pushState({tag: ""}, username, "/" + username);
tags.filter("li:contains(All)").addClass("active");
tag = false;
} else {
_tag = String(_tag);
if (typeof history.pushState == "function") history.pushState({tag: _tag}, username + " - " + _tag, "/" + username + "/" + _tag);
tags.filter("li[data-tag='" + _tag.replace("'", "\\'") + "']").addClass("active");
tag = _tag;
}
_gaq.push(['_trackPageview', '/' + username + "/" + tag]);
originalData = data = r;
$("section#things ul").show(function() {
var searchAdd = $("#searchadd");
if (nonEmpty == true) {
} else if (searchAdd.val() != "") {
searchAdd.val("").keyup();
}
$("button.ir").addClass("search").removeClass("add");
$("sub.results, sub.hint").addClass("hidden");
updateList();
$("section#things ul li:first").addClass("active");
$("section#things ul").fadeIn();
if ($("#bulkControls").is(":visible")) showBulk();
});
retrieveThings();
registerLazyLoad();
updateFlyout(0, false, true);
});
return false;
};
var retrieveQueue = 0, retrieveTimeout = false;
// update items that have not been retrieved
var retrieveThings = function() {
if (retrieveTimeout) {
clearTimeout(retrieveTimeout);
if (retrieveQueue > 3) {
retrieveTimeout = setTimeout(retrieveThings, 3000);
return;
}
}
var l = data.length;
for (var i = 0; i < l; i++) {
if (data[i].retrieved) continue;
if (retrieveQueue > 3) {
retrieveTimeout = setTimeout(retrieveThings, 3000);
break;
}
retrieveQueue += 1;
data[i].thinking = true;
updateList(i);
$.ajax({
url: "/retrieve.php",
type: "post",
data: {id: data[i]._id},
success: function(r) {
retrieveQueue -= 1;
if (typeof r._id == "undefined") return false;
for (var i = 0, l = data.length; i < l; i++) {
if (data[i]._id != r._id) continue;
data[i] = r;
if ($("section#things li.active").index() == i) updateFlyout(i);
updateList(i);
break;
}
},
error: function() {
retrieveQueue -= 1;
}
});
}
};
/* Check if more things can be loaded */
var checkMore = function() {
var l = $('section#things li:not(.no-thing)').length;
var s = $('#searchadd');
var num = parseInt($('#menu li.active .num').text(), 10);
if (isNaN(num)) num = 0;
if (!l || l >= num || (s.length !== 0 && s.val() !== '')) {
$('.loadmore').addClass('inactive').find('a').text('');
return false;
}
$('.loadmore').removeClass('inactive').find('a').text('Show more ↓');
return true;
};
/* init Lazy Loading */
var registerLazyLoad = function(initLoad) {
if (typeof initLoad == 'undefined') initLoad = false;
//page init
$('section#things').data('page', 0);
checkMore();
$(window).unbind('scroll').bind('scroll', function() {
if ($(window).scrollTop() != $(document).height() - $(window).height()) return;
setTimeout(function() {
if ($(window).scrollTop() != $(document).height() - $(window).height()) return;
loadThings(initLoad);
}, 300);
});
$('.loadmore a').unbind('click').live('click', function(e) {
e.preventDefault();
loadThings(initLoad);
});
};
/* load more things */
var loadThings = function(noargs) {
if (!checkMore()) return;
//show loader, increment page count
$('section#things, .loadmore').addClass('loading');
$('section#things').data('page', parseInt($('section#things').data('page'), 10) + 1);
if (typeof noargs !== 'undefined' && noargs ) {
var _data = {
'page': 0
};
} else {
var tag = $('#menu ul li.active').attr('data-tag');
var page = $('section#things').data('page');
var _data = {
'page': page
};
if (typeof tag !== 'undefined' && tag !== '') {
$.extend(_data, {'tag': encodeURIComponent(tag)});
}
if (document.URL.split("?")[1] == 'archived') {
$.extend(_data, {'archived': true});
}
if ( $('#search h4 a').text() !== "" ) {
$.extend(_data, {'username': $('#search h4 a').text()});
}
}
var url, _type = "get";
if (currentQuery) {
url = '/search.php';
_type = "post";
} else if (typeof Thinkery.mainListUrl == "undefined") {
url = '/mainlist.php';
} else {
url = Thinkery.mainListUrl;
}
$.ajax({
url: url,
dataType: 'json',
data: _data,
type: _type,
success: function(r) {
if (r == '') {
$('.loadmore').addClass('inactive').find('a').text('');
} else {
updateData(r);
retrieveThings();
}
$('section#things, .loadmore').removeClass('loading');
}
});
};
var reloadSidebar = function(full) {
if (typeof full == "undefined") full = false;
var sidebarUrl = "/sidebar.php?username=" + encodeURIComponent(username);
if (tag) sidebarUrl += "&tag=" + encodeURIComponent(tag);
if (location.search == "?archived") sidebarUrl += "&archived";
if (full) sidebarUrl += "&full";
var favorites = $("#edittags").hasClass("active");
$("nav#menu").load(sidebarUrl + " nav#menu>*", function() {
if ($("#bulkControls").is(":visible")) {
$('#toggleBulk').addClass("active");
}
if (favorites) {
$("#edittags").click();
}
$(window).trigger( 'reloadSidebar' );
});
};
var updateData = function(d) {
if (!d) {
$('.loadmore').addClass('inactive').find('a').text('');
return;
}
for (i = 0, l = d.length; i < l; i++) {
data.push(d[i]);
}
originalData = data;
updateList();
};
var getPrivacyIcon = function(tmp) {
return '<span class="icn grey ' + getPrivacyClass(tmp) + ' tip ' + (tmp.canEdit ? 'canEdit' : '') + ' title="' + getPrivacyTitle(tmp) + '"></span>';
};
var getPrivacyTitle = function(tmp, html) {
if (typeof html == "undefined") html = false;
var privacyTitle = "Private: only you can see it";
if (!tmp["private"]) {
privacyTitle = "Public: everybody can see it";
if (tmp.shared) {
privacyTitle += '; also shared between ' + implodeTextList(tmp.shared);
}
} else if (tmp.shared) {
privacyTitle = 'Shared between ' + implodeTextList(tmp.shared);
}
if (!html) privacyTitle = privacyTitle.replace(/</g, "<").replace(/>/g, ">");
return privacyTitle;
};
var getPrivacyIconText = function(tmp) {
var friends = tmp.shared ? tmp.shared.length - 1 : 0;
var privacyIconText = "Private";
if (!tmp["private"]) {
privacyIconText = "Public" + (friends > 0 ? " + " + friends + ' Friend' + (friends == 1 ? "" : "s") : "");
} else if (tmp.shared) {
privacyIconText = friends + ' Friend' + (friends == 1 ? "" : "s");
}
return privacyIconText;
};
var getPrivacyClass = function(tmp) {
var privacyClass = "private";
if (!tmp["private"]) {
privacyClass = "public";
} else if (tmp.shared) {
privacyClass = "shared";
}
return privacyClass;
};
var updateList = function(i) {
bulkedit = $("#bulkControls").is(":visible");
var listItem;
if (typeof i != "undefined") {
var tmp = data[i];
listItem = $("section#things li").eq(i);
if (tmp.archived) {
listItem.addClass("archived");
} else {
listItem.removeClass("archived");
}
var allClasses = listItem[0].className.split(" ");
for (var o = 0, l = allClasses.length; o < l; o++) {
if (allClasses[o].substr(0, 6) == "thing-") listItem.removeClass(allClasses[o]);
}
for (var o = 0, l = tmp.classNames.length; o < l; o++) {
listItem.addClass(tmp.classNames[o]);
}
$("article", listItem).html(tmp.htmlTitle + ((typeof tmp.thinking != "undefined" && tmp.thinking) ? '<img src="/img/loading.gif" class="loader" /> <span class="smaller grey">thinking...</span>' : "")).highlight(currentQuery);
$("span.tags", listItem).html(tmp.tags);
var p = $("span.public, span.private, span.shared", listItem);
var privacyClass = getPrivacyClass(tmp);
p.removeClass("private public shared").addClass(privacyClass).attr("title", getPrivacyTitle(tmp, true)).tipTip();
if (privacyClass == "private") $("div.privacy", listItem).hide();
else $("div.privacy", listItem).show();
var bulk = $("input.bulk", listItem);
bulk.attr("checked", typeof tmp.checked != "undefined" && tmp.checked);
if (tmp.canEdit && bulkedit) {
bulk.show();
} else {
bulk.hide();
}
return;
}
var actions, active;
if (typeof i == "undefined" && $('section#things li.active').length != 0) {
active = $("section#things li.active").index();
}
if (data.length == 0) {
$("section#things ul").text("").append($("ul#noThingTemplate li").clone());
return;
}
var list = $("section#things ul"), html = "", oldFirstId = $("section#flyout input.id").val(), firstId = false, tmp, l;
for (j = 0, l = data.length; j < l; j++) {
tmp = data[j];
listItem = "<li class=\"thing-list-item";
if (tmp.archived) listItem += ' archived';
if (tmp.classNames) listItem += ' ' + tmp.classNames.join(" ");
if (tmp.todoStatus) listItem += ' checked';
listItem += '">';
if (tmp.canEdit) listItem += '<span class="drag"></span>';
var privacyIcon = getPrivacyIcon(tmp);
listItem += '<div class="privacy"' + ((!tmp.shared || !tmp.shared.length) && tmp["private"] ? ' style="display: none"' : '') + '>' + privacyIcon + "</div>";
listItem += '<input type="checkbox" name="bulk[]" value="' + tmp._id + '" class="bulk" ' + (typeof tmp.checked != "undefined" && tmp.checked ? ' checked="checked"' : '') + ' />';
listItem += '<input type="checkbox" class="todo" ' + (typeof tmp.todoStatus != "undefined" && tmp.todoStatus ? ' checked="checked"' : '') + ' />';
listItem += '<article>' + tmp.htmlTitle + ((typeof tmp.thinking != "undefined" && tmp.thinking) ? '<img src="/img/loading.gif" class="loader" /> <span class="smaller grey">thinking...</span>' : "") + "</article>";
actions = "";
actions += privacyIcon;
if (tmp.canEdit) {
actions += "<a href=\"\" class=\"icn edit tip\" title=\"Edit\"> </a>"+
"<a href=\"\" class=\"icn archive tip\" title=\""+(tmp.archived ? "Unarchive" : "Move to archive")+"\"> </a>"+
"<a href=\"\" class=\"icn delete tip\" title=\"Delete\"> </a>";
}
listItem += "<sub class=\"meta\">" +
"<span class=\"tags\">" + tmp.tags + "</span> <span data-t=\"" + tmp.date + "\" class=\"info grey dateTime\">just before</span>" +
"<span class=\"actions\">"+ actions + "</span>"+
"</sub>";
listItem += "</li>";
html += listItem;
}
list.html(html);
//check if element and/or edit-mode is active
if (typeof i == 'undefined') i = active;
if (typeof i != "undefined") {
if ($('section#flyout .content.edit').is(":hidden")) {
updateFlyout(i);
}
$('section#things li').eq(i).addClass('active');
}
$("section#things li article").highlight(currentQuery);
$("section#things li span.tags").highlight(currentQuery);
checkMore();
if (typeof data[0] == "undefined") {
$("section#flyout .content").hide();
} /*else if (oldFirstId) {
updateFlyout(0, false, false);
}*/
updateTimeLeft();
$(window).trigger( 'things-list-updated', data );
};
var updatePublicPrivate = function(i) {
var content = $("section#flyout div.content.display");
var active = $("section#things li").eq(i).hasClass("active");
var a = $("nav#sharing ul.dropdown>li>a>span"), pp = $("span.publicprivate", content), permalink = $("a.permalink", content);
var tmp = data[i];
if (active) {
if (tmp.canEdit) $("nav#sharing").show(); else $("nav#sharing").hide();
$("nav#sharing ul ul a").removeClass("active");
}
var friends = tmp.shared ? tmp.shared.length - 1 : 0;
var text = getPrivacyIconText(tmp);
var privacyClass = getPrivacyClass(tmp);
pp.text(text).removeClass("private public shared").addClass(privacyClass).attr("title", getPrivacyTitle(tmp, true)).tipTip();
permalink.attr("title", privacyClass == "private" ? "Private Permalink" : "Public Permalink: use this URL to share it with shared").tipTip();
if (active) {
a.text(text).removeClass("private public shared").addClass(privacyClass);
$("nav#sharing ul ul a." + privacyClass).addClass("active");
}
};
var updateFlyout = function(i, showEdit, fade) {
if (typeof showEdit == "undefined") showEdit = false;
if (typeof data[i] == "undefined") return false;
if (typeof fade == "undefined") fade = true;
var tmp = data[i];
$("section#things li").eq(i).addClass("active").siblings().removeClass("active");
var content = $("section#flyout div.content.display");
var edit = $("section#flyout div.content.edit");
var show = showEdit ? edit : content;
var showIt = function() {
if (tmp.url) {
$("h1.linked a", content).html(tmp.htmlTitle).attr("href", tmp.url).highlight(currentQuery);
$("h1.linked", content).show();
$("h1.unlinked", content).hide();
} else {
$("h1.unlinked", content).html(tmp.htmlTitle).show().highlight(currentQuery);
$("h1.linked", content).hide();
}
$("div.embed", content).html(tmp.html).highlight(currentQuery);
$("span.tags", content).html(tmp.tags).highlight(currentQuery);
$("span.dateTime", show).attr("data-t", tmp.date);
if (tmp.htmlNote && $.trim(String(tmp.htmlNote).replace("<br>", "")).length) {
$("details", content).html(tmp.htmlNote).show().highlight(currentQuery);
$("a.icn.edit.note", content).hide();
} else {
$("details", content).hide();
$("a.icn.edit.note", content).show();
}
$("a.icn.archive", content).text(tmp.archived ? "Unarchive" : "Archive").attr("title", tmp.archived ? "Unarchive" : "Move to archive");
$("a.permalink", content).attr("href", tmp.permalink);
if (tmp.canEdit) $("nav.actions").show(); else $("nav.actions").hide();
updatePublicPrivate(i);
$("input.title", edit).val(tmp.title);
$("input.url", edit).val(tmp.url ? tmp.url : "");
$("input.tags", edit).val(tmp.textTags);
$("input.id", edit).val(tmp._id);
$("textarea.note", edit).val(tmp.note ? tmp.note : "");
$("select[name=private]", edit).eq(0).attr("selectedIndex", tmp["private"] ? 0 : 1);
updateTimeLeft();
var afterShow = function() {
if (showEdit) {
var editor = $("textarea.note", edit).cleditor({
width: "99%",
height: "12%",
controls: "bold italic underline strikethrough | bullets numbering | link unlink | style highlight | undo redo | source",
styles: [["Paragraph", "<p>"], ["Header 1", "<h1>"], ["Header 2", "<h2>"],
["Header 3", "<h3>"], ["Header 4","<h4>"], ["Header 5","<h5>"],
["Header 6","<h6>"]]
})[0].updateFrame().focus();
var resizeEditor = function() {
var d = $("div.cleditorMain");
var p = d.offset();
d.height(Math.max(200, $(window).height() - p.top - 135));
editor.refresh();
};
resizeEditor();
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
$(window).scrollTop( $(window).scrollTop()- 50);
}
//$('#flyout .content.edit').scrollTop(0);
$(window).unbind("resize").resize(resizeEditor);
$("input.title", edit).focus();
}
};
if (fade) {
show.fadeIn(20, afterShow);
} else {
show.show();
afterShow();
}
};
if (fade) {
$(content).add(edit).filter(":visible").fadeOut(10, showIt);
} else {
$(content).add(edit).filter(":visible").hide();
showIt();
}
};
var showBulk = function() {
var bulkControls = $("#bulkControls").show();
var c = 0;
var unarchive = bulkControls.find("button[name=unarchive]"),
archive = bulkControls.find("button[name=archive]"),
publ = bulkControls.find("button[name=public]"),
priv = bulkControls.find("button[name=private]");
if ($("section#things li.archived").length) {// has things that are archived
unarchive.parent().show(); // so offer the unarchive button
c++;
} else {
unarchive.parent().hide();
}
if ($("section#things li:not(.archived)").length) { // has things that are not archived
archive.parent().show(); // so offer the archive button
c++;
} else {
archive.parent().hide();
}
if ($("section#things li span.private").length) { // has things that are private
publ.parent().show(); // so offer the public button
c++;
} else {
publ.parent().hide();
}
if ($("section#things li span.public").length) { // has things that are public
priv.parent().show(); // so offer the private button
c++;
} else {
priv.parent().hide();
}
if (c > 3) {
publ.text("public");
priv.text("private");
} else {
publ.text("make public");
priv.text("make private");
}
if (c > 2) {
$("#closeBulk").text("[x]");
} else {
$("#closeBulk").text("[x] close");
}
$("section#things li").addClass("bulkedit");
$("#toggleAllChecked").attr("checked", false);
$('#toggleBulk').addClass("active");
};
var hideBulk = function() {
$("#bulkControls").hide();
$("section#things li").removeClass("bulkedit");
$('#toggleBulk').removeClass("active");
};
var tags = {};
return {
registerLazyLoad: registerLazyLoad,
loadTag: loadTag,
loadThings: loadThings,
updateList: updateList,
reloadSidebar: reloadSidebar,
findThingById: function( _id ){
for( var i=0, l = data.length; i < l; i++ ) {
if( data[i]._id == _id ) return data[i];
}
return false;
},
saveThing: function( thing, cb, err ){
$.post("/save.php", thing, function( r ) {
if( !r || !r._id ) {
if( err ) err();
return;
}
for(var i = 0, l = data.length; i < l; i++) {
if ( data[i]._id != r._id ) continue;
data[i] = r;
updateFlyout(i);
updatePublicPrivate(i);
updateList(i);
}
if( cb ) cb();
});
},
load: function(_username, _data, _singlePage, _tags ) {
for( var k in _tags ) {
_tags[k]['q'] = k.toLowerCase();
tags[k] = _tags[k];
}
Thinkery.tags = tags;
username = _username;
originalData = data = _data;
singlePage = typeof _singlePage == "boolean" ? _singlePage : false;
$('#main').attr('username', username);
retrieveThings();
$("nav#menu ul li a").live("click", function(e) {
if (!Thinkery.mainListUrl) return true;
var li = $(e.target).closest("li");
if (li.closest("nav#filter").length) return true;
var _tag = li.data("tag");
if (!li.data("all") && (typeof _tag == "undefined" || !_tag)) {
if (!tag) return true;
location.href = "/" + username + "/" + tag + (e.target.search == "?archived" ? "?archived" : "");
return false;
}
if (li.hasClass("smart")) _tag = "smart:" + _tag;
loadTag(_tag);
return false;
});
$("nav#menu ul li span.settings, nav#menu #addsmartfolder").live("click", function(e) {
$.prompt($("#smartfolderTemplate").html(), {
buttons: {"Save": true, "Cancel": false},
classes: 'share',
loaded: function(v) {
var buttons = $("button", "#jqi table");
function firstRemoveButton() {
var rows = $("tr", "#jqi table");
var firstRemove = rows.find("button.remove");
if (rows.length == 1) firstRemove.attr("disabled", true);
else firstRemove.attr("disabled", false);
}
firstRemoveButton();
buttons.live("click", function(r) {
var button = $(r.target);
if (button.hasClass("add")) {
$("#jqi table").append($("#smartfolderTemplate tr").clone());
} else if (button.hasClass("remove")) {
button.closest("tr").remove();
}
firstRemoveButton();
});
}
});
return false;
});
$("a[data-tag]").live("click", function(e) {
if (!Thinkery.mainListUrl) return true;
var _tag = $(e.target).data("tag");
if (typeof _tag == "undefined" || !_tag) return true;
loadTag(_tag);
return false;
});
$('nav#menu .moretags a').live("click", function(e) {
var $this = $(this);
var expanded = !$this.hasClass('expanded');
var p = $this.parent();
var loaded = p.hasClass('loaded');
if (expanded) {
$this.html("Fewer tags ↑");
this.className = "expanded";
if (!loaded) {
$this.html("<img src='/img/loading.gif' />");
reloadSidebar(true);
} else {
$("ul#nonFavoriteTags li").show();
}
} else {
$this.html("All tags ↓");
this.className = "collapsed";
$("ul#nonFavoriteTags li:gt(9)").hide();
}
$('nav#menu').css("position", expanded ? "absolute" : "fixed");
return false;
});
$("section#things li").live("click", function(e) {
if (e.shiftKey) {
var i = $("section#things li.active").index();
var j = $(this).index();
if (j < i) {
var k = j;
j = i;
i = k;
}
var bulks = $("section#things li input.bulk");
if ($("#bulkControls").is(":hidden")) bulks.attr("checked", false);
for (; i <= j; i++) {
data[i].checked = true;
bulks.eq(i).attr("checked", true);
}
showBulk();
return false;
}
updateFlyout($(this).index());
});
$("section#things li input.todo").live("click", function(e) {
var li = $(this).closest("li");
var i = li.index();
data[i].todoStatus = this.checked;
if (this.checked) li.addClass("checked"); else li.removeClass("checked");
$.post("/save.php", {id: data[i]._id, "todo": this.checked ? "checked" : "not-checked" });
});
$("section#things li input.bulk").live("click", function(e) {
data[$(this).closest("li").index()].checked = this.checked;
});
if (isTouchDevice) {
var touchStartThing = false, touchStartTag = false, touchMoves = 0;
$("section#things li").live("touchstart", function(e) {
touchStartThing = $(this).index();
touchMoves = 3;
});
$("section#things li").live("touchmove", function(e) {
if (--touchMoves > 0) return;
touchStartThing = false;
});
$("section#things li").live("touchend", function(e) {
if (touchStartThing === false) return;
if (isIPad) {
updateFlyout($(this).index());
} else {
location.href = data[$(this).index()].permalink;
}
});
$("a[data-tag]").live("touchstart touchmove", function(e) {
touchStartThing = false;
});
$("a[data-tag]").live("touchend", function(e) {
e.preventDefault();
if (!Thinkery.mainListUrl) return true;
touchStartThing = false;
var _tag = $(e.target).data("tag");
if (typeof _tag == "undefined" || !_tag) return true;
loadTag(_tag);
return false;
});
}
$("section#things li a.edit").live("click", function(e) {
e.preventDefault();
updateFlyout($(this).closest("li").index(), /* edit */ true);
return false;
});
$('section#flyout .content .icn.edit').live("click", function(e) {
e.preventDefault();
$("section#things li.active a.edit").click();
return false;
});
$('section#flyout .content.edit nav.actions button.cancel').live("click", function() {
if (isTouchDevice) return location.reload();
$('section#flyout .content.display').show();
$('section#flyout .content.edit').hide();
$('section#flyout').css("position", "fixed");
return false;
});
var updatePrivacy = function(r) {
for (var i = 0, l = data.length; i < l; i++) {
if (data[i]._id != r._id) continue;
data[i] = r;
updateFlyout(i);
updateList(i);
updatePublicPrivate(i);
break;
}
};
$('section#flyout .meta .publicprivate, section#things li span.private, section#things li span.public, section#things li span.shared').live('click', function(e) {
var i = $(this).closest("section#flyout").length ? $("section#things li.active").index() : $(this).closest("li").index();
if (!data[i].canEdit) return false;
var newPrivate = !data[i]["private"];
var id = data[i]._id;
$("#tiptip_holder").hide();
$.post("/save.php", {id: id, "private": newPrivate ? "private" : "public" }, updatePrivacy);
});
$('nav#sharing li').live('click', function(e) {
var $this = $(this);
if ($this.hasClass("dir")) return false;
var i = $("section#things li.active").index();
if (!data[i].canEdit) return false;
var newPrivate = true;
var id = data[i]._id;
switch ($this.text()) {
case "Public":
newPrivate = false;
case "Private":
$.post("/save.php", {id: id, "private": newPrivate ? "private" : "public" }, updatePrivacy);
break;
case "Friends":
$.prompt($('#shareTagPopup').html(), {
buttons: {},
classes: 'share',
loaded: function(v) {
var buttons = $("button", "#jqi");
$("input[name=users]:visible").focus().keyup(function(e) {
if (e.altKey || e.metaKey || e.ctrlKey) return true;
var keyCode = (e == null) ? event.keyCode : e.which;
switch (keyCode) {
case 13:
// buttons.eq(0).click();
return false;
}
});
buttons.eq(0).click(function() {
var users = $("input[name=users]:visible").val();
$.post("/share.php", {id: id, users: users, allowChange: $("input[name=allowChange]:visible").is(":checked")}, function(v) {
$.prompt.close();
if (typeof v.thing != "undefined") {
data[i] = v.thing;
updateFlyout(i);
updateList(i);
updatePublicPrivate(i);
}
$.prompt("Now these users can view this item: " + v.users.join(", "));
});
return false;
});
buttons.eq(1).click(function() {
$.prompt.close();
return false;
});
}
});
break;
}
return false;
});
$('section#flyout .content.edit nav.actions button.save').live("click", function() {
var edit = $("section#flyout .content.edit");
var title = edit.find("input.title").val();
if ($.trim(title).length == 0) {
$.prompt("The title can't be empty.");
return false;
}
var id = edit.find("input.id").val();
var tags = $.trim(edit.find("input.tags").val());
$.post("/save.php", {id: id, title: title, tags: tags, url: edit.find("input.url").val(), note: edit.find("textarea.note").val(), "private": edit.find("select[name=private]").val() }, function(r) {
if (isTouchDevice) return location.reload();
for (var i = 0, l = data.length; i < l; i++) {
if (data[i]._id != id) continue;
data[i] = r;
updateFlyout(i);
updateList(i);
reloadSidebar();
break;
}
});
$('section#flyout').css("position", "fixed");
return false;
});
$("section#flyout a.delete, section#things li a.delete, section#flyout a.archive, section#things li a.archive").live("click", function() {
var question, buttons, del = $(this).hasClass("delete");
var i = $(this).closest("section#flyout").length ? $("section#things li.active").index() : $(this).closest("li").index();
if (del) {
question = "<h1 class='border'>Delete</h1>Really delete <i>" + data[i].title + "</i>?";
buttons = {"Yes, delete it": true, "Cancel": false};
} else {
if (data[i].archived) {
question = "<h1 class='border'>Unarchive</h1>Really unarchive <i>" + data[i].title + "</i>?";
buttons = {"Yes, unarchive it": true, "Cancel": false};
} else {
question = "<h1 class='border'>Archive</h1>Really archive <i>" + data[i].title + "</i>?";
buttons = {"Yes, archive it": true, "Cancel": false};
}
}
$.prompt(question, {
buttons: buttons,
classes: del ? "delete" : "archive",
callback: function(buttonClicked) {
if (!buttonClicked || typeof data[i] == "undefined") return false;
$.post(del ? "/delete.php" : (data[i].archived ? "/archive.php?unarchive" : "/archive.php"), {id: data[i]._id}, function(r) {
if (singlePage) {
if (del) { // item doesn't exist anymore, go to all things
location.href = "/" + username;
return;
}
data[i].archived = !data[i].archived;
} else {
if (!del && data[i].archived) {
data[i].archived = false;
} else {
data.splice(i, 1);
}
}
reloadSidebar();
updateList();
if ($("section#things li").length == 0) {
$("section#things ul").append("<li>No Things found.</li>");
$("section#flyout div.content.display").css("visibility", "hidden");
} else {
var el = $("section#things li").eq(i).click();
scrollIntoView(el);
}
});
}
});
return false;
});
var lastQuery, lastAjax, lastTimeout = null, beforeQuery = null, tmpQuery, ajaxQueryOld, ajaxQueryCurrent;
var autocompleteDiv = $('#tag-autocomplete');
var slStart = null;
var searchAdd = $('#searchadd').bind('focus focusin mouseenter', function(){
return true;
if( check_tag_autocomplete() ) {
// beforeQuery = null;
searchAdd.keyup();
}
});
var searchField = $('#search').bind( 'mouseleave click', function(e){
return true;
autocompleteDiv.empty().hide();
} );
var searchInput = $('#search-input');
var btns = {
bir: $("button.ir"),
hint: $("sub.hint"),
results: $("sub.results")
};
function tag_autocomplete_render( tagName ){
$("<li>"+tagName+" <span class=\"grey flr\">"+tags[tagName].count+"</span></li>").attr('data-tag',tagName).appendTo( autocompleteDiv ).click( function(){
searchAdd.trigger( 'tag-autocomplete', tagName );
} );
}
function check_tag_autocomplete() {
slStart = searchAdd.get(0).selectionStart || slStart;
var sval = searchAdd.val();
if( sval[sval.length-1] == " " ) return false;
if( !slStart ) {
var tmp = $.trim( sval ).split( " " );
} else {
var tmp = $.trim( sval );
tmp = tmp.substr( 0, slStart+1 );
if( tmp[tmp.length-1] == " " ) return false;
tmp = tmp.split( " " );
tmp.reverse();
for( var i=0, l = tmp.length; i < l; i++ ) {
if( tmp[i][0] == "#" ) {
return tmp[i];
} else {
return false;
}
}
tmp.reverse();
}
tmp.reverse();
for( var i=0, l = tmp.length; i < l; i++ ) {
if( tmp[i][0] == "#" ) {
return tmp[i];
}
}
return false;
}
searchAdd.bind('tag-autocomplete', function( evt, tagName ){
if( !tagName || typeof tagName == "undefined" ) return;
// var d = check_tag_autocomplete();
var tmp = $.trim( searchAdd.val() ).split( " " );
tmp.reverse();
for( var i=0, l = tmp.length; i < l; i++ ) {
if( tmp[i][0] == "#" ) {
tmp[i] = '#' + tagName + " ";
break;
}
}
tmp.reverse();
searchAdd.val( tmp.join( " " ) ).data( 'tag.added', true );
autocompleteDiv.empty().hide();
beforeQuery = null;
searchAdd.focus().keyup();
btns.bir.addClass("searchadd").removeClass("add");
btns.hint.addClass("hidden");
btns.results.removeClass("hidden");
}).bind('stop',function(){
if (lastAjax) lastAjax.abort();
clearTimeout(lastTimeout);
searchField.removeClass( 'searching' );
}).keyup(function() {
lastQuery = this.value;
if( $.trim(this.value) == "" ) {
searchAdd.trigger('stop');
btns.bir.addClass("search").removeClass("add").removeClass("searchadd");
btns.hint.addClass("hidden");
btns.results.addClass("hidden");
data = originalData;
currentQuery = false;
updateList();
autocompleteDiv.hide();
return true;
}
if( beforeQuery == lastQuery ) return;
tmpQuery = beforeQuery;
beforeQuery = lastQuery;
// vorherigen ajax request abbrechen wenn neue suche angefangen wird
searchAdd.trigger('stop');
lastTimeout = setTimeout(function() {
searchAdd.focus();
var d = check_tag_autocomplete();
if( d && d[0] == "#" && searchAdd.data( 'tag.added' ) !== true ) {
// tags autocomplete
if( !autocompleteDiv.size() ) {
autocompleteDiv = $('<ul id="tag-autocomplete" class="tag-autocomplete search">').appendTo( "#container" );
}
autocompleteDiv.empty().hide();
d = d.toLowerCase();
var k, q = d.substr( 1 ), ql = q.length, qk;
for( k in tags ) {
qk = tags[k].q;
if( qk.substr( 0, ql ) == q && k != q ) {
tag_autocomplete_render( k );
}
}
if( autocompleteDiv.find( 'li:first' ).addClass('active').size() ) {
autocompleteDiv.show();
// beforeQuery = null;
return;
} else {
autocompleteDiv.hide();
}
} else {
autocompleteDiv.hide();
}
searchAdd.data( 'tag.added', false );
//if( $trim(tmpQuery) == $.trim(beforeQuery) ) {
//}
ajaxQueryCurrent = $.trim(lastQuery);
if( ajaxQueryOld == ajaxQueryCurrent ) return;
searchAdd.trigger('stop');
searchField.addClass( 'searching' );
lastAjax = $.post("/search.php", { q: lastQuery }, function(r) {
ajaxQueryOld = ajaxQueryCurrent;
// if (lastQuery != r.q) return;
data = r.result;
currentQuery = r.q;
if (data.length == 0) {
btns.bir.addClass("add").removeClass("search").removeClass("searchadd");
btns.hint.removeClass("hidden");
btns.results.addClass("hidden");
} else {
btns.bir.addClass("searchadd").removeClass("add");
btns.hint.addClass("hidden");
btns.results.removeClass("hidden").text(
'Search results for "' + (lastQuery.length > 40 ? "..." + lastQuery.substr(lastQuery.length - 20) : lastQuery) + '":'
);
}
updateList();
retrieveThings();
searchField.removeClass( 'searching' );
ajaxQueryOld = ajaxQueryCurrent;
});
}, 100 );
});
$("#toggleBulk").live("click", function(e) {
var bulkControls = $("#bulkControls");
if (bulkControls.is(":visible")) {
hideBulk();
} else {
showBulk();
}
return false;
});
$("#closeBulk").click(function() {
hideBulk();
return false;
});
$("#toggleAllChecked").click(function(e) {
var ch = this.checked;
$("section#things li input.bulk").each(function(i) {
if (e.shiftKey) this.checked = !this.checked;
else this.checked = ch;
data[i].checked = this.checked;
});
});
$("button.bulk").click(function() {
var checked = $("section#things li:has(input.bulk:checked)");
var el = this;
var formSubmit = function(r) {
if (r == "error" || typeof(r) == "string") {
$.prompt("An error was reported from the server, please try again." /* + r */);
return;
}
var ids = {};
for (var i = 0, l = r.length; i < l; i++) {
ids[r[i]._id] = r[i];
}
var activeIndex = $("section#things li.active").index();
var updateWholeList = false;
for (var i = data.length - 1; i >= 0; i--) {
var j = data[i]._id;
if (typeof ids[j] == "undefined") continue;
if (typeof ids[j].deleted != "undefined" && ids[j].deleted) {
data.splice(i, 1);
updateWholeList = true;
continue;
}
data[i] = ids[j];
data[i].checked = true;
updateList(i);
if (activeIndex == i) {
updatePublicPrivate(i);
updateFlyout(i);
}
}
if (updateWholeList) {
updateList();
}
if (!(el.name == "public" || el.name == "private")) {
reloadSidebar();
}
if (data.length) {
showBulk();
} else {
if (tag != "") loadTag("");
hideBulk();
}
};
var sendForm = function() {
var form = $("form[name=bulk]");
$.post(form.attr("action"), form.serialize() + "&" + el.name + "=" + encodeURIComponent(el.value), formSubmit);
};
switch (this.name) {
case "add-tag":
if (checked.length == 0) {
action = "add a tag to";
break;
}
$.prompt('<h1 class="border">Add which tag?</h1><input type="text" name="add-tag" data-only-one="1" /><div class="status"></div>', {
buttons: { "Add tag": true, "Cancel": false},
callback: function (buttonClicked, message, fields) {
if (!buttonClicked) return;
el.value = fields["add-tag"];
sendForm();
},
loaded: function(v) {
$("input[name=add-tag]:visible").focus().keyup(function(e) {
if (e.altKey || e.metaKey || e.ctrlKey) return true;
var keyCode = (e == null) ? event.keyCode : e.which;
switch (keyCode) {
case 13:
$(this).closest("#jqi").find("button").eq(0).click();
}
});
},
submit: function(buttonClicked) {
if (!buttonClicked) return true;
var input = $("input[name=add-tag]:visible");
if ($.trim(input.val()) == "") {
input.closest("#jqi").find("div.status").addClass("error").html("Please enter a tag.");
input.focus();
return false;
}
return true;
}
});
return false;
case "remove-tag":
if (checked.length == 0) {
action = "remove a tag from";
break;
}
$.prompt('<h1 class="border">Remove which tag?</h1><input type="text" name="remove-tag" data-only-one="1" /><div class="status"></div>', {
buttons: { "Remove tag": true, "Cancel": false},
callback: function (buttonClicked, message, fields) {
if (!buttonClicked) return;
el.value = fields["remove-tag"];
sendForm();
},
loaded: function(v) {
$("input[name=remove-tag]:visible").focus().keyup(function(e) {
if (e.altKey || e.metaKey || e.ctrlKey) return true;
var keyCode = (e == null) ? event.keyCode : e.which;
var jqi = $(this).closest("#jqi");
switch (keyCode) {
case 13:
jqi.find("button").eq(0).click();
return;
}
var affected = checked.find("span.tags a[data-tag=\"" + $.trim(this.value).replace('"', '\\"') + "\"]").length;
if (!affected) {
$("div.status", jqi).removeClass("ok").addClass("error").text("None of your selected things have that tag.");
} else {
$("div.status", jqi).removeClass("error").addClass("ok").text(affected + " selected thing" + (affected == 1 ? " has" : "s have") + " this tag.");
}
});
},
submit: function(buttonClicked) {
if (!buttonClicked) return true;
var input = $("input[name=remove-tag]:visible");
input.val( $.trim(input.val()) );
if ($.trim(input.val()) == "") {
input.closest("#jqi").find("div.status").addClass("error").html("Please enter a tag.");
input.focus();
return false;
}
var affected = checked.find("span.tags a[data-tag=\"" + input.val().replace('"', '\\"') + "\"]").length;
if (!affected) return false;
return true;
}
});
return false;
case "delete":
if (checked.length == 0) {
action = "delete";
return false;
}
var t = checked.length + " thing" + (checked.length == 1 ? "" : "s");
var buttons = {};
buttons["Yes, delete " + t] = true;
buttons["Cancel"] = false;
$.prompt("<h1 class='Delete'></h1>This will delete " + t + ". This cannot be undone. Are you sure?", {
buttons: buttons,
classes: "delete",
callback: function(buttonClicked) {
if (!buttonClicked) return;
sendForm();
}
});
return false;
case "public": action = "publish"; break;
case "private": action = "make private"; break;
case "archive": action = "archive"; break;
}
if (checked.length == 0) {
$.prompt("You haven't marked any things to " + action + ".");
return false;
}
sendForm();
return false;
});
},
showBulk: showBulk,
hideBulk: hideBulk,
tag: function(t) {
tag = t;
}
};
})();
var waiting = {}, timeout = {}, last = {};
var showStatus = function(t, status, req, container) {
if (typeof status == "undefined") status = "ok";
if (timeout[t]) clearTimeout(timeout[t]);
if (typeof req == "undefined" || waiting[t] == req) {
container.find("div.loading img").hide();
} else {
return;
}
var div = $("div.status", container).text(status).removeClass("untouched");
if (status == "ok") {
div.addClass("ok").removeClass("error");
} else if (status == "") {
div.removeClass("error").removeClass("ok");
} else {
div.addClass("error").removeClass("ok");
}
};
var checkField = function(inputField, name) {
if (timeout[name]) clearTimeout(timeout[name]);
var container = $(inputField).closest("div");
timeout[name] = setTimeout(function() {
container.find("div.loading img").show();
$("div.status", container).text("");
}, 100);
if (typeof waiting[name] == "undefined") waiting[name] = 1;
else waiting[name] += 1;
if ($.trim(inputField.value) != inputField.value) inputField.value = $.trim(inputField.value);
var post = {js: 1, req: waiting[name]};
post[name] = inputField.value;
$.post(container.closest("form").attr("action"), post, function(t) {
var i = t.indexOf(":");
var status = t.substr(i + 1);
var req = t.substr(0, i);
showStatus(name, status, req, container);
});
};
$(document).ready(function() {
$(".toggle").live("click", function () {
$(this).toggleClass("closed").next().slideToggle("slow");
});
var searchInput = $('#search-input input');
var placeholder = $("#search-input #placeholder");
if (!isTouchDevice) {
placeholder.click(function() {
$(this).hide();
searchInput.focus();
return false;
});
}
if (isIPad) {
$('#search-input').css("marginLeft", "40px");
searchInput.css("width", "80%");
}
var makeFavoriteTag = function(e) {
var el = $(e.target);
var li = el.closest("li");
var tag = li.data("tag");
if (li.closest("ul").is("#favoriteTags")) {
li.appendTo("ul#nonFavoriteTags");
$.post("/favorite-tag.php", {remove: tag});
} else {
li.appendTo("ul#favoriteTags");
$.post("/favorite-tag.php", {add: tag});
}
var ul = $("ul#favoriteTags");
ul.children().length ? ul.show() : ul.hide();
};
$("#edittags").live("click", function() {
var lis = $("nav#menu ul li");
if ($("nav#menu ul li.edit").length) {
$(this).text("Tag settings");
$(this).removeClass("active");
lis.removeClass("edit");
return false;
}
$(this).text("Save settings");
$(this).addClass("active");
lis.addClass("edit");
if (lis.find("div.fav").length) return false; // just display them
lis.each(function() {
if (!$(this).data("tag")) return true;
$("<div>").addClass("fav").click(makeFavoriteTag).prependTo(this);
});
return false;
});
var hidePlaceholderHelper = function(e) {
if (e.altKey || e.metaKey || e.ctrlKey) return true;
var keyCode = (e == null) ? event.keyCode : e.which;
switch (keyCode) {
case 38: // up
case 40: // down
this.blur();
//if (keyCode == 40) {
// el = $("section#things li.active").next().click();
// scrollIntoView(el);
//}
return true;
}
if ($.trim(this.value) == "") {
if (!isTouchDevice && placeholder.is(":hidden")) {
placeholder.show();
}
return true;
}
if (placeholder.is(":visible")) {
placeholder.hide();
}
return true;
};
var getUrlParameter = function(name) {
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(location.href);
if (!results) return false;
return results[1];
};
searchInput.focus(hidePlaceholderHelper).keyup(hidePlaceholderHelper);
if (getUrlParameter("from") != "bookmarklet") searchInput.focus(); else hidePlaceholderHelper({which: 0});
searchInput.closest("form").submit(function() {
if ($.trim(searchInput.val()).length == 0) return false;
});
var hover = {
"section#things ul li": {
"": {
"-webkit-transition": "background 250ms linear",
"-moz-transition": "background 250ms linear",
"-o-transition": "background 250ms linear",
transition: "background 250ms linear",
cursor: "pointer"
},
".actions": {
"-thinkery-timeout": 400,
display: "inline-block",
margin: 0
},
".actions a": {
border: 0,
margin: "0 0.5em 0 0",
"padding-top": "0.25em",
display: "inline-block"
},
".drag": {
"-thinkery-timeout": 400,
display: "block"
}
}
};
var hoverTimeouts = {};
if (isTouchDevice) { // apply some hovers on touch device
for (var selector in hover) {
for (subselector in hover[selector]) {
if (!hover[selector][subselector]['-thinkery-mobile']) continue;
$(this).find(subselector).css(hover[selector][subselector]).addClass("hover");
}
}
} else {
for (var selector in hover) {
$(selector).live("mouseenter", function() {
var t = $(this);
for (subselector in hover[selector]) {
if (hover[selector][subselector]["-thinkery-timeout"]) {
(function(selector, subselector) {
hoverTimeouts[selector + subselector] = setTimeout(function() {
if (subselector != "") {
t.find(subselector).css(hover[selector][subselector]).end();
}
else t.css(hover[selector][subselector]);
}, hover[selector][subselector]["-thinkery-timeout"]);
})(selector, subselector);
} else {
if (subselector != "") t.find(subselector).css(hover[selector][subselector]).addClass("hover").end();
else t.css(hover[selector][subselector]).addClass("hover");
}
}
});
$(selector).live("mouseleave", function() {
for (var subselector in hover[selector]) {
var css = {};
for (var c in hover[selector][subselector]) {
if (c.indexOf("transition") > 0) css[c] = hover[selector][subselector];
else css[c] = "";
}
if (hoverTimeouts[selector + subselector]) clearTimeout(hoverTimeouts[selector + subselector]);
if (subselector != "") $(this).find(subselector).css(css).removeClass("hover").end();
else $(this).css(css).removeClass("hover");
}
});
}
}
Thinkery.registerLazyLoad();
$(document).keydown(function(e) {
if (e.altKey || e.metaKey || e.ctrlKey) return true;
var target = $(e.target);
var keyCode = (e == null) ? event.keyCode : e.which;
var autocompleteDiv = $('#tag-autocomplete');
var el;
switch (keyCode) {
case 27: // escape
var display = $('section#flyout .content.display');
if (display.is(":hidden")) {
display.show();
$('section#flyout .content.edit').hide();
}
if ($("#jqi").is(":visible")) {
$.prompt.close();
return false;
}
if ($("#bulkControls").is(":visible")) {
Thinkery.hideBulk();
return false;
}
if( !autocompleteDiv.is(':hidden') ) {
autocompleteDiv.empty().hide();
}
if (searchInput.val() != "") searchInput.trigger('stop').val("").keyup();
return false;
}
if( autocompleteDiv.size() != 0 && !autocompleteDiv.is(':hidden') && $("#searchadd").data( 'tag.added' ) !== true && autocompleteDiv.find('li').size() !== 0 ) {
switch (keyCode) {
case 13: // enter
case 9: // tab
// load tag
var t = autocompleteDiv.find("li.active").attr('data-tag');
if( t && autocompleteDiv.find("li.active").size() ) {
searchInput.trigger( 'tag-autocomplete', t );
return false;
}
case 38: // up
// top
if ( autocompleteDiv.find("li.active").index() == 0 ) {
searchInput.focus();
return true;
}
if( autocompleteDiv.find("li").size() == 1 ) {
var t = autocompleteDiv.find("li").attr('data-tag');
searchInput.trigger( 'tag-autocomplete', t );
return false;
}
autocompleteDiv.find('li.active').removeClass('active').prev().addClass('active');
return false;
case 40: // down
if( autocompleteDiv.find("li").size() == 1 ) {
var t = autocompleteDiv.find("li").attr('data-tag');
searchInput.trigger( 'tag-autocomplete', t );
return false;
}
if( autocompleteDiv.find('li.active').next().size() ) {
autocompleteDiv.find('li.active').removeClass('active').next().addClass('active');
}
return false;
}
// return;
}
if (target.is("input,select,textarea,button") && target.is(":visible")) {
return true;
}
switch (keyCode) {
case 9: // tab
// searchInput.keyup();
return false;
case 13: // enter
if ($.trim(searchInput.val()).length > 0) {
searchInput.trigger( 'stop' );
return true;
}
var link = $("div.embed a");
if (!link.length) {
link = $("section#flyout div.content.edit input.url").val();
if (link) {
location.href = link;
return false;
}
}
location.href = link.eq(0).attr("href");
return false;
case 38: // up
if ($("section#things li.active").index() == 0) {
searchInput.focus();
return true;
}
el = $("section#things li.active").prev().click();
scrollIntoView(el);
return false;
case 40: // down
el = $("section#things li.active").next().click();
scrollIntoView(el);
return false;
}
var keyPressed = String.fromCharCode(keyCode);
keyPressed = e.shiftKey ? keyPressed.toUpperCase() : keyPressed.toLowerCase();
switch (keyPressed) {
case "e":
$("section#things li.active a.edit").click();
return false;
case "a":
$("section#things li.active a.archive").click();
return false;
case "b":
$('#toggleBulk').click();
return false;
case "m":
$("section#things li.active input.bulk").click();
return false;
case "d":
$("section#things li.active a.delete").click();
return false;
case "s":
$("#searchadd").focus();
return false;
}
return true;
});
$("a.login").live("click", function() {
$.prompt.close();
$.prompt($('#loginPopup').html(), {
buttons: {},
classes: 'login',
loaded: function(v) {
$("input[name=username]:visible").focus();
}
});
return false;
});
$("div#notifications a.clear").live("click", function(e) {
$(e.target).siblings().remove();
$("a.notifications").closest("li").remove();
$.post("/notifications.php", { clear: 1 });
return false;
});
if (!isTouchDevice) { // don't use tooltips on mobile device
$(".tip").tipTip({
delay: 100,
edgeOffset: 5}
);
}
$('div.expandable').expander({
slicePoint: 500, // default is 100
expandText: '[More]', // default is 'read more...'
collapseTimer: 0, // re-collapses after 5 seconds; default is 0, so no re-collapsing
userCollapseText: '[Less]' // default is '[collapse expanded text]'
});
$("ul.dropdown li.dir").live("click", function(e) {
var $this = $(e.target);
if ($this.closest("li.open").length) return true;
$this.closest("li").addClass("open");
return false;
});
$("body").live('click touchend', function(e) {
if ($(e.target).closest("li.open").length > 0) return true; // click within the dropdown: ok
var openDropdown = $("ul.dropdown li.open");
if (openDropdown.length == 0) return true;
openDropdown.removeClass("open");
return false;
});
/*
* @group Tag Autocompleter fuer Edit, Bulk Edit/Remove Forms
*/
;(function(){
var slStart;
function check_tag_autocomplete( inp ){
try {
slStart = inp.get(0).selectionStart || slStart;
} catch(err) {}
var sval = inp.val();
if( sval[sval.length-1] == " " ) return false;
if( !slStart ) {
var tmp = $.trim( sval ).split( " " );
} else {
var tmp = $.trim( sval );
tmp = tmp.substr( 0, slStart+1 );
if( tmp[tmp.length-1] == " " ) return false;
tmp = tmp.split( " " );
tmp.reverse();
if( tmp.length )
return tmp[0];
}
tmp.reverse();
if( tmp.length )
return tmp[0];
return false;
}
function tag_autocomplete_render( tagName, autocompleteUL, inp ){
$("<li>"+tagName+" <span class=\"grey flr\">"+Thinkery.tags[tagName].count+"</span></li>").attr('data-tag',tagName).appendTo( autocompleteUL ).click( function(){
inp.trigger( 'tag-autocomplete', tagName );
} );
}
$('input.tags,input[name=add-tag],input[name=remove-tag]').live('tag-autocompleter', function(e){
var that = $(this),
autoTag = check_tag_autocomplete( that ),
autocompleteUL = that.next('.tag-autocomplete');
var oldv = that.data('oldv');
if( oldv != that.val() ) {
that.data('oldv', that.val() );
if( autoTag ) {
if( !autocompleteUL.size() ) {
autocompleteUL = $( '<ul class="tag-autocomplete edit">' ).insertAfter(that);
autocompleteUL.parents( '#jqibox,form,#container' ).bind( 'mousedown', function( e ){
if( e.target && $(e.target).parent('.tag-autocomplete').size() ) {
return false;
}
autocompleteUL.hide();
} );
}
autocompleteUL.empty().hide();
var ql = autoTag.length, k, qk;
var tags = ("|" + that.val().split( " " ).join("|") + "|").toLowerCase();
autoTag = autoTag.toLowerCase();
for( k in Thinkery.tags ) {
qk = Thinkery.tags[k].q;
if( qk.substr( 0, ql ) == autoTag && autoTag !== qk && tags.indexOf( "|" + qk + "|" ) == -1 ) {
tag_autocomplete_render( k, autocompleteUL, that );
}
}
if( autocompleteUL.find('li').size() ) {
autocompleteUL.find('li:first').addClass('active');
autocompleteUL.show();
} else {
autocompleteUL.hide();
}
} else {
autocompleteUL.hide();
}
}
} ).live('tag-autocomplete', function( e, tagName ){
var that = $(this),
tmp = $.trim( that.val() ).split( " " ),
onlyone = that.attr( 'data-only-one' ) ? true : false,
autocompleteUL = that.next('.tag-autocomplete');
//slStart = this.selectionStart || slStart;
//if( slStart > -1 ) {
//}
if( onlyone ) {
that.val( tagName );
} else {
tmp.reverse();
for( var i=0, l = tmp.length; i < l; i++ ) {
tmp[i] = tagName + " ";
break;
}
tmp.reverse();
that.val( tmp.join( " " ) );
}
autocompleteUL.empty().hide();
that.focus();
} ).live('keyup', function(){
var that = $(this);
that.trigger( 'tag-autocompleter' );
}).live( 'keydown', function( e ){
if( !e ) return;
var keyCode = e.which,
that = $(this),
keyPressed = String.fromCharCode(keyCode),
autocompleteUL = that.next('.tag-autocomplete');
that.trigger( 'tag-autocompleter' );
switch (keyCode) {
case 9: // tab
// case 13: // enter
if( autocompleteUL.find('li.active').size() ) {
autocompleteUL.find('li.active').trigger('click');
return false;
}
return true;
break;
case 38: // up
if( autocompleteUL.find('li.active').prev().size() ) {
autocompleteUL.find('li.active').removeClass('active').prev().addClass('active');
} else {
autocompleteUL.find('li.active').trigger('click');
}
if( autocompleteUL.find('li.active').size() ) return false;
return true;
break;
case 40: // down
if( autocompleteUL.find('li.active').next().size() ) {
autocompleteUL.find('li.active').removeClass('active').next().addClass('active');
} else {
autocompleteUL.find('li.active').trigger('click');
}
if( autocompleteUL.find('li.active').size() ) return false;
return true;
break;
}
} );
})();
/* @end */
/* @group dragAndDrop for Things in Sidebar tags */
;(function(){
var menu = $('#menu'),
dragOptions = {
opacity: 0.7,
zIndex: 600,
helper: 'clone',
// scope: 'tags',
appendTo: 'body',
handle: '.drag',
cursorAt: { left: 50 },
start: function(){
menu.addClass('drag-drop-enabled');
},
stop: function(){
menu.removeClass('drag-drop-enabled');
}
},
dropOptions = {
accept: '.thing-list-item',
activeClass: 'ui-state-highlight',
hoverClass: 'drophover',
tolerance: 'pointer',
// scope: 'tags',
drop: function( event, ui ) {
var drag = ui.draggable;
if( !drag.size() ) return;
var id = drag.find('.bulk').val(),
tag = $(this).attr('data-tag');
var thing = Thinkery.findThingById( id );
if( !thing ) {
// error
return;
}
if( !tag ) {
// prompt new tag window
$.prompt('<h1 class="border">Add which tag?</h1><input type="text" name="add-tag" data-only-one="1" /><div class="status"></div>', {
buttons: { "Add tag": true, "Cancel": false},
callback: function (buttonClicked, message, fields) {
if (!buttonClicked) return;
Thinkery.saveThing( {
id: thing._id,
title: thing.title,
tags: $.trim( thing.textTags + " " + fields["add-tag"] )
}, function(){
Thinkery.reloadSidebar();
} );
return;
},
loaded: function(v) {
$("input[name=add-tag]:visible").focus().keyup(function(e) {
if (e.altKey || e.metaKey || e.ctrlKey) return true;
var keyCode = (e == null) ? event.keyCode : e.which;
switch (keyCode) {
case 13:
$(this).closest("#jqi").find("button").eq(0).click();
}
});
},
submit: function(buttonClicked) {
if (!buttonClicked) return true;
var input = $("input[name=add-tag]:visible");
if ($.trim(input.val()) == "") {
input.closest("#jqi").find("div.status").addClass("error").html("Please enter a tag.");
input.focus();
return false;
}
return true;
}
});
return;
}
Thinkery.saveThing( {
id: thing._id,
title: thing.title,
tags: $.trim( thing.textTags + " " + tag )
} );
}
};
$(window).bind( 'things-list-updated', function(event, data){
$('#things .thing-list-item').draggable( dragOptions );
} );
$(window).bind( 'reloadSidebar', function(event, data){
$( "#nonFavoriteTags li,#favoriteTags li,#menu .create-new-tag" ).droppable( dropOptions );
} );
$('#things .thing-list-item').draggable( dragOptions );
$( "#nonFavoriteTags li,#favoriteTags li,#menu .create-new-tag" ).droppable( dropOptions );
/*
$('#things .thing-list-item').live( 'mousedown', function( e ){
e.preventDefault();
console.log( e );
} ).live( 'mouseup mousleave', function(){
} )
*/
})();
/* @end */
});