<commit_before>/*
 * Laconica - a distributed open-source microblogging tool
 * Copyright (C) 2008, Controlez-Vous, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

$(document).ready(function(){
	// count character on keyup
	function counter(event){
		var maxLength = 140;
		var currentLength = $("#notice_data-text").val().length;
		var remaining = maxLength - currentLength;
		var counter = $("#notice_text-count");
		counter.text(remaining);

		if (remaining < 0) {
			$("#form_notice").addClass("warning");
		} else {
			$("#form_notice").removeClass("warning");
		}
	}

	function submitonreturn(event) {
		if (event.keyCode == 13) {
			$("#form_notice").submit();
			event.preventDefault();
			event.stopPropagation();
			return false;
		}
		return true;
	}

	if ($("#notice_data-text").length) {
		$("#notice_data-text").bind("keyup", counter);
		$("#notice_data-text").bind("keydown", submitonreturn);

		// run once in case there's something in there
		counter();

        if($('body')[0].id != 'conversation') {
            $("#notice_data-text").focus();
        }
	}

	// XXX: refactor this code

	var favoptions = { dataType: 'xml',
					   success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
												var dis = new_form.id;
												var fav = dis.replace('disfavor', 'favor');
												$('form#'+fav).replaceWith(new_form);
												$('form#'+dis).ajaxForm(disoptions).each(addAjaxHidden);
											  }
					 };

	var disoptions = { dataType: 'xml',
					   success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
												var fav = new_form.id;
												var dis = fav.replace('favor', 'disfavor');
												$('form#'+dis).replaceWith(new_form);
												$('form#'+fav).ajaxForm(favoptions).each(addAjaxHidden);
											  }
					 };

	var joinoptions = { dataType: 'xml',
					   success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
												var leave = new_form.id;
												var join = leave.replace('leave', 'join');
												$('form#'+join).replaceWith(new_form);
												$('form#'+leave).ajaxForm(leaveoptions).each(addAjaxHidden);
											  }
					 };

	var leaveoptions = { dataType: 'xml',
					   success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
												var join = new_form.id;
												var leave = join.replace('join', 'leave');
												$('form#'+leave).replaceWith(new_form);
												$('form#'+join).ajaxForm(joinoptions).each(addAjaxHidden);
											  }
					 };

	function addAjaxHidden() {
		var ajax = document.createElement('input');
		ajax.setAttribute('type', 'hidden');
		ajax.setAttribute('name', 'ajax');
		ajax.setAttribute('value', 1);
		this.appendChild(ajax);
	}

	$("form.form_favor").ajaxForm(favoptions);
	$("form.form_disfavor").ajaxForm(disoptions);
	$("form.form_group_join").ajaxForm(joinoptions);
	$("form.form_group_leave").ajaxForm(leaveoptions);
	$("form.form_favor").each(addAjaxHidden);
	$("form.form_disfavor").each(addAjaxHidden);
	$("form.form_group_join").each(addAjaxHidden);
	$("form.form_group_leave").each(addAjaxHidden);

	$("#form_user_nudge").ajaxForm ({ dataType: 'xml',
		beforeSubmit: function(xml) { $("#form_user_nudge input[type=submit]").attr("disabled", "disabled");
									  $("#form_user_nudge input[type=submit]").addClass("disabled");
									},
		success: function(xml) { $("#form_user_nudge").replaceWith(document._importNode($("#nudge_response", xml).get(0),true));
							     $("#form_user_nudge input[type=submit]").removeAttr("disabled");
							     $("#form_user_nudge input[type=submit]").removeClass("disabled");
							   }
	 });
	$("#form_user_nudge").each(addAjaxHidden);

	var Subscribe = { dataType: 'xml',
					  beforeSubmit: function(formData, jqForm, options) { $(".form_user_subscribe input[type=submit]").attr("disabled", "disabled");
																	      $(".form_user_subscribe input[type=submit]").addClass("disabled");
																	    },
					  success: function(xml) { var form_unsubscribe = document._importNode($('form', xml).get(0), true);
										  	   var form_unsubscribe_id = form_unsubscribe.id;
											   var form_subscribe_id = form_unsubscribe_id.replace('unsubscribe', 'subscribe');
											   $("form#"+form_subscribe_id).replaceWith(form_unsubscribe);
											   $("form#"+form_unsubscribe_id).ajaxForm(UnSubscribe).each(addAjaxHidden);
											   $("dd.subscribers").text(parseInt($("dd.subscribers").text())+1);
											   $(".form_user_subscribe input[type=submit]").removeAttr("disabled");
											   $(".form_user_subscribe input[type=submit]").removeClass("disabled");
										     }
					};

	var UnSubscribe = { dataType: 'xml',
						beforeSubmit: function(formData, jqForm, options) { $(".form_user_unsubscribe input[type=submit]").attr("disabled", "disabled");
																		    $(".form_user_unsubscribe input[type=submit]").addClass("disabled");
																		  },
					    success: function(xml) { var form_subscribe = document._importNode($('form', xml).get(0), true);
										  		 var form_subscribe_id = form_subscribe.id;
												 var form_unsubscribe_id = form_subscribe_id.replace('subscribe', 'unsubscribe');
												 $("form#"+form_unsubscribe_id).replaceWith(form_subscribe);
												 $("form#"+form_subscribe_id).ajaxForm(Subscribe).each(addAjaxHidden);
												 $("#profile_send_a_new_message").remove();
												 $("#profile_nudge").remove();
											     $("dd.subscribers").text(parseInt($("dd.subscribers").text())-1);
												 $(".form_user_unsubscribe input[type=submit]").removeAttr("disabled");
												 $(".form_user_unsubscribe input[type=submit]").removeClass("disabled");
											   }
					  };

	$(".form_user_subscribe").ajaxForm(Subscribe);
	$(".form_user_unsubscribe").ajaxForm(UnSubscribe);
	$(".form_user_subscribe").each(addAjaxHidden);
	$(".form_user_unsubscribe").each(addAjaxHidden);

	var PostNotice = { dataType: 'xml',
					   beforeSubmit: function(formData, jqForm, options) { if ($("#notice_data-text").get(0).value.length == 0) {
																				$("#form_notice").addClass("warning");
																				return false;
																		   }
																		   $("#form_notice").addClass("processing");
																		   $("#notice_action-submit").attr("disabled", "disabled");
																		   $("#notice_action-submit").addClass("disabled");
																		   return true;
												 						 },
					   timeout: '60000',
					   error: function (xhr, textStatus, errorThrown) {	$("#form_notice").removeClass("processing");
																		$("#notice_action-submit").removeAttr("disabled");
																		$("#notice_action-submit").removeClass("disabled");
																		if (textStatus == "timeout") {
																			alert ("Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists");
																		}
																		else {
																			if ($(".error", xhr.responseXML).length > 0) {
																				$('#form_notice').append(document._importNode($(".error", xhr.responseXML).get(0), true));
																			}
																			else {
																				var HTTP20x30x = [200, 201, 202, 203, 204, 205, 206, 300, 301, 302, 303, 304, 305, 306, 307];
																				if(jQuery.inArray(parseInt(xhr.status), HTTP20x30x) < 0) {
																					alert("Sorry! We had trouble sending your notice ("+xhr.status+" "+xhr.statusText+"). Please report the problem to the site administrator if this happens again.");
																				}
																				else {
																					$("#notice_data-text").val("");
																					counter();
																				}
																			}
																		}
																	  },
					   success: function(xml) {	if ($("#error", xml).length > 0) {
													var result = document._importNode($("p", xml).get(0), true);
													result = result.textContent || result.innerHTML;
													alert(result);
												}
												else {
												    if ($("#command_result", xml).length > 0) {
													    var result = document._importNode($("p", xml).get(0), true);
													    result = result.textContent || result.innerHTML;
													    alert(result);
                                                    }
                                                    else {
                                                         li = $("li", xml).get(0);
                                                         if ($("#"+li.id).length == 0) {
                                                            var notice_irt_value = $('#notice_in-reply-to').val();
                                                            var notice_irt = '#notices_primary #notice-'+notice_irt_value;
                                                            if($('body')[0].id == 'conversation') {
                                                                if(notice_irt_value.length > 0 && $(notice_irt+' .notices').length < 1) {
                                                                    $(notice_irt).append('

');
                                                                }
                                                                $($(notice_irt+' .notices')[0]).append(document._importNode(li, true));
                                                            }
                                                            else {
                                                                $("#notices_primary .notices").prepend(document._importNode(li, true));
                                                            }
                                                            $('#'+li.id).css({display:'none'});
                                                            $('#'+li.id).fadeIn(2500);
                                                            NoticeReply();
                                                            NoticeAttachments();
                                                         }
													}
													$("#notice_data-text").val("");
    												$("#notice_data-attach").val("");
    												$("#notice_in-reply-to").val("");
                                                    $('#notice_data-attach_selected').remove();
                                                    counter();
												}
												$("#form_notice").removeClass("processing");
												$("#notice_action-submit").removeAttr("disabled");
												$("#notice_action-submit").removeClass("disabled");
											 }
					   };
	$("#form_notice").ajaxForm(PostNotice);
	$("#form_notice").each(addAjaxHidden);
    NoticeReply();
    NoticeAttachments();
    NoticeDataAttach();
});

function NoticeReply() {
    if ($('#notice_data-text').length > 0 && $('#content .notice_reply').length > 0) {
        $('#content .notice').each(function() {
            var notice = $(this)[0];
            $($('.notice_reply', notice)[0]).click(function() {
                var nickname = ($('.author .nickname', notice).length > 0) ? $($('.author .nickname', notice)[0]) : $('.author .nickname');
                NoticeReplySet(nickname.text(), $($('.notice_id', notice)[0]).text());
                return false;
            });
        });
    }
}

function NoticeReplySet(nick,id) {
	rgx_username = /^[0-9a-zA-Z\-_.]*$/;
	if (nick.match(rgx_username)) {
		replyto = "@" + nick + " ";
		var text = $("#notice_data-text");
		if (text.length) {
			text.val(replyto + text.val());
			$("#form_notice input#notice_in-reply-to").val(id);
			if (text.get(0).setSelectionRange) {
				var len = text.val().length;
				text.get(0).setSelectionRange(len,len);
				text.get(0).focus();
			}
			return false;
		}
	}
	return true;
}

function NoticeAttachments() {
    $.fn.jOverlay.options = {
        method : 'GET',
        data : '',
        url : '',
        color : '#000',
        opacity : '0.6',
        zIndex : 99,
        center : false,
        imgLoading : $('address .url')[0].href+'theme/base/images/illustrations/illu_progress_loading-01.gif',
        bgClickToClose : true,
        success : function() {
            $('#jOverlayContent').append('<button>×</button>');
            $('#jOverlayContent button').click($.closeOverlay);
        },
        timeout : 0,
        autoHide : true,
        css : {'max-width':'542px', 'top':'5%', 'left':'32.5%'}
    };

    $('#content .notice a.attachment').click(function() {
        $().jOverlay({url: $('address .url')[0].href+'attachment/' + ($(this).attr('id').substring('attachment'.length + 1)) + '/ajax'});
        return false;
    });

    var t;
    $("body:not(#shownotice) #content .notice a.thumbnail").hover(
        function() {
            var anchor = $(this);
            $("a.thumbnail").children('img').hide();
            anchor.closest(".entry-title").addClass('ov');

            if (anchor.children('img').length == 0) {
                t = setTimeout(function() {
                    $.get($('address .url')[0].href+'attachment/' + (anchor.attr('id').substring('attachment'.length + 1)) + '/thumbnail', null, function(data) {
                        anchor.append(data);
                    });
                }, 500);
            }
            else {
                anchor.children('img').show();
            }
        },
        function() {
            clearTimeout(t);
            $("a.thumbnail").children('img').hide();
            $(this).closest(".entry-title").removeClass('ov');
        }
    );
}

function NoticeDataAttach() {
    NDA = $('#notice_data-attach');
    NDA.change(function() {
        S = '
'+$(this).val()+' <button>×</button>
';
        NDAS = $('#notice_data-attach_selected');
        (NDAS.length > 0) ? NDAS.replaceWith(S) : $('#form_notice').append(S);
        $('#notice_data-attach_selected button').click(function(){
            $('#notice_data-attach_selected').remove();
            NDA.val('');
        });
    });
}
<commit_msg>Ticket 1758 Multiple replies in web interface on "profile" page appends own username<commit_after>/*
 * Laconica - a distributed open-source microblogging tool
 * Copyright (C) 2008, Controlez-Vous, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

$(document).ready(function(){
	// count character on keyup
	function counter(event){
		var maxLength = 140;
		var currentLength = $("#notice_data-text").val().length;
		var remaining = maxLength - currentLength;
		var counter = $("#notice_text-count");
		counter.text(remaining);

		if (remaining < 0) {
			$("#form_notice").addClass("warning");
		} else {
			$("#form_notice").removeClass("warning");
		}
	}

	function submitonreturn(event) {
		if (event.keyCode == 13) {
			$("#form_notice").submit();
			event.preventDefault();
			event.stopPropagation();
			return false;
		}
		return true;
	}

	if ($("#notice_data-text").length) {
		$("#notice_data-text").bind("keyup", counter);
		$("#notice_data-text").bind("keydown", submitonreturn);

		// run once in case there's something in there
		counter();

        if($('body')[0].id != 'conversation') {
            $("#notice_data-text").focus();
        }
	}

	// XXX: refactor this code

	var favoptions = { dataType: 'xml',
					   success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
												var dis = new_form.id;
												var fav = dis.replace('disfavor', 'favor');
												$('form#'+fav).replaceWith(new_form);
												$('form#'+dis).ajaxForm(disoptions).each(addAjaxHidden);
											  }
					 };

	var disoptions = { dataType: 'xml',
					   success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
												var fav = new_form.id;
												var dis = fav.replace('favor', 'disfavor');
												$('form#'+dis).replaceWith(new_form);
												$('form#'+fav).ajaxForm(favoptions).each(addAjaxHidden);
											  }
					 };

	var joinoptions = { dataType: 'xml',
					   success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
												var leave = new_form.id;
												var join = leave.replace('leave', 'join');
												$('form#'+join).replaceWith(new_form);
												$('form#'+leave).ajaxForm(leaveoptions).each(addAjaxHidden);
											  }
					 };

	var leaveoptions = { dataType: 'xml',
					   success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
												var join = new_form.id;
												var leave = join.replace('join', 'leave');
												$('form#'+leave).replaceWith(new_form);
												$('form#'+join).ajaxForm(joinoptions).each(addAjaxHidden);
											  }
					 };

	function addAjaxHidden() {
		var ajax = document.createElement('input');
		ajax.setAttribute('type', 'hidden');
		ajax.setAttribute('name', 'ajax');
		ajax.setAttribute('value', 1);
		this.appendChild(ajax);
	}

	$("form.form_favor").ajaxForm(favoptions);
	$("form.form_disfavor").ajaxForm(disoptions);
	$("form.form_group_join").ajaxForm(joinoptions);
	$("form.form_group_leave").ajaxForm(leaveoptions);
	$("form.form_favor").each(addAjaxHidden);
	$("form.form_disfavor").each(addAjaxHidden);
	$("form.form_group_join").each(addAjaxHidden);
	$("form.form_group_leave").each(addAjaxHidden);

	$("#form_user_nudge").ajaxForm ({ dataType: 'xml',
		beforeSubmit: function(xml) { $("#form_user_nudge input[type=submit]").attr("disabled", "disabled");
									  $("#form_user_nudge input[type=submit]").addClass("disabled");
									},
		success: function(xml) { $("#form_user_nudge").replaceWith(document._importNode($("#nudge_response", xml).get(0),true));
							     $("#form_user_nudge input[type=submit]").removeAttr("disabled");
							     $("#form_user_nudge input[type=submit]").removeClass("disabled");
							   }
	 });
	$("#form_user_nudge").each(addAjaxHidden);

	var Subscribe = { dataType: 'xml',
					  beforeSubmit: function(formData, jqForm, options) { $(".form_user_subscribe input[type=submit]").attr("disabled", "disabled");
																	      $(".form_user_subscribe input[type=submit]").addClass("disabled");
																	    },
					  success: function(xml) { var form_unsubscribe = document._importNode($('form', xml).get(0), true);
										  	   var form_unsubscribe_id = form_unsubscribe.id;
											   var form_subscribe_id = form_unsubscribe_id.replace('unsubscribe', 'subscribe');
											   $("form#"+form_subscribe_id).replaceWith(form_unsubscribe);
											   $("form#"+form_unsubscribe_id).ajaxForm(UnSubscribe).each(addAjaxHidden);
											   $("dd.subscribers").text(parseInt($("dd.subscribers").text())+1);
											   $(".form_user_subscribe input[type=submit]").removeAttr("disabled");
											   $(".form_user_subscribe input[type=submit]").removeClass("disabled");
										     }
					};

	var UnSubscribe = { dataType: 'xml',
						beforeSubmit: function(formData, jqForm, options) { $(".form_user_unsubscribe input[type=submit]").attr("disabled", "disabled");
																		    $(".form_user_unsubscribe input[type=submit]").addClass("disabled");
																		  },
					    success: function(xml) { var form_subscribe = document._importNode($('form', xml).get(0), true);
										  		 var form_subscribe_id = form_subscribe.id;
												 var form_unsubscribe_id = form_subscribe_id.replace('subscribe', 'unsubscribe');
												 $("form#"+form_unsubscribe_id).replaceWith(form_subscribe);
												 $("form#"+form_subscribe_id).ajaxForm(Subscribe).each(addAjaxHidden);
												 $("#profile_send_a_new_message").remove();
												 $("#profile_nudge").remove();
											     $("dd.subscribers").text(parseInt($("dd.subscribers").text())-1);
												 $(".form_user_unsubscribe input[type=submit]").removeAttr("disabled");
												 $(".form_user_unsubscribe input[type=submit]").removeClass("disabled");
											   }
					  };

	$(".form_user_subscribe").ajaxForm(Subscribe);
	$(".form_user_unsubscribe").ajaxForm(UnSubscribe);
	$(".form_user_subscribe").each(addAjaxHidden);
	$(".form_user_unsubscribe").each(addAjaxHidden);

	var PostNotice = { dataType: 'xml',
					   beforeSubmit: function(formData, jqForm, options) { if ($("#notice_data-text").get(0).value.length == 0) {
																				$("#form_notice").addClass("warning");
																				return false;
																		   }
																		   $("#form_notice").addClass("processing");
																		   $("#notice_action-submit").attr("disabled", "disabled");
																		   $("#notice_action-submit").addClass("disabled");
																		   return true;
												 						 },
					   timeout: '60000',
					   error: function (xhr, textStatus, errorThrown) {	$("#form_notice").removeClass("processing");
																		$("#notice_action-submit").removeAttr("disabled");
																		$("#notice_action-submit").removeClass("disabled");
																		if (textStatus == "timeout") {
																			alert ("Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists");
																		}
																		else {
																			if ($(".error", xhr.responseXML).length > 0) {
																				$('#form_notice').append(document._importNode($(".error", xhr.responseXML).get(0), true));
																			}
																			else {
																				var HTTP20x30x = [200, 201, 202, 203, 204, 205, 206, 300, 301, 302, 303, 304, 305, 306, 307];
																				if(jQuery.inArray(parseInt(xhr.status), HTTP20x30x) < 0) {
																					alert("Sorry! We had trouble sending your notice ("+xhr.status+" "+xhr.statusText+"). Please report the problem to the site administrator if this happens again.");
																				}
																				else {
																					$("#notice_data-text").val("");
																					counter();
																				}
																			}
																		}
																	  },
					   success: function(xml) {	if ($("#error", xml).length > 0) {
													var result = document._importNode($("p", xml).get(0), true);
													result = result.textContent || result.innerHTML;
													alert(result);
												}
												else {
												    if ($("#command_result", xml).length > 0) {
													    var result = document._importNode($("p", xml).get(0), true);
													    result = result.textContent || result.innerHTML;
													    alert(result);
                                                    }
                                                    else {
                                                         li = $("li", xml).get(0);
                                                         if ($("#"+li.id).length == 0) {
                                                            var notice_irt_value = $('#notice_in-reply-to').val();
                                                            var notice_irt = '#notices_primary #notice-'+notice_irt_value;
                                                            if($('body')[0].id == 'conversation') {
                                                                if(notice_irt_value.length > 0 && $(notice_irt+' .notices').length < 1) {
                                                                    $(notice_irt).append('

');
                                                                }
                                                                $($(notice_irt+' .notices')[0]).append(document._importNode(li, true));
                                                            }
                                                            else {
                                                                $("#notices_primary .notices").prepend(document._importNode(li, true));
                                                            }
                                                            $('#'+li.id).css({display:'none'});
                                                            $('#'+li.id).fadeIn(2500);
                                                            NoticeReply();
                                                            NoticeAttachments();
                                                         }
													}
													$("#notice_data-text").val("");
    												$("#notice_data-attach").val("");
    												$("#notice_in-reply-to").val("");
                                                    $('#notice_data-attach_selected').remove();
                                                    counter();
												}
												$("#form_notice").removeClass("processing");
												$("#notice_action-submit").removeAttr("disabled");
												$("#notice_action-submit").removeClass("disabled");
											 }
					   };
	$("#form_notice").ajaxForm(PostNotice);
	$("#form_notice").each(addAjaxHidden);
    NoticeReply();
    NoticeAttachments();
    NoticeDataAttach();
});

function NoticeReply() {
    if ($('#notice_data-text').length > 0 && $('#content .notice_reply').length > 0) {
        $('#content .notice').each(function() {
            var notice = $(this)[0];
            $($('.notice_reply', notice)[0]).click(function() {
                var nickname = ($('.author .nickname', notice).length > 0) ? $($('.author .nickname', notice)[0]) : $('.author .nickname.uid');
                NoticeReplySet(nickname.text(), $($('.notice_id', notice)[0]).text());
                return false;
            });
        });
    }
}

function NoticeReplySet(nick,id) {
	rgx_username = /^[0-9a-zA-Z\-_.]*$/;
	if (nick.match(rgx_username)) {
		replyto = "@" + nick + " ";
		var text = $("#notice_data-text");
		if (text.length) {
			text.val(replyto + text.val());
			$("#form_notice input#notice_in-reply-to").val(id);
			if (text.get(0).setSelectionRange) {
				var len = text.val().length;
				text.get(0).setSelectionRange(len,len);
				text.get(0).focus();
			}
			return false;
		}
	}
	return true;
}

function NoticeAttachments() {
    $.fn.jOverlay.options = {
        method : 'GET',
        data : '',
        url : '',
        color : '#000',
        opacity : '0.6',
        zIndex : 99,
        center : false,
        imgLoading : $('address .url')[0].href+'theme/base/images/illustrations/illu_progress_loading-01.gif',
        bgClickToClose : true,
        success : function() {
            $('#jOverlayContent').append('<button>×</button>');
            $('#jOverlayContent button').click($.closeOverlay);
        },
        timeout : 0,
        autoHide : true,
        css : {'max-width':'542px', 'top':'5%', 'left':'32.5%'}
    };

    $('#content .notice a.attachment').click(function() {
        $().jOverlay({url: $('address .url')[0].href+'attachment/' + ($(this).attr('id').substring('attachment'.length + 1)) + '/ajax'});
        return false;
    });

    var t;
    $("body:not(#shownotice) #content .notice a.thumbnail").hover(
        function() {
            var anchor = $(this);
            $("a.thumbnail").children('img').hide();
            anchor.closest(".entry-title").addClass('ov');

            if (anchor.children('img').length == 0) {
                t = setTimeout(function() {
                    $.get($('address .url')[0].href+'attachment/' + (anchor.attr('id').substring('attachment'.length + 1)) + '/thumbnail', null, function(data) {
                        anchor.append(data);
                    });
                }, 500);
            }
            else {
                anchor.children('img').show();
            }
        },
        function() {
            clearTimeout(t);
            $("a.thumbnail").children('img').hide();
            $(this).closest(".entry-title").removeClass('ov');
        }
    );
}

function NoticeDataAttach() {
    NDA = $('#notice_data-attach');
    NDA.change(function() {
        S = '
'+$(this).val()+' <button>×</button>
';
        NDAS = $('#notice_data-attach_selected');
        (NDAS.length > 0) ? NDAS.replaceWith(S) : $('#form_notice').append(S);
        $('#notice_data-attach_selected button').click(function(){
            $('#notice_data-attach_selected').remove();
            NDA.val('');
        });
    });
}
<|endoftext|>


<commit_before>"use strict";

define([], function() {
    /**
     * Various utility functions
     */
    var Util = {
        /**
         * We don't need to list en here since that is the default
         */
        supportedLocales: ["boxes", "es", "fr", "pt"],
        /**
         * Returns the phone's locale or null for the default locale (en-US)
         */
        getLang: function() {
            if (!this.isFirefoxOS()) {
                return null;
            }

            // If we're testing via boxes, let that override the current setting
            if (window.translateToBoxes) {
                return "boxes";
            }

            var lang = document.webL10n.getLanguage().substring(0, 2);
            if (this.supportedLocales.indexOf(lang) === -1) {
                return null;
            }
            return lang;
        },
        quit: function() {
            window.close();
        },
        /**
         * Returns true when run within a gaia environment
         */
        isFirefoxOS: function() {
            return window.location.protocol === 'app:';
        },
        /**
         * Determines if the connection is metered (pay per use)
         */
        isMeteredConnection: function() {
            var connection = navigator.connection || navigator.mozConnection;
            if (!connection) {
                return false;
            }
            return connection.metered;
        },
        /**
         * Determines if there's a cap on the bandwidth
         */
        isBandwidthCapped: function() {
            var connection = navigator.connection || navigator.mozConnection;
            if (!connection) {
                return false;
            }
            return connection.bandwidth !== Infinity;
        },
        /**
         * Obtains a URL query parameter
         */
        getParameterByName: function(name, params) {
            if (_.isUndefined(params)) {
                params = window.location.search;
            }
            if (params.length && params[0] !== "?") {
                params = "?" + params;
            }
            var match = RegExp('[?&]' + name + '=([^&]*)').exec(params);
            return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
        },
        /**
         * Adds a query parameter to the specified url
         */
        appendQueryParam: function(url, name, value) {
            if (url.indexOf("?") === -1) {
                url += "?";
            } else {
                url += "&";
            }
            return url + name + "=" + value;
        },
        /**
         * Formats a number with thousand separators
         * http://stackoverflow.com/a/2901298/3153
         */
        numberWithCommas: function(x) {
            if (_.isUndefined(x)) {
                return 0;
            }
            return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
        },
        /**
         * Binds a set of arguments to a function without modifying the bound `this`
         */
        partial: function( fn /*, args...*/) {
          var aps = Array.prototype.slice;
          var args = aps.call(arguments, 1);
          return function() {
              return fn.apply(this, args.concat(aps.call(arguments)));
          };
        },
        // An example generic Mixin that you can add to any component that should react
        // to changes in a Backbone component. The use cases we've identified thus far
        // are for Collections -- since they trigger a change event whenever any of
        // their constituent items are changed there's no need to reconcile for regular
        // models. One caveat: this relies on getBackboneModels() to always return the
        // same model instances throughout the lifecycle of the component. If you're
        // using this mixin correctly (it should be near the top of your component
        // hierarchy) this should not be an issue.
        // https://github.com/facebook/react/blob/1be9a9e/examples/todomvc-backbone/js/app.js#L148-L171
        BackboneMixin : {
          componentDidMount: function() {
            // Whenever there may be a change in the Backbone data, trigger a reconcile.
            this.getBackboneModels().forEach(function(model) {
              model.on('add change remove', this.forceUpdate.bind(this, null), this);
            }, this);
          },

          componentWillUnmount: function() {
            // Ensure that we clean up any dangling references when the component is
            // destroyed.
            this.getBackboneModels().forEach(function(model) {
              model.off(null, null, this);
            }, this);
          }
        },

        LocalizationMixin: {
            componentDidMount: function() {
                window.document.webL10n.translate(this.getDOMNode());
            },
            componentDidUpdate: function() {
                window.document.webL10n.translate(this.getDOMNode());
            }
        }
    };

    return Util;
});
<commit_msg>Add Util method for loading a script file<commit_after>"use strict";

define([], function() {
    /**
     * Various utility functions
     */
    var Util = {
        /**
         * We don't need to list en here since that is the default
         */
        supportedLocales: ["boxes", "es", "fr", "pt"],
        /**
         * Returns the phone's locale or null for the default locale (en-US)
         */
        getLang: function() {
            if (!this.isFirefoxOS()) {
                return null;
            }

            // If we're testing via boxes, let that override the current setting
            if (window.translateToBoxes) {
                return "boxes";
            }

            var lang = document.webL10n.getLanguage().substring(0, 2);
            if (this.supportedLocales.indexOf(lang) === -1) {
                return null;
            }
            return lang;
        },
        quit: function() {
            window.close();
        },
        /**
         * Returns true when run within a gaia environment
         */
        isFirefoxOS: function() {
            return window.location.protocol === 'app:';
        },
        /**
         * Determines if the connection is metered (pay per use)
         */
        isMeteredConnection: function() {
            var connection = navigator.connection || navigator.mozConnection;
            if (!connection) {
                return false;
            }
            return connection.metered;
        },
        /**
         * Determines if there's a cap on the bandwidth
         */
        isBandwidthCapped: function() {
            var connection = navigator.connection || navigator.mozConnection;
            if (!connection) {
                return false;
            }
            return connection.bandwidth !== Infinity;
        },
        /**
         * Obtains a URL query parameter
         */
        getParameterByName: function(name, params) {
            if (_.isUndefined(params)) {
                params = window.location.search;
            }
            if (params.length && params[0] !== "?") {
                params = "?" + params;
            }
            var match = RegExp('[?&]' + name + '=([^&]*)').exec(params);
            return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
        },
        /**
         * Adds a query parameter to the specified url
         */
        appendQueryParam: function(url, name, value) {
            if (url.indexOf("?") === -1) {
                url += "?";
            } else {
                url += "&";
            }
            return url + name + "=" + value;
        },
        /**
         * Formats a number with thousand separators
         * http://stackoverflow.com/a/2901298/3153
         */
        numberWithCommas: function(x) {
            if (_.isUndefined(x)) {
                return 0;
            }
            return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
        },
        /**
         * Binds a set of arguments to a function without modifying the bound `this`
         */
        partial: function( fn /*, args...*/) {
          var aps = Array.prototype.slice;
          var args = aps.call(arguments, 1);
          return function() {
              return fn.apply(this, args.concat(aps.call(arguments)));
          };
        },
        // An example generic Mixin that you can add to any component that should react
        // to changes in a Backbone component. The use cases we've identified thus far
        // are for Collections -- since they trigger a change event whenever any of
        // their constituent items are changed there's no need to reconcile for regular
        // models. One caveat: this relies on getBackboneModels() to always return the
        // same model instances throughout the lifecycle of the component. If you're
        // using this mixin correctly (it should be near the top of your component
        // hierarchy) this should not be an issue.
        // https://github.com/facebook/react/blob/1be9a9e/examples/todomvc-backbone/js/app.js#L148-L171
        BackboneMixin : {
          componentDidMount: function() {
            // Whenever there may be a change in the Backbone data, trigger a reconcile.
            this.getBackboneModels().forEach(function(model) {
              model.on('add change remove', this.forceUpdate.bind(this, null), this);
            }, this);
          },

          componentWillUnmount: function() {
            // Ensure that we clean up any dangling references when the component is
            // destroyed.
            this.getBackboneModels().forEach(function(model) {
              model.off(null, null, this);
            }, this);
          }
        },

        LocalizationMixin: {
            componentDidMount: function() {
                window.document.webL10n.translate(this.getDOMNode());
            },
            componentDidUpdate: function() {
                window.document.webL10n.translate(this.getDOMNode());
            }
        },

        loadScript: function(filename) {
            var d = $.Deferred();
            var s = document.createElement("script");
            s.type = "text/javascript";
            s.src = filename;
            s.onload = () => {
                d.resolve();
            };
            s.onerror = (e) => {
                console.log("on error: %o", e);
                d.reject();
            };
            document.getElementsByTagName("head")[0].appendChild(s);
            return d.promise();
        }
    };

    return Util;
});
<|endoftext|>


<commit_before>var UTIL = {
    v3 : function (x, y, z) {
        return new THREE.Vector3(x, y, z);
    },
    vtx3 : function (x, y, z) {
        return new THREE.Vertex(UTIL.v3(x, y, z));
    },
    v3c : function (radius, theta, z) {
        var Coord = function (_r, _th, _z) {
            this.radius = _r;
            this.theta = _th;
            this.z = _z;
        };
        Coord.prototype.convertToCartesian = function () {
            return UTIL.v3(
                this.radius * Math.cos(this.theta),
                this.radius * Math.sin(this.theta),
                this.z
            );
        };
        return new Coord(radius, theta, z);
    },
    now : function () {
        return new Date().getTime();
    },

    /*
    Image Utils
    var imagedata = getImageData(imgTexture.image);
    var color = getPixel(imagedata, 10, 10);
    */
    getImageData : function (image) {
        var canvas = document.createElement('canvas'),
            context;
        canvas.width = image.width;
        canvas.height = image.height;

        context = canvas.getContext('2d');
        context.drawImage(image, 0, 0);

        return context.getImageData(0, 0, image.width, image.height);
    },
    rgba : function (r, g, b, a) {
        return {
            r: r,
            g: g,
            b: b,
            a: a
        };
    },
    getPixel : function (imagedata, x, y) {
        var data = imagedata.data,
            position = (x + imagedata.width * y) * 4;
        return UTIL.rgba(
            data[position],
            data[position + 1],
            data[position + 2],
            data[position + 3]
        );
    },
    getRow : function (imagedata, r) {
        var position = (imagedata.width * r) * 4,
            data = imagedata.data,
            row = new Array(imagedata.width),
            end = imagedata.width,
            i;
        for (i = 0; i < end; position += 4, i += 1) {
            row[i] = UTIL.rgba(
                data[position],
                data[position + 1],
                data[position + 2],
                data[position + 3]
            );
        }
        return row;
    },
    getColumn : function (imagedata, c) {
        var position = c,
            data = imagedata.data,
            column = new Array(imagedata.height),
            inc = imagedata.width * 4,
            end = imagedata.height,
            i;
        for (i = 0; i < end; position += inc, i += 1) {
            column[i] = UTIL.rgba(
                data[position],
                data[position + 1],
                data[position + 2],
                data[position + 3]
            );
        }
        return column;
    }
};
<commit_msg>corrected getColumn<commit_after>var UTIL = {
    v3 : function (x, y, z) {
        return new THREE.Vector3(x, y, z);
    },
    vtx3 : function (x, y, z) {
        return new THREE.Vertex(UTIL.v3(x, y, z));
    },
    v3c : function (radius, theta, z) {
        var Coord = function (_r, _th, _z) {
            this.radius = _r;
            this.theta = _th;
            this.z = _z;
        };
        Coord.prototype.convertToCartesian = function () {
            return UTIL.v3(
                this.radius * Math.cos(this.theta),
                this.radius * Math.sin(this.theta),
                this.z
            );
        };
        return new Coord(radius, theta, z);
    },
    now : function () {
        return new Date().getTime();
    },

    /*
    Image Utils
    var imagedata = getImageData(imgTexture.image);
    var color = getPixel(imagedata, 10, 10);
    */
    getImageData : function (image) {
        var canvas = document.createElement('canvas'),
            context;
        canvas.width = image.width;
        canvas.height = image.height;

        context = canvas.getContext('2d');
        context.drawImage(image, 0, 0);

        return context.getImageData(0, 0, image.width, image.height);
    },
    rgba : function (r, g, b, a) {
        return {
            r: r,
            g: g,
            b: b,
            a: a
        };
    },
    getPixel : function (imagedata, x, y) {
        var data = imagedata.data,
            position = (x + imagedata.width * y) * 4;
        return UTIL.rgba(
            data[position],
            data[position + 1],
            data[position + 2],
            data[position + 3]
        );
    },
    getRow : function (imagedata, r) {
        var position = (imagedata.width * r) * 4,
            data = imagedata.data,
            row = new Array(imagedata.width),
            end = imagedata.width,
            i;
        for (i = 0; i < end; position += 4, i += 1) {
            row[i] = UTIL.rgba(
                data[position],
                data[position + 1],
                data[position + 2],
                data[position + 3]
            );
        }
        return row;
    },
    getColumn : function (imagedata, c) {
        var position = c * 4,
            data = imagedata.data,
            column = new Array(imagedata.height),
            inc = imagedata.width * 4,
            end = imagedata.height,
            i;
        for (i = 0; i < end; position += inc, i += 1) {
            column[i] = UTIL.rgba(
                data[position],
                data[position + 1],
                data[position + 2],
                data[position + 3]
            );
        }
        return column;
    }
};
<|endoftext|>


<commit_before>function forEach(al, cb){
	if( al )
		for( var i=0, l=al.length; i<l; i++ ) cb(al[i], i, al);
}

function intToSTR4B(i){
	i=i|0;
	var r = String.fromCharCode((i>>24)&0xFF) +
		String.fromCharCode((i>>16)&0xFF) +
		String.fromCharCode((i>> 8)&0xFF) +
		String.fromCharCode( i     &0xFF);
	return r;
}

function intToBuffer(i){
	return Uint8ClampedArray.from([
		(i>>24)&0xFF,
		(i>>16)&0xFF,
		(i>> 8)&0xFF,
		 i     &0xFF
	]);
}

function atoURL(str, mime){
	str=atob(str);
	var arr = new Uint8ClampedArray(str.length), obj = {};
	for(var i=0, l=str.length; i<l; ++i) arr[i] = str.charCodeAt(i) & 0xFF;
	if( mime ) obj.type = mime;
	return URL.createObjectURL(new Blob([arr], obj));
}

function btoURL(str, mime){
	var arr = decbin(str), obj = {};
	if( mime ) obj.type = mime;
	return URL.createObjectURL(new Blob([arr], obj));
}

function decbin(a){var d={65533:0},b,bm;for(b=0;128>b;)d[b]=b++;[10,13,39,92].forEach((c,e)=>{b=a.charCodeAt(e);d[b]=c;d[c]=b});a=a.substr(4);for(var f=new Uint8ClampedArray(a.length/8*7),c=0,g=d[a.charCodeAt(7)],h=0,e=0,k=a.length;e<k;++h,++c)bm=d[a.charCodeAt(e++)],f[h]=bm|(g>>c&1)<<7,6==c&&(e++,g=d[a.charCodeAt(e+7)],c=-1);return f};

function __decbin(str){
	var start = performance.now();
	var map={65533:0}, t;
	for(t=0; t<128;) map[t]=t++;
	[10,13,39,92].forEach((code, pos)=>{
		t=str.charCodeAt(pos);
		map[t]  = code;
		map[code] = t;
	});

	str = str.substr(4);

	var arr = new Uint8ClampedArray(str.length/8*7);
	var ofbc=0, buf = [], c;
	var mask = map[str.charCodeAt(7)];

	for(var j=0, i=0, l=str.length; i<l; ++j, ++ofbc){
		bm = map[str.charCodeAt(i++)];

		arr[j] = bm | (((mask>>ofbc)&1)<<7);

		if(ofbc != 6) continue;
		i++;
		mask = map[str.charCodeAt(i + 7)];
		ofbc = -1;
	}
	var timeDelta = performance.now() - start;
	console.log("decode time:", timeDelta);
	return arr;
}

(function(){
	var STRLUT = [], i, freq = new Uint32Array(127);

self.encbin = function encbin(b){
	"use strict";
	var start = performance.now();

	var LUT = STRLUT, acc = "'", i=0, l=b.length, c;
	var ofbc=7, ofbacc=0, map={65533:0};

	for(i=0;i<=0x7F;++i)
		STRLUT[i] = String.fromCharCode(i);
	STRLUT[10] = "\\n";
	STRLUT[13] = "\\r";
	STRLUT[39] = "\\'";
	STRLUT[92] = "\\\\";

	freq.fill(0);
	while( i < l ){
		c = b.charCodeAt(i++);
		ofbacc |= (((c&0x80)>>7)<<(7-ofbc));
		freq[c&0x7F]++;

		if(--ofbc) continue;
		ofbc=7;
		c = ofbacc;
		freq[c]++;
		ofbacc = 0;
	}

	ofbacc = 0;
	ofbc = 7;

	var lf=[freq[0]], lfp=[0];
	for(i=1; i < 127; ++i ){
		var freqi = freq[i];
		for(var j=0; j<4; ++j ){
			if( !(freqi >= lf[j]) && STRLUT[i].length==1 ){
				for(var k=3; k>j; --k){
					lf[k]=lf[k-1];
					lfp[k]=lfp[k-1];
				}
				lf[j]=freqi;
				lfp[j]=i;
				break;
			}
		}
	}

	var specials = [10, 13, 39, 92];
	specials.sort(
		(a,b) => freq[a] - freq[b]
	).forEach((k,i) => {
		var t = LUT[k];
		LUT[k] = LUT[lfp[i]];
		LUT[lfp[i]] = t;
	});
	// console.log("LF / LFP:", lf, lfp, specials, specials.map(k => freq[k]));

	acc += LUT[10] + LUT[13] + LUT[39] + LUT[92];

	i=0;
	while( i < l ){
		c = b.charCodeAt(i++);
		ofbacc |= (((c&0x80)>>7)<<(7-ofbc));
		acc += LUT[c&0x7F];
		if(--ofbc) continue;
		ofbc=7;
		acc += LUT[ofbacc];
		ofbacc = 0;
	}

	while(ofbc--)
		acc += "\0";
	acc += LUT[ofbacc] + "'";

	var timeDelta = performance.now() - start;
	console.log("encbin: final size:", acc.length, " input size:", l, "("+ Math.floor(acc.length / l * 100) + "%)", " time:", timeDelta);

	// start = performance.now();
	// var b64 = btoa(b);
	// timeDelta = performance.now() - start;
	// console.log("base64:", b64.length, " addslashes:", Math.floor(acc.length / b64.length * 100) + "%", "time:", timeDelta);

	return acc;
}
})();

function strToBuffer(str){
	var arr = new Uint8ClampedArray(str.length);
	for(var i=0, l=str.length; i<l; ++i) arr[i] = str.charCodeAt(i);
	return arr;
}

function bufferToStr(buf, encoding){
	var dataView = new DataView(buf);
	var decoder = new TextDecoder(encoding || "utf-8");
	return decoder.decode(dataView);
}

(function(){
	var map = {};

	self.arrayToBlobURL = function arrayToBlobURL( array, name, cfg ){
		if( map[name] )
			URL.revokeObjectURL( map[name] );

		if( typeof array == "string" )
			array = strToBuffer(array);

		if( array == null )
			return map[name] = null;

		return map[name] = URL.createObjectURL( new Blob([array], cfg||{}) );
	}
})();

function base64toBlob(base64Data, contentType, sliceSize) {

    var byteCharacters,
        byteArray,
        byteNumbers,
        blobData,
        blob;

    contentType = contentType || '';

    byteCharacters = atob(base64Data);

    // Get blob data sliced or not
    blobData = sliceSize ? getBlobDataSliced() : getBlobDataAtOnce();

    blob = new Blob(blobData, { type: contentType });

    return blob;

    /*
     * Get blob data in one slice.
     * => Fast in IE on new Blob(...)
     */
    function getBlobDataAtOnce() {
        byteNumbers = new Array(byteCharacters.length);

        for (var i = 0; i < byteCharacters.length; i++) {
            byteNumbers[i] = byteCharacters.charCodeAt(i);
        }

        byteArray = new Uint8Array(byteNumbers);

        return [byteArray];
    }

    /*
     * Get blob data in multiple slices.
     * => Slow in IE on new Blob(...)
     */
    function getBlobDataSliced() {

        var slice,
            byteArrays = [];

        for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
            slice = byteCharacters.slice(offset, offset + sliceSize);

            byteNumbers = new Array(slice.length);

            for (var i = 0; i < slice.length; i++) {
                byteNumbers[i] = slice.charCodeAt(i);
            }

            byteArray = new Uint8Array(byteNumbers);

            // Add slice
            byteArrays.push(byteArray);
        }

        return byteArrays;
    }
}

function distance( x1, y1, x2, y2 ){
	x1 -= x2;
	y1 -= y2;
	return Math.sqrt( x1*x1+y1*y1 );
}

function UUID(){
	var id = [];
	for( var i=0; i<5; ++i )
		id[i] = Math.floor( Math.random() * 0x7FFFFFFF ).toString(36);
	return id.join("_");
};<commit_msg>must discard padding in encbin/decbin.<commit_after>function forEach(al, cb){
	if( al )
		for( var i=0, l=al.length; i<l; i++ ) cb(al[i], i, al);
}

function intToSTR4B(i){
	i=i|0;
	var r = String.fromCharCode((i>>24)&0xFF) +
		String.fromCharCode((i>>16)&0xFF) +
		String.fromCharCode((i>> 8)&0xFF) +
		String.fromCharCode( i     &0xFF);
	return r;
}

function intToBuffer(i){
	return Uint8ClampedArray.from([
		(i>>24)&0xFF,
		(i>>16)&0xFF,
		(i>> 8)&0xFF,
		 i     &0xFF
	]);
}

function atoURL(str, mime){
	str=atob(str);
	var arr = new Uint8ClampedArray(str.length), obj = {};
	for(var i=0, l=str.length; i<l; ++i) arr[i] = str.charCodeAt(i) & 0xFF;
	if( mime ) obj.type = mime;
	return URL.createObjectURL(new Blob([arr], obj));
}

function btoURL(str, mime){
	var arr = decbin(str), obj = {};
	if( mime ) obj.type = mime;
	return URL.createObjectURL(new Blob([arr], obj));
}

function decbin(l,a){var d={65533:0},b,bm;for(b=0;128>b;)d[b]=b++;[10,13,39,92].forEach((c,e)=>{b=a.charCodeAt(e);d[b]=c;d[c]=b});a=a.substr(4);for(var f=new Uint8ClampedArray(l),c=0,g=d[a.charCodeAt(7)],h=0,e=0,k=a.length;e<k;++h,++c)bm=d[a.charCodeAt(e++)],f[h]=bm|(g>>c&1)<<7,6==c&&(e++,g=d[a.charCodeAt(e+7)],c=-1);return f};

function __decbin(len,str){
	var start = performance.now();
	var map={65533:0}, t;
	for(t=0; t<128;) map[t]=t++;
	[10,13,39,92].forEach((code, pos)=>{
		t=str.charCodeAt(pos);
		map[t]  = code;
		map[code] = t;
	});

	str = str.substr(4);

	var arr = new Uint8ClampedArray(len);
	var ofbc=0, buf = [], c;
	var mask = map[str.charCodeAt(7)];

	for(var j=0, i=0, l=str.length; i<l; ++j, ++ofbc){
		bm = map[str.charCodeAt(i++)];

		arr[j] = bm | (((mask>>ofbc)&1)<<7);

		if(ofbc != 6) continue;
		i++;
		mask = map[str.charCodeAt(i + 7)];
		ofbc = -1;
	}
	var timeDelta = performance.now() - start;
	console.log("decode time:", timeDelta);
	return arr;
}

(function(){
	var STRLUT = [], i, freq = new Uint32Array(127);

self.encbin = function encbin(b){
	"use strict";
	var start = performance.now();

	var LUT = STRLUT, acc = "'", i=0, l=b.length, c;
	var ofbc=7, ofbacc=0, map={65533:0};

	for(i=0;i<=0x7F;++i)
		STRLUT[i] = String.fromCharCode(i);
	STRLUT[10] = "\\n";
	STRLUT[13] = "\\r";
	STRLUT[39] = "\\'";
	STRLUT[92] = "\\\\";

	freq.fill(0);
	while( i < l ){
		c = b.charCodeAt(i++);
		ofbacc |= (((c&0x80)>>7)<<(7-ofbc));
		freq[c&0x7F]++;

		if(--ofbc) continue;
		ofbc=7;
		c = ofbacc;
		freq[c]++;
		ofbacc = 0;
	}

	ofbacc = 0;
	ofbc = 7;

	var lf=[freq[0]], lfp=[0];
	for(i=1; i < 127; ++i ){
		var freqi = freq[i];
		for(var j=0; j<4; ++j ){
			if( !(freqi >= lf[j]) && STRLUT[i].length==1 ){
				for(var k=3; k>j; --k){
					lf[k]=lf[k-1];
					lfp[k]=lfp[k-1];
				}
				lf[j]=freqi;
				lfp[j]=i;
				break;
			}
		}
	}

	var specials = [10, 13, 39, 92];
	specials.sort(
		(a,b) => freq[a] - freq[b]
	).forEach((k,i) => {
		var t = LUT[k];
		LUT[k] = LUT[lfp[i]];
		LUT[lfp[i]] = t;
	});
	// console.log("LF / LFP:", lf, lfp, specials, specials.map(k => freq[k]));

	acc += LUT[10] + LUT[13] + LUT[39] + LUT[92];

	i=0;
	while( i < l ){
		c = b.charCodeAt(i++);
		ofbacc |= (((c&0x80)>>7)<<(7-ofbc));
		acc += LUT[c&0x7F];
		if(--ofbc) continue;
		ofbc=7;
		acc += LUT[ofbacc];
		ofbacc = 0;
	}

	while(ofbc--)
		acc += "\0";
	acc += LUT[ofbacc] + "'";

	var timeDelta = performance.now() - start;
	console.log("encbin: final size:", acc.length, " input size:", l, "("+ Math.floor(acc.length / l * 100) + "%)", " time:", timeDelta);

	// start = performance.now();
	// var b64 = btoa(b);
	// timeDelta = performance.now() - start;
	// console.log("base64:", b64.length, " addslashes:", Math.floor(acc.length / b64.length * 100) + "%", "time:", timeDelta);

	return l+","+acc;
}
})();

function strToBuffer(str){
	var arr = new Uint8ClampedArray(str.length);
	for(var i=0, l=str.length; i<l; ++i) arr[i] = str.charCodeAt(i);
	return arr;
}

function bufferToStr(buf, encoding){
	var dataView = new DataView(buf);
	var decoder = new TextDecoder(encoding || "utf-8");
	return decoder.decode(dataView);
}

(function(){
	var map = {};

	self.arrayToBlobURL = function arrayToBlobURL( array, name, cfg ){
		if( map[name] )
			URL.revokeObjectURL( map[name] );

		if( typeof array == "string" )
			array = strToBuffer(array);

		if( array == null )
			return map[name] = null;

		return map[name] = URL.createObjectURL( new Blob([array], cfg||{}) );
	}
})();

function base64toBlob(base64Data, contentType, sliceSize) {

    var byteCharacters,
        byteArray,
        byteNumbers,
        blobData,
        blob;

    contentType = contentType || '';

    byteCharacters = atob(base64Data);

    // Get blob data sliced or not
    blobData = sliceSize ? getBlobDataSliced() : getBlobDataAtOnce();

    blob = new Blob(blobData, { type: contentType });

    return blob;

    /*
     * Get blob data in one slice.
     * => Fast in IE on new Blob(...)
     */
    function getBlobDataAtOnce() {
        byteNumbers = new Array(byteCharacters.length);

        for (var i = 0; i < byteCharacters.length; i++) {
            byteNumbers[i] = byteCharacters.charCodeAt(i);
        }

        byteArray = new Uint8Array(byteNumbers);

        return [byteArray];
    }

    /*
     * Get blob data in multiple slices.
     * => Slow in IE on new Blob(...)
     */
    function getBlobDataSliced() {

        var slice,
            byteArrays = [];

        for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
            slice = byteCharacters.slice(offset, offset + sliceSize);

            byteNumbers = new Array(slice.length);

            for (var i = 0; i < slice.length; i++) {
                byteNumbers[i] = slice.charCodeAt(i);
            }

            byteArray = new Uint8Array(byteNumbers);

            // Add slice
            byteArrays.push(byteArray);
        }

        return byteArrays;
    }
}

function distance( x1, y1, x2, y2 ){
	x1 -= x2;
	y1 -= y2;
	return Math.sqrt( x1*x1+y1*y1 );
}

function UUID(){
	var id = [];
	for( var i=0; i<5; ++i )
		id[i] = Math.floor( Math.random() * 0x7FFFFFFF ).toString(36);
	return id.join("_");
};<|endoftext|>


<commit_before>require('dotenv').config();

if (!process.env.SONGKICK_API_KEY) {
  return console.error('❗ Failed to load in the SONGKICK_API_KEY. Is it missing from the `.env` file?');
}

const fetch = require('node-fetch');
const getColors = require('get-image-colors');

const low = require('lowdb');
const FileSync = require('lowdb/adapters/FileSync');
const adapter = new FileSync('data/db.json');
const db = low(adapter);

// set some defaults if database file is empty
db.defaults({ colors: [] }).write();

const getColor = (buffer) => new Promise(resolve => {
  getColors(buffer, 'image/jpeg')
    .then(colors => colors[0]._rgb)
    .then(color => {
      resolve(`rgb(${color.slice(0, -1).join(',')})`);
    })
    .catch(error => {
      // console.error(error);
      resolve(false);
    });
});

const handleColors = (id, imageUrl) => {
  // check if we already have the colour
  const colorsItem = db.get('colors').find({ id }).value();
  if (colorsItem) {
    return colorsItem.color;
  }

  // get color for next time
  fetch(imageUrl.replace('large_avatar', 'medium_avatar'))
    .then(response => response.buffer())
    .then(getColor)
    .then(color => {
      // add new color to database file
      db.get('colors').push({ id, color }).write();
    });

  return false;
};

const uriPrefix = 'https://api.songkick.com/api/3.0/users';

const apiKey = process.env.SONGKICK_API_KEY;

const loadData = (options) => new Promise((resolve, reject) => {
  if (!options.uri) {
    return reject('No uri');
  }

  const uri = options.uri;
  const page = options.page || 1;
  const maxPageAmount = 3;

  return fetch(`${uri}&page=${page}`)
    .then(response => response.json())
    .then(data => {
      if (!data.resultsPage || data.resultsPage.totalEntries <= 0) {
        return reject('No results');
      }

      let pageAmount = Math.ceil(data.resultsPage.totalEntries / data.resultsPage.perPage);

      // dont download the entire world
      if (pageAmount > maxPageAmount) {
        pageAmount = maxPageAmount;
      }

      if (data.resultsPage.page !== pageAmount) {
        return loadData({ uri, page: page + 1 })
          .then(newData => {
            if (typeof data.resultsPage.results.artist !== 'undefined') {
              data.resultsPage.results.artist = data.resultsPage.results.artist.concat(newData.resultsPage.results.artist);
            }

            if (typeof data.resultsPage.results.calendarEntry !== 'undefined') {
              data.resultsPage.results.calendarEntry = data.resultsPage.results.calendarEntry.concat(newData.resultsPage.results.calendarEntry);
            }

            return resolve(data);
          });
      }

      return resolve(data);
    })
    .catch(reject);
});

const getResults = (data) => data.resultsPage.results;

const getEvents = (data) => new Promise((resolve, reject) => {
  if (data.calendarEntry.length <= 0) {
    return reject('No events');
  }

  const events = data.calendarEntry.map(entry => {
    const event = entry.event;
    event.reason = entry.reason;
    return event;
  });

  resolve(events);
});

const getImage = (data) => {
  const IMAGE_PREFIX = 'https://images.sk-static.com/images/media/profile_images';

  if (typeof data.billing !== 'undefined' ) {
    return `${IMAGE_PREFIX}/artists/${data.artist.id}/large_avatar`;
  }

  if (data.type === 'Festival') {
    return `${IMAGE_PREFIX}/events/${data.id}/large_avatar`;
  }

  if (data.performance && data.performance.length > 0) {
    return `${IMAGE_PREFIX}/artists/${data.performance[0].artist.id}/large_avatar`;
  }

  return '';
};

const processPerformances = (performances) => {
  return performances.map(performance => {
    const imageSrc = getImage(performance);
    const imageColor = handleColors(performance.artist.id, imageSrc);

    return {
      id: performance.artist.id,
      type: performance.billing,
      name: performance.artist.displayName,
      image: {
        color: imageColor,
        src: imageSrc
      }
    };
  });
};

function getOrdinal(n) {
  const s = ['th', 'st', 'nd', 'rd'];
  const v = n % 100;
  return s[(v - 20) % 10] || s[v] || s[0];
}

function formatDate(date, type) {
  date = date.trim(); // trim whitespace

  // if we only have the year add some time
  if (date.length === 10) {
    date += ' 00:00:00';
  }

  // replace - with /
  date = date.replace(/-/g, "/");

  // convert strings to date objects
  date = new Date(date);

  const monthNames = [
    'January', 'February', 'March',
    'April', 'May', 'June', 'July',
    'August', 'September', 'October',
    'November', 'December'
  ];

  let amPm = 'AM';
  let minutes = date.getMinutes();

  if (minutes < 10) {
    minutes = '0' + minutes;
  }

  let hours = date.getHours();

  if (hours >= 12) {
    hours -= 12;
    amPm = 'PM';
  }

  const dateString = date.toDateString();
  const dayName = dateString.split(' ')[0];
  const day = date.getDate();
  const dayWithOrdinal = `${day}${getOrdinal(day)}`;
  const monthIndex = date.getMonth();
  const month = monthNames[monthIndex];
  const year = date.getFullYear();

  if (type === 'long') {
    return `${dayName} ${dayWithOrdinal} ${month} ${year}`;
  } else if ( type === 'short') {
    return `${dayName} ${dayWithOrdinal} ${month.substr(0, 3)} `;
  } else if ( type === 'time') {
    return `${hours}:${minutes} ${amPm}`;
  }

  return dateString;
}

const processEvents = (events) => events.map(event => {
  const date = `${event.start.date} ${event.start.time || ''}`;
  const imageSrc = getImage(event);
  const imageColor = handleColors(event.id, imageSrc);
  const newEvent = {
    id: event.id,
    reason: event.reason,
    type: event.type.toLowerCase(),
    performances: processPerformances(event.performance),
    time: {
      iso: date,
      pretty: {
        short: date ? formatDate(date, 'short') : 'Date TBC',
        full:  date ? formatDate(date, 'long') : 'Date to be confirmed',
        doors: date ? formatDate(date, 'time') : 'Doors to be confirmed'
      }
    },
    place: {
      name: event.venue.displayName,
      address: `${event.venue.displayName}, ${event.location.city}`,
      id: event.venue.id,
      uri: event.venue.uri,
      lat: event.venue.lat,
      lon: event.venue.lng
    },
    image: {
      color: imageColor,
      src: imageSrc
    },
    uri: event.uri
  };

  if (event.status === 'cancelled') {
    newEvent.cancelled = true;
  }

  if (newEvent.type === 'festival') {
    newEvent.title = event.displayName;
  }

  return newEvent;
});

function sortUniqueResults(arr) {
  if (arr.length === 0) {
    return arr;
  }

  // sort by id for removing duplicates
  arr = arr.sort((a, b) => {
    return a.id - b.id;
  });

  const newArr = [arr[0]];

  for (let i = 1; i < arr.length; i++) { // start loop at 1 as element 0 can never be a duplicate
    if (arr[i - 1].id !== arr[i].id) {
      newArr.push(arr[i]);
    }
  }

  arr = newArr;

  // sort by date
  arr = arr.sort((a, b) => {
    return new Date(a.start.date) - new Date(b.start.date);
  });

  return arr;
}

function events(username) {
  return new Promise((resolve, reject) => {
    let uri = `${uriPrefix}/${username}/calendar.json?apikey=${apiKey}&reason=attendance`;
    const events = loadData({ uri }).then(getResults).then(getEvents);

    uri = `${uriPrefix}/${username}/calendar.json?apikey=${apiKey}&reason=tracked_artist`;
    const upcomingEvents = loadData({ uri }).then(getResults).then(getEvents);

    Promise.all([upcomingEvents, events]).then(results => {
      results = [].concat(...results);
      results = sortUniqueResults(results);

      resolve(processEvents(results));
    }).catch(reject);
  });
}

module.exports = {
  events
};
<commit_msg>Exit correctly in Songkick file if no ENV<commit_after>require('dotenv').config();

if (!process.env.SONGKICK_API_KEY) {
  console.error('❗ Failed to load in the SONGKICK_API_KEY. Is it missing from the `.env` file?');
  process.exit();
}

const fetch = require('node-fetch');
const getColors = require('get-image-colors');

const low = require('lowdb');
const FileSync = require('lowdb/adapters/FileSync');
const adapter = new FileSync('data/db.json');
const db = low(adapter);

// set some defaults if database file is empty
db.defaults({ colors: [] }).write();

const getColor = (buffer) => new Promise(resolve => {
  getColors(buffer, 'image/jpeg')
    .then(colors => colors[0]._rgb)
    .then(color => {
      resolve(`rgb(${color.slice(0, -1).join(',')})`);
    })
    .catch(error => {
      // console.error(error);
      resolve(false);
    });
});

const handleColors = (id, imageUrl) => {
  // check if we already have the colour
  const colorsItem = db.get('colors').find({ id }).value();
  if (colorsItem) {
    return colorsItem.color;
  }

  // get color for next time
  fetch(imageUrl.replace('large_avatar', 'medium_avatar'))
    .then(response => response.buffer())
    .then(getColor)
    .then(color => {
      // add new color to database file
      db.get('colors').push({ id, color }).write();
    });

  return false;
};

const uriPrefix = 'https://api.songkick.com/api/3.0/users';

const apiKey = process.env.SONGKICK_API_KEY;

const loadData = (options) => new Promise((resolve, reject) => {
  if (!options.uri) {
    return reject('No uri');
  }

  const uri = options.uri;
  const page = options.page || 1;
  const maxPageAmount = 3;

  return fetch(`${uri}&page=${page}`)
    .then(response => response.json())
    .then(data => {
      if (!data.resultsPage || data.resultsPage.totalEntries <= 0) {
        return reject('No results');
      }

      let pageAmount = Math.ceil(data.resultsPage.totalEntries / data.resultsPage.perPage);

      // dont download the entire world
      if (pageAmount > maxPageAmount) {
        pageAmount = maxPageAmount;
      }

      if (data.resultsPage.page !== pageAmount) {
        return loadData({ uri, page: page + 1 })
          .then(newData => {
            if (typeof data.resultsPage.results.artist !== 'undefined') {
              data.resultsPage.results.artist = data.resultsPage.results.artist.concat(newData.resultsPage.results.artist);
            }

            if (typeof data.resultsPage.results.calendarEntry !== 'undefined') {
              data.resultsPage.results.calendarEntry = data.resultsPage.results.calendarEntry.concat(newData.resultsPage.results.calendarEntry);
            }

            return resolve(data);
          });
      }

      return resolve(data);
    })
    .catch(reject);
});

const getResults = (data) => data.resultsPage.results;

const getEvents = (data) => new Promise((resolve, reject) => {
  if (data.calendarEntry.length <= 0) {
    return reject('No events');
  }

  const events = data.calendarEntry.map(entry => {
    const event = entry.event;
    event.reason = entry.reason;
    return event;
  });

  resolve(events);
});

const getImage = (data) => {
  const IMAGE_PREFIX = 'https://images.sk-static.com/images/media/profile_images';

  if (typeof data.billing !== 'undefined' ) {
    return `${IMAGE_PREFIX}/artists/${data.artist.id}/large_avatar`;
  }

  if (data.type === 'Festival') {
    return `${IMAGE_PREFIX}/events/${data.id}/large_avatar`;
  }

  if (data.performance && data.performance.length > 0) {
    return `${IMAGE_PREFIX}/artists/${data.performance[0].artist.id}/large_avatar`;
  }

  return '';
};

const processPerformances = (performances) => {
  return performances.map(performance => {
    const imageSrc = getImage(performance);
    const imageColor = handleColors(performance.artist.id, imageSrc);

    return {
      id: performance.artist.id,
      type: performance.billing,
      name: performance.artist.displayName,
      image: {
        color: imageColor,
        src: imageSrc
      }
    };
  });
};

function getOrdinal(n) {
  const s = ['th', 'st', 'nd', 'rd'];
  const v = n % 100;
  return s[(v - 20) % 10] || s[v] || s[0];
}

function formatDate(date, type) {
  date = date.trim(); // trim whitespace

  // if we only have the year add some time
  if (date.length === 10) {
    date += ' 00:00:00';
  }

  // replace - with /
  date = date.replace(/-/g, "/");

  // convert strings to date objects
  date = new Date(date);

  const monthNames = [
    'January', 'February', 'March',
    'April', 'May', 'June', 'July',
    'August', 'September', 'October',
    'November', 'December'
  ];

  let amPm = 'AM';
  let minutes = date.getMinutes();

  if (minutes < 10) {
    minutes = '0' + minutes;
  }

  let hours = date.getHours();

  if (hours >= 12) {
    hours -= 12;
    amPm = 'PM';
  }

  const dateString = date.toDateString();
  const dayName = dateString.split(' ')[0];
  const day = date.getDate();
  const dayWithOrdinal = `${day}${getOrdinal(day)}`;
  const monthIndex = date.getMonth();
  const month = monthNames[monthIndex];
  const year = date.getFullYear();

  if (type === 'long') {
    return `${dayName} ${dayWithOrdinal} ${month} ${year}`;
  } else if ( type === 'short') {
    return `${dayName} ${dayWithOrdinal} ${month.substr(0, 3)} `;
  } else if ( type === 'time') {
    return `${hours}:${minutes} ${amPm}`;
  }

  return dateString;
}

const processEvents = (events) => events.map(event => {
  const date = `${event.start.date} ${event.start.time || ''}`;
  const imageSrc = getImage(event);
  const imageColor = handleColors(event.id, imageSrc);
  const newEvent = {
    id: event.id,
    reason: event.reason,
    type: event.type.toLowerCase(),
    performances: processPerformances(event.performance),
    time: {
      iso: date,
      pretty: {
        short: date ? formatDate(date, 'short') : 'Date TBC',
        full:  date ? formatDate(date, 'long') : 'Date to be confirmed',
        doors: date ? formatDate(date, 'time') : 'Doors to be confirmed'
      }
    },
    place: {
      name: event.venue.displayName,
      address: `${event.venue.displayName}, ${event.location.city}`,
      id: event.venue.id,
      uri: event.venue.uri,
      lat: event.venue.lat,
      lon: event.venue.lng
    },
    image: {
      color: imageColor,
      src: imageSrc
    },
    uri: event.uri
  };

  if (event.status === 'cancelled') {
    newEvent.cancelled = true;
  }

  if (newEvent.type === 'festival') {
    newEvent.title = event.displayName;
  }

  return newEvent;
});

function sortUniqueResults(arr) {
  if (arr.length === 0) {
    return arr;
  }

  // sort by id for removing duplicates
  arr = arr.sort((a, b) => {
    return a.id - b.id;
  });

  const newArr = [arr[0]];

  for (let i = 1; i < arr.length; i++) { // start loop at 1 as element 0 can never be a duplicate
    if (arr[i - 1].id !== arr[i].id) {
      newArr.push(arr[i]);
    }
  }

  arr = newArr;

  // sort by date
  arr = arr.sort((a, b) => {
    return new Date(a.start.date) - new Date(b.start.date);
  });

  return arr;
}

function events(username) {
  return new Promise((resolve, reject) => {
    let uri = `${uriPrefix}/${username}/calendar.json?apikey=${apiKey}&reason=attendance`;
    const events = loadData({ uri }).then(getResults).then(getEvents);

    uri = `${uriPrefix}/${username}/calendar.json?apikey=${apiKey}&reason=tracked_artist`;
    const upcomingEvents = loadData({ uri }).then(getResults).then(getEvents);

    Promise.all([upcomingEvents, events]).then(results => {
      results = [].concat(...results);
      results = sortUniqueResults(results);

      resolve(processEvents(results));
    }).catch(reject);
  });
}

module.exports = {
  events
};
<|endoftext|>


<commit_before>document.observe("dom:loaded", function() {
  if($('asset-bucket')){
    new Draggable('asset-bucket', { starteffect: false, endeffect: false });
  }
  if($('page-attachments')){
    Asset.ChooseTabByName('page-attachments');
  }
});

var Asset = {};

Asset.Tabs = Behavior.create({
  onclick: function(e){
    e.stop();
    Asset.ChooseTab(this.element);
  }
});

// factored out so that it can be called in an ajax response

Asset.ChooseTab = function (element) {
  var pane = $(element.href.split('#')[1]);
  var panes = $('assets').select('.pane');

  var tabs = $('asset-tabs').select('.asset-tab');
  tabs.each(function(tab) {tab.removeClassName('here');});

  element.addClassName('here');;
  panes.each(function(pane) {Element.hide(pane);});
  Element.show($(pane));
}

Asset.ChooseTabByName = function (tabname) {
  var element = $('tab_' + tabname);
  Asset.ChooseTab(element);
}

// factored out so that it can be called after new page part creation

Asset.MakeDraggables = function () {
  $$('div.asset').each(function(element){
    new Draggable(element, { revert: true });
    element.addClassName('move');
  });
}

Asset.DisableLinks = Behavior.create({
  onclick: function(e){
    e.stop();
  }
});

Asset.AddToPage = Behavior.create({
  onclick: function(e){
    e.stop();
    url = this.element.href;
    new Ajax.Updater('attachments', url, {
      asynchronous : true,
      evalScripts  : true,
      method       : 'get'
      // onComplete   : Element.highlight('page-attachments')
    });

  }
});

Asset.MakeDroppables = function () {
  $$('.textarea').each(function(box){
    if (!box.hasClassName('droppable')) {
      Droppables.add(box, {
        accept: 'asset',
        onDrop: function(element) {
          var link = element.select('a.bucket_link')[0];
          var asset_id = element.id.split('_').last();
          var classes = element.className.split(' ');
          var tag_type = classes[0];
          var tag = '<r:assets:' + tag_type + ' id="' + asset_id + '" size="original" />';
          //Form.Element.focus(box);
        	if(!!document.selection){
        		box.focus();
        		var range = (box.range) ? box.range : document.selection.createRange();
        		range.text = tag;
        		range.select();
        	}else if(!!box.setSelectionRange){
        		var selection_start = box.selectionStart;
        		box.value = box.value.substring(0,selection_start) + tag + box.value.substring(box.selectionEnd);
        		box.setSelectionRange(selection_start + tag.length,selection_start + tag.length);
        	}
        	box.focus();
        }
      });
    	box.addClassName('droppable');
    }
  });
}

Asset.ShowBucket = Behavior.create({
  onclick: function(e){
    e.stop();
    var element = $('asset-bucket');
    center(element);
    element.toggle();
    Asset.MakeDroppables();
  }
});

Asset.HideBucket = Behavior.create({
  onclick: function(e){
    e.stop();
    var element = $('asset-bucket');
    element.hide();
  }
});

Asset.FileTypes = Behavior.create({
  onclick: function(e){
    e.stop();
    var element = this.element;
    var type_id = element.text.downcase();
    var type_check = $(type_id + '-check');
    var search_form = $('filesearchform');
    if(element.hasClassName('pressed')) {
      element.removeClassName('pressed');
      type_check.removeAttribute('checked');
    } else {
      element.addClassName('pressed');
      type_check.setAttribute('checked', 'checked');
    }
    new Ajax.Updater('assets_table', search_form.action, {
      asynchronous: true,
      evalScripts:  true,
      parameters:   Form.serialize(search_form),
      method: 'get',
      onComplete: 'assets_table'
    });
  }
});

Asset.WaitingForm = Behavior.create({
  onsubmit: function(e){
    this.element.addClassName('waiting');
    return true;
  }
});

Asset.ResetForm = function (name) {
  var element = $('asset-upload');
  element.removeClassName('waiting');
  element.reset();
}

Asset.AddAsset = function (name) {
  element = $(name);
  asset = element.select('.asset')[0];
  console.log('inserted element is ', element);
  console.log('contained asset is ', asset);
  if (asset) {
    new Draggable(asset, { revert: true });
  }
}

Event.addBehavior({
  '#asset-tabs a'     : Asset.Tabs,
  '#close-link a'     : Asset.HideBucket,
  '#show-bucket a'    : Asset.ShowBucket,
  '#filesearchform a' : Asset.FileTypes,
  '#asset-upload'     : Asset.WaitingForm,
  'div.asset a'       : Asset.DisableLinks,
  'a.add_asset'       : Asset.AddToPage
});
<commit_msg>Don't log to a non-existant console<commit_after>document.observe("dom:loaded", function() {
  if($('asset-bucket')){
    new Draggable('asset-bucket', { starteffect: false, endeffect: false });
  }
  if($('page-attachments')){
    Asset.ChooseTabByName('page-attachments');
  }
});

var Asset = {};

Asset.Tabs = Behavior.create({
  onclick: function(e){
    e.stop();
    Asset.ChooseTab(this.element);
  }
});

// factored out so that it can be called in an ajax response

Asset.ChooseTab = function (element) {
  var pane = $(element.href.split('#')[1]);
  var panes = $('assets').select('.pane');

  var tabs = $('asset-tabs').select('.asset-tab');
  tabs.each(function(tab) {tab.removeClassName('here');});

  element.addClassName('here');;
  panes.each(function(pane) {Element.hide(pane);});
  Element.show($(pane));
}

Asset.ChooseTabByName = function (tabname) {
  var element = $('tab_' + tabname);
  Asset.ChooseTab(element);
}

// factored out so that it can be called after new page part creation

Asset.MakeDraggables = function () {
  $$('div.asset').each(function(element){
    new Draggable(element, { revert: true });
    element.addClassName('move');
  });
}

Asset.DisableLinks = Behavior.create({
  onclick: function(e){
    e.stop();
  }
});

Asset.AddToPage = Behavior.create({
  onclick: function(e){
    e.stop();
    url = this.element.href;
    new Ajax.Updater('attachments', url, {
      asynchronous : true,
      evalScripts  : true,
      method       : 'get'
      // onComplete   : Element.highlight('page-attachments')
    });

  }
});

Asset.MakeDroppables = function () {
  $$('.textarea').each(function(box){
    if (!box.hasClassName('droppable')) {
      Droppables.add(box, {
        accept: 'asset',
        onDrop: function(element) {
          var link = element.select('a.bucket_link')[0];
          var asset_id = element.id.split('_').last();
          var classes = element.className.split(' ');
          var tag_type = classes[0];
          var tag = '<r:assets:' + tag_type + ' id="' + asset_id + '" size="original" />';
          //Form.Element.focus(box);
        	if(!!document.selection){
        		box.focus();
        		var range = (box.range) ? box.range : document.selection.createRange();
        		range.text = tag;
        		range.select();
        	}else if(!!box.setSelectionRange){
        		var selection_start = box.selectionStart;
        		box.value = box.value.substring(0,selection_start) + tag + box.value.substring(box.selectionEnd);
        		box.setSelectionRange(selection_start + tag.length,selection_start + tag.length);
        	}
        	box.focus();
        }
      });
    	box.addClassName('droppable');
    }
  });
}

Asset.ShowBucket = Behavior.create({
  onclick: function(e){
    e.stop();
    var element = $('asset-bucket');
    center(element);
    element.toggle();
    Asset.MakeDroppables();
  }
});

Asset.HideBucket = Behavior.create({
  onclick: function(e){
    e.stop();
    var element = $('asset-bucket');
    element.hide();
  }
});

Asset.FileTypes = Behavior.create({
  onclick: function(e){
    e.stop();
    var element = this.element;
    var type_id = element.text.downcase();
    var type_check = $(type_id + '-check');
    var search_form = $('filesearchform');
    if(element.hasClassName('pressed')) {
      element.removeClassName('pressed');
      type_check.removeAttribute('checked');
    } else {
      element.addClassName('pressed');
      type_check.setAttribute('checked', 'checked');
    }
    new Ajax.Updater('assets_table', search_form.action, {
      asynchronous: true,
      evalScripts:  true,
      parameters:   Form.serialize(search_form),
      method: 'get',
      onComplete: 'assets_table'
    });
  }
});

Asset.WaitingForm = Behavior.create({
  onsubmit: function(e){
    this.element.addClassName('waiting');
    return true;
  }
});

Asset.ResetForm = function (name) {
  var element = $('asset-upload');
  element.removeClassName('waiting');
  element.reset();
}

Asset.AddAsset = function (name) {
  element = $(name);
  asset = element.select('.asset')[0];
  if (window.console && window.console.log) {
    console.log('inserted element is ', element);
    console.log('contained asset is ', asset);
  }
  if (asset) {
    new Draggable(asset, { revert: true });
  }
}

Event.addBehavior({
  '#asset-tabs a'     : Asset.Tabs,
  '#close-link a'     : Asset.HideBucket,
  '#show-bucket a'    : Asset.ShowBucket,
  '#filesearchform a' : Asset.FileTypes,
  '#asset-upload'     : Asset.WaitingForm,
  'div.asset a'       : Asset.DisableLinks,
  'a.add_asset'       : Asset.AddToPage
});
<|endoftext|>


<commit_before>(function () {
    'use strict';

    /**
     * @ngInject
     */
    function CartoSQLAPI ($http, CartoConfig, Utils) {
        var module = {};

        /*
         *  Retrieves the current data from CartoDB
         *
         *  @return {$httpPromise} object
         */
        module.getCurrentData = function () {
            return makeCartoDBRequest(CartoConfig.data.currQuery);
        };

        module.getAllCurrentData = function () {
            return makeCartoDBRequest(CartoConfig.data.currAllQuery);
        };

        /*
         *  Retrieves the previous data from CartoDB
         *
         *  @return {$httpPromise} object
         */
        module.getPreviousData = function () {
            return makeCartoDBRequest(CartoConfig.data.prevQuery);
        };

        /*
         *  Retrieves the grouped data from CartoDB
         *
         *  @return {$httpPromise} object
         */
        module.getGroupedData = function () {
            return makeCartoDBRequest(CartoConfig.data.groupedQuery);
        };

        /**
         * Get building data for a given id or array of ids
         * @param  {String|Array} buildingId Building ids queried against CartoConfig.uniqueColumn column
         * @return {$httpPromise}
         */
        module.getBuildingData = function (buildingId) {
            var ids = buildingId;
            if (_.isArray(buildingId)) {
                ids = buildingId.join(',');
            }
            return makeCartoDBRequest(CartoConfig.data.detailQuery, {
                id: ids
            });
        };

        /*
         * Combines the rows, keeps the ones where data exists for both years
         *
         * @param {Object} currData Data returned from CartoDB representing current data
         * @param {Object} prevData Data returned from CartoDB representing previous data
         *
         * @return [Array] Merged data
         */
        module.getCombinedData = function (currData, prevData) {
            var currRows = currData.rows;
            var prevRows = prevData.rows;

            var data = {};
            var dataArr = [];
            angular.forEach(prevRows, function (row) {
                data[row.id] = {
                    prev: row
                };
            });
            angular.forEach(currRows, function (row) {
                if (data[row.id]) {
                    data[row.id].curr = row;
                }
            });
            angular.forEach(prevRows, function (row) {
                if (!data[row.id].curr) {
                    delete data[row.id];
                } else {
                    dataArr.push(data[row.id]);
                }
            });

            return dataArr;
        };

        /**
         * Helper function to make a request to the CartoDBAPI
         * @param  {String} query The sql query to make
         * @param  {Object(Optional)} queryParams Object See Utils.strFormat params
         * @return {$httpPromise} The $httpPromise object for the query
         */
        function makeCartoDBRequest(query, queryParams) {

            queryParams = queryParams || {};
            var formattedQuery = Utils.strFormat(query, queryParams);

            return $http.get(CartoConfig.data.url, {
                params: {
                    q: formattedQuery
                }
            });
        }

        return module;
    }

    angular.module('mos.cartodb')

      .factory('CartoSQLAPI', CartoSQLAPI);

})();
<commit_msg>Closes #84: Globally enable $http cache for CartoAPIService<commit_after>(function () {
    'use strict';

    /**
     * @ngInject
     */
    function CartoSQLAPI ($http, CartoConfig, Utils) {
        var module = {};

        /*
         *  Retrieves the current data from CartoDB
         *
         *  @return {$httpPromise} object
         */
        module.getCurrentData = function () {
            return makeCartoDBRequest(CartoConfig.data.currQuery);
        };

        module.getAllCurrentData = function () {
            return makeCartoDBRequest(CartoConfig.data.currAllQuery);
        };

        /*
         *  Retrieves the previous data from CartoDB
         *
         *  @return {$httpPromise} object
         */
        module.getPreviousData = function () {
            return makeCartoDBRequest(CartoConfig.data.prevQuery);
        };

        /*
         *  Retrieves the grouped data from CartoDB
         *
         *  @return {$httpPromise} object
         */
        module.getGroupedData = function () {
            return makeCartoDBRequest(CartoConfig.data.groupedQuery);
        };

        /**
         * Get building data for a given id or array of ids
         * @param  {String|Array} buildingId Building ids queried against CartoConfig.uniqueColumn column
         * @return {$httpPromise}
         */
        module.getBuildingData = function (buildingId) {
            var ids = buildingId;
            if (_.isArray(buildingId)) {
                ids = buildingId.join(',');
            }
            return makeCartoDBRequest(CartoConfig.data.detailQuery, {
                id: ids
            });
        };

        /*
         * Combines the rows, keeps the ones where data exists for both years
         *
         * @param {Object} currData Data returned from CartoDB representing current data
         * @param {Object} prevData Data returned from CartoDB representing previous data
         *
         * @return [Array] Merged data
         */
        module.getCombinedData = function (currData, prevData) {
            var currRows = currData.rows;
            var prevRows = prevData.rows;

            var data = {};
            var dataArr = [];
            angular.forEach(prevRows, function (row) {
                data[row.id] = {
                    prev: row
                };
            });
            angular.forEach(currRows, function (row) {
                if (data[row.id]) {
                    data[row.id].curr = row;
                }
            });
            angular.forEach(prevRows, function (row) {
                if (!data[row.id].curr) {
                    delete data[row.id];
                } else {
                    dataArr.push(data[row.id]);
                }
            });

            return dataArr;
        };

        /**
         * Helper function to make a request to the CartoDBAPI
         * @param  {String} query The sql query to make
         * @param  {Object(Optional)} queryParams Object See Utils.strFormat params
         * @return {$httpPromise} The $httpPromise object for the query
         */
        function makeCartoDBRequest(query, queryParams) {

            queryParams = queryParams || {};
            var formattedQuery = Utils.strFormat(query, queryParams);

            return $http.get(CartoConfig.data.url, {
                params: {
                    q: formattedQuery
                },
                cache: true
            });
        }

        return module;
    }

    angular.module('mos.cartodb')

      .factory('CartoSQLAPI', CartoSQLAPI);

})();
<|endoftext|>


<commit_before><commit_msg>fix core move to server<commit_after>import {List, Map} from 'immutable';

function getWinners(vote) {
  if (!vote) return [];
  const [a, b] = vote.get('pair');
  const aVotes = vote.getIn(['tally', a], 0);
  const bVotes = vote.getIn(['tally', b], 0);
  if      (aVotes > bVotes)  return [a];
  else if (aVotes < bVotes)  return [b];
  else                       return [a, b];
}

export function next(state) {
  const entries = state.get('entries')
                       .concat(getWinners(state.get('vote')));
  return state.merge({
    vote: Map({pair: entries.take(2)}),
    entries: entries.skip(2)
  });
}

export function setEntries(state, entries) {
  return state.set('entries', List(entries));
}

export function next(state) {
  const entries = state.get('entires').concat(getWinners(state.get('vote')));
  if (entries.size === 1) {
    return state.remove('vote')
                .remove('entries')
                .set('winner', entries.first());
  } else {
    return state.merge({
      vote: Map({pair: entries.take(2)}),
      entries: entries.skip(2)
    })
  }
}

export function vote(voteState, entry) {
  return voteState.updateIn(
    ['tally', entry], 0, tally => tally + 1
    );
}

export const INITIAL_STATE = Map();
<|endoftext|>