Commit 3e4c4a9c authored by Robert Lyon's avatar Robert Lyon Committed by Gerrit Code Review
Browse files

Adjusting the switchbox to be css only (Bug #1403703)

And getting it to work in a block configuration form - see the image
block's configuration form

Includes reverting these commits
db7f4520
9e0c498c

and altering this commit to not use the switchbutton jquery plugin
901df0a5



Change-Id: I818c296cdcf573ede63b1783defb1b528d93ae2d
Signed-off-by: Robert Lyon's avatarRobert Lyon <robertl@catalyst.net.nz>
parent 393e1608
......@@ -82,7 +82,7 @@ class PluginBlocktypeImage extends PluginBlocktype {
return array(
'artefactid' => self::filebrowser_element($instance, (isset($configdata['artefactid'])) ? array($configdata['artefactid']) : null),
'showdescription' => array(
'type' => 'checkbox',
'type' => 'switchbox',
'title' => get_string('showdescription', 'blocktype.file/image'),
'defaultvalue' => !empty($configdata['showdescription']) ? true : false,
),
......
......@@ -745,7 +745,7 @@ class BlockInstance {
}
if ($configure) {
list($content, $js) = array_values($this->build_configure_form($new));
list($content, $js, $css) = array_values($this->build_configure_form($new));
}
else {
try {
......@@ -753,6 +753,7 @@ class BlockInstance {
$jsfiles = call_static_method($blocktypeclass, 'get_instance_javascript', $this);
$inlinejs = call_static_method($blocktypeclass, 'get_instance_inline_javascript', $this);
$js = $this->get_get_javascript_javascript($jsfiles) . $inlinejs;
$css = '';
}
catch (NotFoundException $e) {
// Whoops - where did the image go? There is possibly a bug
......@@ -840,8 +841,10 @@ class BlockInstance {
}
}
}
return array('html' => $smarty->fetch('view/blocktypecontainerediting.tpl'), 'javascript' => $js);
if (is_array($css)) {
$css = array_unique($css);
}
return array('html' => $smarty->fetch('view/blocktypecontainerediting.tpl'), 'javascript' => $js, 'pieformcss' => $css);
}
public function render_viewing() {
......@@ -915,7 +918,7 @@ class BlockInstance {
* Builds the configuration pieform for this blockinstance
*
* @return array Array with two keys: 'html' for raw html, 'javascript' for
* javascript to run
* javascript to run, 'css' for dynamic css to add to header
*/
public function build_configure_form($new=false) {
......@@ -1054,7 +1057,6 @@ class BlockInstance {
// by checking for an api function that has been added especially for
// the purpose, but that is not part of Pieforms. Maybe one day later
// it will be though
// $js = '';
foreach ($elements as $key => $element) {
$element['name'] = $key;
$function = 'pieform_element_' . $element['type'] . '_views_js';
......@@ -1071,7 +1073,20 @@ class BlockInstance {
$js .= $configjs;
}
$renderedform = array('html' => $html, 'javascript' => $js);
// We need to load any dynamic css required for the pieform. We do this
// by checking for an api function that has been added especially for
// the purpose, but that is not part of Pieforms. Maybe one day later
// it will be though
$css = array();
foreach ($elements as $key => $element) {
$element['name'] = $key;
$function = 'pieform_element_' . $element['type'] . '_views_css';
if (is_callable($function)) {
$css[] = call_user_func_array($function, array($pieform, $element));
}
}
$renderedform = array('html' => $html, 'javascript' => $js, 'css' => $css);
return $renderedform;
}
......
jQuery UI plugin switchButton
=============================
This javascript library is required to style a checkbox to a switchbox
Website: https://github.com/olance/jQuery-switchButton
Version: 1.0
Dependency package: jquery-ui
Commit: de704ff1c088e20ce528dff23a26162c439762b0
Changes:
* Added ability to stop callbacks firing on page load
* Added ability to call callback function by string reference
jQuery-switchButton
===================
jQuery iPhone-like switch button meant to be used on a ```<input type="checkbox">```.
This widget will replace the receiver element with an iPhone-style switch button with two states: "on" and "off". Labels
of the states are customizable, as are their presence and position. The receiver element's "checked" attribute is updated
according to the state of the switch, so that it can be used in a ```<form>```.
Demo
----
Check out the demo page here: http://olance.github.io/jQuery-switchButton/
Dependencies
------------
This is a jQuery UI plugin, so you'll need jQuery and jQuery UI.
Usage
-----
Say this is your markup:
<form action="...">
<label for="great">Isn't it great?!</label><input type="checkbox" name="great" id="great">
</form>
You can transform this checkbox to a nice-looking switch button by calling ```switchButton()``` on it:
options = { /* see below */ };
$("input#great").switchButton(options);
By default, this will display a button with "ON" and "OFF" labels on each side of the switch. You can control this and other
parameters at initialization or by calling ```switchButton("option", "optionName", value)```.
Here are the available options:
checked: undefined // State of the switch
show_labels: true // Should we show the on and off labels?
labels_placement: "both" // Position of the labels: "both", "left" or "right"
on_label: "ON" // Text to be displayed when checked
off_label: "OFF" // Text to be displayed when unchecked
width: 25 // Width of the button in pixels
height: 11 // Height of the button in pixels
button_width: 12 // Width of the sliding part in pixels
clear: true // Should we insert a div with style="clear: both;" after the switch button?
clear_after: null // Override the element after which the clearing div should be inserted (null > right after the button)
Styling
-------
The button and labels are styled with a few lines of CSS in ```jquery.switchButton.css```.
Have a look at this file and fiddle with it to change the look of you switch button!
Wordpress users
---------------
Have a look at [this answer](http://wordpress.stackexchange.com/questions/108257/how-to-load-jquery-easing-script-in-wordpress/108267#108267?newreg=7700a444aabf4aadbd1819e794d1d6c4) on StackExchange to include jQuery easing functions in order to make this plugin work in Wordpress.
License
-------
Copyright (c) Olivier Lance - Released under MIT License:
> Permission is hereby granted, free of charge, to any person
> obtaining a copy of this software and associated documentation
> files (the "Software"), to deal in the Software without
> restriction, including without limitation the rights to use,
> copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the
> Software is furnished to do so, subject to the following
> conditions:
>
> The above copyright notice and this permission notice shall be
> included in all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> OTHER DEALINGS IN THE SOFTWARE.
.switch-button-label {
float: left;
font-size: 10pt;
cursor: pointer;
}
.switch-button-label.off {
color: #adadad;
}
.switch-button-label.on {
color: #0088CC;
}
.switch-button-background {
float: left;
position: relative;
background: #ccc;
border: 1px solid #aaa;
margin: 1px 10px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
cursor: pointer;
}
.switch-button-button {
position: absolute;
left: -1px;
top : -1px;
background: #FAFAFA;
border: 1px solid #aaa;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.switch-wrapper-inline {
display: inline-block;
position: relative;
vertical-align: text-bottom;
padding-left: 5px;
}
\ No newline at end of file
/**
* jquery.switchButton.js v1.0
* jQuery iPhone-like switch button
* @author Olivier Lance <olivier.lance@sylights.com>
*
* Copyright (c) Olivier Lance - released under MIT License {{{
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
* }}}
*/
/*
* Meant to be used on a <input type="checkbox">, this widget will replace the receiver element with an iPhone-style
* switch button with two states: "on" and "off".
* Labels of the states are customizable, as are their presence and position. The receiver element's "checked" attribute
* is updated according to the state of the switch, so that it can be used in a <form>.
*
*/
(function($) {
$.widget("sylightsUI.switchButton", {
options: {
checked: undefined, // State of the switch
show_labels: true, // Should we show the on and off labels?
labels_placement: "both", // Position of the labels: "both", "left" or "right"
on_label: "ON", // Text to be displayed when checked
off_label: "OFF", // Text to be displayed when unchecked
width: 25, // Width of the button in pixels
height: 11, // Height of the button in pixels
button_width: 12, // Width of the sliding part in pixels
clear: true, // Should we insert a div with style="clear: both;" after the switch button?
clear_after: null, // Override the element after which the clearing div should be inserted (null > right after the button)
on_callback: undefined, //callback function that will be executed after going to on state
off_callback: undefined, //callback function that will be executed after going to off state
trigger_callback: false
},
_create: function() {
// Init the switch from the checkbox if no state was specified on creation
if (this.options.checked === undefined) {
this.options.checked = this.element.prop("checked");
}
this._initLayout();
this._initEvents();
},
_initLayout: function() {
// Hide the receiver element - but we can't use .hide() as screenreaders
// cannot find it in tab index so we need to move it off screen
this.element.css({"position": "absolute",
"left": "-3000px"});
// Create our objects: two labels and the button
this.off_label = $("<span>").addClass("switch-button-label");
this.on_label = $("<span>").addClass("switch-button-label");
this.button_bg = $("<div>").addClass("switch-button-background");
this.button = $("<div>").addClass("switch-button-button");
// Insert the objects into the DOM
this.off_label.insertAfter(this.element);
this.button_bg.insertAfter(this.off_label);
this.on_label.insertAfter(this.button_bg);
this.button_bg.append(this.button);
// Insert a clearing element after the specified element if needed
if(this.options.clear)
{
if (this.options.clear_after === null) {
this.options.clear_after = this.on_label;
}
$("<div>").css({
clear: "left"
}).insertAfter(this.options.clear_after);
}
// Call refresh to update labels text and visibility
this._refresh();
// Init labels and switch state
// This will animate all checked switches to the ON position when
// loading... this is intentional!
this.options.checked = !this.options.checked;
this._toggleSwitch();
},
_refresh: function() {
// Refresh labels display
if (this.options.show_labels) {
this.off_label.show();
this.on_label.show();
}
else {
this.off_label.hide();
this.on_label.hide();
}
// Move labels around depending on labels_placement option
switch(this.options.labels_placement) {
case "both":
{
// Don't move anything if labels are already in place
if(this.button_bg.prev() !== this.off_label || this.button_bg.next() !== this.on_label)
{
// Detach labels form DOM and place them correctly
this.off_label.detach();
this.on_label.detach();
this.off_label.insertBefore(this.button_bg);
this.on_label.insertAfter(this.button_bg);
// Update label classes
this.on_label.addClass(this.options.checked ? "on" : "off").removeClass(this.options.checked ? "off" : "on");
this.off_label.addClass(this.options.checked ? "off" : "on").removeClass(this.options.checked ? "on" : "off");
}
break;
}
case "left":
{
// Don't move anything if labels are already in place
if(this.button_bg.prev() !== this.on_label || this.on_label.prev() !== this.off_label)
{
// Detach labels form DOM and place them correctly
this.off_label.detach();
this.on_label.detach();
this.off_label.insertBefore(this.button_bg);
this.on_label.insertBefore(this.button_bg);
// update label classes
this.on_label.addClass("on").removeClass("off");
this.off_label.addClass("off").removeClass("on");
}
break;
}
case "right":
{
// Don't move anything if labels are already in place
if(this.button_bg.next() !== this.off_label || this.off_label.next() !== this.on_label)
{
// Detach labels form DOM and place them correctly
this.off_label.detach();
this.on_label.detach();
this.off_label.insertAfter(this.button_bg);
this.on_label.insertAfter(this.off_label);
// update label classes
this.on_label.addClass("on").removeClass("off");
this.off_label.addClass("off").removeClass("on");
}
break;
}
}
// Refresh labels texts
this.on_label.html(this.options.on_label);
this.off_label.html(this.options.off_label);
// Refresh button's dimensions
this.button_bg.width(this.options.width);
this.button_bg.height(this.options.height);
this.button.width(this.options.button_width);
this.button.height(this.options.height);
},
_initEvents: function() {
var self = this;
// Toggle switch when the switch is clicked
this.button_bg.click(function(e) {
e.preventDefault();
e.stopPropagation();
self._toggleSwitch();
return false;
});
this.button.click(function(e) {
e.preventDefault();
e.stopPropagation();
self._toggleSwitch();
return false;
});
// Set switch value when clicking labels
this.on_label.click(function(e) {
if (self.options.checked && self.options.labels_placement === "both") {
return false;
}
self._toggleSwitch();
return false;
});
this.off_label.click(function(e) {
if (!self.options.checked && self.options.labels_placement === "both") {
return false;
}
self._toggleSwitch();
return false;
});
},
_setOption: function(key, value) {
if (key === "checked") {
this._setChecked(value);
return;
}
this.options[key] = value;
this._refresh();
},
_setChecked: function(value) {
if (value === this.options.checked) {
return;
}
this.options.checked = !value;
this._toggleSwitch();
},
_toggleSwitch: function() {
this.options.checked = !this.options.checked;
var newLeft = "";
if (this.options.checked) {
// Update the underlying checkbox state
this.element.prop("checked", true);
this.element.change();
var dLeft = this.options.width - this.options.button_width;
newLeft = "+=" + dLeft;
// Update labels states
if(this.options.labels_placement == "both")
{
this.off_label.removeClass("on").addClass("off");
this.on_label.removeClass("off").addClass("on");
}
else
{
this.off_label.hide();
this.on_label.show();
}
this.button_bg.addClass("checked");
//execute on state callback if its supplied
if(this.options.trigger_callback === true) {
if(typeof this.options.on_callback === 'function') this.options.on_callback.call(this);
else if(typeof window[this.options.on_callback] === 'function') window[this.options.on_callback].call(this);
}
this.options.trigger_callback = true;
}
else {
// Update the underlying checkbox state
this.element.prop("checked", false);
this.element.change();
newLeft = "-1px";
// Update labels states
if(this.options.labels_placement == "both")
{
this.off_label.removeClass("off").addClass("on");
this.on_label.removeClass("on").addClass("off");
}
else
{
this.off_label.show();
this.on_label.hide();
}
this.button_bg.removeClass("checked");
//execute off state callback if its supplied
if(this.options.trigger_callback === true) {
if(typeof this.options.off_callback === 'function') this.options.off_callback.call(this);
else if(typeof window[this.options.off_callback] === 'function') window[this.options.off_callback].call(this);
}
this.options.trigger_callback = true;
}
// Animate the switch
this.button.animate({ left: newLeft }, 250, "easeInOutCubic");
}
});
})(jQuery);
......@@ -1239,7 +1239,14 @@
// configblock.javascript might use MochiKit so $ must have its default value
eval(configblock.javascript);
})(getElement);
if (configblock.pieformcss) {
for (var i = 0; i < configblock.pieformcss.length; i++) {
var id = $(configblock.pieformcss[i]).attr('id');
if ($("#" + id).length == 0) {
$('head').append(configblock.pieformcss[i]);
}
}
}
// Lock focus to the newly opened dialog
newblock.find('.deletebutton').focus();
keytabbinginadialog(newblock, newblock.find('.deletebutton'), newblock.find('.cancel'));
......
......@@ -18,18 +18,8 @@ require_once(get_config('docroot') . 'lib/pieforms/pieform/elements/checkbox.php
* @param array $element The element to render
*
* The element can contain these variables (all are optional):
* show_labels boolean Should we show the on_label and/or off_label labels?
* labels_placement text Position of the labels: "both", "left" or "right"
* on_label text Text to be displayed when checked
* off_label text Text to be displayed when unchecked
* width integer Width of the button in pixels
* height integer Height of the button in pixels
* button_width integer Width of the sliding part in pixels
* clear boolean Should we insert a div with style="clear: both;" after the switch button?
* clear_after text Override the element after which the clearing div should be
* inserted. Accepts valid jQuery selector value eg '#foo'. Default is null.
* on_callback function Callback function that will be executed after going to on state
* off_callback function Callback function that will be executed after going to off state
* switchtext text Text to be displayed on button - chosen by style
* valid options are 'onoff', 'yesno', 'truefalse' - used for headdata
* wrapperclass text Class to use on the div wrapper
*
* @return string The HTML for the element
......@@ -37,32 +27,69 @@ requi