Created
December 18, 2013 04:47
-
-
Save miketaylr/8017405 to your computer and use it in GitHub Desktop.
Pinterest Mobile JS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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> ' + 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