Merge pull request #278 from bergware/6.4-wip

More changes in Docker and VM
This commit is contained in:
tom mortensen
2018-03-07 09:16:43 -08:00
committed by GitHub
22 changed files with 120 additions and 1872 deletions

View File

@@ -4,6 +4,19 @@ Tag="cubes"
Cond="(pgrep('dockerd')!==false)"
Markdown="false"
---
<?PHP
/* Copyright 2005-2018, Lime Technology
* Copyright 2014-2018, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2018, Bergware International.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
?>
<link type="text/css" rel="stylesheet" href="/webGui/styles/jquery.ui.css">
<link type="text/css" rel="stylesheet" href="/webGui/styles/jquery.switchbutton.css">
@@ -22,6 +35,7 @@ img.stopped{opacity:0.3}
.started{color:#009900}
.stopped{color:#EF3D47}
.switch-button-label.off{color:inherit}
th.three{width:3%}
</style>
<form id="formAutostart" method="POST" action="/plugins/dynamix.docker.manager/include/UpdateConfig.php" target="progressFrame">
@@ -37,7 +51,7 @@ img.stopped{opacity:0.3}
<div id="iframe-popup" style="display:none;-webkit-overflow-scrolling:touch;"></div>
<span class="status" style="margin-top:-44px"><span style="float:right;margin-left:48px"><input type="checkbox" class="advancedview"></span><span style="float:right"><input type="checkbox" class="expandedlist"></span></span>
<table class="tablesorter shift" id="docker_containers">
<thead><tr><th></th><th>Application</th><th>Version</th><th>Network</th><th>Port Mappings <small>(App to Host)</small></th><th>Volume Mappings <small>(App to Host)</small></th><th width="80px" style="text-align:center">Autostart</th><th>Log</th></tr></thead>
<thead><tr><th></th><th>Application</th><th>Version</th><th>Network</th><th>Port Mappings <small>(App to Host)</small></th><th>Volume Mappings <small>(App to Host)</small></th><th width="80px" style="text-align:center">Autostart</th><th class="three">Log</th></tr></thead>
<tbody id="docker_list"><tr><td colspan='8' style='text-align:center;padding-top:12px'><i class='fa fa-spinner fa-spin icon'></i>Please wait... retrieving container information</td></tr></tbody>
</table>
<input type="button" onclick="addContainer()" value="Add Container"/>
@@ -50,12 +64,12 @@ img.stopped{opacity:0.3}
<script>
function startAll() {
$('input[type=button]').prop('disabled',true);
for (var i=0,ct; ct=docker[i]; i++) if (ct.state=='false') $('#'+ct.id).addClass('fa-spin');
for (var i=0,ct; ct=docker[i]; i++) if (ct.state=='false') $('#'+ct.id).find('i').addClass('fa-spin');
$.post('/plugins/dynamix.docker.manager/include/ContainerManager.php',{action:'start'}, function(){loadlist();});
}
function stopAll() {
$('input[type=button]').prop('disabled',true);
for (var i=0,ct; ct=docker[i]; i++) if (ct.state=='true') $('#'+ct.id).addClass('fa-spin');
for (var i=0,ct; ct=docker[i]; i++) if (ct.state=='true') $('#'+ct.id).find('i').addClass('fa-spin');
$.post('/plugins/dynamix.docker.manager/include/ContainerManager.php',{action:'stop'}, function(){loadlist();});
}
<?if ($display['resize']):?>

View File

@@ -144,7 +144,7 @@ function rmImage(image, imageName) {
function eventControl(params, reload) {
var spin = typeof reload != 'undefined';
if (spin) $('#'+params['container']).addClass('fa-spin');
if (spin) $('#'+params['container']).find('i').addClass('fa-spin');
$.post(eventURL, params, function(data) {
if (data.success === true) {
if (spin) setTimeout(reload+'()',500); else location=window.location.href;

View File

@@ -15,7 +15,6 @@ Markdown="false"
* all copies or substantial portions of the Software.
*/
?>
<?
require_once "$docroot/plugins/dynamix.vm.manager/VMedit.php";
require_once "$docroot/plugins/dynamix.vm.manager/classes/VMedit.php";
?>

View File

@@ -15,7 +15,6 @@ Markdown="false"
* all copies or substantial portions of the Software.
*/
?>
<?
require_once "$docroot/plugins/dynamix.vm.manager/VMedit.php";
require_once "$docroot/plugins/dynamix.vm.manager/classes/VMedit.php";
?>

View File

@@ -86,10 +86,7 @@ if ($subaction) {
}
echo "<script>clearHistory();</script>";
}
if ($libvirt_running=='yes') {
$vms = $lv->get_domains() ?: [];
sort($vms);
}
if ($libvirt_running=='yes') $vms = $lv->get_domains();
if (empty($vms)) {
$msg = $libvirt_running=='yes'
? 'No VMs defined. Create from template or add XML.'
@@ -110,10 +107,11 @@ div.four label.cpu2{width:33%}
div.Panel{float:unset;margin:4px;height:inherit;border:none;}
div.Panel:hover{background-color:unset;}
div.PanelText{display:none;}
th.five{width:5%}
</style>
<table class="tablesorter shift kvm" id="kvm_table">
<thead><tr><th><i class="fa fa-th-list"></i></th><th>Name</th><th>Description</th><th>CPUs</th><th>Memory</th><th>vDisks</th><th>Graphics</th><th>Autostart</th></tr></thead>
<tbody id="kvm_list"><tr><td colspan='8' style='text-align:center;padding-top:12px'><i class='fa fa-spinner fa-spin icon'></i>Please wait... retrieving VM information</td></tr></tbody>
<thead><tr><th><i class="fa fa-th-list"></i></th><th>Name</th><th>Description</th><th>CPUs</th><th>Memory</th><th>vDisks</th><th>Graphics</th><th class="five">Autostart</th><th class="five"><i class="fa fa-sort"></i></th></tr></thead>
<tbody id="kvm_list"><tr><td colspan='9' style='text-align:center;padding-top:12px'><i class='fa fa-spinner fa-spin icon'></i>Please wait... retrieving VM information</td></tr></tbody>
</table>
<input type="button" onclick="addVM()" id="btnAddVM" value="Add VM"/>
<input type="button" onclick="startAll()" value="Start all VMs"/>
@@ -126,12 +124,12 @@ div.PanelText{display:none;}
<script>
function startAll() {
$('input[type=button]').prop('disabled',true);
for (var i=0,vm; vm=kvm[i]; i++) if (vm.state!='running') $('#vm-'+vm.id).addClass('fa-spin');
for (var i=0,vm; vm=kvm[i]; i++) if (vm.state!='running') $('#vm-'+vm.id).find('i').addClass('fa-spin');
$.post('/plugins/dynamix.vm.manager/classes/VMManager.php',{action:'start'}, function(){loadlist();});
}
function stopAll() {
$('input[type=button]').prop('disabled',true);
for (var i=0,vm; vm=kvm[i]; i++) if (vm.state=='running') $('#vm-'+vm.id).addClass('fa-spin');
for (var i=0,vm; vm=kvm[i]; i++) if (vm.state=='running') $('#vm-'+vm.id).find('i').addClass('fa-spin');
$.post('/plugins/dynamix.vm.manager/classes/VMManager.php',{action:'stop'}, function(){loadlist();});
}
function vncOpen() {
@@ -204,12 +202,35 @@ foreach ($vms as $vm) {
<?endif;?>
$('.autostart').switchButton({labels_placement:"right"});
$('.autostart').change(function() {
$.post('/plugins/dynamix.vm.manager/VMajax.php',{action:'domain-autostart',uuid:$(this).attr('uuid'),autostart:$(this).prop('checked'),response:'json'},function(data){
$.post('/plugins/dynamix.vm.manager/classes/VMajax.php',{action:'domain-autostart',uuid:$(this).attr('uuid'),autostart:$(this).prop('checked'),response:'json'},function(data){
$(this).prop('checked', data.autostart);
},'json');
});
context.init({preventDoubleContext:false});
$('input[type=button]').prop('disabled',false);
$('.text').click(showInput);
$('.input').blur(hideInput);
$('i.up,i.down').click(function() {
var row1 = $(this).parents('tr:first');
var row2 = row1.next();
var color1 = row1.css('background-color');
if ($(this).is('.up')) {
var color2 = row1.prev().prev().css('background-color');
row1.prev().prev().css('background-color',color1);
row1.css('background-color',color2);
row1.insertBefore(row1.prev().prev());
row2.insertBefore(row2.prev().prev());
} else {
var color2 = row1.next().next().css('background-color');
row1.next().next().css('background-color',color1);
row1.css('background-color',color2);
row2.insertAfter(row2.next().next());
row1.insertAfter(row1.next().next());
}
var names = ''; var index = '';
row1.parent().children().find('td.vm-name').each(function(){names+=$(this).text()+';';index+=$(this).parent().parent().children().index($(this).parent())+';';});
$.post('/plugins/dynamix.vm.manager/classes/UserPrefs.php',{names:names,index:index});
});
});
}
$(function() {
@@ -217,8 +238,6 @@ $(function() {
<?$color = strpos($msg, "rror:")!==false ? 'red-text':'green-text'?>
$('#countdown').html("<span class='<?-$color?>'><?=$msg?></span>");
<?endif;?>
$('.text').click(showInput);
$('.input').blur(hideInput);
$('#btnAddVM').click(function AddVMEvent(){$('.tab>input#tab2').click();});
loadlist();
});

View File

@@ -334,11 +334,11 @@ $(function(){
return;
}
if ($('#pcie_acs_override').val() == '1') {
$.getJSON("/plugins/dynamix.vm.manager/VMajax.php", {action: "acs-override-enable"}, function(data) {
$.getJSON("/plugins/dynamix.vm.manager/classes/VMajax.php", {action: "acs-override-enable"}, function(data) {
$("#settingsForm").submit();
});
} else {
$.getJSON("/plugins/dynamix.vm.manager/VMajax.php", {action: "acs-override-disable"}, function(data) {
$.getJSON("/plugins/dynamix.vm.manager/classes/VMajax.php", {action: "acs-override-disable"}, function(data) {
$("#settingsForm").submit();
});
}
@@ -365,7 +365,7 @@ $(function(){
$form.find('input,select').prop('disabled', true);
$button.removeClass('fa-download').addClass('fa-circle-o-notch fa-spin');
$.post("/plugins/dynamix.vm.manager/VMajax.php", postdata, function( data ) {
$.post("/plugins/dynamix.vm.manager/classes/VMajax.php", postdata, function( data ) {
if (data.error) {
$("#download_status").html('<span style="color: red">' + data.error + '</span>');
} else {
@@ -419,7 +419,7 @@ $(function(){
file: $(this).val()
};
$.get("/plugins/dynamix.vm.manager/VMajax.php", params, function( data ) {
$.get("/plugins/dynamix.vm.manager/classes/VMajax.php", params, function( data ) {
if (!data.exists) {
$("#download_button").show('fast');

View File

@@ -0,0 +1,21 @@
<?PHP
/* Copyright 2005-2018, Lime Technology
* Copyright 2015-2018, Derek Macias, Eric Schultz, Jon Panozzo.
* Copyright 2012-2018, Bergware International.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
?>
<?
$names = explode(';',$_POST['names']);
$index = explode(';',$_POST['index']);
$save = []; $i = 0;
foreach ($names as $name) if ($name) $save[] = "$name=\"".$index[$i++]."\"";
file_put_contents('/boot/config/plugins/dynamix.vm.manager/userprefs.txt', implode("\n",$save)."\n");
?>

View File

@@ -16,12 +16,19 @@ $docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
require_once "$docroot/webGui/include/Helpers.php";
require_once "$docroot/plugins/dynamix.vm.manager/classes/libvirt_helpers.php";
$vms = $lv->get_domains() ?: [];
sort($vms);
$txt = '/boot/config/plugins/dynamix.vm.manager/userprefs.txt';
$vms = $lv->get_domains();
if (empty($vms)) {
echo '<tr><td colspan="8" style="text-align:center;padding-top:12px">No Virtual Machines installed</td></tr>';
return;
}
if (file_exists($txt)) {
$prefs = parse_ini_file($txt); $sort = [];
foreach ($vms as $vm) $sort[] = $prefs[$vm] ?? 999;
array_multisort($sort,SORT_NUMERIC,$vms);
} else {
natsort($vms);
}
$i = 0;
$menu = [];
$kvm = ['var kvm=[];'];
@@ -75,13 +82,14 @@ foreach ($vms as $vm) {
/* VM information */
echo "<tr style='background-color:".bcolor($i)."'>";
echo "<td style='width:48px;padding:4px'>".renderVMContentIcon($uuid, $vm, $vmicon, $state)."</td>";
echo "<td><a href='#' onclick='return toggle_id(\"name{$i}\")' title='click for more VM info'>$vm</a></td>";
echo "<td class='vm-name'><a href='#' onclick='return toggle_id(\"name{$i}\")' title='click for more VM info'>$vm</a></td>";
echo "<td>$desc</td>";
echo "<td><a class='vcpu{$i}' style='cursor:pointer'>$vcpu</a></td>";
echo "<td>$mem</td>";
echo "<td title='$diskdesc'>$disks</td>";
echo "<td>$graphics</td>";
echo "<td><input class='autostart' type='checkbox' name='auto_{$vm}' title='Toggle VM auostart' uuid='$uuid' $auto></td></tr>";
echo "<td><input class='autostart' type='checkbox' name='auto_{$vm}' title='Toggle VM auostart' uuid='$uuid' $auto></td>";
echo "<td><a href='#' title='Move row up'><i class='fa fa-arrow-up up'></i></a>&nbsp;<a href='#' title='Move row down'><i class='fa fa-arrow-down down'></i></a></td></tr>";
/* Disk device information */
echo "<tr id='name".($i++)."' style='display:none'>";

View File

@@ -27,7 +27,7 @@ foreach ($vms as $vm) {
case 'stop':
if ($state!='running') continue;
$result = $lv->domain_shutdown($domName) ? ['success'=>true, 'state'=>$lv->domain_get_state($domName)] : ['error'=>$lv->get_last_error()];
$n = 10; // wait for VM to die
$n = 20; // wait for VM to die
while ($result['success'] && $lv->domain_get_state($domName)=='running') {sleep(1); if(!--$n) break;}
break;
case 'start':

View File

@@ -118,10 +118,9 @@ switch ($action) {
$arrResponse = $lv->domain_shutdown($domName) ?
['success' => true, 'state' => $lv->domain_get_state($domName)] :
['error' => $lv->get_last_error()];
$n = 10; // wait for VM to die
$n = 20; // wait for VM to die
while ($arrResponse['success'] && $lv->domain_get_state($domName)=='running') {
sleep(1);
if(!--$n) break;
sleep(1); if(!--$n) break;
}
break;

View File

@@ -1,7 +1,7 @@
function ajaxVMDispatch(params, reload){
var spin = typeof reload != 'undefined';
if (spin) $('#vm-'+params['uuid']).addClass('fa-spin');
$.post("/plugins/dynamix.vm.manager/VMajax.php", params, function(data) {
if (spin) $('#vm-'+params['uuid']).find('i').addClass('fa-spin');
$.post("/plugins/dynamix.vm.manager/classes/VMajax.php", params, function(data) {
if (data.error) {
swal({title:"Execution error",text:data.error,type:"error"});
} else {

View File

@@ -1133,7 +1133,7 @@ $(function() {
$disk_bus_sections.filter('.wasadvanced').removeClass('wasadvanced').addClass('advanced');
slideDownRows($disk_bus_sections.not(isVMAdvancedMode() ? '.basic' : '.advanced'));
$.getJSON("/plugins/dynamix.vm.manager/VMajax.php?action=file-info&file=" + encodeURIComponent($disk_input.val()), function( info ) {
$.getJSON("/plugins/dynamix.vm.manager/classes/VMajax.php?action=file-info&file=" + encodeURIComponent($disk_input.val()), function( info ) {
if (info.isfile || info.isblock) {
slideUpRows($disk_file_sections);
$disk_file_sections.filter('.advanced').removeClass('advanced').addClass('wasadvanced');
@@ -1159,7 +1159,7 @@ $(function() {
$disk_bus_sections.filter('.wasadvanced').removeClass('wasadvanced').addClass('advanced');
slideDownRows($disk_bus_sections.not(isVMAdvancedMode() ? '.basic' : '.advanced'));
$.getJSON("/plugins/dynamix.vm.manager/VMajax.php?action=file-info&file=" + encodeURIComponent(auto_disk_path), function( info ) {
$.getJSON("/plugins/dynamix.vm.manager/classes/VMajax.php?action=file-info&file=" + encodeURIComponent(auto_disk_path), function( info ) {
if (info.isfile || info.isblock) {
slideUpRows($disk_file_sections);
$disk_file_sections.filter('.advanced').removeClass('advanced').addClass('wasadvanced');
@@ -1277,7 +1277,7 @@ $(function() {
$("#vmform").on("click", ".mac_generate", function generateMac() {
var $input = $(this).prev('input');
$.getJSON("/plugins/dynamix.vm.manager/VMajax.php?action=generate-mac", function( data ) {
$.getJSON("/plugins/dynamix.vm.manager/classes/VMajax.php?action=generate-mac", function( data ) {
if (data.mac) {
$input.val(data.mac);
}

View File

@@ -1028,7 +1028,7 @@ $(function() {
$("#vmform").on("click", ".mac_generate", function generateMac() {
var $input = $(this).prev('input');
$.getJSON("/plugins/dynamix.vm.manager/VMajax.php?action=generate-mac", function (data) {
$.getJSON("/plugins/dynamix.vm.manager/classes/VMajax.php?action=generate-mac", function (data) {
if (data.mac) {
$input.val(data.mac);
}

View File

@@ -1031,7 +1031,7 @@ $(function() {
$("#vmform").on("click", ".mac_generate", function generateMac() {
var $input = $(this).prev('input');
$.getJSON("/plugins/dynamix.vm.manager/VMajax.php?action=generate-mac", function (data) {
$.getJSON("/plugins/dynamix.vm.manager/classes/VMajax.php?action=generate-mac", function (data) {
if (data.mac) {
$input.val(data.mac);
}

View File

@@ -14,12 +14,13 @@
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
require_once "$docroot/webGui/include/Helpers.php";
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
require_once "$docroot/plugins/dynamix.vm.manager/classes/libvirt_helpers.php";
// Get the webGui configuration preferences
extract(parse_plugin_cfg('dynamix',true));
if (pgrep('dockerd')!==false && ($display['dashapps']=='icons' || $display['dashapps']=='docker')) {
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
$DockerClient = new DockerClient();
$DockerTemplates = new DockerTemplates();
$containers = $DockerClient->getDockerContainers() ?: [];
@@ -51,9 +52,15 @@ if (pgrep('dockerd')!==false && ($display['dashapps']=='icons' || $display['dash
}
if (pgrep('libvirtd')!==false && ($display['dashapps']=='icons' || $display['dashapps']=='vms')) {
require_once "$docroot/plugins/dynamix.vm.manager/classes/libvirt_helpers.php";
$vms = $lv->get_domains() ?: [];
sort($vms);
$txt = '/boot/config/plugins/dynamix.vm.manager/userprefs.txt';
$vms = $lv->get_domains();
if (file_exists($txt)) {
$prefs = parse_ini_file($txt); $sort = [];
foreach ($vms as $vm) $sort[] = $prefs[$vm] ?? 999;
array_multisort($sort,SORT_NUMERIC,$vms);
} else {
natsort($vms);
}
foreach ($vms as $vm) {
$res = $lv->get_domain_by_name($vm);
$uuid = libvirt_domain_get_uuid_string($res);

File diff suppressed because one or more lines are too long

View File

@@ -1,166 +0,0 @@
/*
* Context.js
* Copyright Jacob Kelley
* MIT License
*/
var context = context || (function () {
var options = {
fadeSpeed: 100,
filter: function ($obj) {
// Modify $obj, Do not return
},
above: 'auto',
preventDoubleContext: true,
compress: false
};
function initialize(opts) {
options = $.extend({}, options, opts);
$(document).on('click', 'html', function () {
$('.dropdown-context').fadeOut(options.fadeSpeed, function(){
$('.dropdown-context').css({display:''}).find('.drop-left').removeClass('drop-left');
});
});
if(options.preventDoubleContext){
$(document).on('contextmenu', '.dropdown-context', function (e) {
e.preventDefault();
});
}
$(document).on('mouseenter', '.dropdown-submenu', function(){
var $sub = $(this).find('.dropdown-context-sub:first'),
subWidth = $sub.width(),
subLeft = $sub.offset().left,
collision = (subWidth+subLeft) > window.innerWidth;
if(collision){
$sub.addClass('drop-left');
}
});
}
function updateOptions(opts){
options = $.extend({}, options, opts);
}
function buildMenu(data, id, subMenu) {
var subClass = (subMenu) ? ' dropdown-context-sub' : '',
compressed = options.compress ? ' compressed-context' : '',
$menu = $('<ul class="dropdown-menu dropdown-context' + subClass + compressed+'" id="dropdown-' + id + '"></ul>');
var i = 0, linkTarget = '', useIcons = false;
for(i; i<data.length; i++) {
if (typeof data[i].icon !== 'undefined' && data[i].icon !== '' ) {
$menu.addClass('fa-ul');
useIcons = true;
break;
}
}
for(i = 0; i<data.length; i++) {
var icon = '';
if (typeof data[i].divider !== 'undefined') {
$menu.append('<li class="divider"></li>');
} else if (typeof data[i].header !== 'undefined') {
if (typeof data[i].image !== 'undefined' && data[i].image !== '') {
$menu.append('<li class="nav-header"><img src="' + data[i].image + '"/> ' + data[i].header + '</li>');
} else {
$menu.append('<li class="nav-header">' + data[i].header + '</li>');
}
} else {
if (typeof data[i].href == 'undefined') {
data[i].href = '#';
}
if (typeof data[i].target !== 'undefined') {
linkTarget = ' target="'+data[i].target+'"';
}
if (useIcons){
if (! options.compress ) {
largeIcon = " fa-lg ";
} else {
largeIcon = "";
}
if (typeof data[i].icon !== 'undefined' && data[i].icon !== '' ) {
icon = ' <i class="fa fa-fw ' + data[i].icon + largeIcon + '"></i>';
} else {
icon = ' <i class="fa fa-fw"></i>';
}
}
if (typeof data[i].subMenu !== 'undefined') {
$sub = ('<li><a tabindex="-1" href="' + data[i].href + '">' + icon + "&nbsp;&nbsp;" + data[i].text + '</a></li>');
} else {
$sub = $('<li><a tabindex="-1" href="' + data[i].href + '"'+linkTarget+'>' + icon + "&nbsp;&nbsp;" + data[i].text + '</a></li>');
}
if (typeof data[i].action !== 'undefined') {
var actiond = new Date(),
actionID = 'event-' + actiond.getTime() * Math.floor(Math.random()*100000),
eventAction = data[i].action;
$sub.find('a').attr('id', actionID);
$('#' + actionID).addClass('context-event');
$(document).on('click', '#' + actionID, eventAction);
}
$menu.append($sub);
if (typeof data[i].subMenu != 'undefined') {
var subMenuData = buildMenu(data[i].subMenu, id, true);
$menu.find('li:last').append(subMenuData);
}
}
if (typeof options.filter == 'function') {
options.filter($menu.find('li:last'));
}
}
return $menu;
}
function addContext(selector, data) {
destroyContext(selector);
var id = selector.replace('#', ''),
$menu = buildMenu(data, id);
$('body').append($menu);
$(document).on('click', selector.replace(/(:|\.|\[|\]|,)/g, "\\$1"), function (e) {
e.preventDefault();
e.stopPropagation();
$('.dropdown-context:not(.dropdown-context-sub)').hide();
$dd = $('#dropdown-' + id.replace(/(:|\.|\[|\]|,)/g, "\\$1"));
var place_above = false;
if (typeof options.above == 'boolean') {
place_above = options.above;
} else if (typeof options.above == 'string' && options.above == 'auto') {
place_above = ((e.pageY + $dd.height() + 32) > $(window).height() + $(document).scrollTop());
}
if (place_above) {
$dd.addClass('dropdown-context-up').css({
top: e.pageY - 24 - $dd.height(),
left: Math.min(Math.max(e.pageX - 13, 0), window.innerWidth - 168)
}).fadeIn(options.fadeSpeed);
} else {
$dd.removeClass('dropdown-context-up').css({
top: e.pageY + 24,
left: Math.min(Math.max(e.pageX - 13, 0), window.innerWidth - 168)
}).fadeIn(options.fadeSpeed);
}
});
}
function destroyContext(selector) {
selector = selector.replace(/(:|\.|\[|\]|,)/g, "\\$1");
$(document).off('contextmenu', selector).off('click', '.context-event');
$('#dropdown-' + selector.replace('#', '')).remove();
}
return {
init: initialize,
settings: updateOptions,
attach: addContext,
destroy: destroyContext
};
})();

File diff suppressed because one or more lines are too long

View File

@@ -1,249 +1,3 @@
/*
* Default text - jQuery plugin for html5 dragging files from desktop to browser
*
* Author: Weixi Yen
*
* Email: [Firstname][Lastname]@gmail.com
*
* Copyright (c) 2010 Resopollution
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Project home:
* http://www.github.com/weixiyen/jquery-filedrop
*
* Version: 0.1.0
* Adapted by Bergware for use in unRAID OS6 (June 2015)
*
* Features:
* Allows sending of extra parameters with file.
* Works with Firefox 3.6+
* Future-compliant with HTML5 spec (will work with Webkit browsers and IE9)
* Usage:
* See README at project homepage
*
*/
(function($) {
// bergware: expanded dataTransfer reading
var hook = jQuery.event.fixHooks.drop;
if (!hook) {
jQuery.event.fixHooks.drop = {props:['dataTransfer']};
} else {
if (hook.props) hook.props.push('dataTransfer'); else hook.props = ['dataTransfer'];
}
var opts = {}, defaults = {
url: '',
refresh: 1000,
paramname: 'userfile',
maxfiles: 25,
maxfilesize: 1024, // 1MB (bergware: changed unit from MB to KB)
data: {},
drop: empty,
dragEnter: empty,
dragOver: empty,
dragLeave: empty,
docEnter: empty,
docOver: empty,
docLeave: empty,
beforeEach: empty,
afterAll: empty,
rename: empty,
error: function(err, file, i) {alert(err);},
uploadStarted: empty,
uploadFinished: empty,
progressUpdated: empty,
speedUpdated: empty
},
errors = ["BrowserNotSupported", "TooManyFiles", "FileTooLarge"],
doc_leave_timer,
stop_loop = false,
files_count = 0,
files;
$.fn.filedrop = function(options) {
opts = $.extend({}, defaults, options);
this.bind('drop', drop).bind('dragenter', dragEnter).bind('dragover', dragOver).bind('dragleave', dragLeave);
$(document).bind('drop', docDrop).bind('dragenter', docEnter).bind('dragover', docOver).bind('dragleave', docLeave);
};
function drop(e) {
opts.drop(e);
files = e.dataTransfer.files;
if (files === null || files === undefined) {
opts.error(errors[0]);
return false;
}
files_count = files.length;
e.preventDefault();
return upload(); // bergware: return success/failure state
}
function getBuilder(filename, filedata) {
// bergware: rewrite of function to handle file transfer using standard POST request
var builder = [];
$.each(opts.data, function(key, val) {
if (typeof val === 'function') val = val();
builder.push(key + '=' + val);
});
builder.push('filename=' + encodeURI(filename));
builder.push('filedata=' + filedata);
return builder.join('&');
}
function progress(e) {
if (e.lengthComputable) {
var percentage = Math.round((e.loaded * 100) / e.total);
if (this.currentProgress != percentage) {
this.currentProgress = percentage;
opts.progressUpdated(this.index, this.file, this.currentProgress);
var elapsed = new Date().getTime();
var diffTime = elapsed - this.currentStart;
if (diffTime >= opts.refresh) {
var diffData = e.loaded - this.startData;
var speed = diffData / diffTime; // KB per second
opts.speedUpdated(this.index, this.file, speed);
this.startData = e.loaded;
this.currentStart = elapsed;
}
}
}
}
function upload() {
stop_loop = false;
if (!files) {
opts.error(errors[0]);
return false;
}
var filesDone = 0, filesRejected = 0;
if (files_count > opts.maxfiles) {
opts.error(errors[1]);
return false;
}
for (var i=0; i<files_count; i++) {
if (stop_loop) return false;
try {
if (beforeEach(files[i]) != false) {
if (i === files_count) return;
var reader = new FileReader(),
max_file_size = 1024 * opts.maxfilesize; // bergware: changed unit from MB to KB
reader.index = i;
if (files[i].size > max_file_size) {
opts.error(errors[2], files[i], i);
filesRejected++;
continue;
}
reader.onloadend = send;
reader.readAsDataURL(files[i]); // bergware: changed binary upload to base64 upload
} else {
filesRejected++;
}
} catch(err) {
opts.error(errors[0]);
return false;
}
}
function send(e) {
// Sometimes the index is not attached to the
// event object. Find it by size. Hack for sure.
// bergware: adapted function to handle file transfer using standard POST request
if (e.target.index == undefined) {
e.target.index = getIndexBySize(e.total);
}
var xhr = new XMLHttpRequest(), upload = xhr.upload, file = files[e.target.index], index = e.target.index, start_time = new Date().getTime(), builder;
newName = rename(file.name);
if (typeof newName === "string") {
builder = getBuilder(newName, e.target.result);
} else {
builder = getBuilder(file.name, e.target.result);
}
upload.index = index;
upload.file = file;
upload.downloadStartTime = start_time;
upload.currentStart = start_time;
upload.currentProgress = 0;
upload.startData = 0;
upload.addEventListener("progress", progress, false);
xhr.open("POST", opts.url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send(builder);
opts.uploadStarted(index, file, files_count);
xhr.onload = function() {
if (xhr.responseText) {
var now = new Date().getTime(), timeDiff = now - start_time, result = opts.uploadFinished(index, file, xhr.responseText, timeDiff);
filesDone++;
if (filesDone == files_count - filesRejected) afterAll();
if (result === false) stop_loop = true;
}
};
}
return (filesRejected==0);
}
function getIndexBySize(size) {
for (var i=0; i<files_count; i++) {
if (files[i].size == size) return i;
}
return undefined;
}
function rename(name) {
return opts.rename(name);
}
function beforeEach(file) {
return opts.beforeEach(file);
}
function afterAll() {
return opts.afterAll();
}
function dragEnter(e) {
clearTimeout(doc_leave_timer);
e.preventDefault();
opts.dragEnter(e);
}
function dragOver(e) {
clearTimeout(doc_leave_timer);
e.preventDefault();
opts.docOver(e);
opts.dragOver(e);
}
function dragLeave(e) {
clearTimeout(doc_leave_timer);
opts.dragLeave(e);
e.stopPropagation();
}
function docDrop(e) {
e.preventDefault();
opts.docLeave(e);
return false;
}
function docEnter(e) {
clearTimeout(doc_leave_timer);
e.preventDefault();
opts.docEnter(e);
return false;
}
function docOver(e) {
clearTimeout(doc_leave_timer);
e.preventDefault();
opts.docOver(e);
return false;
}
function docLeave(e) {
doc_leave_timer = setTimeout(function(){
opts.docLeave(e);
}, 200);
}
function empty(){}
})(jQuery);
/* jquery-filedrop. Version: 0.1.0 Author: Weixi Yen Copyright (c) 2010 Resopollution */
/* Adapted by Bergware for use in unRAID OS6 (June 2015) */
!function(e){var r=jQuery.event.fixHooks.drop;r?r.props?r.props.push("dataTransfer"):r.props=["dataTransfer"]:jQuery.event.fixHooks.drop={props:["dataTransfer"]};var t,n,a={},o={url:"",refresh:1e3,paramname:"userfile",maxfiles:25,maxfilesize:1024,data:{},drop:x,dragEnter:x,dragOver:x,dragLeave:x,docEnter:x,docOver:x,docLeave:x,beforeEach:x,afterAll:x,rename:x,error:function(e,r,t){alert(e)},uploadStarted:x,uploadFinished:x,progressUpdated:x,speedUpdated:x},i=["BrowserNotSupported","TooManyFiles","FileTooLarge"],d=!1,u=0;function s(e){return a.drop(e),null==(n=e.dataTransfer.files)?(a.error(i[0]),!1):(u=n.length,e.preventDefault(),function(){if(d=!1,!n)return a.error(i[0]),!1;var e=0,r=0;if(u>a.maxfiles)return a.error(i[1]),!1;for(var t=0;t<u;t++){if(d)return!1;try{if(0!=(p=n[t],a.beforeEach(p))){if(t===u)return;var o=new FileReader,s=1024*a.maxfilesize;if(o.index=t,n[t].size>s){a.error(i[2],n[t],t),r++;continue}o.onloadend=c,o.readAsDataURL(n[t])}else r++}catch(e){return a.error(i[0]),!1}}var p;function c(t){null==t.target.index&&(t.target.index=function(e){for(var r=0;r<u;r++)if(n[r].size==e)return r;return}(t.total));var o,i,s=new XMLHttpRequest,p=s.upload,c=n[t.target.index],v=t.target.index,g=(new Date).getTime();newName=(i=c.name,a.rename(i)),o="string"==typeof newName?f(newName,t.target.result):f(c.name,t.target.result),p.index=v,p.file=c,p.downloadStartTime=g,p.currentStart=g,p.currentProgress=0,p.startData=0,p.addEventListener("progress",l,!1),s.open("POST",a.url,!0),s.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),s.send(o),a.uploadStarted(v,c,u),s.onload=function(){if(s.responseText){var t=(new Date).getTime(),n=t-g,o=a.uploadFinished(v,c,s.responseText,n);++e==u-r&&a.afterAll(),!1===o&&(d=!0)}}}return 0==r}())}function f(r,t){var n=[];return e.each(a.data,function(e,r){"function"==typeof r&&(r=r()),n.push(e+"="+r)}),n.push("filename="+encodeURI(r)),n.push("filedata="+t),n.join("&")}function l(e){if(e.lengthComputable){var r=Math.round(100*e.loaded/e.total);if(this.currentProgress!=r){this.currentProgress=r,a.progressUpdated(this.index,this.file,this.currentProgress);var t=(new Date).getTime(),n=t-this.currentStart;if(n>=a.refresh){var o=(e.loaded-this.startData)/n;a.speedUpdated(this.index,this.file,o),this.startData=e.loaded,this.currentStart=t}}}}function p(e){clearTimeout(t),e.preventDefault(),a.dragEnter(e)}function c(e){clearTimeout(t),e.preventDefault(),a.docOver(e),a.dragOver(e)}function v(e){clearTimeout(t),a.dragLeave(e),e.stopPropagation()}function g(e){return e.preventDefault(),a.docLeave(e),!1}function h(e){return clearTimeout(t),e.preventDefault(),a.docEnter(e),!1}function m(e){return clearTimeout(t),e.preventDefault(),a.docOver(e),!1}function T(e){t=setTimeout(function(){a.docLeave(e)},200)}function x(){}e.fn.filedrop=function(r){a=e.extend({},o,r),this.bind("drop",s).bind("dragenter",p).bind("dragover",c).bind("dragleave",v),e(document).bind("drop",g).bind("dragenter",h).bind("dragover",m).bind("dragleave",T)}}(jQuery);

View File

@@ -1,240 +1,2 @@
/**
* jQuery File Tree Plugin
*
* @author - Cory S.N. LaViska - A Beautiful Site (http://abeautifulsite.net/) - 24 March 2008
* @author - Dave Rogers - https://github.com/daverogers/jQueryFileTree
*
*
* Usage: $('.fileTreeDemo').fileTree( options, callback )
*
* Options: root - root folder to display; default = /
* filter - filter on file extension; default = none
* match - regex filter on file name for inclusion; default = .* (match all)
* script - location of the serverside AJAX file to use; default = FileTree.php
* folderEvent - event to trigger expand/collapse; default = click
* expandSpeed - default = 500 (ms); use -1 for no animation
* collapseSpeed - default = 500 (ms); use -1 for no animation
* expandEasing - easing function to use on expand (optional)
* collapseEasing - easing function to use on collapse (optional)
* multiFolder - whether or not to limit the browser to one subfolder at a time
* loadMessage - Message to display while initial tree loads (can be HTML)
* multiSelect - append checkbox to each line item to select more than one
*
*
* TERMS OF USE
*
* This plugin is dual-licensed under the GNU General Public License and the MIT License and
* is copyright 2008 A Beautiful Site, LLC.
*/
if(jQuery) (function($){
$.extend($.fn, {
fileTree: function(options, file, folder) {
// Default options
if( options.root === undefined ) options.root = '/mnt/';
if( options.filter === undefined ) options.filter = '';
if( options.match === undefined ) options.match = '.*';
if( options.script === undefined ) options.script = '/webGui/include/FileTree.php';
if( options.folderEvent === undefined ) options.folderEvent = 'click';
if( options.expandSpeed === undefined ) options.expandSpeed = 300;
if( options.collapseSpeed === undefined ) options.collapseSpeed = 300;
if( options.expandEasing === undefined ) options.expandEasing = null;
if( options.collapseEasing === undefined ) options.collapseEasing = null;
if( options.multiFolder === undefined ) options.multiFolder = false;
if( options.loadMessage === undefined ) options.loadMessage = 'Loading...';
if( options.multiSelect === undefined ) options.multiSelect = false;
if( options.allowBrowsing === undefined ) options.allowBrowsing = false;
$(this).each( function() {
function showTree(element, dir, show_parent) {
$(element).addClass('wait');
$(".jqueryFileTree.start").remove();
$.post(options.script,
{
dir: dir,
multiSelect: options.multiSelect,
filter: options.filter,
match: options.match,
show_parent : show_parent
})
.done(function(data){
$(element).find('.start').html('');
$(element).removeClass('wait').append(data);
if( options.root == dir ) $(element).find('UL:hidden').show(); else $(element).find('UL:hidden').slideDown({ duration: options.expandSpeed, easing: options.expandEasing });
bindTree(element);
//$(this).parent().removeClass('collapsed').addClass('expanded');
_trigger($(this), 'filetreeexpanded', data);
})
.fail(function(){
$(element).find('.start').html('');
$(element).removeClass('wait').append("<li>Unable to get file tree information</li>");
});
}
function bindTree(element) {
$(element).find('LI A').on(options.folderEvent, function(event) {
event.preventDefault();
// set up data object to send back via trigger
var data = {};
data.li = $(this).closest('li');
data.type = ( data.li.hasClass('directory') ? 'directory' : 'file' );
data.value = $(this).text();
data.rel = $(this).prop('rel');
if ($(this).text() == "..") {
// Restart fileTree with the parent dir as root
options.root = data.rel;
if (folder) folder($(this).attr('rel'));
_trigger($(this), 'filetreefolderclicked', data);
root = $(this).closest('ul.jqueryFileTree');
root.html('<ul class="jqueryFileTree start"><li class="wait">' + options.loadMessage + '<li></ul>');
showTree( $(root), options.root, options.allowBrowsing );
} else if( $(this).parent().hasClass('directory') ) {
if( $(this).parent().hasClass('collapsed') ) {
// Expand
_trigger($(this), 'filetreeexpand', data);
if( !options.multiFolder ) {
$(this).parent().parent().find('UL').slideUp({ duration: options.collapseSpeed, easing: options.collapseEasing });
$(this).parent().parent().find('LI.directory').removeClass('expanded').addClass('collapsed');
}
$(this).parent().removeClass('collapsed').addClass('expanded');
$(this).parent().find('UL').remove(); // cleanup
showTree( $(this).parent(), $(this).attr('rel').match( /.*\// )[0], false );
} else {
// Collapse
_trigger($(this), 'filetreecollapse', data);
$(this).parent().find('UL').slideUp({ duration: options.collapseSpeed, easing: options.collapseEasing });
$(this).parent().removeClass('expanded').addClass('collapsed');
_trigger($(this), 'filetreecollapsed', data);
}
// this is a folder click, return folder information
if (folder) folder($(this).attr('rel'));
_trigger($(this), 'filetreefolderclicked', data);
} else {
// this is a file click, return file information
if (file) file($(this).attr('rel'));
_trigger($(this), 'filetreeclicked', data);
}
return false;
});
// Prevent A from triggering the # on non-click events
if( options.folderEvent.toLowerCase != 'click' ) $(element).find('LI A').on('click', function(event) { event.preventDefault(); return false; });
}
// Loading message
$(this).html('<ul class="jqueryFileTree start"><li class="wait">' + options.loadMessage + '<li></ul>');
// Get the initial file list
showTree( $(this), options.root, options.allowBrowsing );
// wrapper to append trigger type to data
function _trigger(element, eventType, data) {
data.trigger = eventType;
element.trigger(eventType, data);
}
// checkbox event (multiSelect)
$(this).on('change', 'input:checkbox' , function(){
var data = {};
data.li = $(this).closest('li');
data.type = ( data.li.hasClass('directory') ? 'directory' : 'file' );
data.value = data.li.children('a').text();
data.rel = data.li.children('a').prop('rel');
// propagate check status to (visible) child checkboxes
data.li.find('input:checkbox').prop( 'checked', $(this).prop('checked') );
// set triggers
if( $(this).prop('checked') )
_trigger($(this), 'filetreechecked', data);
else
_trigger($(this), 'filetreeunchecked', data);
});
});
},
// Univeral file tree attacher
//
// Valid options:
// pickfolders (true/false) -- if true, the input value is populated when clicking folders within the tree picker
// pickfilter (string) -- File extension to filter on, comma-seperated for multiple
// pickmatch (string) -- File name to filter on by regex
// pickroot (string) -- The initial path to "start in" and list folders from
// pickcloseonfile (true/false) -- if true, hides the tree picker after selecting a file
//
// The above options can exists (and override) as html data attributes (e.g. data-pickroot="/mnt/" )
fileTreeAttach: function(options, file_event, folder_event) {
var baseconfig = {};
if ($.isFunction(options)) {
if ($.isFunction(file_event)) {
folder_event = file_event;
}
file_event = options;
} else if (options) {
$.extend(baseconfig, options);
}
$(this).each( function() {
var input = $(this);
var config = $.extend({}, baseconfig, input.data());
var picker = input.next(".fileTree");
if (picker.length === 0) {
$(document).mousedown(function hideTreePicker(e) {
var container = $(".fileTree");
if (!container.is(e.target) && container.has(e.target).length === 0) {
container.slideUp('fast');
}
});
picker = $('<div>', {'class': 'textarea fileTree'});
input.after(picker);
}
input.click(function() {
if (picker.is(':visible')) {
picker.slideUp('fast');
} else {
if (picker.html() === "") {
picker.html('<span style="padding-left: 20px"><img src="/webGui/images/spinner.gif"> Loading...</span>');
picker.fileTree({
root: config.pickroot,
filter: (config.pickfilter || '').split(","),
match: config.pickmatch || '.*'
},
($.isFunction(file_event) ? file_event : function(file) {
input.val(file).change();
if (config.hasOwnProperty('pickcloseonfile')) {
picker.slideUp('fast');
}
}),
($.isFunction(folder_event) ? folder_event : function(folder) {
if (config.hasOwnProperty('pickfolders')) {
input.val(folder).change();
}
})
);
}
picker.offset({left: input.position().left});
picker.slideDown('fast');
}
});
});
}
});
})(jQuery);
/* jQuery File Tree. Authors - Cory S.N. LaViska & Dave Rogers. Copyright 2008 A Beautiful Site, LLC. */
jQuery&&function(e){e.extend(e.fn,{fileTree:function(i,t,l){void 0===i.root&&(i.root="/mnt/"),void 0===i.filter&&(i.filter=""),void 0===i.match&&(i.match=".*"),void 0===i.script&&(i.script="/webGui/include/FileTree.php"),void 0===i.folderEvent&&(i.folderEvent="click"),void 0===i.expandSpeed&&(i.expandSpeed=300),void 0===i.collapseSpeed&&(i.collapseSpeed=300),void 0===i.expandEasing&&(i.expandEasing=null),void 0===i.collapseEasing&&(i.collapseEasing=null),void 0===i.multiFolder&&(i.multiFolder=!1),void 0===i.loadMessage&&(i.loadMessage="Loading..."),void 0===i.multiSelect&&(i.multiSelect=!1),void 0===i.allowBrowsing&&(i.allowBrowsing=!1),e(this).each(function(){function s(r,n,o){e(r).addClass("wait"),e(".jqueryFileTree.start").remove(),e.post(i.script,{dir:n,multiSelect:i.multiSelect,filter:i.filter,match:i.match,show_parent:o}).done(function(o){var d;e(r).find(".start").html(""),e(r).removeClass("wait").append(o),i.root==n?e(r).find("UL:hidden").show():e(r).find("UL:hidden").slideDown({duration:i.expandSpeed,easing:i.expandEasing}),e(d=r).find("LI A").on(i.folderEvent,function(r){r.preventDefault();var n={};return n.li=e(this).closest("li"),n.type=n.li.hasClass("directory")?"directory":"file",n.value=e(this).text(),n.rel=e(this).prop("rel"),".."==e(this).text()?(i.root=n.rel,l&&l(e(this).attr("rel")),a(e(this),"filetreefolderclicked",n),root=e(this).closest("ul.jqueryFileTree"),root.html('<ul class="jqueryFileTree start"><li class="wait">'+i.loadMessage+"<li></ul>"),s(e(root),i.root,i.allowBrowsing)):e(this).parent().hasClass("directory")?(e(this).parent().hasClass("collapsed")?(a(e(this),"filetreeexpand",n),i.multiFolder||(e(this).parent().parent().find("UL").slideUp({duration:i.collapseSpeed,easing:i.collapseEasing}),e(this).parent().parent().find("LI.directory").removeClass("expanded").addClass("collapsed")),e(this).parent().removeClass("collapsed").addClass("expanded"),e(this).parent().find("UL").remove(),s(e(this).parent(),e(this).attr("rel").match(/.*\//)[0],!1)):(a(e(this),"filetreecollapse",n),e(this).parent().find("UL").slideUp({duration:i.collapseSpeed,easing:i.collapseEasing}),e(this).parent().removeClass("expanded").addClass("collapsed"),a(e(this),"filetreecollapsed",n)),l&&l(e(this).attr("rel")),a(e(this),"filetreefolderclicked",n)):(t&&t(e(this).attr("rel")),a(e(this),"filetreeclicked",n)),!1}),"click"!=i.folderEvent.toLowerCase&&e(d).find("LI A").on("click",function(e){return e.preventDefault(),!1}),a(e(this),"filetreeexpanded",o)}).fail(function(){e(r).find(".start").html(""),e(r).removeClass("wait").append("<li>Unable to get file tree information</li>")})}function a(e,i,t){t.trigger=i,e.trigger(i,t)}e(this).html('<ul class="jqueryFileTree start"><li class="wait">'+i.loadMessage+"<li></ul>"),s(e(this),i.root,i.allowBrowsing),e(this).on("change","input:checkbox",function(){var i={};i.li=e(this).closest("li"),i.type=i.li.hasClass("directory")?"directory":"file",i.value=i.li.children("a").text(),i.rel=i.li.children("a").prop("rel"),i.li.find("input:checkbox").prop("checked",e(this).prop("checked")),e(this).prop("checked")?a(e(this),"filetreechecked",i):a(e(this),"filetreeunchecked",i)})})},fileTreeAttach:function(i,t,l){var s={};e.isFunction(i)?(e.isFunction(t)&&(l=t),t=i):i&&e.extend(s,i),e(this).each(function(){var i=e(this),a=e.extend({},s,i.data()),r=i.next(".fileTree");0===r.length&&(e(document).mousedown(function(i){var t=e(".fileTree");t.is(i.target)||0!==t.has(i.target).length||t.slideUp("fast")}),r=e("<div>",{class:"textarea fileTree"}),i.after(r)),i.click(function(){r.is(":visible")?r.slideUp("fast"):(""===r.html()&&(r.html('<span style="padding-left: 20px"><img src="/webGui/images/spinner.gif"> Loading...</span>'),r.fileTree({root:a.pickroot,filter:(a.pickfilter||"").split(","),match:a.pickmatch||".*"},e.isFunction(t)?t:function(e){i.val(e).change(),a.hasOwnProperty("pickcloseonfile")&&r.slideUp("fast")},e.isFunction(l)?l:function(e){a.hasOwnProperty("pickfolders")&&i.val(e).change()})),r.offset({left:i.position().left}),r.slideDown("fast"))})})}})}(jQuery);

View File

@@ -1,302 +1,2 @@
/**
* 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
},
_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
this.element.hide();
// 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(typeof this.options.on_callback === 'function') this.options.on_callback.call(this);
}
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(typeof this.options.off_callback === 'function') this.options.off_callback.call(this);
}
// Animate the switch
this.button.animate({ left: newLeft }, 250, "easeInOutCubic");
}
});
})(jQuery);
/* jquery.switchButton.js v1.0. Copyright (c) Olivier Lance */
!function(t){t.widget("sylightsUI.switchButton",{options:{checked:void 0,show_labels:!0,labels_placement:"both",on_label:"ON",off_label:"OFF",width:25,height:11,button_width:12,clear:!0,clear_after:null,on_callback:void 0,off_callback:void 0},_create:function(){void 0===this.options.checked&&(this.options.checked=this.element.prop("checked")),this._initLayout(),this._initEvents()},_initLayout:function(){this.element.hide(),this.off_label=t("<span>").addClass("switch-button-label"),this.on_label=t("<span>").addClass("switch-button-label"),this.button_bg=t("<div>").addClass("switch-button-background"),this.button=t("<div>").addClass("switch-button-button"),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),this.options.clear&&(null===this.options.clear_after&&(this.options.clear_after=this.on_label),t("<div>").css({clear:"left"}).insertAfter(this.options.clear_after)),this._refresh(),this.options.checked=!this.options.checked,this._toggleSwitch()},_refresh:function(){switch(this.options.show_labels?(this.off_label.show(),this.on_label.show()):(this.off_label.hide(),this.on_label.hide()),this.options.labels_placement){case"both":this.button_bg.prev()===this.off_label&&this.button_bg.next()===this.on_label||(this.off_label.detach(),this.on_label.detach(),this.off_label.insertBefore(this.button_bg),this.on_label.insertAfter(this.button_bg),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":this.button_bg.prev()===this.on_label&&this.on_label.prev()===this.off_label||(this.off_label.detach(),this.on_label.detach(),this.off_label.insertBefore(this.button_bg),this.on_label.insertBefore(this.button_bg),this.on_label.addClass("on").removeClass("off"),this.off_label.addClass("off").removeClass("on"));break;case"right":this.button_bg.next()===this.off_label&&this.off_label.next()===this.on_label||(this.off_label.detach(),this.on_label.detach(),this.off_label.insertAfter(this.button_bg),this.on_label.insertAfter(this.off_label),this.on_label.addClass("on").removeClass("off"),this.off_label.addClass("off").removeClass("on"))}this.on_label.html(this.options.on_label),this.off_label.html(this.options.off_label),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 t=this;this.button_bg.click(function(e){return e.preventDefault(),e.stopPropagation(),t._toggleSwitch(),!1}),this.button.click(function(e){return e.preventDefault(),e.stopPropagation(),t._toggleSwitch(),!1}),this.on_label.click(function(e){return(!t.options.checked||"both"!==t.options.labels_placement)&&(t._toggleSwitch(),!1)}),this.off_label.click(function(e){return!(!t.options.checked&&"both"===t.options.labels_placement)&&(t._toggleSwitch(),!1)})},_setOption:function(t,e){"checked"!==t?(this.options[t]=e,this._refresh()):this._setChecked(e)},_setChecked:function(t){t!==this.options.checked&&(this.options.checked=!t,this._toggleSwitch())},_toggleSwitch:function(){this.options.checked=!this.options.checked;var t="";this.options.checked?(this.element.prop("checked",!0),this.element.change(),t="+="+(this.options.width-this.options.button_width),"both"==this.options.labels_placement?(this.off_label.removeClass("on").addClass("off"),this.on_label.removeClass("off").addClass("on")):(this.off_label.hide(),this.on_label.show()),this.button_bg.addClass("checked"),"function"==typeof this.options.on_callback&&this.options.on_callback.call(this)):(this.element.prop("checked",!1),this.element.change(),t="-1px","both"==this.options.labels_placement?(this.off_label.removeClass("off").addClass("on"),this.on_label.removeClass("on").addClass("off")):(this.off_label.show(),this.on_label.hide()),this.button_bg.removeClass("checked"),"function"==typeof this.options.off_callback&&this.options.off_callback.call(this));this.button.animate({left:t},250,"easeInOutCubic")}})}(jQuery);