Skip to content

Instantly share code, notes, and snippets.

@miketaylr
Created December 18, 2013 04:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miketaylr/8017405 to your computer and use it in GitHub Desktop.
Save miketaylr/8017405 to your computer and use it in GitHub Desktop.
Pinterest Mobile JS
/* Windows Phone 7
-----------------------------------------------------------------------------------*/
var MinimumIE = 9;
var InternetExplorer;
var IEVersion;
if ($.browser.msie) {
InternetExplorer = true;
IEVersion = $.browser.version;
} else {
InternetExplorer = false;
IEVersion = false;
}
/* Android
-----------------------------------------------------------------------------------*/
var ua = navigator.userAgent.toLowerCase();
var Android = ua.indexOf("android") > -1; //&& ua.indexOf("mobile");
/* Global Variables
-----------------------------------------------------------------------------------*/
// Active Elements
var ActiveDropdown = false;
var ActiveSheet = false;
// CSS values for transforms.
/* Fix for touch delay
See: http://cubiq.org/remove-onclick-delay-on-webkit-for-iphone
-----------------------------------------------------------------------------------*/
if (window.Touch) {
clickTrigger = 'touchstart';
} else {
clickTrigger = 'click';
}
/* Cookie & CSRF Functions
-----------------------------------------------------------------------------------*/
function getCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
// Setting custom header for ajax post request to avoid csrf attacks
$('html').ajaxSend(function(event, xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
});
$(document).ready(function() {
// Route all anchors through /offsite to track clicks and stop spam
$("body").delegate("a", "click", function() {
// Ignore relative URLs
var url = $(this).attr("href");
if (url === undefined || !url.match(/^(http|https):\/\//) || url.match(/\.pinterest\.com/gi) || $(this).hasClass('safelink'))
return true;
var pin_id = ($(this).parents(".pin").attr("data-id") ||
$(this).parents(".pin").attr("pin-id") ||
$(this).attr("data-id"));
var pin = (pin_id) ? "&pin=" + pin_id : '';
var csrf = new jsSHA(getCookie('csrftoken'), 'ASCII').getHash('HEX');
window.open("/offsite/?url="+encodeURIComponent(url)+"&shatoken="+csrf + pin);
return false;
});
});
/* Objects
-----------------------------------------------------------------------------------*/
/* === Action Sheet ============================================================*/
var Sheet = function(type, button, height, delay) {
/**
* type = The type of sheet to initiate.
* button = The pressed button object.
* height = The sheet's height.
* delay = The delay before the sheet is populated (Optional)
* wrapper = The sheet's wrapper.
*/
this.type = type;
this.button = button;
this.height = height;
this.delay = delay || 300;
this.overlay = $('<div class="sheet_overlay"></div>');
this.initialized = false;
this.wrapper, this.height, this.populated;
this.offset = 1180;
this.visibleTransform = 'matrix(1, 0, 0, 1, 0, -' + this.offset + ')';
/* Initiates action sheet ----------------------------------------------- */
this.init = function() {
this.wrapper = this.createWrapper();
this.appendWrapper();
this.show();
var that = this;
var populateAndFocus = function(that) {
that.populate();
that.focus();
};
setTimeout(function() { populateAndFocus(that); }, that.delay);
this.initialized = true;
// Set the global variables.
ActiveSheet = this;
};
/* Destroys action sheet ------------------------------------------------ */
this.destroy = function(delay) {
this.hide();
var that = this;
var cleanUp = function(that) {
that.clean();
that.destroyWrapper();
};
setTimeout(function() { cleanUp(that); }, delay);
// Set the global variables.
ActiveSheet = false;
};
/* Shows the action sheet ----------------------------------------------- */
this.show = function() {
if (!Android) this.showOverlay(); // This breaks selecting a different board, for some reason
var that = this;
// This is for iOS & IE10
var transform = function(that) {
$(that.wrapper).css({
'-webkit-transform' : 'translate3d(0, -' + that.offset + 'px, 0)',
'-ms-transform' : 'translate3d(0, -' + that.offset + 'px, 0)',
'transform' : 'translate3d(0, -' + that.offset + 'px, 0)',
'overflow' : 'visible'
});
};
// This is for Android & >IE10
var explorer = function(that) {
$(that.wrapper).addClass("visible");
};
$(that.wrapper).parents('.pin').css('border-color', '#fff');
// Animate the wrapper in.
if ((!InternetExplorer || InternetExplorer && IEVersion > MinimumIE) && !Android) {
// If we're running Webkit or IE10, use transforms.
setTimeout(function() { transform(that); }, 100);
} else {
// If we're running Android or IE9 or earlier, just set the `top` property.
setTimeout(function() { explorer(that); }, 100);
}
// Fixes a bad Android bug, see:
// http://stackoverflow.com/questions/2562206/android-webkit-absolutely-positioned-elements-dont-respect-z-index
if (Android) {
$(this.wrapper).parents('.pin').nextAll('.pin:first').find('.pinner').css('visibility', 'hidden');
}
this.button.addClass('disabled');
};
/* Hides the action sheet ----------------------------------------------- */
this.hide = function() {
// First, find and hide the sheet's arrow.
this.wrapper.find('.mobile_arrow').css('opacity', 0);
// Bring back the border.
$(this.wrapper).parents('.pin').css('border-color', '#ccc');
var that = this;
// This is for iOS & IE10
var transform = function(that) {
$(that.wrapper).css({
'-webkit-transform' : 'translate3d(0, 0, 0)',
'-ms-transform' : 'translate3d(0, 0, 0)',
'transform' : 'translate3d(0, 0, 0)'
});
};
// This is for Android & >IE10
var explorer = function(that) {
$(that.wrapper).removeClass("visible");
};
// Then, transform the wrapper out.
// We don't need to do this in IE9 because we don't have transitions,
// and the wrapper will get destroyed anyway.
if ((!InternetExplorer || InternetExplorer && IEVersion > MinimumIE) && !Android) {
// If we're running Webkit or IE10, use transforms.
setTimeout(function() { transform(that); }, 100);
} else {
// If we're running Android or IE9 or earlier, just set the `top` property.
setTimeout(function() { explorer(that); }, 100);
}
// Fixes a bad Android bug, see:
// http://stackoverflow.com/questions/2562206/android-webkit-absolutely-positioned-elements-dont-respect-z-index
if (Android) {
$(this.wrapper).parents('.pin').nextAll('.pin:first').find('.pinner').css('visibility', 'visible');
}
this.button.removeClass('disabled');
this.hideOverlay();
};
/* Populates the action sheet with interface elements ------------------- */
this.populate = function() {
var submit;
var arrow;
var textarea;
switch(this.type) {
case 'comment':
// Element Variables
arrow = $('<div class="mobile_arrow"></div>');
textarea = $('<textarea class="comment_text"></textarea>');
var commentText = $('body').data('text-comment');
submit = $('<a class="submit_comment red mbtn" ontouchstart=""><strong>' +
commentText +
'</strong><span></span></a>');
// Population
this.wrapper.append(arrow);
this.wrapper.children('.comment').append(textarea);
this.wrapper.children('.comment').append(submit);
break;
case 'captcha':
var captcha = $('<div id="recaptcha"></div>');
submit = $('<a class="submit_captcha red mbtn" ontouchstart=""><strong>Submit</strong><span></span></a>');
this.wrapper.children('.captcha').append(captcha);
this.wrapper.children('.captcha').append(submit);
var RecaptchaPublicKey = "6LdYxc8SAAAAAHyLKDUP3jgHt11fSDW_WBwSPPdF";
Recaptcha.create(RecaptchaPublicKey, captcha[0], {theme: "clean", callback: Recaptcha.focus_response_field});
break;
case 'repin':
// Determine the user's social settings
var is_facebook_user = $('#hidden #is_facebook_user').prop('checked');
var publish_timeline = $('#hidden #publish_timeline').prop('checked');
var publish_facebook = $('#hidden #publish_facebook').prop('checked');
var is_twitter_user = $('#hidden #is_twitter_user').prop('checked');
var publish_twitter = $('#hidden #publish_twitter').prop('checked');
var granted_permission = $('#hidden #granted_permission').prop('checked');
var fbPublish, twPublish;
var checkFb = is_facebook_user && !publish_timeline;
var checkTw = is_twitter_user;
if (publish_facebook) { fbPublish = 'checked="checked"'; }
if (publish_twitter) { twPublish = 'checked="checked"'; }
var socialClass = (checkFb && checkTw) ? "almost_half" : "";
// Element Variables
arrow = $('<div class="mobile_arrow"></div>');
var select = $('#hidden select').clone();
var board_input = $('#hidden #create_board_wrapper').clone();
textarea = $('<textarea class="repin_text" name="details" tabindex="2">' + this.wrapper.parent('.pin_actions').siblings('.pin_description').text().replace(/^\s+|\s+$/g,"") + '</textarea>');
var social = $('<div id="social_wrapper"></div>');
var characterCount = $('<span class="CharacterCount colorless">500</span>');
var facebook = $('<div class="social ' + socialClass + ' fb">' +
'<label for="id_repin_publish_to_facebook">' +
'<input id="id_repin_publish_to_facebook" class="social_checkbox" type="checkbox" name="publish_to_facebook" ' + fbPublish + ' />' +
'Facebook' +
'</label>' +
'</div>');
var twitter = $('<div class="social ' + socialClass + ' tw">' +
'<label for="id_repin_publish_to_twitter">' +
'<input id="id_repin_publish_to_twitter" class="social_checkbox" type="checkbox" name="publish_to_twitter" ' + twPublish + ' />' +
'Twitter</label>' +
'</label>' +
'</div>');
var repinText = $('body').data('text-repin');
submit = $('<a class="submit_repin red mbtn" ontouchstart=""><strong>' +
repinText + '</strong><span></span></a>');
var repinForm = this.wrapper.find('form.repin');
// Append arrow, select, textarea
this.wrapper.append(arrow);
repinForm.append(select);
repinForm.append(board_input);
repinForm.append(textarea);
repinForm.append(social);
social.append(characterCount);
// Append Facebook / Twitter checkboxes
if (checkFb) { social.append(facebook); }
if (checkTw) { social.append(twitter); }
// Append button
repinForm.append(submit);
CharacterCount.truncateData(textarea, 500);
CharacterCount.setup(textarea, characterCount, submit);
window.setTimeout(function() {
textarea.focus();
}, 100);
if (is_facebook_user && !publish_facebook && !granted_permission) {
$("#id_repin_publish_to_facebook").click(function() {
Facebook.startFacebookConnect('publish_stream', false, false);
});
}
break;
}
this.populated = true;
};
/* Cleans the action sheet's interface elements ------------------------- */
this.clean = function() {
this.wrapper.children('.whitespace').remove();
// Comment-only
this.wrapper.children('.comment_arrow').remove();
this.wrapper.find('.comment_text').remove();
this.wrapper.find('.submit_comment').remove();
// Captcha-only
this.wrapper.find('#recaptcha').remove();
this.wrapper.find('.submit_captcha').remove();
if (window.Recaptcha !== undefined) {
Recaptcha.destroy();
}
// Repin-only
this.wrapper.children('.repin_arrow').remove();
this.wrapper.find('.repin_text').remove();
this.wrapper.find('select').remove();
this.wrapper.find('.social.fb').remove();
this.wrapper.find('.social.tw').remove();
this.wrapper.find('.submit_repin').remove();
};
/* Focuses the action sheet by scrolling to it -------------------------- */
this.focus = function() {
var container = $('body');
var buttons = $(this.wrapper).parent('.pin_actions');
var buttonsTop = buttons.offset().top - buttons.height() - 50;
container.animate({
scrollTop: buttonsTop
});
};
/* Creates appropriate wrapper for action sheet ------------------------- */
this.createWrapper = function() {
var wrapper;
switch (this.type) {
case 'comment':
wrapper = $('<div class="sheet" id="comment"></div>');
wrapper.append('<div class="comment"></div>');
break;
case 'captcha':
wrapper = $('<div class="sheet" id="captcha"></div>');
wrapper.append('<div class="captcha"></div>');
break;
case 'repin':
wrapper = $('<div class="sheet" id="repin"></div>');
wrapper.append('<form class="repin"></form>');
break;
}
return wrapper;
};
this.appendWrapper = function() {
this.button.parent().append(this.wrapper);
};
/* Destroys the wrapper for action sheet -------------------------------- */
this.destroyWrapper = function() {
this.button.siblings('.sheet').remove();
};
/* Creates an overlay underneath the action sheet ----------------------- */
this.showOverlay = function() {
this.wrapper.parents('.pin').after(this.overlay);
this.overlay.fadeIn(250);
};
/* Destroys the overlay underneath the action sheet --------------------- */
this.hideOverlay = function() {
this.overlay.fadeOut(250, function() {
$(this).remove();
});
};
/* Compares with another action sheet ----------------------------------- */
this.compare = function(that) {
var comparison = false;
if (this.button.parent()[0] == that.button.parent()[0] &&
this.type == that.type)
comparison = true;
return comparison;
};
/* This toggles any active sheets and the current object ---------------- */
this.toggle = function() {
var that = this;
if (!ActiveSheet) {
this.init();
} else {
if (!this.compare(ActiveSheet)) {
setTimeout(function() { that.init(); }, 300);
}
ActiveSheet.destroy();
}
};
/* This calculates and stores the sheet's height ----------------------- */
this.getHeight = function() {
if (this.populated)
this.height = $(this.wrapper).height();
};
};
/* === Dropdown ================================================================*/
var Dropdown = function(button, wrapper, translation) {
/**
* button = The button to press.
* wrapper = The dropdown's wrapper.
* translation = Y-translation for the dropdown (%).
* pixels = Pixel height for IE.
* hiddenValue = The default height.
*/
this.wrapper = wrapper;
this.button = button;
this.translation = translation;
this.hiddenValue = '-310px';
this.overlay = $('<div class="dropdown_overlay"></div>');
if (InternetExplorer && IEVersion <= MinimumIE)
this.pixels = '48px';
else
this.pixels = null;
/* Shows the dropdown --------------------------------------------------- */
this.show = function() {
// If there's already a dropdown active, we should hide it.
if (ActiveDropdown) {
ActiveDropdown.hide();
}
// Press the button and perform the transformation for Webkit and IE.
this.button.addClass('disabled');
// If we don't have the pixel height for IE9, we transform for Webkit and IE10.
// Otherwise, we set the `top` property for IE9 and animate it with jQuery.
if (!this.pixels) {
this.wrapper.css({
'-webkit-transform': 'translate3d(0,' + this.translation + ', 0)',
'-ms-transform': 'translate3d(0, ' + this.translation + ', 0)'
});
} else {
this.wrapper.animate({ 'top': this.pixels });
}
// Turn on the overlay that covers the drop shadow.
$('.overlay', this.button).css('opacity', '1');
this.wrapper.after(this.overlay);
// Set the global variables.
ActiveDropdown = this;
};
/* Hides the dropdown --------------------------------------------------- */
this.hide = function() {
this.button.removeClass('disabled');
// If this isn't an Internet Explorer device, we transform for Webkit and IE10.
// We set the `top` property for IE9, it won't affect other browsers because
// that value hasn't changed.
if (!this.pixels) {
this.wrapper.css({
'-webkit-transform': 'translate3d(0, 0, 0)',
'-ms-transform' : 'translate3d(0, 0, 0)'
});
} else {
this.wrapper.animate({ 'top': '-300px' });
}
$('.overlay', this.button).css('opacity', '0');
var resetMenu = function() {
$('#search_dropdown').find('.moved').each(function() {
$(this).removeClass('moved');
});
};
// Reset the position of the Search/Explore menu.
setTimeout(function() { resetMenu(); }, 300);
$('.dropdown_overlay').remove();
// Set the global variable.
ActiveDropdown = false;
};
/* Toggles the dropdown's visibility ------------------------------------ */
this.toggle = function() {
if (!InternetExplorer || InternetExplorer && IEVersion > MinimumIE) {
if (!isTransformed(this.wrapper))
this.show();
else
this.hide();
} else {
if (this.wrapper.css('top') == '-300px')
this.show();
else
this.hide();
}
};
};
/* Helper Functions
-----------------------------------------------------------------------------------*/
// usage: log('inside coolFunc',this,arguments);
// http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function() {
log.history = log.history || []; // store logs to an array for reference
log.history.push(arguments);
if (this.console)
console.log(Array.prototype.slice.call(arguments));
};
/**
* Trims a string.
*
* str = The string to trim.
*
*/
var trim = function(str) {
str = str.replace(/^\s+/, '');
for (var i = str.length - 1; i >= 0; i--) {
if (/\S/.test(str.charAt(i))) {
str = str.substring(0, i + 1);
break;
}
}
return str;
};
/**
* Tests for a CSS transform in Webkit and IE10.
*
* wrapper = The wrapper to test.
*
*/
var isTransformed = function(wrapper) {
var transformed = true;
var emptyMatrix = 'matrix(1, 0, 0, 1, 0, 0)';
var emptyTransform = 'translate3d(0px, 0px, 0px)';
if (wrapper.css('-webkit-transform') == emptyMatrix ||
wrapper.css('-webkit-transform') == emptyTransform ||
wrapper.css('-ms-transform') == emptyMatrix ||
wrapper.css('-ms-transform') == emptyTransform) {
transformed = false;
}
return transformed;
};
/**
* Show a captcha dialog.
*
* callback = A callback function for completion.
*/
var showCaptcha = function(button, callback) {
$.getScript("http://www.google.com/recaptcha/api/js/recaptcha_ajax.js", function () {
var sheet = new Sheet('captcha', button, 130);
sheet.toggle();
$(".submit_captcha").live("click", function () {
$(".feedback", sheet.wrapper).text("");
$.post('/verify_captcha/', {challenge: Recaptcha.get_challenge(), response: Recaptcha.get_response()},
function (data) {
if (data.status == 'success') {
sheet.toggle();
Recaptcha.destroy();
if (callback !== undefined) {
callback();
}
} else {
$(".feedback", sheet.wrapper).text("Try again");
Recaptcha.reload();
}
}, "json");
});
});
};
/**
* Submits a comment onto a pin.
*
* pin = The pin object.
* button = The submit button.
* comment = The comment text.
* closeup = Is this closeup?
* callback = A callback function for completion.
*
*/
var submitComment = function(pin, button, comment, closeup, callback) {
var home = 1;
if (closeup > 0) home = 0;
// Disable the submit comment button.
button.children('strong').html('Posting');
button.attr('disabled', 'disabled').addClass('disabled');
var yePin = pin, yeButton = button, yeComment = comment;
$.ajax({
type: 'POST',
url: pin.comment_post_url,
dataType: 'json',
async: true,
data: {
'text' : comment,
'replies' : '',
'home' : home,
'closeup' : closeup
},
success: function(j) {
if (j.status == 'success') {
callback(yePin, yeButton, yeComment);
} else if (j.captcha) {
var button = ActiveSheet.button;
ActiveSheet.destroy();
// we should really populate the comment text back...
showCaptcha(button);
} else {
yeButton.children('strong').html('Comment');
yeButton.removeAttr('disabled').removeClass('disabled');
alert(j.message);
}
}
});
};
/**
* Callback for commenting on Home
*
* pin = The pin object.
* button = The submit button.
* theComment = The comment.
*
*/
var commentToHome = function(pin, button, theComment) {
var comment =
'<p>' +
'<a class="new_comment" href="' + pin.username +'">' + pin.name + '</a>' +
'<span>&nbsp;' + theComment + '</span>' +
'</p>';
var commentSheet = button.parents('.pin_actions').siblings('.pin_comments');
var comments = commentSheet.find('td.comment_text');
comments.append(comment);
// Show the comments if they are hidden.
if (commentSheet.css('display') == 'none')
commentSheet.css('display', 'block');
ActiveSheet.destroy(300);
};
/**
* Callback for commenting on Closeup
*
* pin = The pin object.
* button = The submit button.
* theComment = The comment.
*
*/
var commentToCloseup = function(pin, button, theComment) {
var comment =
'<tr>' +
'<td class="closeup_commenter">' +
'<img src="' + $('#profile_btn.wrapper img').attr('src') + '" alt="Picture of {{comment.user.get_full_name()|e}}" />' +
'</td>' +
'<td>' +
'<p><a href="/' + pin.username + '/">' + pin.name + '</a></p>' +
'<p>' + theComment + '</p>' +
'</td>' +
'</tr>';
// TODO: quit using tables and crawling the DOM
var commentSheet = button.parents('.pin_actions').siblings('.pin_comments');
var table = commentSheet.find('tbody');
// Append the new comment to the cell.
table.append(comment);
// Show the comments if they are hidden.
if (commentSheet.children('.inner').css('display') == 'none')
commentSheet.children('.inner').css('display', 'block');
ActiveSheet.destroy(300);
};
/**
* Submits a repin.
*
* pin = The pin object.
* button = The submit button.
*
*/
var submitRepin = function(pin, button, boardName, boardId) {
var selected = button.siblings('select').children('option:selected');
var details = button.siblings('textarea').val();
var publish_to_facebook = '';
var facebookCheckbox = button.siblings('#social_wrapper').children('.fb').find('.social_checkbox');
if (facebookCheckbox.length) {
publish_to_facebook = facebookCheckbox.prop('checked') ? 'on' : 'off';
}
var publish_to_twitter = '';
var twitterCheckbox = button.siblings('#social_wrapper').children('.tw').find('.social_checkbox');
if (twitterCheckbox.length) {
publish_to_twitter = twitterCheckbox.prop('checked') ? 'on' : 'off';
}
// Disable the submit comment button.
button.children('strong').html('Pinning');
button.attr('disabled', 'disabled').addClass('disabled').css('margin-top', '10px');
if (boardId === undefined) {
alert('There was a problem repinning. Please try again.');
return;
}
var postData = {
'id': pin.id,
'board' : boardId,
'board_name': boardName,
'details' : details
};
if (publish_to_facebook !== '') {
postData['publish_to_facebook'] = publish_to_facebook;
$('#hidden #publish_facebook').prop('checked', publish_to_facebook === 'on');
}
if (publish_to_twitter !== '') {
postData['publish_to_twitter'] = publish_to_twitter;
$('#hidden #publish_twitter').prop('checked', publish_to_twitter === 'on');
}
$.post(pin.repin_post_url, postData, function(data) {
if (data.status == 'success') {
var form = button.parents('form');
form.children().each(function() {
$(this).fadeOut(250, function() {
$(this).remove();
});
});
// Show the repins if they are hidden, and increment the number.
var stats = $('.pin_repins', button.parents('.pin'));
stats.show();
$('span', stats).html(data.count_str);
// Create the success state elements and append them.
var image = $('#profile_btn.wrapper').find('img').clone();
image.addClass('success_image');
var text = '<p class="success_text">Repinned to <b>' + trim(boardName) + '</b>.</p>';
form.append(image).append(text);
form.children().css('opacity', '1');
setTimeout(function() { ActiveSheet.destroy(300); }, 3000);
} else {
// If this fires, something went wrong on our end.
button.children('strong').html('Repin');
button.removeAttr('disabled').removeClass('disabled');
if ($('#create_board_wrapper').length) {
var select = button.siblings('#create_board_wrapper').children('select');
var option = '<option selected="selected" data="' + boardId + '">' + boardName + '</selected>';
select.children('option').attr('selected', '');
select.prepend(option);
$('#create_board_wrapper').remove();
}
alert(data.message);
}
}, 'json');
};
var getDropDownTop = function () {
var hh = 0;
var translation = 0;
var header = $('#header');
if (header[0]) {
hh = header[0].offsetHeight;
}
translation = 300 + hh;
/* dodge the new black app nag bar */
var nag = $('#AppNag');
if (nag[0]) {
translation = translation + nag[0].offsetHeight;
}
translation = translation + 'px';
return translation;
};
var performAutoFollow = function (button) {
if (!button.hasClass('follow')) {
// We are already following.
return;
}
var CLASS_BUTTON_FOLLOW = 'follow red',
CLASS_BUTTON_UNFOLLOW = 'unfollow disabled pressed',
data = {auto_follow: 1},
isBoard = button.hasClass('board'),
newClass, newText, oldClass, oldText;
newClass = CLASS_BUTTON_UNFOLLOW;
newText = button.data('text-unfollow');
oldClass = CLASS_BUTTON_FOLLOW;
oldText = button.data('text-follow');
$.post(button.attr('href'), data, function(data) {
if (data.status == 'success' && data.auto_follow) {
button.removeClass(oldClass).addClass(newClass);
button.children('strong').html(newText);
}
});
return false;
}
/* Listeners
-----------------------------------------------------------------------------------*/
$(document).ready(function() {
/*
Mobile Dropdown
Dismiss on click outside of dropdown
This needs to be fixed to ignore clicks on the search input
$('html').click(function() {
$('.pressable').removeClass('disabled');
$('#user_dropdown').css('-webkit-transform', 'translate3d(0, 0, 0)');
$('#search_dropdown').css('-webkit-transform', 'translate3d(0, 0, 0)');
$('.overlay').css('opacity', '0');
});
*/
//if (InternetExplorer && IEVersion <= MinimumIE)
$('ul.actions').addClass('hidden_ie');
$('#footer_btn').live('click', function(e) {
e.preventDefault();
});
$('#badge').retina('.2x');
/* === User Dropdown =========================================================== */
$('#profile_btn.wrapper').bind(clickTrigger, function() {
/* Element Variables -------------------------- */
var button = $(this);
var wrapper = $('#user_dropdown');
/* Animation Values --------------------------- */
var dropdown = new Dropdown(button, wrapper, getDropDownTop());
dropdown.toggle();
return false;
}); // End User Dropdown
/* === Search Dropdown ========================================================= */
$('#search.wrapper').bind(clickTrigger, function() {
/* Element Variables -------------------------- */
var button = $(this);
var wrapper = $('#search_dropdown');
/* Animation Values --------------------------- */
// set this dynamically rather than using a percentage
var dropdown = new Dropdown(button, wrapper, getDropDownTop());
dropdown.toggle();
return false;
}); // End Search Dropdown
/* === Move Dropdown Menus ===================================================== */
$('#everything').click(function() {
$('#search_dropdown').find('#search_explore').addClass('moved');
$('#search_dropdown').find('#categories').addClass('moved');
return false;
});
/* === Dropdown Overlay ================================================================ */
$('.dropdown_overlay').live(clickTrigger, function() {
ActiveDropdown.hide();
});
/* === Open Comment ============================================================ */
$('.comment_btn').live('click', function(e) {
var button = $(this);
var sheet = new Sheet('comment', button, 130);
sheet.toggle();
return false;
});
/* === Open Repin ============================================================= */
$('.repin_btn').live('click', function(e) {
var button = $(this);
var sheet = new Sheet('repin', button, 310);
sheet.toggle();
return false;
});
/* === Sheet Overlay ================================================================ */
$('.sheet_overlay').live(clickTrigger, function() {
ActiveSheet.destroy(300);
return false;
});
/* === Submit Comment ========================================================== */
$('.submit_comment').live('click', function(e) {
var button = $(this);
var pinId = $(this).parents('.pin').attr('data-id');
var pin = window['Pin' + pinId];
var comment = $(this).parents('.pin').find('textarea.comment_text').val();
var callback;
if ($(this).parents('.pinboard').hasClass('closeup')) {
callback = commentToCloseup;
} else {
callback = commentToHome;
}
if ($(this).siblings('textarea').val() !== '')
submitComment(pin, button, comment, 0, callback);
else
alert('Please type a comment!');
return false;
});
/* === Submit Repin ============================================================ */
$('.submit_repin').live('click', function(e) {
$('form.repin').submit();
});
$('form.repin').live('submit', function() {
var button = $(this).children('.submit_repin');
var pinId = button.parents('.pin').attr('data-id');
var pin = window['Pin' + pinId];
if (button.siblings('textarea').val() !== '') {
var newBoardInput = button.siblings('#create_board_wrapper').children('input');
var select = newBoardInput.parent().siblings('select');
// Test if the new board input is present.
if (newBoardInput.length > 0) {
// Test if the new board input has a value.
// If it does, then initiate the POST request chain that will create the board,
// and then submit the repin to that board.
if (newBoardInput.val() !== '') {
//createBoard(select, newBoardInput.val(), true, 'submitRepin', { pin, button, repinCallback });
$.post('/board/create/', {
'name': newBoardInput.val(),
'pass_category': true
}, function(data) {
if (data && data.status == "success") {
submitRepin(pin, button, data.name, data.id);
} else {
alert('There was a problem creating the board. Please try again.');
}
});
} else {
alert('Please enter a name for your new board, or select an existing board!');
}
} else {
// If we're repinning to an existing board, we can just submit the repin.
var selected = button.siblings('select').children('option:selected');
if (selected && selected.attr('data')) {
submitRepin(pin, button, selected.text(), selected.attr("data"));
} else {
alert('Please select a board.');
}
}
} else {
alert('Please enter a description for your pin!');
}
return false;
});
/* === Like Pins =============================================================== */
$('.like_btn').live('click', function(e) {
/* Element Variables -------------------------- */
var button = $(this);
var wrapper = button.parents('.pin_actions').siblings('.pin_stats').children('.pin_likes');
// Visually re-style the button into a 'Liked' button.
$(button).removeClass('like_btn')
.addClass('unlike_btn pressed');
$(button).children('strong').html(button.data('text-unlike'));
// Get the Pin ID, create the URL and perform the POST request.
var pinId = $(this).parents('.pin').attr('data-id');
var likeUrl = '/pin/' + pinId + '/like/';
$.post(likeUrl, {'closeup': '1'}, function(j) {
if (j.status == 'success') {
wrapper.show();
$('span', wrapper).html(j.count_str);
} else if (j.captcha){
showCaptcha(button);
} else {
if (j.message != 'undefined') {
alert(j.message);
// Revert to a like button.
$(button).addClass('like_btn')
.removeClass('unlike_btn pressed');
$(button).html('<strong>' + button.data('text-like') + '</strong><span></span>');
}
}
}, 'json');
return false;
}); // End Like Pins
/* === Unlike Pins ============================================================= */
$('.unlike_btn').live('click', function(e) {
/* Element Variables -------------------------- */
var button = $(this);
var wrapper = button.parents('.pin_actions').siblings('.pin_stats').find('.pin_likes');
// Unpress the button.
$(button).children('strong').html(button.data('text-like'));
$(button).removeClass('unlike_btn pressed')
.addClass('like_btn');
// Perform the GET request to actually unlike the pin.
$.post(button.attr('href'), {unlike: 1}, function(data) {
if (!data.count) {
wrapper.hide();
}
$('span', wrapper).html(data.count_str);
if (data.status != "success") { alert(data.message); }
}, 'json');
return false;
}); // End Unlike Pins
/* === Create Board Listener =================================================== */
$('select').live('change', function() {
var select = this;
var input = '<div id="create_board_wrapper"><input class="full" placeholder="Enter a board title" tabindex="1" type="text"></div>';
if ($('option#create', this).attr('selected') == 'selected')
$(select).after(input);
else
$(select).siblings('#create_board_wrapper').remove();
});
/* === Search Again ============================================================ */
$('#searchable').live(clickTrigger, function(e) {
var queryObj = $('.query');
var query = queryObj.text();
var filters = $('ul.filters');
var actions = $('ul.actions');
if (!filters.hasClass('hidden')) {
var form = $('<form class="re_search" action="/search/" method="get"><input name="q" type="text"></form>');
form.find('input').val(query);
// Hide the filters bar for both Webkit and IE browsers.
filters.addClass('hidden').removeClass('show');
if (InternetExplorer && IEVersion <= MinimumIE)
filters.addClass('ie_hidden').removeClass('show_ie');
// Show the actions bar for Webkit and IE browsers
// after the 300ms animation has completed.
var timeout = function(actions) {
actions.addClass('show').removeClass('hidden hidden_ie');
if (InternetExplorer && IEVersion <= MinimumIE) {
filters.addClass('hidden_ie');
actions.addClass('show_ie');
}
};
setTimeout(function() { timeout(actions); }, 300);
// Fade out the query string.
queryObj.fadeOut(250);
// Append the form after the search icon.
$('#search_icon').after(form);
// Fade in the form and focus it.
form.fadeIn(250).focus();
}
}); // End Search Again
/* === Submit Search, Again ==================================================== */
$('#search_bar .actions a.mbtn').live(clickTrigger, function(e) {
$('.re_search').submit();
}); // End Submit Search, Again
/* === Cancel Search Again ===================================================== */
$('a.cancel').live(clickTrigger, function(e) {
var filters = $('ul.filters');
var actions = $('ul.actions');
if (filters.hasClass('hidden')) {
// Fade in the query string.
var queryObj = $('.query');
queryObj.fadeIn(250);
// Find the form, fade it out and remove it.
var form = queryObj.siblings('form');
form.fadeOut(250).remove();
// Hide the actions bar for Webkit and IE browsers.
actions.removeClass('show show_ie').addClass('hidden');
if (InternetExplorer && IEVersion <= MinimumIE)
actions.addClass('hidden_ie');
var timeout = function(filters) {
filters.removeClass('hidden hidden_ie').addClass('show');
if (InternetExplorer && IEVersion <= MinimumIE) {
filters.addClass('show_ie');
actions.addClass('hidden_ie');
}
};
setTimeout(function() { $('ul.filters').removeClass('hidden hidden_ie'); }, 300);
}
}); // End Cancel Search Again
function onFollowButtonClick() {
var CLASS_BUTTON_FOLLOW = 'follow red',
CLASS_BUTTON_UNFOLLOW = 'unfollow disabled pressed',
button = $(this),
data = {},
isBoard = button.hasClass('board'),
isFollowButton = button.hasClass('follow'),
newClass, newText, oldClass, oldText;
if (isBoard && window.location.pathname == "/") {
data.home = 1;
}
if (isFollowButton) {
newClass = CLASS_BUTTON_UNFOLLOW;
newText = button.data('text-unfollow');
oldClass = CLASS_BUTTON_FOLLOW;
oldText = button.data('text-follow');
} else {
newClass = CLASS_BUTTON_FOLLOW;
newText = button.data('text-follow');
oldClass = CLASS_BUTTON_UNFOLLOW;
oldText = button.data('text-unfollow');
data.unfollow = 1;
}
button.removeClass(oldClass).addClass(newClass);
button.children('strong').html(newText);
$.post(button.attr('href'), data, function(data) {
if (data.status !== 'success') {
alert(data.message);
button.removeClass(newClass).addClass(oldClass);
button.children('strong').html(oldText);
}
});
return false;
}
/* === Follow Board ============================================================ */
$(".follow.board").live("click", onFollowButtonClick);
/* === Unfollow Board =============================================================== */
$(".unfollow.board").live("click", onFollowButtonClick);
/* === Follow User ============================================================= */
$(".follow.user").live('click', onFollowButtonClick);
/* === Unfollow User =========================================================== */
$(".unfollow.user").live('click', onFollowButtonClick);
/* === Landing Page ============================================================ */
$('#invite_form').submit(function() {
var input = $('#invite_me input');
if (input.val().length > 0) {
$.get("/landing/",{
'email' : input.val()
}, function(json) {
if (json.status == 'success') {
$('#invite_form').fadeOut();
$('#invite_success').fadeIn();
if (json.message.length) {
$('#invite_success p').html('You\'re already on the list.<br>We\'ll send you an invite very soon!');
}
} else {
var error = '<p class="error">There was an error! Please try again.</p>';
$('#invite_form h2').after(error);
}
}, "json"); //get.
} else {
if ($('#invite_form p').length < 1) {
var error = '<p class="error">Please enter your email address!</p>';
$('#invite_form h2').after(error);
}
}
return false;
});
$('#invite_form a').click(function() {
$('#invite_form').submit();
});
$('#invite_me input').focus(function() {
if ($('#invite_form p').length) {
$('#invite_form p').remove();
}
});
/* === Forgot Password =========================================================== */
var reset = "/password/reset/";
var login = "/login/";
var form = $('.last_cont form');
var nonInputs = $('.non_inputs', form);
var loginInput = $('.user.password', form);
$('#resetPassword').click(function() {
loginInput.fadeOut(500, function() {
nonInputs.parents('form').attr('action', reset);
$('.mbtn strong', nonInputs).text('Reset');
});
$('#resetPassword').fadeOut(500);
$('#backToLogin').fadeIn(500);
return false;
});
/* === Back to Login ============================================================= */
$('#backToLogin').click(function() {
loginInput.fadeIn(500, function() {
nonInputs.parents('form').attr('action', login);
$('.mbtn strong', nonInputs).text('Login');
});
$('#backToLogin').fadeOut(500);
$('#resetPassword').fadeIn(500);
return false;
});
/* === Logout ============================================================= */
$("#logout_button").click(function() {
var button = $(this);
$.post(button.attr('href'), function(data) {
window.location = "/";
});
return false;
}); // End Follow User
}); // End Listeners
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment