mourningdove/htdocs/js/pages/entry/new.js
2026-05-24 01:03:05 +00:00

645 lines
23 KiB
JavaScript

var postForm = (function($) {
function hasRemote() {
return $("#js-remote").val() === "" ? false : true;
}
var initMainForm = function($form) {
$form.collapse({ endpointUrl: hasRemote() ? "/__rpc_entryformcollapse" : "" });
$form.fancySelect();
};
var initToolbar = function($form, minAnimation) {
$("#js-entry-settings").find("a").click(function(e) {
e.preventDefault();
var $link = $(this);
var $settings = $("#js-settings-panel");
var $settingsForm = $settings.children( "form:visible" );
if ( $settingsForm.length > 0 ) {
$settingsForm.trigger( "settings.cancel" )
$settings.slideUp();
} else {
$link.addClass( "spinner" );
$settings.load(Site.siteroot + "/__rpc_entryoptions", function(html,status,jqxhr) {
$(this).slideDown();
$link.removeClass( "spinner" );
})
}
});
$.fx.off = minAnimation;
};
var initButtons = function($form, $crosspost, strings) {
function openPreview(e) {
var form = e.target.form;
var action = form.action;
var target = form.target;
var $password = $(form).find( "input[type='password']:enabled" );
$password.prop( "disabled", true );
form.action = "/entry/preview";
form.target = 'preview';
window.open( '',
'preview',
'width=760,height=600,resizable=yes,status=yes,toolbar=no,location=no,menubar=no,scrollbars=yes'
);
form.submit();
form.action = action;
form.target = target;
$password.prop( "disabled", false );
e.preventDefault();
}
function handleDelete(e) {
$(this.form).data( "skipchecks", "delete" );
var do_delete = confirm( strings.delete_confirm );
if ( do_delete ) {
do_delete = $crosspost.crosspost( "confirmDelete", strings.delete_xposts_confirm );
}
if ( ! do_delete ) {
e.preventDefault();
}
}
function handleLoginModal(e) {
var $modal = $("#js-post-entry-login");
$form.find("input[name=username]").val( $modal.find("input[name=username]").val() );
$form.find("input[name=password]").val( $modal.find("input[name=password]").val() );
$modal.find("input[name=password]").val("")
if ( $modal.find("input[name=remember_me]").is(":checked") ) {
$form.find("input[name=remember_me]").val(1);
}
$form.submit();
}
$("#js-preview-button").click(openPreview);
$("#js-delete-button").click(handleDelete);
if ( ! hasRemote() ) {
$("input[name='action:post']").attr("data-reveal-id", "js-post-entry-login");
$("#js-post-entry-login").find("input[type=submit]").click(handleLoginModal);
}
};
var initCommunitySection = function($form) {
$form.on("journalselect-full", function(e, journal) {
if ( journal.name && journal.isremote ) {
if ( journal.iscomm && journal.canManage) {
$(".community-administration").show();
} else {
$(".community-administration").hide();
}
}
});
}
var initCurrents = function($form, moodpics) {
var $moodSelect = $("#js-current-mood");
var $customMood = $("#js-current-mood-other");
function _mood() {
var selectedMood = $moodSelect.val();
return moodpics[selectedMood] ? moodpics[selectedMood] : ["", ""];
}
var updatePreview = function() {
if ( ! moodpics ) return;
$("#js-moodpreview .moodpreview-image").fadeOut("fast", function() {
var $this = $(this);
$this.empty();
$("#js-moodpreview")
.removeClass("columns medium-4")
.prev()
.removeClass("medium-8");
var mood = _mood();
if ( mood[1] !== "" ) {
$this.append($("<img />",{ src: mood[1], width: mood[2], height: mood[3]}))
.fadeIn();
$("#js-moodpreview")
.addClass("columns medium-4")
.prev()
.addClass("columns medium-8");
}
});
}
var updatePreviewText = function () {
var customMoodText = $customMood.val();
if ( ! customMoodText ) {
var mood = _mood();
customMoodText = mood[0];
}
$("#js-moodpreview .moodpreview-text").text( customMoodText );
}
// initialize...
if( moodpics ) {
$moodSelect
.change(updatePreview)
.change(updatePreviewText)
.closest(".columns")
.after("<div id='js-moodpreview' class='moodpreview'>"
+ "<div class='moodpreview-text'></div>"
+ "<div class='moodpreview-image'></div>"
+ "</div>");
$customMood.change(updatePreviewText);
updatePreview();
updatePreviewText();
}
};
var initSecurity = function($form, security_options, opts) {
var $custom_groups = $("#js-custom-groups");
var $custom_access_group_members = $("#js-custom-group-members");
var $custom_edit_button = $('<button class="secondary" data-reveal-id="js-custom-groups" aria-label="Edit custom entries">Edit</button>');
var $security_select = $("#js-security");
// create an "edit custom groups" button
$security_select.closest(".fancy-select")
.after($custom_edit_button);
// show the custom groups modal
$security_select.change( function(e, init) {
var $this = $(this);
if ( $this.val() == "custom" ) {
if ( !init ) {
$custom_groups.foundation('reveal', 'open');
}
$custom_edit_button.show();
} else {
$custom_edit_button.hide();
}
}).triggerHandler("change", true);
// update the list of people who can see the entry
function updatePostingMembers(e, useCached) {
var members_data = []
var requests = []
if(useCached && $custom_access_group_members.data("fetched")) return;
$custom_access_group_members.data("fetched", true);
$custom_groups.find(":checkbox").each(function() {
if (this.checked) {
requests.push($.getJSON("/__rpc_general?mode=list_filter_members&user=" + $form.data("journal") + "&filterid=" + this.value, function(data) {
for ( member in data.filter_members.filterusers) {
var the_name = data.filter_members.filterusers[member].fancy_username;
var position = members_data.indexOf(the_name);
if( position == -1) {
members_data.push(the_name);
}
}
}))
}
});
$.when.apply($, requests).done(function() {
var members_data_list = "";
members_data.sort();
members_data.forEach(function(member) {
members_data_list = members_data_list + "<li>" + member + "</li>";
});
$custom_access_group_members.html(members_data_list);
});
}
function saveCurrentGroups() {
$custom_groups.data( "original_data", $custom_groups.find("input[name=custom_bit]").serializeArray() );
}
function onOpen() {
updatePostingMembers(undefined, true);
saveCurrentGroups();
}
function close(e) {
e.preventDefault();
// hide the modal (retains current state)
$custom_groups.foundation('reveal', 'close');
$custom_groups.detach().appendTo(".components.js-only");
}
function cancel() {
// reset to initial selected custom groups
var data = $custom_groups.data("original_data");
var groups = {};
for ( var i = 0; i < data.length; i++ ) {
groups[data[i].value] = true;
}
$custom_groups.find("input[name=custom_bit]").each(function(i, elem) {
if (groups[elem.value]) {
$(elem).prop("checked", "checked")
} else {
$(elem).removeProp("checked");
}
});
}
$custom_groups.find("input[name=custom_bit]").click(updatePostingMembers);
$(document).on('open.fndtn.reveal', "#js-custom-groups", onOpen);
$("#js-custom-groups-select").click(close);
$custom_groups.find(".close-reveal-modal").click(cancel);
// update the options when journal changes
function adjustSecurityDropdown(data, journal) {
if ( !data ) return;
if ( journal && data.ret ) {
$form.trigger( "journalselect-full", $.extend( {}, journal, {
canManage: data.ret.can_manage
}) );
}
function createOption(option) {
var security = security_options[option];
var img = security.image ? security.image.src +
":" + security.image.width +
":" + security.image.height : "";
return '<option value="' + security.value + '"' +
' data-fancyselect-img="' + img + '"' +
' data-fancyselect-format="' + security.format + '"' +
'>' + security.label + '</option>';
}
var $security = $("#js-security");
var oldval = $security.closest('select').find('option').filter(':selected').val();
var rank = { "public": "0", "access": "1", "private": "2", "custom": "3" };
$security.empty();
if ( data.ret ) {
if ( data.ret["minsecurity"] == "friends" ) data.ret["minsecurity"] = "access";
var opts;
if ( data.ret['is_comm'] ) {
opts = [
createOption( "public" ),
createOption( "members" )
];
if ( data.ret['can_manage'] )
opts.push( createOption( "admin" ) );
} else {
opts = [
createOption( "public" ),
createOption( "access" ),
createOption( "private" )
];
if ( data.ret['friend_groups_exist'] )
opts.push( createOption( "custom" ) );
}
$security.append(opts.join(""));
// select the minsecurity value and disable the values with lesser security
var minsecrank = rank[data.ret['minsecurity']] || 0;
$security.val(rank[oldval] >= minsecrank ? oldval : data.ret['minsecurity']);
if ( data.ret['minsecurity'] == 'access' ) {
$security.find("option[value='public']").prop("disabled", true);
} else if ( data.ret['minsecurity'] == 'private' ) {
$security.find("option[value='public'],option[value='access'],option[value='custom']")
.prop("disabled", true);
}
$security.trigger( "change" );
} else {
$security
.append([
createOption( "public" ),
createOption( "access" ),
createOption( "private" )
].join(""))
.val(oldval)
.trigger( "change" );
}
}
$form.bind( "journalselect", function(e, journal) {
var anon = ! journal.name;
if ( $security_select.length > 0 ) {
if ( anon ) {
// no custom groups
adjustSecurityDropdown({})
} else if ( ! opts.edit ) {
$.getJSON( Site.siteroot + "/__rpc_getsecurityoptions",
{ "user": journal.name }, function(data) { adjustSecurityDropdown(data, journal) } );
}
}
} );
};
var initJournal = function($form) {
$("#js-usejournal").change(function() {
var $usejournal = $(this);
var journal, iscomm;
if ( $usejournal.is("select") ) {
var $option = $usejournal.find("option:selected");
journal = $option.text();
iscomm = $option.val() !== "";
} else {
journal = $usejournal.val();
iscomm = $usejournal.data( "is-comm" ) ? true : false;
}
var journalData = {
"name": journal,
"iscomm": iscomm,
isremote: hasRemote()
};
$form.data( "journal", journal )
.trigger( "journalselect", journalData );
var dataAttribute = $usejournal.attr( "data-is-admin" );
if ( dataAttribute !== undefined ) {
var isAdmin = dataAttribute === "1" ? true : false;
$form.trigger( "journalselect-full", $.extend( journalData, { canManage: isAdmin } ) );
$usejournal.removeAttr("data-is-admin");
}
});
};
var initSlug = function($form, $dateElement) {
var $slug = $("#js-entry-slug");
var $slugBase = $("#js-slug-base");
var slug = $slug.val(), base_url = '';
// Takes an input string and sluggifies it. If you update this, please
// also update LJ::canonicalize_slug in cgi-bin/LJ/Web.pm.
function toSlug(inp) {
return inp
.trim()
.replace(/\s+/g, "-")
.replace(/[^a-z0-9_-]/gi, "")
.replace(/-+/g, "-")
.replace(/^-|-$/g, "")
.toLowerCase();
}
function updateSlugBase() {
var dval = $dateElement.val().replace(/-/g, '/');
$slugBase.text(base_url + "/" + dval + "/");
}
$slug.change(function(e) {
slug = toSlug($slug.val());
$slug.val(slug);
updateSlugBase();
e.preventDefault();
});
$dateElement.change(function(e) {
updateSlugBase();
});
$form.bind('journalselect', function(evt, journal) {
base_url = 'http://' + (journal.name || "[journal]") + '.' + Site.user_domain;
updateSlugBase();
});
updateSlugBase();
};
var initTags = function($form) {
$form.one("journalselect", function(e, journal) {
var $taglist = $("#js-taglist");
var canGetTags = hasRemote() && journal.name;
var options = {
grow: true,
maxlength: 40
}
if ( canGetTags ) {
options.populateSource = Site.siteroot + "/__rpc_gettags?user=" + journal.name;
options.populateId = journal.name;
}
$taglist.autocompletewithunknown(options);
if ( canGetTags )
$taglist.tagBrowser({fallbackLink: "#js-taglist-link"});
$form.bind("journalselect", function(e, journal) {
if ( journal.name ) {
$taglist.autocompletewithunknown( "populate",
Site.siteroot + "/__rpc_gettags?user=" + journal.name, journal.name );
} else {
$taglist.autocompletewithunknown( "clear" )
}
})
});
};
var initDate = function($form) {
function zeropad(num) { return num < 10 ? "0" + num : num }
function padAll(text, sep) {
return $.map( text.split(sep), function(value, index) {
return zeropad(parseInt(value, 10));
} ).join(sep);
}
// Hack: the 3rd-party date/time picker expects a trigger button with no
// child elements, causing bad behavior on our icon <button>s.
// jQuery can't do capturing events, so we do this raw.
document.getElementById('collapse-target-displaydate')
.addEventListener('click', mungePickerTargets, true);
function mungePickerTargets(e) {
if ( $(e.target).is('#js-entrytime-date-button > span, #js-entrytime-time-button > span') ) {
e.stopPropagation();
e.preventDefault();
e.target.parentNode.click();
}
}
$("#js-entrytime-date").pickadate({
editable: true,
format: 'yyyy-mm-dd',
trigger: document.getElementById("js-entrytime-date-button"),
container: '.displaydate-component .picker-output',
klass: {
picker: 'picker picker--date',
navPrev: 'picker__nav--prev fi-icon fi-arrow-left',
navNext: 'picker__nav--next fi-icon fi-arrow-right',
buttonClear: 'picker__button--clear secondary',
buttonToday: 'picker__button--today',
buttonClose: 'picker__button--close secondary'
}
}).change(function(e) {
var picker = $(e.target).pickadate('picker');
var oldValue = picker.get('select', 'yyyy-mm-dd');
var newValue = padAll(picker.get('value'), '-');
if ( oldValue !== newValue ) {
picker.set('select', newValue);
}
});
$("#js-entrytime-time").pickatime({
editable: true,
format: "HH:i",
interval: 1,
max: 1439,
trigger: document.getElementById("js-entrytime-time-button"),
container: '.displaydate-component .picker-output'
}).change(function(e) {
var picker = $(e.target).pickatime('picker');
var oldValue = picker.get('select', 'HH:i');
var newValue = picker.get('value');
if ( oldValue !== newValue ) {
// tweak interval so that we don't round off to the nearest interval
// when setting the value
picker.set('interval', 1);
picker.set('select', newValue);
picker.set('interval', 30);
}
});
function setTimeToNow() {
var now = new Date();
var date = [ now.getFullYear(),
zeropad(now.getMonth() + 1),
zeropad(now.getDate())
].join("-");
$("#js-entrytime-date").val(date).trigger("change");
var time = [ zeropad(now.getHours()), zeropad(now.getMinutes()) ];
$("#js-entrytime-time").val(time).trigger("change");
$("#js-trust-datetime").val(1);
}
if ( $("#js-trust-datetime").val() != 1 ) {
setTimeToNow();
}
$("#js-entrytime-autoupdate").click(function() {
var $inputs = $(".displaydate-component .inner").find("input[type=text], button");
$inputs.prop("disabled", $(this).is(":checked"));
});
$form.submit(function() {
if ( $("#js-entrytime-autoupdate").is(":checked") ) {
setTimeToNow();
var $inputs = $(".displaydate-component .inner").find("input[type=text], button");
$inputs.prop("disabled", false);
}
});
};
var initCrosspost = function($form) {
if ( ! $.fn.crosspost ) {
return;
}
function setLastVisible() {
$(".crosspost-component")
.find(".last-visible")
.removeClass("last-visible")
.end()
.find(".row:visible:last")
.addClass("last-visible");
}
var $crosspost = $(".crosspost-component");
$crosspost.crosspost();
$crosspost.find("input[type=checkbox]").change(setLastVisible);
setLastVisible();
$form.bind("journalselect", function(e, journal) {
if ( journal.name && journal.isremote )
$crosspost.crosspost("toggle", "community", ! journal.iscomm, true);
else
$crosspost.crosspost("toggle", "unknown", false, true);
});
};
var initSticky = function($form) {
$form.bind("journalselect-full", function(e, journal) {
if ( journal.name && journal.isremote ) {
if ( journal.iscomm ) {
$(".components-columns .sticky-component:not(.inactive-component)").hide();
} else {
$(".components-columns .sticky-component:not(.inactive-component)").show();
}
$(".sticky-component")
.filter(":visible")
.find("input").removeAttr("disabled")
.end().end()
.filter(":not(:visible)")
.find("input").attr("disabled", "");
}
});
};
var init = function(formData) {
$("#nojs").val(0);
if ( ! formData ) formData = {};
var entryForm = $("#js-post-entry");
initMainForm(entryForm);
initToolbar(entryForm, formData.minAnimation);
initButtons(entryForm, $( ".crosspost-component" ), formData.strings);
initCommunitySection(entryForm);
initCurrents(entryForm, formData.moodpics);
initSecurity(entryForm, formData.security, { edit: formData.edit } );
initJournal(entryForm);
initSlug(entryForm, $("#js-entrytime-date"));
initTags(entryForm);
initDate(entryForm);
initCrosspost(entryForm);
initSticky(entryForm);
$("#js-usejournal").triggerHandler("change");
$("#js-entrytime-autoupdate").triggerHandler("click");
$(".icons-component .js-only").show();
};
return {
init: init
};
})(jQuery);
jQuery(function($) {
postForm.init(window.postFormInitData);
});