admin MDL-22806 Added a colourpicker admin setting + supporting JavaScript
This commit is contained in:
@@ -631,6 +631,7 @@ $string['latexpreamble'] = 'LaTeX preamble';
|
||||
$string['latexsettings'] = 'LaTeX renderer Settings';
|
||||
$string['latinexcelexport'] = 'Excel encoding';
|
||||
$string['licensesettings'] = 'License settings';
|
||||
$string['loading'] = 'Loading';
|
||||
$string['localetext'] = 'Sitewide locale';
|
||||
$string['localstringcustomization'] = 'Local string customization';
|
||||
$string['location'] = 'Location';
|
||||
|
||||
@@ -6940,3 +6940,96 @@ class admin_setting_managewebservicetokens extends admin_setting {
|
||||
return highlight($query, $return);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Colour picker
|
||||
*
|
||||
* @copyright 2010 Sam Hemelryk
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class admin_setting_configcolourpicker extends admin_setting {
|
||||
|
||||
/**
|
||||
* Information for previewing the colour
|
||||
*
|
||||
* @var array|null
|
||||
*/
|
||||
protected $previewconfig = null;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $visiblename
|
||||
* @param string $description
|
||||
* @param string $defaultsetting
|
||||
* @param array $previewconfig Array('selector'=>'.some .css .selector','style'=>'backgroundColor');
|
||||
*/
|
||||
public function __construct($name, $visiblename, $description, $defaultsetting, array $previewconfig=null) {
|
||||
$this->previewconfig = $previewconfig;
|
||||
parent::__construct($name, $visiblename, $description, $defaultsetting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the setting
|
||||
*
|
||||
* @return mixed returns config if successful else null
|
||||
*/
|
||||
public function get_setting() {
|
||||
return $this->config_read($this->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the setting
|
||||
*
|
||||
* @param string $data
|
||||
* @return bool
|
||||
*/
|
||||
public function write_setting($data) {
|
||||
$data = $this->validate($data);
|
||||
if ($data === false) {
|
||||
return get_string('validateerror', 'admin');
|
||||
}
|
||||
return ($this->config_write($this->name, $data) ? '' : get_string('errorsetting', 'admin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the colour that was entered by the user
|
||||
*
|
||||
* @param string $data
|
||||
* @return string|false
|
||||
*/
|
||||
protected function validate($data) {
|
||||
if (preg_match('/^#?([a-fA-F0-9]{3}){1,2}$/', $data)) {
|
||||
if (strpos($data, '#')!==0) {
|
||||
$data = '#'.$data;
|
||||
}
|
||||
return $data;
|
||||
} else if (preg_match('/^[a-zA-Z]{3, 25}$/')) {
|
||||
return $data;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the HTML for the setting
|
||||
*
|
||||
* @global moodle_page $PAGE
|
||||
* @global core_renderer $OUTPUT
|
||||
* @param string $data
|
||||
* @param string $query
|
||||
*/
|
||||
public function output_html($data, $query = '') {
|
||||
global $PAGE, $OUTPUT;
|
||||
$PAGE->requires->js_init_call('M.util.init_colour_picker', array($this->get_id(), $this->previewconfig));
|
||||
$content = html_writer::start_tag('div', array('class'=>'form-colourpicker defaultsnext'));
|
||||
$content .= html_writer::tag('div', $OUTPUT->pix_icon('i/loading', get_string('loading', 'admin'), 'moodle', array('class'=>'loadingicon')), array('class'=>'admin_colourpicker clearfix'));
|
||||
$content .= html_writer::empty_tag('input', array('type'=>'text','id'=>$this->get_id(), 'name'=>$this->get_full_name(), 'value'=>$this->get_setting(), 'size'=>'12'));
|
||||
if (!empty($this->previewconfig)) {
|
||||
$content .= html_writer::empty_tag('input', array('type'=>'button','id'=>$this->get_id().'_preview', 'value'=>get_string('preview'), 'class'=>'admin_colourpicker_preview'));
|
||||
}
|
||||
$content .= html_writer::end_tag('div');
|
||||
return format_admin_setting($this, $this->visiblename, $content, $this->description, false, '', $this->get_defaultsetting(), $query);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -427,6 +427,166 @@ M.util.init_toggle_class_on_click = function(Y, id, cssselector, toggleclassname
|
||||
}, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises a colour picker
|
||||
*
|
||||
* Designed to be used with admin_setting_configcolourpicker although could be used
|
||||
* anywhere, just give a text input an id and insert a div with the class admin_colourpicker
|
||||
* above or below the input (must have the same parent) and then call this with the
|
||||
* id.
|
||||
*
|
||||
* This code was mostly taken from my [Sam Hemelryk] css theme tool available in
|
||||
* contrib/blocks. For better docs refer to that.
|
||||
*
|
||||
* @param {YUI} Y
|
||||
* @param {int} id
|
||||
* @param {object} previewconf
|
||||
*/
|
||||
M.util.init_colour_picker = function(Y, id, previewconf) {
|
||||
/**
|
||||
* We need node and event-mouseenter
|
||||
*/
|
||||
Y.use('node', 'event-mouseenter', function(){
|
||||
/**
|
||||
* The colour picker object
|
||||
*/
|
||||
var colourpicker = {
|
||||
box : null,
|
||||
input : null,
|
||||
image : null,
|
||||
preview : null,
|
||||
current : null,
|
||||
eventClick : null,
|
||||
eventMouseEnter : null,
|
||||
eventMouseLeave : null,
|
||||
eventMouseMove : null,
|
||||
width : 300,
|
||||
height : 100,
|
||||
factor : 5,
|
||||
/**
|
||||
* Initalises the colour picker by putting everything together and wiring the events
|
||||
*/
|
||||
init : function() {
|
||||
this.input = Y.one('#'+id);
|
||||
this.box = this.input.ancestor().one('.admin_colourpicker');
|
||||
this.image = Y.Node.create('<img alt="" class="colourdialogue" />');
|
||||
this.image.setAttribute('src', M.util.image_url('i/colourpicker', 'moodle'));
|
||||
this.preview = Y.Node.create('<div class="previewcolour"></div>');
|
||||
this.preview.setStyle('width', this.height/2).setStyle('height', this.height/2).setStyle('backgroundColor', this.input.get('value'));
|
||||
this.current = Y.Node.create('<div class="currentcolour"></div>');
|
||||
this.current.setStyle('width', this.height/2).setStyle('height', this.height/2 -1).setStyle('backgroundColor', this.input.get('value'));
|
||||
this.box.setContent('').append(this.image).append(this.preview).append(this.current);
|
||||
|
||||
if (typeof(previewconf) === 'object' && previewconf !== null) {
|
||||
Y.one('#'+id+'_preview').on('click', function(e){
|
||||
Y.one(previewconf.selector).setStyle(previewconf.style, this.input.get('value'));
|
||||
}, this);
|
||||
}
|
||||
|
||||
this.eventClick = this.image.on('click', this.pickColour, this);
|
||||
this.eventMouseEnter = Y.on('mouseenter', this.startFollow, this.image, this);
|
||||
},
|
||||
/**
|
||||
* Starts to follow the mouse once it enter the image
|
||||
*/
|
||||
startFollow : function(e) {
|
||||
this.eventMouseEnter.detach();
|
||||
this.eventMouseLeave = Y.on('mouseleave', this.endFollow, this.image, this);
|
||||
this.eventMouseMove = this.image.on('mousemove', function(e){
|
||||
this.preview.setStyle('backgroundColor', this.determineColour(e));
|
||||
}, this);
|
||||
},
|
||||
/**
|
||||
* Stops following the mouse
|
||||
*/
|
||||
endFollow : function(e) {
|
||||
this.eventMouseMove.detach();
|
||||
this.eventMouseLeave.detach();
|
||||
this.eventMouseEnter = Y.on('mouseenter', this.startFollow, this.image, this);
|
||||
},
|
||||
/**
|
||||
* Picks the colour the was clicked on
|
||||
*/
|
||||
pickColour : function(e) {
|
||||
var colour = this.determineColour(e);
|
||||
this.input.set('value', colour);
|
||||
this.current.setStyle('backgroundColor', colour);
|
||||
},
|
||||
/**
|
||||
* Calculates the colour fromthe given co-ordinates
|
||||
*/
|
||||
determineColour : function(e) {
|
||||
var eventx = Math.floor(e.pageX-e.target.getX());
|
||||
var eventy = Math.floor(e.pageY-e.target.getY());
|
||||
|
||||
var imagewidth = this.width;
|
||||
var imageheight = this.height;
|
||||
var factor = this.factor;
|
||||
var colour = [255,0,0];
|
||||
|
||||
var matrices = [
|
||||
[ 0, 1, 0],
|
||||
[ -1, 0, 0],
|
||||
[ 0, 0, 1],
|
||||
[ 0, -1, 0],
|
||||
[ 1, 0, 0],
|
||||
[ 0, 0, -1]
|
||||
];
|
||||
|
||||
var matrixcount = matrices.length;
|
||||
var limit = Math.round(imagewidth/matrixcount);
|
||||
var heightbreak = Math.round(imageheight/2);
|
||||
|
||||
for (var x = 0; x < imagewidth; x++) {
|
||||
var divisor = Math.floor(x / limit);
|
||||
var matrix = matrices[divisor];
|
||||
|
||||
colour[0] += matrix[0]*factor;
|
||||
colour[1] += matrix[1]*factor;
|
||||
colour[2] += matrix[2]*factor;
|
||||
|
||||
if (eventx==x) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var pixel = [colour[0], colour[1], colour[2]];
|
||||
if (eventy < heightbreak) {
|
||||
pixel[0] += Math.floor(((255-pixel[0])/heightbreak) * (heightbreak - eventy));
|
||||
pixel[1] += Math.floor(((255-pixel[1])/heightbreak) * (heightbreak - eventy));
|
||||
pixel[2] += Math.floor(((255-pixel[2])/heightbreak) * (heightbreak - eventy));
|
||||
} else if (eventy > heightbreak) {
|
||||
pixel[0] = Math.floor((imageheight-eventy)*(pixel[0]/heightbreak));
|
||||
pixel[1] = Math.floor((imageheight-eventy)*(pixel[1]/heightbreak));
|
||||
pixel[2] = Math.floor((imageheight-eventy)*(pixel[2]/heightbreak));
|
||||
}
|
||||
|
||||
return this.convert_rgb_to_hex(pixel);
|
||||
},
|
||||
/**
|
||||
* Converts an RGB value to Hex
|
||||
*/
|
||||
convert_rgb_to_hex : function(rgb) {
|
||||
var hex = '#';
|
||||
var hexchars = "0123456789ABCDEF";
|
||||
for (var i=0; i<3; i++) {
|
||||
var number = Math.abs(rgb[i]);
|
||||
if (number == 0 || isNaN(number)) {
|
||||
hex += '00';
|
||||
} else {
|
||||
hex += hexchars.charAt((number-number%16)/16)+hexchars.charAt(number%16);
|
||||
}
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Initialise the colour picker :) Hoorah
|
||||
*/
|
||||
colourpicker.init();
|
||||
});
|
||||
}
|
||||
|
||||
//=== old legacy JS code, hopefully to be replaced soon by M.xx.yy and YUI3 code ===
|
||||
|
||||
function popupchecker(msg) {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.DS_Store
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
@@ -148,4 +148,13 @@
|
||||
#adminsettings .form-item .patherror {margin-left: 0.5em;}
|
||||
|
||||
#adminthemeselector .selectedtheme td.c0 {border:1px solid;border-right-width:0;}
|
||||
#adminthemeselector .selectedtheme td.c1 {border:1px solid;border-left-width:0;}
|
||||
#adminthemeselector .selectedtheme td.c1 {border:1px solid;border-left-width:0;}
|
||||
|
||||
.admin_colourpicker,
|
||||
.admin_colourpicker_preview {display:none;}
|
||||
.jsenabled .admin_colourpicker_preview {display:inline;}
|
||||
.jsenabled .admin_colourpicker {display:block;height:102px;width:410px;margin-bottom:10px;}
|
||||
.admin_colourpicker .loadingicon {vertical-align:center;margin-left:auto;}
|
||||
.admin_colourpicker .colourdialogue {float:left;border:1px solid #000;}
|
||||
.admin_colourpicker .previewcolour {border:1px solid #000;margin-left:301px;}
|
||||
.admin_colourpicker .currentcolour {border:1px solid #000;margin-left:301px;border-top-width:0;}
|
||||
|
||||
Reference in New Issue
Block a user