1812 lines
38 KiB
JavaScript
1812 lines
38 KiB
JavaScript
|
/*global $gp:false, gpui:false, gplinks:false, gpinputs:false isadmin:false, gpBase:false, strip_from:false, gpRem:false, gpBLink:false */
|
|||
|
/*jshint forin:true, noarg:true, noempty:true, eqeqeq:true, bitwise:true, strict:true, undef:true, unused:true, curly:true, browser:true, jquery:true, indent:4, maxerr:100, newcap:false, white:false*/
|
|||
|
//"use strict";
|
|||
|
|
|||
|
var gp_editor = false;
|
|||
|
|
|||
|
$gp.curr_edit_id = null;
|
|||
|
$gp.interface = []; // storage for editing interfaces
|
|||
|
$gp.cached = {};
|
|||
|
$gp.defaults = {};
|
|||
|
$gp.editors = []; // storage for editing objects
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Get the coordinates for positioning editable area overlays
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.Coords = function(area){
|
|||
|
if( area.hasClass('inner_size') ){
|
|||
|
area = area.children().first();
|
|||
|
}
|
|||
|
var loc = area.offset();
|
|||
|
loc.w = area.outerWidth();
|
|||
|
loc.h = area.outerHeight();
|
|||
|
return loc;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Create a <div> in the #gp_admin_html space
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.div = function(id,div_class){
|
|||
|
var div = $('#'+id);
|
|||
|
div_class = div_class || '';
|
|||
|
if( div.length === 0 ){
|
|||
|
div = $('<div id="'+id+'" class="'+div_class+'"></div>').appendTo('#gp_admin_html');
|
|||
|
}
|
|||
|
return div;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Dynamically load inline editing
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.links.inline_edit_generic = function(evt,arg){
|
|||
|
|
|||
|
evt.preventDefault();
|
|||
|
|
|||
|
var area_id = $gp.AreaId( $(this) );
|
|||
|
|
|||
|
$gp.LoadEditor(this.href, area_id, arg);
|
|||
|
|
|||
|
|
|||
|
//show editor when a edit link is clicked in the
|
|||
|
var $target = $(evt.target);
|
|||
|
if( $target.closest('.panel_tabs').length && typeof(gp_editing) != 'undefined' ){
|
|||
|
if( $target.data('mode') == 'extra' ){
|
|||
|
gp_editing.is_extra_mode = true;
|
|||
|
}else{
|
|||
|
gp_editing.is_extra_mode = false;
|
|||
|
}
|
|||
|
gp_editing.ShowEditor();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
$gp._loadingEditor = false;
|
|||
|
$gp.LoadEditor = function(href, area_id, arg){
|
|||
|
|
|||
|
area_id = area_id || 0;
|
|||
|
|
|||
|
if( area_id === $gp.curr_edit_id ){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if( $gp._loadingEditor ){
|
|||
|
console.log('editor still loading');
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
$gp._loadingEditor = true;
|
|||
|
|
|||
|
//first time editing, get default $gp.links, $gp.inputs, $gp.response
|
|||
|
if( typeof(gp_editing) == 'undefined' ){
|
|||
|
$gp.defaults['links'] = $gp.Properties($gp.links);
|
|||
|
$gp.defaults['inputs'] = $gp.Properties($gp.inputs);
|
|||
|
$gp.defaults['response'] = $gp.Properties($gp.response);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
$gp.CacheInterface(function(){
|
|||
|
|
|||
|
//set the current editing interface aside so the new one can be created
|
|||
|
if( typeof(gp_editing) !== 'undefined' ){
|
|||
|
if( gp_editing.RestoreCached(area_id) ){
|
|||
|
$gp._loadingEditor = false;
|
|||
|
return;
|
|||
|
}
|
|||
|
}else{
|
|||
|
$gp.LoadStyle('/include/css/inline_edit.css');
|
|||
|
$gp.LoadStyle('/include/css/manage_sections.css');
|
|||
|
// $gp.LoadStyle('/include/css/manage_sections_compact.css'); // alternative compact style
|
|||
|
}
|
|||
|
|
|||
|
$gp.curr_edit_id = area_id;
|
|||
|
var $edit_div = $gp.CurrentDiv();
|
|||
|
|
|||
|
$gp.DefinedObjects();
|
|||
|
$gp.loading();
|
|||
|
|
|||
|
|
|||
|
//legacy inline editing support
|
|||
|
//can also be used for development/troubleshooting
|
|||
|
if( typeof(gplinks[arg]) === 'function' ){
|
|||
|
gplinks[arg].call(this,arg,evt);
|
|||
|
$gp._loadingEditor = false;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
var script = strip_from(href,'#');
|
|||
|
script += '&gpreq=json&defined_objects='+$gp.DefinedObjects();
|
|||
|
|
|||
|
if( arg != 'manage_sections' ){
|
|||
|
script += '&cmd=inlineedit&area_id='+area_id+'§ion='+$edit_div.data('gp-section');
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//get the new editor
|
|||
|
$.getScript( script,function(data){
|
|||
|
if( data === 'false' ){
|
|||
|
alert($gp.error);
|
|||
|
$gp.loaded();
|
|||
|
$gp._loadingEditor = false;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if( typeof(gp_editor.wake) == 'function' ){
|
|||
|
gp_editor.wake();
|
|||
|
}
|
|||
|
$gp._loadingEditor = false;
|
|||
|
});
|
|||
|
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Get object properties
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.Properties = function(obj){
|
|||
|
var properties = [];
|
|||
|
for( var i in obj ){
|
|||
|
if( obj.hasOwnProperty(i) ){
|
|||
|
properties.push(i);
|
|||
|
}
|
|||
|
}
|
|||
|
return properties;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Get the current editing div
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.CurrentDiv = function(){
|
|||
|
return $('#ExtraEditArea'+$gp.curr_edit_id);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Cache the current editing interface
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.CacheInterface = function(callback){
|
|||
|
|
|||
|
|
|||
|
$gp.CurrentDiv().removeClass('gp_edit_current');
|
|||
|
|
|||
|
|
|||
|
//if gp_editing is not defined then we don't have anything to cache yet
|
|||
|
if( typeof(gp_editing) == 'undefined' ){
|
|||
|
callback.call();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//only continue if we can save
|
|||
|
gp_editing.SaveChanges(function(){
|
|||
|
|
|||
|
|
|||
|
if( typeof(gp_editor.sleep) == 'function' ){
|
|||
|
gp_editor.sleep();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
$gp.interface[$gp.curr_edit_id] = $('#ck_area_wrap').children().detach();
|
|||
|
$gp.editors[$gp.curr_edit_id] = gp_editor;
|
|||
|
|
|||
|
|
|||
|
//cache $gp.links that were defined by the current gp_editor
|
|||
|
$gp.cached[$gp.curr_edit_id] = {};
|
|||
|
$gp.CacheObjects( 'links' );
|
|||
|
$gp.CacheObjects( 'inputs' );
|
|||
|
$gp.CacheObjects( 'response' );
|
|||
|
|
|||
|
|
|||
|
$('.cktabs .ckeditor_control.selected').removeClass('selected');
|
|||
|
|
|||
|
callback.call();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Cache $gp.links, $gp.inputs and $gp.Response
|
|||
|
* ?? gpresponse, gplinks, gpinputs ??
|
|||
|
*/
|
|||
|
$gp.CacheObjects = function(type, cache_loc){
|
|||
|
|
|||
|
var from = $gp[type];
|
|||
|
$gp.cached[$gp.curr_edit_id][type] = {};
|
|||
|
|
|||
|
for( var i in from ){
|
|||
|
if( !from.hasOwnProperty(i) ){
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if( $gp.defaults[type].indexOf(i) > -1 ){
|
|||
|
continue;
|
|||
|
}
|
|||
|
$gp.cached[$gp.curr_edit_id][type][i] = from[i];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Restore $gp.links, $gp.inputs and $gp.Response
|
|||
|
* ?? gpresponse, gplinks, gpinputs ??
|
|||
|
*/
|
|||
|
$gp.RestoreObjects = function(type, id){
|
|||
|
|
|||
|
var from = $gp.cached[id][type];
|
|||
|
|
|||
|
for( var i in from ){
|
|||
|
if( !from.hasOwnProperty(i) ){
|
|||
|
continue;
|
|||
|
}
|
|||
|
$gp[type][i] = from[i];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Send to the server which javascript objects are already defined
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.defined_objects = [];
|
|||
|
$gp.DefinedObjects = function(){
|
|||
|
|
|||
|
//get all objects the first time
|
|||
|
if( typeof(gp_editing) == 'undefined' ){
|
|||
|
for( var i in window ) {
|
|||
|
if( typeof(window[i]) != 'object' ){
|
|||
|
continue;
|
|||
|
}
|
|||
|
$gp.defined_objects.push(i);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//compare with $gp.defined_objects
|
|||
|
var objects = [];
|
|||
|
for( var i in window ) {
|
|||
|
if( typeof(window[i]) != 'object' ){
|
|||
|
continue;
|
|||
|
}
|
|||
|
if( $gp.defined_objects.indexOf(i) != -1 ){
|
|||
|
continue;
|
|||
|
}
|
|||
|
objects.push(i);
|
|||
|
}
|
|||
|
|
|||
|
return objects.join(',');
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Remote Browse
|
|||
|
* @param object evt Event object
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.links.remote = function(evt){
|
|||
|
evt.preventDefault();
|
|||
|
var src = $gp.jPrep(this.href,'gpreq=body');
|
|||
|
|
|||
|
//can remote install
|
|||
|
if( gpRem ){
|
|||
|
var pathArray = window.location.href.split( '/' );
|
|||
|
var url = pathArray[0] + '//' + pathArray[2]+gpBase;
|
|||
|
if( window.location.href.indexOf('index.php') > 0 ){
|
|||
|
url += '/index.php';
|
|||
|
}
|
|||
|
|
|||
|
src += '&inUrl='+encodeURIComponent(url)
|
|||
|
+ '&gpRem='+encodeURIComponent(gpRem);
|
|||
|
}
|
|||
|
|
|||
|
//40px margin + 17px*2 border + 20px padding + 10 (extra padding) = approx 130
|
|||
|
// var height = $gp.$win.height() - 130;
|
|||
|
|
|||
|
var opts = {context:'iframe',width:780};
|
|||
|
|
|||
|
var iframe = '<iframe src="'+src+'" frameborder="0" />';
|
|||
|
$gp.AdminBoxC(iframe,opts);
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Add stylesheets to the current document
|
|||
|
* @param string file
|
|||
|
* @param bool already_prefixed
|
|||
|
*/
|
|||
|
$gp.LoadStyle = function(file, already_prefixed){
|
|||
|
|
|||
|
var time = req_time || new Date().getTime();
|
|||
|
file = already_prefixed ? file : gpBase+file;
|
|||
|
file = file+'?t='+time;
|
|||
|
|
|||
|
|
|||
|
//already loaded?
|
|||
|
if( $('link[href="'+file+'"]').length ){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//href set after appending to head so that it works properly in IE
|
|||
|
$('<link rel="stylesheet" type="text/css" />')
|
|||
|
.appendTo('head')
|
|||
|
.attr({'href':file});
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Show content (data) in #gp_admin_box
|
|||
|
* This is used instead of colorbox for admin content
|
|||
|
* - this box resizes without javascript calls (height)
|
|||
|
* - less animation
|
|||
|
*/
|
|||
|
$gp.AdminBoxC = function(data, options){
|
|||
|
$gp.CloseAdminBox();
|
|||
|
if( data === '' ){
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
if( typeof(options) == 'string' ){
|
|||
|
options = {context:options};
|
|||
|
}else if( typeof(options) == 'undefined' ){
|
|||
|
options = {};
|
|||
|
}
|
|||
|
|
|||
|
options = $.extend({
|
|||
|
context : '',
|
|||
|
width : 680,
|
|||
|
zIndex: 11000
|
|||
|
},
|
|||
|
options);
|
|||
|
|
|||
|
/*
|
|||
|
var win_width = $gp.$win.width();
|
|||
|
var box_width = Math.max(660, Math.round(win_width*0.70));
|
|||
|
*/
|
|||
|
var box_width = options.width;
|
|||
|
|
|||
|
$gp.div('gp_admin_box1')
|
|||
|
.css({
|
|||
|
'zIndex' : options.zIndex
|
|||
|
})
|
|||
|
.stop(true,true)
|
|||
|
.fadeTo(0,0) //fade in from transparent
|
|||
|
.fadeTo((options.replaceBox ? 0 : 200), 0.2);
|
|||
|
|
|||
|
$gp.div('gp_admin_box')
|
|||
|
.css({
|
|||
|
'zIndex' : options.zIndex,
|
|||
|
})
|
|||
|
.stop(true,true)
|
|||
|
.fadeIn((options.replaceBox ? 0 : 400))
|
|||
|
.html('<a class="gp_admin_box_close" data-cmd="admin_box_close"></a>'
|
|||
|
+ '<div id="gp_admin_boxc" class="' + (options.context || '') + '" '
|
|||
|
+ 'style="width:' + box_width + 'px">'
|
|||
|
+ '</div>')
|
|||
|
.find('#gp_admin_boxc')
|
|||
|
.html(data)
|
|||
|
.find('input:visible').first()
|
|||
|
.trigger('focus');
|
|||
|
|
|||
|
$('.messages').detach();
|
|||
|
|
|||
|
//close on escape key
|
|||
|
$gp.$doc.on('keyup.abox',function(e) {
|
|||
|
if( e.keyCode == 27 ){
|
|||
|
$gp.CloseAdminBox();
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
return true;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Close gp_admin_box
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.CloseAdminBox = function(evt){
|
|||
|
if( evt ){
|
|||
|
evt.preventDefault();
|
|||
|
}
|
|||
|
|
|||
|
$gp.$doc.off('keyup.abox');
|
|||
|
|
|||
|
$('#gp_admin_box1').fadeOut();
|
|||
|
$('#gp_admin_box').fadeOut(300,function(){
|
|||
|
|
|||
|
//move contents back to document if they came from an inline element
|
|||
|
//remove other content
|
|||
|
var boxc = $('#gp_admin_boxc');
|
|||
|
if( boxc.hasClass('inline') ){
|
|||
|
$('#gp_admin_boxc').children().appendTo('#gp_hidden');
|
|||
|
}else{
|
|||
|
$('#gp_admin_boxc').children().remove();
|
|||
|
}
|
|||
|
|
|||
|
});
|
|||
|
if( typeof($.fn.colorbox) !== 'undefined' ){
|
|||
|
$.fn.colorbox.close();
|
|||
|
}
|
|||
|
};
|
|||
|
$gp.links.admin_box_close = $gp.inputs.admin_box_close = $gp.CloseAdminBox;
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Save admin user settings
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.SaveGPUI = function(){
|
|||
|
if( !isadmin ){
|
|||
|
return;
|
|||
|
}
|
|||
|
var data = 'cmd=SaveGPUI';
|
|||
|
$.each(gpui,function(i,value){
|
|||
|
data += '&gpui_'+i+'='+value;
|
|||
|
});
|
|||
|
|
|||
|
var url = gpBLink+'/Admin/Preferences';
|
|||
|
$gp.postC( url, data);
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Drop down menus
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.links.dd_menu = function(evt){
|
|||
|
|
|||
|
evt.preventDefault();
|
|||
|
evt.stopPropagation();
|
|||
|
|
|||
|
$('.messages').detach(); //remove messages since we can't set the z-index properly
|
|||
|
var that = this;
|
|||
|
var $list = $(this).parent().find('.dd_list');
|
|||
|
|
|||
|
//display the list and add other handlers
|
|||
|
$list.show();
|
|||
|
|
|||
|
//scroll to show selected
|
|||
|
var $selected = $list.find('.selected');
|
|||
|
if( $selected.length ){
|
|||
|
var $ul = $list.find('ul').first();
|
|||
|
var pos = $list.find('.selected').prev().prev().prev().position();
|
|||
|
if( pos ){
|
|||
|
$ul.scrollTop( pos.top + $ul.scrollTop() );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//hide the list and remove handlers
|
|||
|
$('body').on('click.gp_select',function(evt){
|
|||
|
$list.hide();
|
|||
|
$list.off('.gp_select');
|
|||
|
$('body').off('.gp_select');
|
|||
|
|
|||
|
//stop propogation if it's a click on the current menu so it will remain hidden
|
|||
|
if( $(evt.target).closest(that).length ){
|
|||
|
evt.stopPropagation();
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* A simple tab method for switching content area visibility
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.links.tabs = function(evt){
|
|||
|
|
|||
|
evt.preventDefault();
|
|||
|
var $this = $(this);
|
|||
|
$this.siblings('a').removeClass('selected').each(function(b,c){
|
|||
|
if( c.hash ){
|
|||
|
$(c.hash).hide()
|
|||
|
.find('input[type=submit],button[type=submit]').prop('disabled',true);
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
if( this.hash ){
|
|||
|
$this.addClass('selected');
|
|||
|
$(this.hash).show()
|
|||
|
.find('input[type=submit],button[type=submit]').prop('disabled',false);
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Use jQuery's Ajax functions to load javascripts and call callback when complete
|
|||
|
* @depredated 2.0.2 Keep for Simple Slideshow Plugin
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.Loaded = {};
|
|||
|
$gp.LoadScripts = function(scripts,callback,relative_path){
|
|||
|
|
|||
|
var script_count = scripts.length,
|
|||
|
d=new Date(),
|
|||
|
t=d.getTime(),
|
|||
|
base='';
|
|||
|
|
|||
|
relative_path = relative_path||false;
|
|||
|
|
|||
|
if( relative_path ){
|
|||
|
base = gpBase;
|
|||
|
}
|
|||
|
|
|||
|
//use $.each to prevent Array.prototype.xxxx from affecting the for loop
|
|||
|
$.each(scripts,function(i,script){
|
|||
|
script = base+script;
|
|||
|
if( $gp.Loaded[script] ){
|
|||
|
sload();
|
|||
|
}else{
|
|||
|
$gp.Loaded[script] = true;
|
|||
|
$.getScript( $gp.jPrep(script,'t='+t), function(){
|
|||
|
sload();
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
function sload(){
|
|||
|
script_count--;
|
|||
|
if(script_count === 0){
|
|||
|
if( typeof(callback) === 'function' ){
|
|||
|
callback.call(this);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Refresh the current page
|
|||
|
* ie doesn't handle href="" the same way as other browsers
|
|||
|
*/
|
|||
|
$gp.links.gp_refresh = function(evt){
|
|||
|
evt.preventDefault();
|
|||
|
$gp.Reload();
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Change the display of the admin toolbar
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.links.toggle_panel = function(evt){
|
|||
|
var c,panel = $('#simplepanel');
|
|||
|
evt.preventDefault();
|
|||
|
|
|||
|
var classes = '';
|
|||
|
|
|||
|
if( panel.hasClass('minb') ){
|
|||
|
classes = '';
|
|||
|
c = 0;
|
|||
|
}else if( panel.hasClass('compact') ){
|
|||
|
classes = 'minb toggledmin';
|
|||
|
c = 3;
|
|||
|
}else{
|
|||
|
classes = 'compact';
|
|||
|
c = 1;
|
|||
|
}
|
|||
|
if( !panel.hasClass('toggledmin') ){
|
|||
|
panel.off('mouseenter touchstart').on('mouseenter touchstart',function(event){panel.off(event).removeClass('toggledmin');});
|
|||
|
}
|
|||
|
panel.attr('class','keep_viewable '+classes);
|
|||
|
|
|||
|
gpui.cmpct = c;
|
|||
|
$gp.SaveGPUI();
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Handle clicks on headers within the main admin toolbar
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.links.toplink = function(){
|
|||
|
|
|||
|
//must not be compact
|
|||
|
var $this = $(this);
|
|||
|
var $panel = $('#simplepanel');
|
|||
|
if( $panel.hasClass('compact') ){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
var b = $this.next();
|
|||
|
gpui.vis = !(b.is(':visible') && (b.height() > 0));
|
|||
|
|
|||
|
//hide visible areas
|
|||
|
$panel.find('.panelgroup2:visible').slideUp(300);
|
|||
|
|
|||
|
if( gpui.vis ){
|
|||
|
gpui.vis = $this.data('arg');
|
|||
|
b.slideDown(300);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
$gp.SaveGPUI();
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Collapsible area
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.links.collapsible = function(){
|
|||
|
var area = $(this).parent();
|
|||
|
|
|||
|
//only show one
|
|||
|
if( area.hasClass('one') && area.hasClass('gp_collapsed') ){
|
|||
|
area.parent().find('.head').addClass('gp_collapsed');
|
|||
|
area.parent().find('.collapsearea').slideUp(300);
|
|||
|
area.removeClass('gp_collapsed').next().slideDown(300);
|
|||
|
//ability to show multiple
|
|||
|
}else{
|
|||
|
area.toggleClass('gp_collapsed').next().slideToggle(300);
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Load content in #gp_admin_box
|
|||
|
* @deprecated 2.5, use data-cmd="gpabox" instead
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.links.ajax_box = $gp.links.admin_box = function(evt){
|
|||
|
alert(' "ajax_box" and "admin_box" are deprecated link arguments. Use gpabox instead.');
|
|||
|
evt.preventDefault();
|
|||
|
$gp.loading();
|
|||
|
var href = $gp.jPrep(this.href,'gpreq=flush');
|
|||
|
$.get(href,'',function(data){
|
|||
|
$gp.AdminBoxC(data);
|
|||
|
$gp.loaded();
|
|||
|
},'html');
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Load content for #gp_admin_box
|
|||
|
* This method allows for other actions to be sent to the client in addition to admin_box content
|
|||
|
*/
|
|||
|
$gp.links.gpabox = function(evt){
|
|||
|
evt.preventDefault();
|
|||
|
$gp.loading();
|
|||
|
var href = $gp.jPrep(this.href)+'&gpx_content=gpabox';
|
|||
|
var this_context = this;
|
|||
|
$.getJSON(href,function(data,textStatus,jqXHR){
|
|||
|
$gp.Response.call(this_context,data,textStatus,jqXHR);
|
|||
|
});
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Add a table row
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.links.add_table_row = function(evt){
|
|||
|
var $tr = $(this).closest('tr');
|
|||
|
var $new_row = $tr.closest('tbody').find('tr').first().clone();
|
|||
|
$new_row.find('.class_only').remove();
|
|||
|
$new_row.find('input').val('').attr('value','');
|
|||
|
$new_row.find('textarea').val('').text('');
|
|||
|
$tr.before($new_row);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Remove a table row
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.links.rm_table_row = function(evt){
|
|||
|
var $this = $(this);
|
|||
|
if( $this.closest('tbody').find('.rm_table_row').length < 2 ){
|
|||
|
return;
|
|||
|
}
|
|||
|
$this.closest('tr').remove();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* POST a link (without ajax)
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.links.post = function(evt){
|
|||
|
evt.preventDefault();
|
|||
|
|
|||
|
var query = strip_to(this.search,'?');
|
|||
|
var params = ParseQuery(query);
|
|||
|
params.verified = this.dataset.nonce;
|
|||
|
|
|||
|
var form = document.createElement('form');
|
|||
|
|
|||
|
form.method = 'POST';
|
|||
|
form.action = this.pathname;
|
|||
|
|
|||
|
|
|||
|
for( const [name, value] of Object.entries(params) ){
|
|||
|
var element = document.createElement('input');
|
|||
|
element.type = 'hidden';
|
|||
|
element.name = name;
|
|||
|
element.value = value;
|
|||
|
form.appendChild(element);
|
|||
|
}
|
|||
|
|
|||
|
document.body.appendChild(form);
|
|||
|
|
|||
|
form.submit();
|
|||
|
}
|
|||
|
|
|||
|
function ParseQuery(queryString) {
|
|||
|
var query = {};
|
|||
|
var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
|
|||
|
for (var i = 0; i < pairs.length; i++) {
|
|||
|
var pair = pairs[i].split('=');
|
|||
|
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');
|
|||
|
}
|
|||
|
return query;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Post a gpabox request
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.inputs.gpabox = function(){
|
|||
|
return $gp.post(this,'gpx_content=gpabox');
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Toggle the "checked" class on the parent of a checkbox when clicked
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.inputs.gpcheck = function(){
|
|||
|
if( this.checked ){
|
|||
|
$(this).parent().addClass('checked');
|
|||
|
}else{
|
|||
|
$(this).parent().removeClass('checked');
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Check or uncheck all checkboxes in a form
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.inputs.check_all = function(){
|
|||
|
$(this).closest('form').find('input[type=checkbox]').prop('checked',this.checked);
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Send form using cookiecmd
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.inputs.cnreq = function(evt){
|
|||
|
evt.preventDefault();
|
|||
|
var query = $(this.form).serialize();
|
|||
|
$gp.SetCookieCmd(query);
|
|||
|
//$gp.Cookie('cookie_cmd',encodeURIComponent(query),1);
|
|||
|
window.location = strip_from(strip_from(this.form.action,'#'),'?');
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Escape special html characters in a string similar to php's htmlspecialchars() function
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.htmlchars = function(str){
|
|||
|
str = str || '';
|
|||
|
return $('<a>').text(str).html();
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Redirect the user's browser to a url
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.response.location = function(obj){
|
|||
|
window.setTimeout(function(){
|
|||
|
window.location = obj.SELECTOR;
|
|||
|
},obj.CONTENT);
|
|||
|
window.setInterval(function(){
|
|||
|
$('#redir-countdown').text($('#redir-countdown').text() - 1);
|
|||
|
}, 1000);
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* toggle the isPrivate class for the <html> element
|
|||
|
* obj.SELECTOR must evaluate as true or false
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.response.toggle_vis_class = function(obj){
|
|||
|
$('html').toggleClass('isPrivate', !!obj.SELECTOR);
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Get the edit area id
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.AreaId = function( $node ){
|
|||
|
|
|||
|
var area_id = $node.data('gp-area-id');
|
|||
|
|
|||
|
if( typeof(area_id) != 'undefined' ){
|
|||
|
return parseInt(area_id);
|
|||
|
}
|
|||
|
|
|||
|
//ExtraEditArea6
|
|||
|
//ExtraEditLink6
|
|||
|
var area_id = $node.attr('id');
|
|||
|
if( typeof(area_id) != 'undefined' ){
|
|||
|
return parseInt($node.attr('id').substr(13));
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Expand sub lists
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.links.expand = function(){
|
|||
|
|
|||
|
var list = $(this).siblings('ul');
|
|||
|
|
|||
|
if( list.css('display') == 'block' ){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
list.css('display','block');
|
|||
|
|
|||
|
$(document).one('click',function(evt){
|
|||
|
list.css('display','');
|
|||
|
});
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Indicate if there's an extra area that is a draft
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.IndicateDraft = function(){
|
|||
|
|
|||
|
$('.gp_extra_edit').removeClass('msg_publish_draft');
|
|||
|
|
|||
|
$('.editable_area').each(function(){
|
|||
|
if( $(this).data('draft') == 1 ){
|
|||
|
$('.gp_extra_edit').addClass('msg_publish_draft');
|
|||
|
return false;
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Onload
|
|||
|
*
|
|||
|
*/
|
|||
|
$(function(){
|
|||
|
|
|||
|
$gp.$win = $(window);
|
|||
|
$gp.$doc = $(document);
|
|||
|
|
|||
|
//add return value to form
|
|||
|
$gp.$doc.on('mousedown','form',function(){
|
|||
|
var $this = $(this);
|
|||
|
|
|||
|
if( $this.data('gpForms') === 'checked' ){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if( typeof(this['return']) !== 'undefined' ){
|
|||
|
console.log('return');
|
|||
|
this['return'].value = window.location; //set the return path
|
|||
|
}
|
|||
|
|
|||
|
$this.data('gpForms','checked');
|
|||
|
});
|
|||
|
|
|||
|
if( !isadmin || (typeof(gp_bodyashtml) !== 'undefined') ){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
$('body, html').addClass('gpAdmin');
|
|||
|
|
|||
|
$gp.IndicateDraft();
|
|||
|
|
|||
|
window.setTimeout(function(){
|
|||
|
EditOutlines();
|
|||
|
UIEffects();
|
|||
|
},1);
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Update character counts
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.$doc.on('keyup keypress paste change', '.show_character_count textarea', function(){
|
|||
|
$(this).parent().find('.character_count span').html( this.value.length );
|
|||
|
});
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Editable area outline
|
|||
|
*
|
|||
|
*/
|
|||
|
function EditOutlines(){
|
|||
|
var timeout = false, overlay, lnk_span=false, edit_area, highlight_box, fixed_pos = false;
|
|||
|
|
|||
|
overlay = $gp.div('gp_edit_overlay');
|
|||
|
overlay.on('click', function(evt){
|
|||
|
|
|||
|
//if a link is clicked, prevent the overlay from being shown right away
|
|||
|
var target = $(evt.target);
|
|||
|
if( target.filter('a').length > 0 ){
|
|||
|
if( target.hasClass('gp_overlay_close') ){
|
|||
|
evt.preventDefault();
|
|||
|
}
|
|||
|
if( edit_area){
|
|||
|
edit_area.addClass('gp_no_overlay');
|
|||
|
}
|
|||
|
}
|
|||
|
HideOverlay();
|
|||
|
|
|||
|
}).on('mouseleave touchend',function(){
|
|||
|
StartOverlayHide();
|
|||
|
}).on('mouseenter touchstart',function(){
|
|||
|
if( timeout ){
|
|||
|
window.clearTimeout(timeout);
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
//show the edit link when hovering over an editable area
|
|||
|
// using mouseenter to show link an area filled with an iframe
|
|||
|
$('.editable_area').on('mousemove.gp mouseenter.gp touchstart.gp',function(e){
|
|||
|
if( timeout ){
|
|||
|
window.clearTimeout(timeout);
|
|||
|
}
|
|||
|
|
|||
|
var new_area = $(this);
|
|||
|
|
|||
|
// don't show overlay
|
|||
|
// - for an area that is being edited
|
|||
|
// - if we've already shown it
|
|||
|
if( new_area.hasClass('gp_no_overlay') || new_area.hasClass('gp_editing') ){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if( new_area.parent().closest('.editable_area').length > 0 ){
|
|||
|
e.stopPropagation();
|
|||
|
// trigger a substitute event, plugin JS can listen to
|
|||
|
new_area.trigger("admin:" + e.type);
|
|||
|
}
|
|||
|
|
|||
|
//area han't changed, so just show the span
|
|||
|
if( lnk_span && edit_area && new_area.attr('id') === edit_area.attr('id') ){
|
|||
|
lnk_span.show();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
rmNoOverlay(edit_area);
|
|||
|
|
|||
|
edit_area = new_area;
|
|||
|
|
|||
|
AreaOverlay(edit_area);
|
|||
|
|
|||
|
}).on('mouseleave touchend',function(){
|
|||
|
StartOverlayHide();
|
|||
|
rmNoOverlay(edit_area);
|
|||
|
});
|
|||
|
|
|||
|
$gp.$win.on('scroll', function(){
|
|||
|
SpanPosition();
|
|||
|
});
|
|||
|
|
|||
|
|
|||
|
function rmNoOverlay(edit_area){
|
|||
|
|
|||
|
if( !edit_area ){
|
|||
|
return;
|
|||
|
}
|
|||
|
edit_area.removeClass('gp_no_overlay');
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Make sure the span for the current edit area is within the viewable window
|
|||
|
*
|
|||
|
*/
|
|||
|
function SpanPosition(){
|
|||
|
|
|||
|
if( !lnk_span || fixed_pos ){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
var off = lnk_span.offset(),
|
|||
|
pos = lnk_span.position(),
|
|||
|
top = $gp.$win.scrollTop(),
|
|||
|
diff = Math.max(0,top - (off.top - pos.top));
|
|||
|
|
|||
|
lnk_span.stop(true,true).animate({'top':diff});
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function StartOverlayHide(){
|
|||
|
if( timeout ){
|
|||
|
window.clearTimeout(timeout);
|
|||
|
}
|
|||
|
|
|||
|
timeout = window.setTimeout(
|
|||
|
function(){
|
|||
|
HideOverlay();
|
|||
|
},200);
|
|||
|
}
|
|||
|
|
|||
|
function HideOverlay(){
|
|||
|
|
|||
|
//hide links
|
|||
|
if( lnk_span ){
|
|||
|
lnk_span
|
|||
|
.stop(true,true)
|
|||
|
.hide(500,function(){
|
|||
|
ResetMenu();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
fixed_pos = false;
|
|||
|
|
|||
|
|
|||
|
//hide the box
|
|||
|
var box = overlay.find('div');
|
|||
|
box.stop(true,true).fadeOut();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Display the edit links and overlay that outlines an editable area
|
|||
|
*
|
|||
|
*/
|
|||
|
function AreaOverlay(edit_area){
|
|||
|
var id,loc,width;
|
|||
|
|
|||
|
id = edit_area.attr('id');
|
|||
|
if( !id ){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
id = id.substr(13); //edit_area is always ExtraEditArea#
|
|||
|
|
|||
|
//get the edit links
|
|||
|
var edit_links = $('#ExtraEditLnks'+id).children();
|
|||
|
if( edit_links.length === 0 ){
|
|||
|
edit_links = $('#ExtraEditLink'+id);
|
|||
|
if( edit_links.length === 0 ){
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//edit area location
|
|||
|
loc = $gp.Coords(edit_area);
|
|||
|
overlay.show().css({'top':(loc.top-3),'left':(loc.left-2),'width':(loc.w+6)});
|
|||
|
|
|||
|
if( !lnk_span ){
|
|||
|
lnk_span = $('<span>');
|
|||
|
highlight_box = $('<div>');
|
|||
|
overlay.html(highlight_box).append(lnk_span);
|
|||
|
}else{
|
|||
|
lnk_span.stop(true,true).show().removeClass('gp_hover');
|
|||
|
}
|
|||
|
|
|||
|
highlight_box.stop(true,true).hide().css({'height':(loc.h+5),'width':(loc.w+4)});
|
|||
|
|
|||
|
SpanPosition();
|
|||
|
|
|||
|
//add the edit links
|
|||
|
edit_links = edit_links.clone(true)
|
|||
|
.removeClass('ExtraEditLink');
|
|||
|
|
|||
|
//
|
|||
|
lnk_span.html('<a class="gp_overlay_expand fa fa-pencil"></a>')
|
|||
|
.append(edit_links);
|
|||
|
|
|||
|
|
|||
|
ResetMenu();
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Reset Context Menu
|
|||
|
*
|
|||
|
*/
|
|||
|
function ResetMenu(){
|
|||
|
fixed_pos = false;
|
|||
|
lnk_span
|
|||
|
.css({'left':'auto','top':0,'right':0,'position':'absolute'})
|
|||
|
.removeClass('gp_hover')
|
|||
|
.off('mouseenter touchstart')
|
|||
|
.one('mouseenter touchstart',function(){
|
|||
|
if( edit_area.hasClass('gp_no_overlay') ){
|
|||
|
return;
|
|||
|
}
|
|||
|
ShowMenu();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Display the editable area options
|
|||
|
*
|
|||
|
*/
|
|||
|
function ShowMenu(){
|
|||
|
lnk_span
|
|||
|
.addClass('gp_hover')
|
|||
|
.stop(true,true)
|
|||
|
.show();
|
|||
|
|
|||
|
//show the overlay
|
|||
|
highlight_box.stop(true,true).fadeIn();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Left click to show menu
|
|||
|
* This may not always work. Some template/user js may cancel event bubbling
|
|||
|
* Clicking on links still works
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.$doc.on('click.gp','.editable_area, #gp_edit_overlay',function(evt){
|
|||
|
if( ShowableMenu(evt) ){
|
|||
|
MenuPos(evt);
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Position link at cursor
|
|||
|
*
|
|||
|
*/
|
|||
|
function MenuPos(evt){
|
|||
|
|
|||
|
fixed_pos = true;
|
|||
|
var left = evt.pageX-$gp.$win.scrollLeft();
|
|||
|
var diff = left + lnk_span.width() - $gp.$win.width();
|
|||
|
var top = evt.pageY - $gp.$win.scrollTop();
|
|||
|
|
|||
|
if( diff > 0 ){
|
|||
|
left -= diff;
|
|||
|
}
|
|||
|
|
|||
|
lnk_span.show().stop(true,true).css({'top':top,'left':left,'right':'auto','position':'fixed'});
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Return true if we can show the Typesetter context menu
|
|||
|
*
|
|||
|
*/
|
|||
|
function ShowableMenu(evt){
|
|||
|
|
|||
|
if( evt.ctrlKey || evt.altKey || evt.shiftKey ){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if( !edit_area || edit_area.hasClass('gp_editing') || edit_area.hasClass('gp_no_overlay') || !lnk_span ){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
} /* end EditOutlines */
|
|||
|
|
|||
|
|
|||
|
function UIEffects(){
|
|||
|
|
|||
|
if( !$('html').hasClass('admin_body') ){
|
|||
|
SimpleDrag('#simplepanel .toolbar, #simplepanel .toolbar a', '#simplepanel', 'fixed', function(newpos){
|
|||
|
gpui.tx = newpos.left;
|
|||
|
gpui.ty = newpos.top;
|
|||
|
$gp.SaveGPUI();
|
|||
|
},true);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//keep expanding areas within the viewable window
|
|||
|
$('.in_window').parent().on('mouseenter touchstart',function(){
|
|||
|
var $this = $(this);
|
|||
|
var panel = $this.children('.in_window').css({'right':'auto','left':'100%','top':0});
|
|||
|
window.setTimeout(function(){
|
|||
|
var pos = panel.offset();
|
|||
|
var right = pos.left + panel.width();
|
|||
|
var bottom = pos.top + panel.height();
|
|||
|
|
|||
|
|
|||
|
if( right > $gp.$win.width() + $gp.$win.scrollLeft() ){
|
|||
|
panel.css({'right':'100%','left':'auto'});
|
|||
|
}
|
|||
|
|
|||
|
var winbottom = $gp.$win.height() + $gp.$win.scrollTop();
|
|||
|
if( bottom > winbottom ){
|
|||
|
var diff = winbottom + - bottom - 10;
|
|||
|
panel.css({'top':diff});
|
|||
|
}
|
|||
|
},1);
|
|||
|
});
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Reduce a list of titles by search criteria entered in gpsearch areas
|
|||
|
*
|
|||
|
*/
|
|||
|
$(document).on('keyup','input.gpsearch',function(){
|
|||
|
var search = this.value.toLowerCase();
|
|||
|
$(this.form).find('.gp_scrolllist > div > *').each(function(){
|
|||
|
var $this = $(this);
|
|||
|
if( $this.text().toLowerCase().indexOf(search) == -1 ){
|
|||
|
$this.addClass('filtered');
|
|||
|
}else{
|
|||
|
$this.removeClass('filtered');
|
|||
|
}
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Configuration -> Settings
|
|||
|
* Disable minifyjs when combinejs is unchecked
|
|||
|
*
|
|||
|
*/
|
|||
|
function CheckCombineJs(){
|
|||
|
var checked = $('#admincontent_inner input[type="checkbox"][name="combinejs"]').prop("checked");
|
|||
|
$('#admincontent_inner input[type="checkbox"][name="minifyjs"]').prop("disabled", !checked);
|
|||
|
}
|
|||
|
|
|||
|
$('#admincontent_inner input[type="checkbox"][name="combinejs"]').on('change', CheckCombineJs);
|
|||
|
CheckCombineJs();
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Modifier key names based on UI language and OS
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.mod_keys = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform) ?
|
|||
|
{
|
|||
|
// Apple
|
|||
|
ctrlKey: '˄ control',
|
|||
|
shiftKey: '⇑ shift',
|
|||
|
altKey: '⌥ option',
|
|||
|
metaKey: '⌘ command'
|
|||
|
} :
|
|||
|
{
|
|||
|
// others
|
|||
|
ctrlKey: gplang.ctrlKey,
|
|||
|
shiftKey: '⇑ ' + gplang.shiftKey,
|
|||
|
altKey: gplang.altKey,
|
|||
|
metaKey: 'Meta'
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Get visual representation of modifier keys in a <span>
|
|||
|
* @param array of keys, possible values: ctrlKey, shiftKey, altKey, metaKey
|
|||
|
* @return html
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.GetModkeys = function(mod_keys){
|
|||
|
if( !mod_keys.length ){
|
|||
|
return '';
|
|||
|
}
|
|||
|
var html = '';
|
|||
|
$.each(mod_keys, function(i, k){
|
|||
|
html += '<kbd class="keyboard-key">' + $gp.mod_keys[k] + '</kbd> + ';
|
|||
|
});
|
|||
|
return '<span class="show_modkeys">' + html + '</span>';
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Insert modifier keys pepresentation to an element
|
|||
|
* @param stringa valid jQuery selector
|
|||
|
* @param string 'before' or 'after''
|
|||
|
* @param array of keys, modifier keys and regular key, e.g. ['ctrlKey','H'], optional
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.InsertModkeys = function(selector, where, mod_keys){
|
|||
|
$(selector).siblings('.show_modkeys').remove();
|
|||
|
if( typeof(mod_keys) == 'undefined' ){
|
|||
|
// get from hideAdminUIcfg
|
|||
|
var mod_keys = hideAdminUIcfg.hotkey_modkeys;
|
|||
|
}
|
|||
|
|
|||
|
var modkeys_html = $gp.GetModkeys(mod_keys);
|
|||
|
if( where == 'before' ){
|
|||
|
$(modkeys_html).insertBefore(selector);
|
|||
|
}else{
|
|||
|
$(modkeys_html).insertAfter(selector);
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Get hotkey hint
|
|||
|
* @param array of keys, modifier keys and regular key, e.g. ['ctrlKey','H']
|
|||
|
* @return string e.g. for title attr
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.GetHotkeyHint = function(keys){
|
|||
|
var hint = '';
|
|||
|
if( typeof(keys) == 'undefinded' || !keys.length ){
|
|||
|
return '';
|
|||
|
}
|
|||
|
$.each(keys, function(i, k){
|
|||
|
switch(k){
|
|||
|
case 'ctrlKey':
|
|||
|
case 'shiftKey':
|
|||
|
case 'altKey':
|
|||
|
case 'metaKey':
|
|||
|
hint += '[' + $gp.mod_keys[k] + ']+';
|
|||
|
break;
|
|||
|
default:
|
|||
|
hint += '[' + k + ']';
|
|||
|
break;
|
|||
|
}
|
|||
|
});
|
|||
|
return hint;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* Hide Admin UI
|
|||
|
* Configuration -> Settings
|
|||
|
* input capture hotkey combination
|
|||
|
*/
|
|||
|
|
|||
|
$('#admin_ui_hotkey').on('focus', function(){
|
|||
|
$(this).select();
|
|||
|
}).on('keydown', function(evt){
|
|||
|
var key_stroke = $.inArray(evt.key, ['Control', 'Shift', 'Alt', 'AltGraph', 'Meta']) != -1 ? '' : evt.key.toUpperCase();
|
|||
|
var key_which = $.inArray(evt.key, ['Control', 'Shift', 'Alt', 'AltGraph', 'Meta']) != -1 ? '' : evt.which;
|
|||
|
|
|||
|
var mod_keys = [];
|
|||
|
evt.ctrlKey && mod_keys.push('ctrlKey');
|
|||
|
evt.shiftKey && mod_keys.push('shiftKey');
|
|||
|
evt.altKey && mod_keys.push('altKey');
|
|||
|
evt.metaKey && mod_keys.push('metaKey');
|
|||
|
|
|||
|
// show the modifier keys
|
|||
|
$gp.InsertModkeys('#admin_ui_hotkey', 'before', mod_keys);
|
|||
|
|
|||
|
var key_code =
|
|||
|
(evt.ctrlKey ? 'ctrlKey+' : '') +
|
|||
|
(evt.shiftKey ? 'shiftKey+' : '') +
|
|||
|
(evt.altKey ? 'altKey+' : '') +
|
|||
|
(evt.metaKey ? 'metaKey+' : '') +
|
|||
|
key_which;
|
|||
|
|
|||
|
if( key_stroke == '' ||
|
|||
|
key_stroke == ' ' ||
|
|||
|
key_stroke == 'DEAD' ||
|
|||
|
key_stroke == 'DELETE' ||
|
|||
|
key_stroke == 'BACKSPACE'
|
|||
|
){
|
|||
|
key_stroke = '';
|
|||
|
key_code = '';
|
|||
|
}
|
|||
|
$(this).val(key_stroke);
|
|||
|
$('#admin_ui_hotkey_code').val(key_code);
|
|||
|
evt.stopPropagation();
|
|||
|
evt.preventDefault();
|
|||
|
|
|||
|
}).on('keyup', function(evt){
|
|||
|
var code_val = $('#admin_ui_hotkey_code').val();
|
|||
|
var has_modifier_key = /ctrlKey\+|shiftKey\+|altKey\+|metaKey\+/g.test(code_val);
|
|||
|
if( code_val == '' || !has_modifier_key ){
|
|||
|
$(this).val('');
|
|||
|
$('#admin_ui_hotkey_code').val('');
|
|||
|
$gp.InsertModkeys('#admin_ui_hotkey', 'before', []);
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
// make the input smaller and show the modifier keys on load
|
|||
|
if( $('#admin_ui_hotkey').length ){
|
|||
|
$('#admin_ui_hotkey').width(96);
|
|||
|
$gp.InsertModkeys('#admin_ui_hotkey', 'before');
|
|||
|
}
|
|||
|
|
|||
|
}); /* end on DOM ready */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Hide Admin UI
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.HideAdminUI = {
|
|||
|
|
|||
|
init: function(){
|
|||
|
|
|||
|
$gp.HideAdminUI.hotkey_hint = '';
|
|||
|
if( hideAdminUIcfg.hotkey != '' && hideAdminUIcfg.hotkey_code != '' ){
|
|||
|
var hotkey_arr = hideAdminUIcfg.hotkey_modkeys;
|
|||
|
hotkey_arr.push(hideAdminUIcfg.hotkey);
|
|||
|
$gp.HideAdminUI.hotkey_hint = ' ' + $gp.GetHotkeyHint(hotkey_arr);
|
|||
|
}
|
|||
|
|
|||
|
$('<div class="show-admin-ui" '
|
|||
|
+ 'title="' + gplang.ShowAdminUI + $gp.HideAdminUI.hotkey_hint + '"'
|
|||
|
+ '><i class="fa fa-user-circle"></i></div>')
|
|||
|
.on('click', function(){
|
|||
|
$gp.HideAdminUI.toggle(false);
|
|||
|
}).appendTo('body');
|
|||
|
|
|||
|
$('.admin-link-hide-ui')
|
|||
|
.attr('title', $('.admin-link-hide-ui').attr('title') + $gp.HideAdminUI.hotkey_hint);
|
|||
|
|
|||
|
if( hideAdminUIcfg.autohide_below ){
|
|||
|
$gp.HideAdminUI.ww = $gp.$win.width();
|
|||
|
$gp.$win.on('load', function(evt){
|
|||
|
var ww = $gp.$win.width();
|
|||
|
if( ww < hideAdminUIcfg.autohide_below ){
|
|||
|
$gp.HideAdminUI.toggle(true);
|
|||
|
$gp.HideAdminUI.ww = ww;
|
|||
|
}
|
|||
|
}).on('resize', function(evt){
|
|||
|
var ww = $gp.$win.width();
|
|||
|
var threshold = hideAdminUIcfg.autohide_below;
|
|||
|
if( ww < threshold && $gp.HideAdminUI.ww >= threshold ){
|
|||
|
$gp.HideAdminUI.toggle(true);
|
|||
|
$gp.HideAdminUI.ww = ww;
|
|||
|
}else if( ww >= threshold && $gp.HideAdminUI.ww < threshold ){
|
|||
|
$gp.HideAdminUI.toggle(false);
|
|||
|
$gp.HideAdminUI.ww = ww;
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
if( hideAdminUIcfg.hotkey_which != '' ){
|
|||
|
$gp.$doc.on('keydown.hideAdminUI', function(evt){
|
|||
|
var modkeys_pressed = true;
|
|||
|
$.each(hideAdminUIcfg.hotkey_modkeys, function(i, key){
|
|||
|
if( evt[key] === false ){
|
|||
|
modkeys_pressed = false;
|
|||
|
return false;
|
|||
|
}
|
|||
|
});
|
|||
|
if( modkeys_pressed && evt.which == hideAdminUIcfg.hotkey_which ){
|
|||
|
evt.preventDefault();
|
|||
|
$gp.HideAdminUI.toggle();
|
|||
|
}
|
|||
|
if( evt.which == 27 ){ /* 27 [Esc] key always exits hidden state */
|
|||
|
$gp.HideAdminUI.toggle(false);
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
toggle: function(show_hide){
|
|||
|
if( typeof(show_hide) == 'boolean' ){
|
|||
|
$("html").toggleClass("override_admin_style", show_hide);
|
|||
|
}else{
|
|||
|
$("html").toggleClass("override_admin_style");
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* A simple drag function for use with Typesetter admin areas
|
|||
|
* Works with absolute and fixed positioned elements
|
|||
|
* Different from other drag script in that the mouse will not trigger any mouseover/mousenter events because the drag box will be under the mouse
|
|||
|
*
|
|||
|
* @param string selector
|
|||
|
* @param string drag_area
|
|||
|
* @param string positioning (absolute,relative,fixed)
|
|||
|
* @param function callback_done function to call once the drag 'n drop is done
|
|||
|
*/
|
|||
|
function SimpleDrag(selector, drag_area, positioning, callback_done){
|
|||
|
|
|||
|
var tolerance = -10;
|
|||
|
var $drag_area = $(drag_area);
|
|||
|
|
|||
|
|
|||
|
//dragging
|
|||
|
$gp.$doc.off('mousedown.sdrag',selector).on('mousedown.sdrag',selector,function(e){
|
|||
|
|
|||
|
if( e.which != 1 ){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
var box, click_offsetx, click_offsety;
|
|||
|
e.preventDefault();
|
|||
|
if( $drag_area.length < 1 ){
|
|||
|
return;
|
|||
|
}
|
|||
|
init();
|
|||
|
function init(){
|
|||
|
var pos = $drag_area.offset();
|
|||
|
click_offsetx = e.clientX - pos.left + $gp.$win.scrollLeft();
|
|||
|
click_offsety = e.clientY - pos.top + $gp.$win.scrollTop();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
$gp.$doc.on('mousemove.sdrag',function(e){
|
|||
|
|
|||
|
//initiate the box
|
|||
|
if( !box ){
|
|||
|
var pos = $drag_area.offset();
|
|||
|
var w = $drag_area.width();
|
|||
|
var h = $drag_area.height();
|
|||
|
box = $gp.div('admin_drag_box')
|
|||
|
.css({'top':pos.top,'left':pos.left,'width':w,'height':h});
|
|||
|
}
|
|||
|
|
|||
|
box.css({'left':Math.max(tolerance,e.clientX - click_offsetx),'top': Math.max(tolerance,e.clientY - click_offsety)});
|
|||
|
e.preventDefault();
|
|||
|
|
|||
|
return false;
|
|||
|
});
|
|||
|
|
|||
|
|
|||
|
|
|||
|
$gp.$doc.off('mouseup.sdrag').on('mouseup.sdrag',function(e){
|
|||
|
var newposleft,newpostop,pos_obj;
|
|||
|
$gp.$doc.off('mousemove.sdrag mouseup.sdrag');
|
|||
|
|
|||
|
if( !box ){
|
|||
|
return false;
|
|||
|
}
|
|||
|
e.preventDefault();
|
|||
|
|
|||
|
//clean
|
|||
|
box.remove();
|
|||
|
box = false;
|
|||
|
|
|||
|
//new
|
|||
|
newposleft = e.clientX - click_offsetx;
|
|||
|
newpostop = e.clientY - click_offsety;
|
|||
|
//newposleft = Math.max(0,e.clientX - click_offsetx);
|
|||
|
//newpostop = Math.max(0,e.clientY - click_offsety);
|
|||
|
|
|||
|
//add scroll back in for absolute position
|
|||
|
if( positioning === 'absolute' ){
|
|||
|
newposleft += $gp.$win.scrollLeft();
|
|||
|
newpostop += $gp.$win.scrollTop();
|
|||
|
}
|
|||
|
|
|||
|
newposleft = Math.max(tolerance,newposleft);
|
|||
|
newpostop = Math.max(tolerance,newpostop);
|
|||
|
|
|||
|
|
|||
|
pos_obj = {'left':newposleft,'top': newpostop};
|
|||
|
|
|||
|
$drag_area.css(pos_obj).data({'gp_left':newposleft,'gp_top':newpostop});
|
|||
|
|
|||
|
if( typeof(callback_done) === 'function' ){
|
|||
|
callback_done.call($drag_area,pos_obj,e);
|
|||
|
}
|
|||
|
|
|||
|
$drag_area.trigger('dragstop');
|
|||
|
return false;
|
|||
|
});
|
|||
|
|
|||
|
return false;
|
|||
|
});
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if( $drag_area.css('position') === 'fixed' || $drag_area.parent().css('position') === 'fixed' ){
|
|||
|
KeepViewable( $drag_area.addClass('keep_viewable') ,true);
|
|||
|
}
|
|||
|
|
|||
|
function KeepViewable($elem,init){
|
|||
|
|
|||
|
if( !$elem.hasClass('keep_viewable') ){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
var gp_left
|
|||
|
, css = {}
|
|||
|
, pos = $elem.position();
|
|||
|
|
|||
|
|
|||
|
//move back to the right if $elem has been moved left
|
|||
|
if( init ){
|
|||
|
$elem.data({'gp_left':pos.left,'gp_top':pos.top});
|
|||
|
}else if( gp_left = $elem.data('gp_left') ){
|
|||
|
pos.left = css.left = gp_left;
|
|||
|
pos.top = css.top = $elem.data('gp_top');
|
|||
|
}
|
|||
|
|
|||
|
var width = $elem.width();
|
|||
|
|
|||
|
|
|||
|
//keep the top of the area from being placed too high in the window
|
|||
|
var winbottom = $gp.$win.height();
|
|||
|
if( pos.top < tolerance ){
|
|||
|
css.top = tolerance;
|
|||
|
|
|||
|
//keep the top of the area from being placed too low
|
|||
|
}else if( pos.top > winbottom ){
|
|||
|
css.top = winbottom + 2*tolerance; //tolerance is negative
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//right
|
|||
|
var checkright = $gp.$win.width() - width - tolerance;
|
|||
|
if( pos.left > checkright ){
|
|||
|
css.left = checkright;
|
|||
|
}
|
|||
|
|
|||
|
if( css.left || css.top ){
|
|||
|
$elem.css(css);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
$gp.$win.on('resize', function(){
|
|||
|
$('.keep_viewable').each(function(){
|
|||
|
KeepViewable($(this),false);
|
|||
|
});
|
|||
|
});
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Initialize functionality for the rename/details dialog
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.response.renameprep = function(){
|
|||
|
|
|||
|
|
|||
|
var $form = $('#gp_rename_form');
|
|||
|
var old_title = $('#old_title').val().toLowerCase();
|
|||
|
var $new_title = $form.find('input.new_title').on('keyup change',ShowRedirect);
|
|||
|
var space_char = $('#gp_space_char').val();
|
|||
|
|
|||
|
|
|||
|
$('input:disabled').each(function(a,b){
|
|||
|
$(b).fadeTo(400,0.6);
|
|||
|
});
|
|||
|
|
|||
|
$('input.title_label').on('keyup change', SyncSlug).trigger('change');
|
|||
|
|
|||
|
$gp.links.showmore = function(){
|
|||
|
$('#gp_rename_table tr').css('display','table-row');
|
|||
|
$(this).parent().remove();
|
|||
|
};
|
|||
|
|
|||
|
/**
|
|||
|
* Toggle synchronization/customization of a field
|
|||
|
*
|
|||
|
*/
|
|||
|
$gp.links.ToggleSync = function(evt){
|
|||
|
var td = $(this).closest('td');
|
|||
|
var vis = td.find('a:visible');
|
|||
|
|
|||
|
td.find('a').show();
|
|||
|
vis.hide();
|
|||
|
|
|||
|
vis = td.find('a:visible');
|
|||
|
|
|||
|
if( vis.length ){
|
|||
|
if( vis.hasClass('slug_edit') ){
|
|||
|
td.find('input').addClass('sync_label').prop('readonly',true).fadeTo(400,0.6);
|
|||
|
SyncSlug();
|
|||
|
}else{
|
|||
|
td.find('input').removeClass('sync_label').prop('readonly',false).fadeTo(400,1);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Show the redirct option if the new slug doesn't match the old slug
|
|||
|
*
|
|||
|
*/
|
|||
|
function ShowRedirect(){
|
|||
|
var new_val = $new_title.val().replace(/ /g,space_char).toLowerCase();
|
|||
|
|
|||
|
if( new_val !== old_title ){
|
|||
|
$('#gp_rename_redirect').show(500);
|
|||
|
}else{
|
|||
|
$('#gp_rename_redirect').hide(300);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Update the value of the slug/url field with the title
|
|||
|
*
|
|||
|
*/
|
|||
|
function SyncSlug(){
|
|||
|
|
|||
|
var label = $('input.title_label').val();
|
|||
|
|
|||
|
|
|||
|
$new_title.filter('.sync_label').val( LabelToSlug(label) );
|
|||
|
|
|||
|
$('input.browser_title.sync_label').val(label);
|
|||
|
|
|||
|
ShowRedirect();
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Convert a label to a slug
|
|||
|
*
|
|||
|
*/
|
|||
|
function LabelToSlug(str){
|
|||
|
|
|||
|
// Remove control characters
|
|||
|
str = str.replace(/[\x00-\x1F\x7F]/g,'');
|
|||
|
|
|||
|
//illegal characters
|
|||
|
//str = str.replace(/("|'|\?|\*|:|#)/g,'');
|
|||
|
str = str.replace(/(\?|\*|:|#)/g,'');
|
|||
|
|
|||
|
//after removing tags, unescape special characters
|
|||
|
str = strip_tags(str);
|
|||
|
|
|||
|
str = SlugSlashes(str);
|
|||
|
|
|||
|
//all spaces should be underscores
|
|||
|
return str.replace(/ /g,space_char);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Remove html tags from a string
|
|||
|
*
|
|||
|
*/
|
|||
|
function strip_tags(str){
|
|||
|
return str.replace(/(<(\/?[a-zA-Z0-9][^<>]*)>)/ig,"");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Take care of slashes and periods
|
|||
|
*
|
|||
|
*/
|
|||
|
function SlugSlashes(str){
|
|||
|
|
|||
|
//replace \
|
|||
|
str = str.replace(/[\\]/g,'/');
|
|||
|
|
|||
|
//remove trailing "/."
|
|||
|
str = str.replace(/^\.+[\/\/]/,'/');
|
|||
|
|
|||
|
//remove trailing "/."
|
|||
|
str = str.replace(/[\/\/]\.+$/,'/');
|
|||
|
|
|||
|
//remove any "/./"
|
|||
|
str = str.replace(/[\/\/]\.+[\/\/]/g,'/');
|
|||
|
|
|||
|
//remove consecutive slashes
|
|||
|
str = str.replace(/[\/\/]+/g,'/');
|
|||
|
|
|||
|
if( str === '.' ){
|
|||
|
return '';
|
|||
|
}
|
|||
|
|
|||
|
//left trim /
|
|||
|
str = str.replace(/^\/\/*/g,'');
|
|||
|
|
|||
|
return str;
|
|||
|
}
|
|||
|
|
|||
|
};
|