');
}
meter
.find('.bar')
.attr('class', 'bar password-strength-'+passResult.score)
.css('width', offset.width+'%');
});
}
/**
* Mask/unmask password input field.
*
* @since 4.6.0
*/
textpattern.passwordMask = function()
{
$('form').on('click', '#show_password', function() {
var inputBox = $(this).closest('form').find('input.txp-maskable');
var newType = (inputBox.attr('type') === 'password') ? 'text' : 'password';
textpattern.changeType(inputBox, newType);
});
}
/**
* Change the type of an input element.
*
* @param {object} elem The element
* @param {string} type The desired type
*
* @see https://gist.github.com/3559343 for original
* @since 4.6.0
*/
textpattern.changeType = function(elem, type)
{
if (elem.prop('type') === type) {
// Already the correct type.
return elem;
}
try {
// May fail if browser prevents it.
return elem.prop('type', type);
} catch(e) {
// Create the element by hand.
// Clone it via a div (jQuery has no html() method for an element).
var html = $("
").append(elem.clone()).html();
// Match existing attributes of type=text or type="text".
var regex = /type=(\")?([^\"\s]+)(\")?/;
// If no match, add the type attribute to the end; otherwise, replace it.
var tmp = $(html.match(regex) == null ?
html.replace(">", ' type="' + type + '">') :
html.replace(regex, 'type="' + type + '"'));
// Copy data from old element.
tmp.data('type', elem.data('type'));
var events = elem.data('events');
var cb = function(events) {
return function() {
// Re-bind all prior events.
for(var idx in events) {
var ydx = events[idx];
for(var jdx in ydx) {
tmp.bind(idx, ydx[jdx].handler);
}
}
}
}(events);
elem.replaceWith(tmp);
// Wait a smidge before firing callback.
setTimeout(cb, 10);
return tmp;
}
}
/**
* Encodes a string for a use in HTML.
*
* @param {string} string The string
* @return {string} Encoded string
* @since 4.6.0
*/
textpattern.encodeHTML = function (string)
{
return $('').text(string).html();
};
/**
* Translates given substrings.
*
* @param {string} string The string being translated
* @param {object} replacements Translated substrings
* @return string Translated string
* @since 4.6.0
* @example
* textpattern.tr('hello world, and bye!', {'hello' : 'bye', 'bye' : 'hello'});
*/
textpattern.tr = function (string, replacements)
{
var match, position, output = '', replacement;
for (position = 0; position < string.length; position++) {
match = false;
$.each(replacements, function (from, to)
{
if (string.substr(position, from.length) === from) {
match = true;
replacement = to;
position = (position + from.length) - 1;
return;
}
});
if (match) {
output += replacement;
} else {
output += string.charAt(position);
}
}
return output;
};
/**
* Returns an i18n string.
*
* @param {string} i18n The i18n string
* @param {object} atts Replacement map
* @param {boolean} escape TRUE to escape HTML in atts
* @return {string} The string
* @example
* textpattern.gTxt('string', {'{name}' : 'example'}, true);
*/
textpattern.gTxt = function (i18n, atts, escape)
{
var tags = atts || {};
var string = i18n;
var name = string.toLowerCase();
if ($.type(textpattern.textarray[name]) !== 'undefined') {
string = textpattern.textarray[name];
}
if (escape !== false) {
string = textpattern.encodeHTML(string);
$.each(tags, function (key, value)
{
tags[key] = textpattern.encodeHTML(value);
});
}
string = textpattern.tr(string, tags);
return string;
};
/**
* Replaces HTML contents of each matched with i18n string.
*
* This is a jQuery plugin for textpattern.gTxt().
*
* @param {object|string} options Options or the i18n string
* @param {string} options.string The i18n string
* @param {object} options.tags Replacement map
* @param {boolean} options.escape TRUE to escape HTML in tags
* @param {object} tags Replacement map
* @param {boolean} escape TRUE to escape HTML in tags
* @return {object} this
* @see textpattern.gTxt()
* @example
* $('p').gTxt('string').class('alert-block warning');
*/
jQuery.fn.gTxt = function (opts, tags, escape)
{
var options = $.extend({
'string' : opts,
'tags' : tags,
'escape' : escape
}, opts);
this.html(textpattern.gTxt(options.string, options.tags, options.escape));
return this;
};
/**
* ESC button closes alert messages.
*
* @since 4.5.0
*/
$(document).keyup(function (e)
{
if (e.keyCode == 27) {
$('.close').parent().remove();
}
});
/**
* Search tool.
*
* @since 4.6.0
*/
function txp_search()
{
var $ui = $('.txp-search');
$ui.find('.txp-search-button').button({
showLabel: false,
icon: 'ui-icon-search'
}).click(function ()
{
$ui.submit();
});
$ui.find('.txp-search-options').button({
showLabel: false,
icon: 'ui-icon-triangle-1-s'
}).on('click', function (e)
{
if (langdir === 'rtl') {
var menu = $ui.find('.txp-dropdown').toggle().position(
{
my: "left top",
at: "left bottom",
of: this
});
} else {
var menu = $ui.find('.txp-dropdown').toggle().position(
{
my: "right top",
at: "right bottom",
of: this
});
};
$(document).one('click blur', function ()
{
menu.hide();
});
return false;
});
$ui.find('.txp-search-buttons').controlgroup();
$ui.find('.txp-dropdown').hide().menu().click(function (e) {
e.stopPropagation();
});
$ui.txpMultiEditForm({
'checkbox' : 'input[name="search_method[]"][type=checkbox]',
'row' : '.txp-dropdown li',
'highlighted' : '.txp-dropdown li',
'confirmation': false
});
}
/**
* Set expanded/collapsed nature of all twisty boxes in a panel.
*
* The direction can either be 'expand' or 'collapse', passed
* in as an argument to the handler.
*
* @param {event} ev Event that triggered the function
* @since 4.6.0
*/
function txp_expand_collapse_all(ev) {
ev.preventDefault();
var direction = ev.data.direction,
container = ev.data.container || (ev.delegateTarget == ev.target ? 'body' : ev.delegateTarget);
$(container).find('.txp-summary a').each(function (i, elm) {
var $elm = $(elm);
if (direction === 'collapse') {
if ($elm.parent(".txp-summary").hasClass("expanded")) {
$elm.click();
}
} else {
if (!$elm.parent(".txp-summary").hasClass("expanded")) {
$elm.click();
}
}
});
}
/**
* Restore sub-panel twistys to their as-stored state.
*
* @return {[type]} [description]
*/
jQuery.fn.restorePanes = function ()
{
// Initialize dynamic WAI-ARIA attributes.
$(this).find('.txp-summary a').each(function (i, elm)
{
// Get id of toggled region.
var $elm = $(elm), region = $elm.attr('href');
if (region) {
var $region = $(region);
region = region.substr(1);
var pane = $elm.data("txp-pane");
if (pane === undefined) {
pane = region;
}
if (textpattern.storage.data[pane] !== undefined) {
if (textpattern.storage.data[pane]) {
$elm.parent(".txp-summary").addClass("expanded");
$region.show();
} else {
$elm.parent(".txp-summary").removeClass("expanded");
$region.hide();
}
}
var vis = $region.is(':visible').toString();
$elm.attr('aria-controls', region).attr('aria-pressed', vis);
$region.attr('aria-expanded', vis);
}
});
}
/**
* Cookie status.
*
* @deprecated in 4.6.0
*/
var cookieEnabled = true;
// Setup panel.
textpattern.Route.add('setup', function ()
{
textpattern.passwordMask();
textpattern.passwordStrength({
'gtxt_prefix' : 'setup_'
});
});
// Login panel.
textpattern.Route.add('login', function ()
{
// Check cookies.
if (!checkCookies()) {
cookieEnabled = false;
$('main').prepend($('').text(textpattern.gTxt('cookies_must_be_enabled')));
}
// Focus on either username or password when empty.
$('#login_form input').each(function() {
if (this.value === '') {
this.focus();
return false;
}
});
textpattern.passwordMask();
textpattern.passwordStrength();
});
// Write panel.
textpattern.Route.add('article', function ()
{
// Assume users would not change the timestamp if they wanted to
// 'publish now'/'reset time'.
$(document).on('change',
'#write-timestamp input.year,' +
'#write-timestamp input.month,' +
'#write-timestamp input.day,' +
'#write-timestamp input.hour,' +
'#write-timestamp input.minute,' +
'#write-timestamp input.second',
function ()
{
$('#publish_now').prop('checked', false);
$('#reset_time').prop('checked', false);
}
);
var status = $('select[name=Status]'), form = status.parents('form'), submitButton = form.find('input[type=submit]');
status.change(function ()
{
if (!form.hasClass('published')) {
if ($(this).val() < 4) {
submitButton.val(textpattern.gTxt('save'));
} else {
submitButton.val(textpattern.gTxt('publish'));
}
}
});
$('.txp-actions').on('click', '.txp-clone', function (e)
{
e.preventDefault();
form.append(''+
'');
form.off('submit.txpAsyncForm').trigger('submit');
});
// Switch to Text/HTML/Preview mode.
$(document).on('click',
'[data-view-mode]',
function (e)
{
e.preventDefault();
$('input[name="view"]').val($(this).data('view-mode'));
document.article_form.submit();
}
);
});
// Uncheck reset on timestamp change.
textpattern.Route.add('article, file', function ()
{
$(document).on('change', '.posted input', function (e)
{
$('#publish_now, #reset_time').prop('checked', false);
});
});
// 'Clone' button on Pages, Forms, Styles panels.
textpattern.Route.add('css, page, form', function ()
{
$('.txp-clone').click(function (e)
{
e.preventDefault();
var target = $(this).data('form');
if (target) {
$('#'+target).append('');
$('.txp-save input').click();
}
});
});
// Tagbuilder.
textpattern.Route.add('page, form, file, image', function ()
{
// Set up asynchronous tag builder links.
textpattern.Relay.register('txpAsyncLink.success', function (event, data)
{
$('#tagbuild_links').dialog('close').html($(data['data'])).dialog('open').restorePanes();
$('#txp-tagbuilder-output').select();
});
textpattern.Relay.register('txpAsyncForm.success', function (event, data)
{
$('#tagbuild_links').html($(data['data']));
$('#txp-tagbuilder-output').select();
});
$('#tagbuild_links, .files_detail, .images_detail').on('click', '.txp-tagbuilder-link', function(ev) {
txpAsyncLink(ev);
});
$('#tagbuild_links').dialog({
dialogClass: 'txp-tagbuilder-container',
autoOpen: false,
focus: function(ev, ui) {
$(ev.target).closest('.ui-dialog').focus();
}
});
$('.txp-tagbuilder-dialog').on('click', function(ev) {
ev.preventDefault();
if ($("#tagbuild_links").dialog('isOpen')) {
$("#tagbuild_links").dialog('close');
} else {
$("#tagbuild_links").dialog('open');
}
});
// Set up delegated asynchronous tagbuilder form submission.
$('#tagbuild_links').on('click', 'form.asynchtml input[type="submit"]', function(ev) {
$(this).closest('form.asynchtml').txpAsyncForm({
dataType: 'html',
error: function ()
{
window.alert(textpattern.gTxt('form_submission_error'));
},
success: function()
{
}
});
});
});
// Forms panel.
textpattern.Route.add('form', function ()
{
$('#allforms_form').txpMultiEditForm({
'checkbox' : 'input[name="selected_forms[]"][type=checkbox]',
'row' : '.switcher-list li, .form-list-name',
'highlighted' : '.switcher-list li'
});
});
// Admin panel.
textpattern.Route.add('admin', function ()
{
textpattern.passwordMask();
textpattern.passwordStrength();
});
// Plugins panel.
textpattern.Route.add('plugin', function ()
{
textpattern.Relay.register('txpAsyncHref.success', function (event, data)
{
$(data['this']).closest('tr').toggleClass('active');
});
});
// All panels?
textpattern.Route.add('', function ()
{
// Collapse/Expand all support.
$('#supporting_content, #tagbuild_links, #content_switcher').on('click', '.txp-collapse-all', {direction: 'collapse'}, txp_expand_collapse_all)
.on('click', '.txp-expand-all', {direction: 'expand'}, txp_expand_collapse_all);
// Pane states
var prefsGroup = $('form:has(.switcher-list li a[data-txp-pane])');
if (prefsGroup.length == 0) {
return;
}
var prefTabs = prefsGroup.find('.switcher-list li');
var $switchers = prefTabs.children('a[data-txp-pane]');
var $section = window.location.hash ? prefsGroup.find($(window.location.hash).closest('section')) : [];
if ($section.length) {
selectedTab = $section.index();
}
else if (textpattern.storage.data[textpattern.event] !== undefined) {
$switchers.each(function (i, elm) {
if ($(elm).data('txp-pane') == textpattern.storage.data[textpattern.event]) {
selectedTab = i;
$(elm).parent().addClass('ui-tabs-active ui-state-active');
} else {
$(elm).parent().removeClass('ui-tabs-active ui-state-active');
}
});
}
if (selectedTab === undefined) {
selectedTab = 0;
}
prefsGroup.tabs({active: selectedTab}).removeClass('ui-widget ui-widget-content ui-corner-all').addClass('ui-tabs-vertical');
prefsGroup.find('.switcher-list').removeClass('ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
prefTabs.removeClass('ui-state-default ui-corner-top');
prefsGroup.find('.txp-prefs-group').removeClass('ui-widget-content ui-corner-bottom');
prefTabs.on('click focus', function(ev)
{
var me = $(this).children('a[data-txp-pane]');
if (!window.localStorage) sendAsyncEvent({
event : 'pane',
step : 'tabVisible',
pane : me.data('txp-pane'),
origin : textpattern.event,
token : me.data('txp-token')
});
var data = new Object;
data[textpattern.event] = me.data('txp-pane');
textpattern.storage.update(data);
});
});
// Initialize JavaScript.
$(document).ready(function ()
{
// Confirmation dialogs.
$(document).on('click.txpVerify', 'a[data-verify]', function (e)
{
return verify($(this).data('verify'));
});
$(document).on('submit.txpVerify', 'form[data-verify]', function (e)
{
return verify($(this).data('verify'));
});
// Disable spellchecking on all elements of class "code" in capable browsers.
var c = $(".code")[0];
if (c && "spellcheck" in c) {
$(".code").prop("spellcheck", false);
}
// Enable spellcheck for all elements mentioned in textpattern.do_spellcheck.
c = $(textpattern.do_spellcheck)[0];
if (c && "spellcheck" in c) {
$(textpattern.do_spellcheck).prop("spellcheck", true);
}
// Attach toggle behaviours.
$(document).on('click', '.txp-summary a[class!=pophelp]', toggleDisplayHref);
// Attach multi-edit form.
$('.multi_edit_form').txpMultiEditForm();
// Establish AJAX timeout from prefs.
if ($.ajaxSetup().timeout === undefined) {
$.ajaxSetup({timeout : textpattern.ajax_timeout});
}
// Set up asynchronous forms.
$('form.async').txpAsyncForm({
error: function ()
{
window.alert(textpattern.gTxt('form_submission_error'));
}
});
// Set up asynchronous links.
$('a.async:not(.script)').txpAsyncHref({
error: function ()
{
window.alert(textpattern.gTxt('form_submission_error'));
}
});
$('a.async.script').txpAsyncHref({
dataType : 'script',
error : function ()
{
window.alert(textpattern.gTxt('form_submission_error'));
}
});
// Close button on the announce pane.
$(document).on('click', '.close', function (e)
{
e.preventDefault();
$(this).parent().remove();
});
$('body').restorePanes();
// Hide popup elements.
$('.txp-dropdown').hide();
// Event handling and automation.
$(document).on('change.txpAutoSubmit', 'form [data-submit-on="change"]', function (e)
{
$(this).parents('form').submit();
});
// Polyfills.
// Add support for form attribute in submit buttons.
if ($('html').hasClass('no-formattribute')) {
$('.txp-save input[form]').click(function(e) {
var targetForm = $(this).attr('form');
$('form[id='+targetForm+']').submit();
});
}
// Establish UI defaults.
$('.txp-dialog').txpDialog();
$('.txp-dialog.modal').dialog('option', 'modal', true);
$('.txp-datepicker').txpDatepicker();
$('.txp-sortable').txpSortable();
// TODO: integrate jQuery UI stuff properly --------------------------------
// Selectmenu
$('.jquery-ui-selectmenu').selectmenu();
// Button
$('.jquery-ui-button').button();
// Button set
$('.jquery-ui-controlgroup').controlgroup();
// TODO: end integrate jQuery UI stuff properly ----------------------------
// Find and open associated dialogs.
$(document).on('click.txpDialog', '[data-txp-dialog]', function (e)
{
$($(this).data('txp-dialog')).dialog('open');
e.preventDefault();
});
// Initialize panel specific JavaScript.
textpattern.Route.init();
// Arm UI.
$('body').removeClass('not-ready');
});