690 lines
20 KiB
JavaScript
690 lines
20 KiB
JavaScript
|
|
/*
|
||
|
|
|
||
|
|
contentfilters.js
|
||
|
|
|
||
|
|
Provides the various functions that we use on the content filters management
|
||
|
|
page to enable easy filter management.
|
||
|
|
|
||
|
|
Authors:
|
||
|
|
Mark Smith <mark@dreamwidth.org>
|
||
|
|
|
||
|
|
Copyright (c) 2009 by Dreamwidth Studios, LLC.
|
||
|
|
|
||
|
|
This program is free software; you may redistribute it and/or modify it under
|
||
|
|
the same terms as Perl itself. For a copy of the license, please reference
|
||
|
|
'perldoc perlartistic' or 'perldoc perlgpl'.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
data structures... I was going nuts not having this referencable, so I
|
||
|
|
have broken down all of the globals and what's in them.
|
||
|
|
|
||
|
|
|
||
|
|
cfSubs = {
|
||
|
|
userid => {
|
||
|
|
showbydefault => 0/1,
|
||
|
|
fgcolor => '#000000',
|
||
|
|
bgcolor => '#ffffff',
|
||
|
|
groupmask => 2394829347,
|
||
|
|
journaltype => 'P',
|
||
|
|
username => 'test3',
|
||
|
|
},
|
||
|
|
userid => ...,
|
||
|
|
userid => ...,
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
cfFilters = {
|
||
|
|
filterid => {
|
||
|
|
id => 1,
|
||
|
|
name => 'filter',
|
||
|
|
public => 1/0,
|
||
|
|
sortorder => 234,
|
||
|
|
|
||
|
|
// populated only when a filter is clicked on, initially null
|
||
|
|
members => {
|
||
|
|
userid => {
|
||
|
|
user => 'username',
|
||
|
|
|
||
|
|
// all of these are optional and may not be present
|
||
|
|
adult_content => enum('any', 'nonexplicit', 'sfw'),
|
||
|
|
poster_type => enum('any', 'maintainer', 'moderator'),
|
||
|
|
tags_mode => enum('any_of', 'all_of', 'none_of'),
|
||
|
|
tags => [ 1, 3, 59, 23, ... ],
|
||
|
|
},
|
||
|
|
userid => ...,
|
||
|
|
userid => ...,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
filterid => ...,
|
||
|
|
filterid => ...,
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
cfTags = {
|
||
|
|
userid => {
|
||
|
|
tagid => {
|
||
|
|
name => 'tagname',
|
||
|
|
uses => 13,
|
||
|
|
},
|
||
|
|
tagid => ...,
|
||
|
|
tagid => ...,
|
||
|
|
},
|
||
|
|
userid => ...,
|
||
|
|
userid => ...,
|
||
|
|
};
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
var cfSelectedFilterId = null, cfCurrentUserid = null;
|
||
|
|
var cfSubs = {}, cfTags = {}, cfFilters = {};
|
||
|
|
|
||
|
|
var cfTypeFilter = '';
|
||
|
|
var cfSubsSorted = [];
|
||
|
|
|
||
|
|
// [ total count, selected ]
|
||
|
|
var cfTagCount = [ 0, 0 ];
|
||
|
|
|
||
|
|
// current save timer
|
||
|
|
var cfTimerId = null, cfSaveTicksLeft = 0;
|
||
|
|
|
||
|
|
|
||
|
|
function cfShowTypes( newtype ) {
|
||
|
|
if ( cfTypeFilter == newtype )
|
||
|
|
return;
|
||
|
|
cfTypeFilter = newtype;
|
||
|
|
cfPopulateLists();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfPopulateLists(selectValue) {
|
||
|
|
// whenever we repopulate the lists, we lose what is selected
|
||
|
|
cfHideOptions();
|
||
|
|
|
||
|
|
// short circuit, if we have no filter, just empty both
|
||
|
|
if ( ! cfSelectedFilterId ) {
|
||
|
|
$('#cf-in-list, #cf-notin-list').empty();
|
||
|
|
$('#cf-rename, #cf-delete, #cf-view, #cf-edit').hide();
|
||
|
|
$('#cf-intro').show();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// show our rename button
|
||
|
|
$('#cf-rename, #cf-delete, #cf-view, #cf-edit').show();
|
||
|
|
$('#cf-intro').hide();
|
||
|
|
|
||
|
|
var filt = cfFilters[cfSelectedFilterId];
|
||
|
|
|
||
|
|
// creates a sorted list of userids
|
||
|
|
cfSubsSorted = [];
|
||
|
|
for ( i in cfSubs )
|
||
|
|
if ( cfTypeFilter == '' || cfSubs[i].journaltype == cfTypeFilter )
|
||
|
|
cfSubsSorted.push( i );
|
||
|
|
cfSubsSorted.sort( function( a, b ) {
|
||
|
|
return ( cfSubs[a].username < cfSubs[b].username ) ? -1 : ( cfSubs[a].username > cfSubs[b].username ) ? 1 : 0;
|
||
|
|
} );
|
||
|
|
|
||
|
|
var inOpts = '', outOpts = '';
|
||
|
|
for ( idx in cfSubsSorted ) {
|
||
|
|
var i = cfSubsSorted[idx];
|
||
|
|
var isIn = false;
|
||
|
|
|
||
|
|
for ( j in filt.members ) {
|
||
|
|
if ( filt.members[j].user == cfSubs[i].username )
|
||
|
|
isIn = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( isIn )
|
||
|
|
inOpts += '<option value="' + i + '">' + cfSubs[i].username + '</option>';
|
||
|
|
else
|
||
|
|
outOpts += '<option value="' + i + '">' + cfSubs[i].username + '</option>';
|
||
|
|
}
|
||
|
|
|
||
|
|
$('#cf-in-list').html( inOpts );
|
||
|
|
$('#cf-notin-list').html( outOpts ).val( selectValue );
|
||
|
|
|
||
|
|
if ($.browser.msie && parseInt($.browser.version, 10) <= 8) $('#cf-in-list, #cf-notin-list').css('width', 'auto').css('width', '100%'); // set #cf-in-list and #cf-notin-list width (IE n..7 bug)
|
||
|
|
}
|
||
|
|
|
||
|
|
function cfPopulateOptions( ) {
|
||
|
|
$('#cf-public').val( cfFilters[cfSelectedFilterId]['public'] );
|
||
|
|
$('#cf-sortorder').val( String( cfFilters[cfSelectedFilterId]['sortorder'] ) );
|
||
|
|
$('#cf-foname').text( cfFilters[cfSelectedFilterId]['name'] );
|
||
|
|
$('#cf-filtopts').show();
|
||
|
|
}
|
||
|
|
|
||
|
|
function cfSelectedFilter() {
|
||
|
|
// filter options are not implemented yet, so don't show that box :)
|
||
|
|
|
||
|
|
cfPopulateLists();
|
||
|
|
cfPopulateOptions();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfSelectFilter( filtid ) {
|
||
|
|
// do nothing case
|
||
|
|
if ( filtid < 1 ) filtid = null;
|
||
|
|
if ( cfSelectedFilterId != null && cfSelectedFilterId == filtid )
|
||
|
|
return;
|
||
|
|
|
||
|
|
// store this for usefulness
|
||
|
|
cfSelectedFilterId = filtid;
|
||
|
|
|
||
|
|
// have to hide the options now, as we're not sure what the user is doing
|
||
|
|
cfHideOptions();
|
||
|
|
|
||
|
|
// if they've chosen nothing...
|
||
|
|
if ( filtid == null )
|
||
|
|
return cfPopulateLists();
|
||
|
|
|
||
|
|
// if this filter already has loaded members, just return
|
||
|
|
if ( cfFilters[filtid].members != null )
|
||
|
|
return cfSelectedFilter();
|
||
|
|
|
||
|
|
// get the members of this filter
|
||
|
|
$.getJSON( '/__rpc_contentfilters?mode=list_members&user=' + DW.currentUser + '&filterid=' + filtid,
|
||
|
|
function( data ) {
|
||
|
|
cfFilters[filtid].members = data.members;
|
||
|
|
cfSelectedFilter();
|
||
|
|
}
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfUpdateTags( data ) {
|
||
|
|
// cfTags[cfCurrentUser] = data.tags
|
||
|
|
|
||
|
|
var member = cfFilters[cfSelectedFilterId].members[cfCurrentUserid];
|
||
|
|
if ( ! member )
|
||
|
|
return;
|
||
|
|
|
||
|
|
// initialize our tag structure
|
||
|
|
if ( ! member.tags )
|
||
|
|
member.tags = {};
|
||
|
|
|
||
|
|
// reset the global tag counts
|
||
|
|
cfTagCount = [ 0, 0 ];
|
||
|
|
|
||
|
|
var html = '', htmlin = '';
|
||
|
|
|
||
|
|
//sort tags alphabetically
|
||
|
|
function sorttags( tag_a, tag_b ) {
|
||
|
|
var name_a = data.tags[tag_a].name;
|
||
|
|
var name_b = data.tags[tag_b].name;
|
||
|
|
if ( name_a < name_b ) {
|
||
|
|
return -1;
|
||
|
|
} else if ( name_a > name_b ) {
|
||
|
|
return 1;
|
||
|
|
} else {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
var sorted_tags = [];
|
||
|
|
for ( id in data.tags ) {
|
||
|
|
sorted_tags.push( id );
|
||
|
|
}
|
||
|
|
|
||
|
|
sorted_tags = sorted_tags.sort( sorttags );
|
||
|
|
|
||
|
|
// go through tag list alphabetically
|
||
|
|
for(var i=0; i<sorted_tags.length; i++){
|
||
|
|
var id = sorted_tags[i];
|
||
|
|
// count every tag
|
||
|
|
cfTagCount[0]++;
|
||
|
|
|
||
|
|
// see if this tag is in the list ...
|
||
|
|
var isin = member.tags[id] ? true : false;
|
||
|
|
|
||
|
|
if ( isin ) {
|
||
|
|
// count every selected tag and build our HTML
|
||
|
|
cfTagCount[1]++
|
||
|
|
htmlin += '<span id="' + id + '" class="cf-tag-on cf-tag"><a href="javascript:void(0);">' + data.tags[id].name + '</a>[' + data.tags[id].uses + ']</span> ';
|
||
|
|
} else {
|
||
|
|
html += '<span id="' + id + '" class="cf-tag"><a href="javascript:void(0);">' + data.tags[id].name + '</a>[' + data.tags[id].uses + ']</span> ';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// do some default stuff if nothing is selected
|
||
|
|
$('#cf-notagsavail').toggle( html == '' );
|
||
|
|
$('#cf-notagssel').toggle( htmlin == '' );
|
||
|
|
|
||
|
|
// and now show/hide the other boxes
|
||
|
|
$('#cf-t-box2').toggle( html != '' );
|
||
|
|
$('#cf-t-box3').toggle( htmlin != '' );
|
||
|
|
|
||
|
|
// now pass this into the page for the user to view
|
||
|
|
$('#cf-t-box2').html( html );
|
||
|
|
$('#cf-t-box3').html( htmlin );
|
||
|
|
|
||
|
|
// now, all of these tags need an onclick handler
|
||
|
|
$('span.cf-tag').bind( 'click', function( e ) { cfClickTag( $(this).attr( 'id' ) ); } );
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfClickTag( id ) {
|
||
|
|
var obj = $('span.cf-tag#' + id);
|
||
|
|
var filt = cfFilters[cfSelectedFilterId];
|
||
|
|
var member = filt.members[cfCurrentUserid];
|
||
|
|
if ( !obj || !filt || !member || !DW.userIsPaid )
|
||
|
|
return;
|
||
|
|
|
||
|
|
// first, let's toggle the class that boldens the tag
|
||
|
|
obj.toggleClass( 'cf-tag-on' );
|
||
|
|
|
||
|
|
// now make sure we have a tags array...
|
||
|
|
if ( ! member.tags )
|
||
|
|
member.tags = {};
|
||
|
|
|
||
|
|
// now, if the class is ON, we need to move this tag to the bucket
|
||
|
|
if ( obj.hasClass( 'cf-tag-on') ) {
|
||
|
|
$('#cf-t-box3').append(' '); // thanks Janine!
|
||
|
|
obj.appendTo('#cf-t-box3');
|
||
|
|
member.tags[id] = true;
|
||
|
|
cfTagCount[1]++;
|
||
|
|
|
||
|
|
// and if it's off, remove it
|
||
|
|
} else {
|
||
|
|
$('#cf-t-box2').append(' '); // damn splits...
|
||
|
|
obj.appendTo('#cf-t-box2');
|
||
|
|
delete member.tags[id];
|
||
|
|
cfTagCount[1]--;
|
||
|
|
}
|
||
|
|
|
||
|
|
// now show/hide our UI markers
|
||
|
|
$('#cf-notagssel').toggle( cfTagCount[1] == 0 );
|
||
|
|
$('#cf-notagsavail').toggle( cfTagCount[0] == 0 || ( cfTagCount[0] - cfTagCount[1] == 0 ) );
|
||
|
|
|
||
|
|
// and now... tag contents
|
||
|
|
$('#cf-t-box3').toggle( cfTagCount[1] > 0 );
|
||
|
|
$('#cf-t-box2').toggle( cfTagCount[0] > 0 && ( cfTagCount[0] - cfTagCount[1] > 0 ) );
|
||
|
|
|
||
|
|
// kick off a save
|
||
|
|
cfSaveChanges();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfSaveChanges() {
|
||
|
|
// if we have a save timer, nuke it
|
||
|
|
if ( cfTimerId )
|
||
|
|
clearTimeout( cfTimerId );
|
||
|
|
|
||
|
|
// set a timer... then try to save, which actually sets a new timer
|
||
|
|
// for us to use.
|
||
|
|
cfSaveTicksLeft = 6;
|
||
|
|
cfTrySave();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfTrySave() {
|
||
|
|
// our timer has fired
|
||
|
|
cfTimerId = null;
|
||
|
|
|
||
|
|
// now, if we're out of ticks just save
|
||
|
|
if ( --cfSaveTicksLeft <= 0 )
|
||
|
|
return cfDoSave();
|
||
|
|
|
||
|
|
// okay, wait another second
|
||
|
|
cfTimerId = setTimeout( cfTrySave, 1000 );
|
||
|
|
|
||
|
|
// now update the text
|
||
|
|
$('#cf-unsaved').html( 'Saving in ' + cfSaveTicksLeft + ' seconds...' );
|
||
|
|
$('#cf-unsaved, #cf-hourglass').show();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfDoSave() {
|
||
|
|
// this actually posts the save
|
||
|
|
$.post( '/__rpc_contentfilters?mode=save_filters&user=' + DW.currentUser,
|
||
|
|
{ 'json': JSON.stringify( cfFilters ) },
|
||
|
|
function( data ) {
|
||
|
|
// FIXME: error handling...
|
||
|
|
if ( !data.ok )
|
||
|
|
return;
|
||
|
|
|
||
|
|
// we're saved
|
||
|
|
cfTimerId = null;
|
||
|
|
$('#cf-unsaved, #cf-hourglass').hide();
|
||
|
|
},
|
||
|
|
'json'
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfSelectMember( sel ) {
|
||
|
|
// if we have selected more than one (or less than one) thing, then hide the
|
||
|
|
// options box and call it good
|
||
|
|
if ( sel.length < 1 || sel.length > 1 ) {
|
||
|
|
cfCurrentUserid = null;
|
||
|
|
return cfHideOptions();
|
||
|
|
}
|
||
|
|
|
||
|
|
// some variables we're going to use later, in particular cfCurrentUserid is
|
||
|
|
// used in many places so we know who we're editing
|
||
|
|
var userid = sel[0];
|
||
|
|
user = cfSubs[userid];
|
||
|
|
cfCurrentUserid = userid;
|
||
|
|
|
||
|
|
// these have to be true, or we have serious issues
|
||
|
|
var filt = cfFilters[cfSelectedFilterId];
|
||
|
|
var member = filt.members[cfCurrentUserid];
|
||
|
|
if ( !filt || !member )
|
||
|
|
return;
|
||
|
|
|
||
|
|
// FIXME: don't always reget the tags
|
||
|
|
$.getJSON( '/__rpc_general?mode=list_tags&user=' + user.username, cfUpdateTags );
|
||
|
|
|
||
|
|
// clear out both of the tag lists
|
||
|
|
$('#cf-t-box2, #cf-t-box3').empty();
|
||
|
|
|
||
|
|
// if this is a comm show the extra community options
|
||
|
|
$('#cf-pt-box').toggle( user.journaltype == 'C' );
|
||
|
|
|
||
|
|
// default the member to a few options...
|
||
|
|
if ( ! member.adultcontent )
|
||
|
|
member.adultcontent = 'any';
|
||
|
|
if ( ! member.postertype )
|
||
|
|
member.postertype = 'any';
|
||
|
|
if ( ! member.tagmode )
|
||
|
|
member.tagmode = 'any_of';
|
||
|
|
|
||
|
|
// now fill the options in
|
||
|
|
$('#cf-adultcontent').val( member.adultcontent );
|
||
|
|
$('#cf-postertype').val( member.postertype );
|
||
|
|
$('#cf-tagmode').val( member.tagmode );
|
||
|
|
|
||
|
|
// and now show the actual options box
|
||
|
|
cfShowOptions();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfHideOptions() {
|
||
|
|
$('#cf-options').hide();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfShowOptions() {
|
||
|
|
// if the user is not paid, make sure we disable things, etc
|
||
|
|
if ( ! DW.userIsPaid ) {
|
||
|
|
$('#cf-adultcontent, #cf-postertype, #cf-tagmode').attr( 'disabled', 'disabled' );
|
||
|
|
$('#cf-free-warning').show();
|
||
|
|
}
|
||
|
|
|
||
|
|
$('#cf-options').show();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfAddMembers() {
|
||
|
|
var members = $('#cf-notin-list').val();
|
||
|
|
var filt = cfFilters[cfSelectedFilterId];
|
||
|
|
if ( !filt || members.length <= 0 )
|
||
|
|
return;
|
||
|
|
|
||
|
|
// simply create a new row in the filter members list for this person
|
||
|
|
for ( i in members ) {
|
||
|
|
var userid = members[i];
|
||
|
|
|
||
|
|
filt.members[userid] = {
|
||
|
|
'user': cfSubs[userid].username
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
// kick off a save event
|
||
|
|
cfSaveChanges();
|
||
|
|
|
||
|
|
var $opt = $("#cf-notin-list option");
|
||
|
|
var lastsel = $opt.filter(":selected:last").index();
|
||
|
|
var at_end = $opt.length - 1 - lastsel == 0;
|
||
|
|
var $newsel = $opt.filter((at_end?":lt(":":gt(") + lastsel+")").filter(":not(:selected)" + (at_end?":last":":first"))
|
||
|
|
|
||
|
|
// and then redisplay our lists
|
||
|
|
cfPopulateLists( $newsel.val() );
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfRemoveMembers() {
|
||
|
|
var members = $('#cf-in-list').val();
|
||
|
|
var filt = cfFilters[cfSelectedFilterId];
|
||
|
|
if ( ! filt || members.length <= 0 )
|
||
|
|
return;
|
||
|
|
|
||
|
|
// simply delete the row in the filter members list for this person
|
||
|
|
for ( i in members ) {
|
||
|
|
var userid = members[i];
|
||
|
|
|
||
|
|
delete filt.members[userid];
|
||
|
|
}
|
||
|
|
|
||
|
|
// kick off a save event
|
||
|
|
cfSaveChanges();
|
||
|
|
|
||
|
|
// and then redisplay our lists
|
||
|
|
cfPopulateLists();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfChangedTagMode() {
|
||
|
|
var tagmode = $('#cf-tagmode').val();
|
||
|
|
var filt = cfFilters[cfSelectedFilterId];
|
||
|
|
var member = filt.members[cfCurrentUserid];
|
||
|
|
if ( !tagmode || !filt || !member )
|
||
|
|
return;
|
||
|
|
|
||
|
|
member.tagmode = tagmode;
|
||
|
|
cfSaveChanges();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfChangedAdultContent() {
|
||
|
|
var adultcontent = $('#cf-adultcontent').val();
|
||
|
|
var filt = cfFilters[cfSelectedFilterId];
|
||
|
|
var member = filt.members[cfCurrentUserid];
|
||
|
|
if ( !adultcontent || !filt || !member )
|
||
|
|
return;
|
||
|
|
|
||
|
|
member.adultcontent = adultcontent;
|
||
|
|
cfSaveChanges();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfChangedPosterType() {
|
||
|
|
var postertype = $('#cf-postertype').val();
|
||
|
|
var filt = cfFilters[cfSelectedFilterId];
|
||
|
|
var member = filt.members[cfCurrentUserid];
|
||
|
|
if ( !postertype || !filt || !member )
|
||
|
|
return;
|
||
|
|
|
||
|
|
member.postertype = postertype;
|
||
|
|
cfSaveChanges();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfNewFilter() {
|
||
|
|
// prompt the user for a filter name...
|
||
|
|
var name = prompt( 'New filter name:', '' );
|
||
|
|
if ( ! name )
|
||
|
|
return;
|
||
|
|
|
||
|
|
// now that we have a name, kick off a request to make a new filter
|
||
|
|
$.getJSON( '/__rpc_contentfilters?mode=create_filter&user=' + DW.currentUser + '&name=' + name,
|
||
|
|
function( data ) {
|
||
|
|
// no id means some sort of failure
|
||
|
|
// FIXME: error handling so the user knows what's up
|
||
|
|
if ( !data.id || !data.name )
|
||
|
|
return;
|
||
|
|
|
||
|
|
// save a roundtrip, we don't have to hit the server since it just gave us
|
||
|
|
// the filter information
|
||
|
|
cfFilters[data.id] = {
|
||
|
|
'id': data.id,
|
||
|
|
'name': data.name,
|
||
|
|
'public': data["public"],
|
||
|
|
'sortorder': data.sortorder
|
||
|
|
};
|
||
|
|
|
||
|
|
// we have to do this first, before the update of the filter select, due to the
|
||
|
|
// way the code is structured
|
||
|
|
cfSelectFilter( data.id );
|
||
|
|
|
||
|
|
// happens last
|
||
|
|
cfUpdateFilterSelect();
|
||
|
|
}
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfRenameFilter() {
|
||
|
|
var filt = cfFilters[cfSelectedFilterId];
|
||
|
|
if ( !filt )
|
||
|
|
return;
|
||
|
|
|
||
|
|
// FIXME: don't think dialogs are accessible at all
|
||
|
|
var renamed = prompt( 'Rename filter to:', filt.name );
|
||
|
|
if ( renamed != null )
|
||
|
|
filt.name = renamed;
|
||
|
|
|
||
|
|
// and now update the select dialog
|
||
|
|
cfUpdateFilterSelect();
|
||
|
|
// and any labeling
|
||
|
|
$('#cf-foname').text( cfFilters[cfSelectedFilterId]['name'] );
|
||
|
|
|
||
|
|
// kick off a saaaaaaaave!
|
||
|
|
cfSaveChanges();
|
||
|
|
}
|
||
|
|
|
||
|
|
function cfSortOrder() {
|
||
|
|
cfFilters[cfSelectedFilterId]['sortorder'] = parseInt( $('#cf-sortorder').val(), 10 );
|
||
|
|
|
||
|
|
cfSaveChanges();
|
||
|
|
cfUpdateFilterSelect();
|
||
|
|
}
|
||
|
|
|
||
|
|
function cfPublic( sel ) {
|
||
|
|
cfFilters[cfSelectedFilterId]['public'] = sel === "1" ? 1 : 0;
|
||
|
|
|
||
|
|
cfSaveChanges();
|
||
|
|
}
|
||
|
|
|
||
|
|
function cfViewFilter() {
|
||
|
|
var filt = cfFilters[cfSelectedFilterId];
|
||
|
|
|
||
|
|
$.getJSON( '/__rpc_contentfilters?mode=view_filter&user=' + DW.currentUser + '&name=' + filt.name,
|
||
|
|
function( data ) {
|
||
|
|
if ( !data.url )
|
||
|
|
return;
|
||
|
|
|
||
|
|
window.open(data.url);
|
||
|
|
}
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// function used for sorting filters -- compares based on sort order, then name
|
||
|
|
function compareFilters( a, b ) {
|
||
|
|
if ( a.sortorder == b.sortorder ) {
|
||
|
|
return a.name > b.name ? 1 : a.name < b.name ? -1 : 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
return a.sortorder > b.sortorder ? 1 : -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
function cfUpdateFilterSelect() {
|
||
|
|
// regenerate HTML for the Filter: dropdown
|
||
|
|
var options = '<option value="0">( select filter )</option>';
|
||
|
|
|
||
|
|
// sort by sortorder, then name
|
||
|
|
var sortedFilters = [];
|
||
|
|
for ( i in cfFilters ) {
|
||
|
|
sortedFilters.push(cfFilters[i]);
|
||
|
|
}
|
||
|
|
sortedFilters.sort(compareFilters);
|
||
|
|
|
||
|
|
for ( var i = 0; i < sortedFilters.length; i++ ) {
|
||
|
|
var id = sortedFilters[i]['id'];
|
||
|
|
cfFilters[id]['members'] = null;
|
||
|
|
options += '<option value="' + id + '">' + cfFilters[id].name + '</option>';
|
||
|
|
}
|
||
|
|
$('#cf-filters').html( options );
|
||
|
|
|
||
|
|
// and if we have a current filter id, reselect
|
||
|
|
if ( cfSelectedFilterId )
|
||
|
|
$('#cf-filters').val( cfSelectedFilterId );
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfRefreshFilterList() {
|
||
|
|
// in a function because we call from multiple places
|
||
|
|
$.getJSON( '/__rpc_contentfilters?mode=list_filters&user=' + DW.currentUser, function( data ) {
|
||
|
|
cfFilters = data.filters;
|
||
|
|
cfUpdateFilterSelect();
|
||
|
|
} );
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
function cfDeleteFilter() {
|
||
|
|
var filt = cfFilters[cfSelectedFilterId];
|
||
|
|
if ( !filt )
|
||
|
|
return;
|
||
|
|
|
||
|
|
// confirm!
|
||
|
|
if ( ! confirm( 'Really delete this content filter? There is no turning back if you say yes.' ) )
|
||
|
|
return;
|
||
|
|
|
||
|
|
$.getJSON( '/__rpc_contentfilters?mode=delete_filter&user=' + DW.currentUser + '&id=' + filt.id,
|
||
|
|
function( data ) {
|
||
|
|
// FIXME: error handling ...
|
||
|
|
if ( !data.ok )
|
||
|
|
return;
|
||
|
|
|
||
|
|
// the filter is gone, so nuke from some of our stuff
|
||
|
|
delete cfFilters[filt.id];
|
||
|
|
|
||
|
|
// and update the UI, again, the order of these two calls matters
|
||
|
|
cfSelectFilter( null );
|
||
|
|
cfUpdateFilterSelect();
|
||
|
|
}
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
jQuery( function($) {
|
||
|
|
|
||
|
|
// load the current filters into the box
|
||
|
|
cfRefreshFilterList();
|
||
|
|
|
||
|
|
// and get who this person is subscribed to, we're going to need this later
|
||
|
|
$.getJSON( '/__rpc_general?mode=list_subscriptions&user=' + DW.currentUser, function( data ) {
|
||
|
|
cfSubs = {};
|
||
|
|
for ( i in data.subs ) {
|
||
|
|
cfSubs[i] = data.subs[i];
|
||
|
|
}
|
||
|
|
cfPopulateLists();
|
||
|
|
} );
|
||
|
|
|
||
|
|
// setup our click handlers
|
||
|
|
$('#cf-filters').bind( 'change', function(e) { cfSelectFilter( $(e.target).val() ); } );
|
||
|
|
$('#cf-in-list').bind( 'change', function(e) { cfSelectMember( $(e.target).val() ); } );
|
||
|
|
$('#cf-add-btn').bind( 'click', function(e) { cfAddMembers(); } );
|
||
|
|
$('#cf-del-btn').bind( 'click', function(e) { cfRemoveMembers(); } );
|
||
|
|
$('#cf-new').bind( 'click', function(e) { cfNewFilter(); } );
|
||
|
|
$('#cf-rename').bind( 'click', function(e) { cfRenameFilter(); } );
|
||
|
|
$('#cf-view').bind( 'click', function(e) { cfViewFilter(); } );
|
||
|
|
$('#cf-delete').bind( 'click', function(e) { cfDeleteFilter(); } );
|
||
|
|
$('#cf-showtypes').bind( 'change', function(e) { cfShowTypes( $(e.target).val() ); } );
|
||
|
|
$('#cf-public').bind( 'change', function(e) { cfPublic( $(e.target).val() ); } );
|
||
|
|
// not working on the input element? put the function in directly as onChange
|
||
|
|
//$('#cf-sortorder').bind( 'change', function(e) { cfSortOrder( $(e.target).val() ); } );
|
||
|
|
|
||
|
|
// if the user is paid, we bind these. note that even if someone goes through the
|
||
|
|
// trouble of hacking up the form and submitting data, the server won't actually give
|
||
|
|
// you an advanced filter. so don't waste your time!
|
||
|
|
if ( DW.userIsPaid ) {
|
||
|
|
$('#cf-adultcontent').bind( 'change', function(e) { cfChangedAdultContent(); } );
|
||
|
|
$('#cf-postertype').bind( 'change', function(e) { cfChangedPosterType(); } );
|
||
|
|
$('#cf-tagmode').bind( 'change', function(e) { cfChangedTagMode(); } );
|
||
|
|
}
|
||
|
|
|
||
|
|
} );
|