function setCookie(name, value, exdays) { var exdate = new Date(); exdate.setDate(exdate.getDate() + exdays); value = escape(value) + '; path=/' + ((exdays == null) ? '' : '; expires=' + exdate.toUTCString()); document.cookie = name + '=' + value; } function getCookie(name) { var value = document.cookie; var start = value.indexOf(' ' + name + '='); if (start == -1) start = value.indexOf(name + '='); if (start == -1) return null; start = value.indexOf('=', start) + 1; var end = value.indexOf(';', start); if (end == -1) end = value.length; return unescape(value.substring(start, end)); } function rememberLastSearchQuery() { //lastSearchQuery variable is obtained from layout setCookie('last-search-query', lastSearchQuery); } //core functionalities, prototypes function getJSON(data) { if (typeof(data.headers) === 'undefined') data.headers = {}; data.headers['X-Ajax'] = '1'; data.type = 'GET'; return $.ajax(data); }; function postJSON(data) { if (typeof(data.headers) === 'undefined') data.headers = {}; data.headers['X-Ajax'] = '1'; data.type = 'POST'; return $.ajax(data); }; $.fn.hasAttr = function(name) { return this.attr(name) !== undefined; }; $.fn.bindOnce = function(name, eventName, callback) { $.each(this, function(i, item) { if ($(item).data(name) == name) return; $(item).data(name, name); $(item).on(eventName, callback); }); }; //basic event listeners $(function() { $('body').bind('dom-update', function() { //event confirmations function confirmEvent(e) { if (!confirm($(this).attr('data-confirm-text'))) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); } } $('form.confirmable').bindOnce('confirmation', 'submit', confirmEvent); $('a.confirmable').bindOnce('confirmation', 'click', confirmEvent); //simple action buttons $('a.simple-action').bindOnce('simple-action', 'click', function(e) { if (e.isPropagationStopped()) return; e.preventDefault(); rememberLastSearchQuery(); var aDom = $(this); if (aDom.hasClass('inactive')) return; aDom.addClass('inactive'); var url = $(this).attr('href'); postJSON({ url: url }).success(function(data) { if (aDom.hasAttr('data-redirect-url')) window.location.href = aDom.attr('data-redirect-url'); else if (aDom.data('callback')) aDom.data('callback')(); else window.location.reload(); }).error(function(xhr) { alert(xhr.responseJSON ? xhr.responseJSON.message : 'Fatal error'); aDom.removeClass('inactive'); }); }); //simple action forms $('form.simple-action').bindOnce('simple-action', 'submit', function(e) { e.preventDefault(); rememberLastSearchQuery(); var formDom = $(this); if (formDom.hasClass('inactive')) return; formDom.addClass('inactive'); formDom.find(':input').attr('readonly', true); var url = formDom.attr('action'); var fd = new FormData(formDom[0]); var ajaxData = { url: url, data: fd, processData: false, contentType: false, }; postJSON(ajaxData) .success(function(data) { if (data.message) alert(data.message); console.log(data); disableExitConfirmation(); formDom.find(':input').attr('readonly', false); formDom.removeClass('inactive'); if (data.redirectUrl) window.location.href = data.redirectUrl; else window.location.reload(); }) .error(function(xhr) { alert(xhr.responseJSON ? xhr.responseJSON.message : 'Fatal error'); formDom.find(':input').attr('readonly', false); formDom.removeClass('inactive'); }); }); //attach data from submit buttons to forms before .submit() gets called $('.submit').each(function() { $(this).bindOnce('submit-faux-input', 'click', function() { var form = $(this).closest('form'); form.find('.faux-submit').remove(); var input = $('').attr({ name: $(this).attr('name'), value: $(this).val() }); form.append(input); }); }); }); //try to remember last search query window.onbeforeunload = rememberLastSearchQuery; }); //modify DOM on small viewports function processSidebar() { if ($('#small-screen').is(':visible')) $('#sidebar').insertAfter($('#inner-content')); else $('#sidebar').insertBefore($('#inner-content')); } $(function() { $(window).resize(function() { fixSize(); if ($('body').width() == $('body').data('last-width')) return; $('body').data('last-width', $('body').width()); $('body').trigger('dom-update'); }); $('body').bind('dom-update', processSidebar); fixSize(); }); var fixedEvenOnce = false; function fixSize() { if ($('#small-screen').is(':visible')) return; var multiply = 168; var oldWidth = $('.main-wrapper:eq(0)').width(); $('.main-wrapper:eq(0)').width(''); var newWidth = $('.main-wrapper:eq(0)').width(); if (oldWidth != newWidth || !fixedEvenOnce) { $('.main-wrapper').width(multiply * Math.floor(newWidth / multiply)); fixedEvenOnce = true; } } //autocomplete function split(val) { return val.split(/\s+/); } function retrieveTags(searchTerm, cb) { var options = { url: '/tags-autocomplete', data: { search: searchTerm } }; getJSON(options) .success(function(data) { var tags = $.map(data.tags.slice(0, 15), function(tag) { var ret = { label: tag.name + ' (' + tag.count + ')', value: tag.name, }; return ret; }); cb(tags); }); } $(function() { $('.autocomplete').each(function() { var options = { minLength: 1, source: function(request, response) { var terms = split(request.term); var term = terms.pop(); if (term != '') retrieveTags(term, response); }, focus: function(e) { // prevent value inserted on focus e.preventDefault(); }, select: function(e, ui) { e.preventDefault(); var terms = split(this.value); terms.pop(); terms.push(ui.item.value); terms.push(''); this.value = terms.join(' '); } }; if ($(this).parents('#top-nav').length != 0) { options['position'] = { my: 'right top', at: 'right bottom' }; } var searchInput = $(this); searchInput // don't navigate away from the field on tab when selecting an item .bind('keydown', function(e) { if (e.keyCode === $.ui.keyCode.TAB && $(this).data('autocomplete').menu.active) e.preventDefault(); }).autocomplete(options); }); }); function attachTagIt(target) { var tagItOptions = { caseSensitive: false, onTagClicked: function(e, ui) { var targetTagit = ui.tag.parents('.tagit'); var context = target.tagit('assignedTags'); var options = { url: '/tags-related', data: { context: context, tag: ui.tagLabel } }; if (targetTagit.siblings('.related-tags:eq(0)').data('for') == options.data.tag) { targetTagit.siblings('.related-tags').slideUp(function() { $(this).remove(); }); return; } getJSON(options).success(function(data) { var list = $('
Related tags:
'); div.append(list); div.append(''); div.insertAfter(targetTagit).hide().slideDown(); }); }, autocomplete: { source: function(request, response) { var tagit = this; //var context = tagit.element.tagit('assignedTags'); retrieveTags(request.term.toLowerCase(), function(tags) { if (!tagit.options.allowDuplicates) { tags = $.grep(tags, function(tag) { return tagit.assignedTags().indexOf(tag.value) == -1; }); } response(tags); }); }, } }; tagItOptions.placeholderText = target.attr('placeholder'); target.tagit(tagItOptions); } //prevent keybindings from executing when flash posts are focused var oldMousetrapBind = Mousetrap.bind; Mousetrap.bind = function(key, func, args) { oldMousetrapBind(key, function() { if ($(document.activeElement).parents('.post-type-flash').length > 0) return false; func(); }, args); }; //hotkeys $(function() { Mousetrap.bind('q', function() { $('#top-nav input').focus(); return false; }, 'keyup'); Mousetrap.bind('w', function() { $('body,html').animate({scrollTop: '-=150px'}, 200); }); Mousetrap.bind('s', function() { $('body,html').animate({scrollTop: '+=150px'}, 200); }); Mousetrap.bind('a', function() { var url = $('.paginator:visible .prev:not(.disabled) a').attr('href'); if (typeof url !== 'undefined') window.location.href = url; }, 'keyup'); Mousetrap.bind('d', function() { var url = $('.paginator:visible .next:not(.disabled) a').attr('href'); if (typeof url !== 'undefined') window.location.href = url; }, 'keyup'); Mousetrap.bind('p', function() { $('.post a').eq(0).focus(); return false; }, 'keyup'); }); function enableExitConfirmation() { $(window).bind('beforeunload', function(e) { return 'There are unsaved changes.'; }); } function disableExitConfirmation() { $(window).unbind('beforeunload'); }