Skip to content

Instantly share code, notes, and snippets.

@igorbenic
Last active January 14, 2019 21:15
Show Gist options
  • Save igorbenic/26fd033d8860c41a78386103b35d4e84 to your computer and use it in GitHub Desktop.
Save igorbenic/26fd033d8860c41a78386103b35d4e84 to your computer and use it in GitHub Desktop.
WordPress Customizer Flexible List Control | http://www.ibenic.com/wordpress-customizer-flexible-list-control
.removeInput {
position: absolute;
right: 15px;
z-index: 999;
background-color: white;
display: block;
border-radius: 10px;
font-size: 10px;
line-height: 20px;
width: 20px;
height: 20px;
text-align: center;
margin-top: 2px;
cursor: pointer;
}
function serialize(e){var r,t,n,a="",i="",o=0,c=function(e){var r=0,t=0,n=e.length,a="";for(t=0;n>t;t++)a=e.charCodeAt(t),r+=128>a?1:2048>a?2:3;return r};switch(_getType=function(e){var r,t,n,a,i=typeof e;if("object"===i&&!e)return"null";if("object"===i){if(!e.constructor)return"object";n=e.constructor.toString(),r=n.match(/(\w+)\(/),r&&(n=r[1].toLowerCase()),a=["boolean","number","string","array"];for(t in a)if(n===a[t]){i=a[t];break}}return i},type=_getType(e),type){case"function":r="";break;case"boolean":r="b:"+(e?"1":"0");break;case"number":r=(Math.round(e)===e?"i":"d")+":"+e;break;case"string":r="s:"+c(e)+':"'+e+'"';break;case"array":case"object":r="a";for(t in e)if(e.hasOwnProperty(t)){if(a=_getType(e[t]),"function"===a)continue;n=t.match(/^[0-9]+$/)?parseInt(t,10):t,i+=this.serialize(n)+this.serialize(e[t]),o++}r+=":"+o+":{"+i+"}";break;case"undefined":default:r="N"}return"object"!==type&&"array"!==type&&("string"===type&&-1!==r.indexOf("}")||(r+=";")),r}
(function($){
$(document).ready(function(){
// Our JS Code will go here
});
})(jQuery);
<?php
if( class_exists( 'WP_Customize_Control' ) ):
class SNT_List_Control extends WP_Customize_Control {
public $type = 'list';
public function render_content() {
// Our HTML will go here
}
}
endif;
(function($){
$(document).ready(function(){
$(document).on('click', ".list-control-add", function(){
var id = $(this).attr("data-id");
var list = $("#list-control-" + id );
list.append('<div class="listinput"><span class="removeInput" >X</span><input type="text" value="" /></div>');
});
$(document).on('click', ".list-control-confirm", function(){
var id = $(this).attr("data-id");
var list = $("#list-control-" + id );
var values = [];
list.children().each(function(){
var value = $(this).find('input').val();
values.push(value);
});
$("#list-input-" + id ).val( serialize( values ) ).trigger("change");
});
$(document).on('click',".removeInput", function(){
var $parent = $(this).parent(".listinput");
$parent.remove();
});
});
})(jQuery);
<?php
// ...
public function render_content() {
// Get Value from this setting
$values = $this->value();
// if is reliazed, unserialize it so that we can use it as array
if ( is_serialized( $values ) ) {
$values = unserialize( $values );
}
?>
<label>
<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
</label>
<div class="control-list" id="list-control-<?php echo $this->id; ?>">
<?php
if( is_array( $values ) ) {
// For each $values, create an input
foreach ($values as $value ) { ?>
<div class="listinput">
<span class="removeInput" >X</span>
<input type="text" value="<?php echo $value; ?>" placeholder="" />
</div>
<?php
}
}
?>
</div>
<!-- Button for adding new input -->
<button type="button" data-id="<?php echo $this->id; ?>" class="button list-control-add button-default">Add</button>
<!-- Button to confirm the list -->
<button type="button" data-id="<?php echo $this->id; ?>" class="button list-control-confirm button-primary">Confirm List</button>
<?php
// If it's not serialized, serialize it to save in input
if ( ! is_serialized( $values ) ) {
$values = serialize( $values );
}
?>
<!-- Input that is the control setting data -->
<input <?php echo $this->link(); ?> type="hidden" id="list-input-<?php echo $this->id; ?>" name="<?php echo $this->id; ?>" value="<?php echo $values; ?>" placeholder="" />
<?php
}
// ...
<?php
add_action( 'customize_controls_enqueue_scripts', 'snt_customizer_controls_scripts' );
function snt_customizer_controls_scripts() {
wp_enqueue_script( 'custom_snt_control_js', get_stylesheet_directory_uri() . '/js/customizer-controls.js', array( 'customize-preview', 'jquery' ) );
wp_enqueue_style( 'custom_snt_control_style', get_stylesheet_directory_uri() . '/css/customizer-controls.css' );
}
function serialize(mixed_value) {
// discuss at: http://phpjs.org/functions/serialize/
// original by: Arpad Ray (mailto:[email protected])
// improved by: Dino
// improved by: Le Torbi (http://www.letorbi.de/)
// improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net/)
// bugfixed by: Andrej Pavlovic
// bugfixed by: Garagoth
// bugfixed by: Russell Walker (http://www.nbill.co.uk/)
// bugfixed by: Jamie Beck (http://www.terabit.ca/)
// bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net/)
// bugfixed by: Ben (http://benblume.co.uk/)
// input by: DtTvB (http://dt.in.th/2008-09-16.string-length-in-bytes.html)
// input by: Martin (http://www.erlenwiese.de/)
// note: We feel the main purpose of this function should be to ease the transport of data between php & js
// note: Aiming for PHP-compatibility, we have to translate objects to arrays
// example 1: serialize(['Kevin', 'van', 'Zonneveld']);
// returns 1: 'a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}'
// example 2: serialize({firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'});
// returns 2: 'a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}'
var val, key, okey,
ktype = '',
vals = '',
count = 0,
_utf8Size = function(str) {
var size = 0,
i = 0,
l = str.length,
code = '';
for (i = 0; i < l; i++) {
code = str.charCodeAt(i);
if (code < 0x0080) {
size += 1;
} else if (code < 0x0800) {
size += 2;
} else {
size += 3;
}
}
return size;
};
_getType = function(inp) {
var match, key, cons, types, type = typeof inp;
if (type === 'object' && !inp) {
return 'null';
}
if (type === 'object') {
if (!inp.constructor) {
return 'object';
}
cons = inp.constructor.toString();
match = cons.match(/(\w+)\(/);
if (match) {
cons = match[1].toLowerCase();
}
types = ['boolean', 'number', 'string', 'array'];
for (key in types) {
if (cons === types[key]) {
type = types[key];
break;
}
}
}
return type;
};
type = _getType(mixed_value);
switch (type) {
case 'function':
val = '';
break;
case 'boolean':
val = 'b:' + (mixed_value ? '1' : '0');
break;
case 'number':
val = (Math.round(mixed_value) === mixed_value ? 'i' : 'd') + ':' + mixed_value;
break;
case 'string':
val = 's:' + _utf8Size(mixed_value) + ':"' + mixed_value + '"';
break;
case 'array':
case 'object':
val = 'a';
/*
if (type === 'object') {
var objname = mixed_value.constructor.toString().match(/(\w+)\(\)/);
if (objname === undefined) {
return;
}
objname[1] = this.serialize(objname[1]);
val = 'O' + objname[1].substring(1, objname[1].length - 1);
}
*/
for (key in mixed_value) {
if (mixed_value.hasOwnProperty(key)) {
ktype = _getType(mixed_value[key]);
if (ktype === 'function') {
continue;
}
okey = (key.match(/^[0-9]+$/) ? parseInt(key, 10) : key);
vals += this.serialize(okey) + this.serialize(mixed_value[key]);
count++;
}
}
val += ':' + count + ':{' + vals + '}';
break;
case 'undefined':
// Fall-through
default:
// if the JS object has a property which contains a null value, the string cannot be unserialized by PHP
val = 'N';
break;
}
if (type !== 'object' && type !== 'array') {
if ( type === 'string' && val.indexOf('}') !== -1 ) {
} else {
val += ';';
}
}
return val;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment