2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 12:49:34 +00:00

git-svn-id: https://svn.fhem.de/fhem/trunk@3162 2b470e98-0d58-463d-a4d8-8e2adae1ed80

This commit is contained in:
pahenning 2013-05-09 05:17:20 +00:00
parent 7ff4017bed
commit f9e2152340
44 changed files with 27900 additions and 0 deletions

416
fhem/contrib/YAF/01_YAF.pm Normal file
View File

@ -0,0 +1,416 @@
########################################################################################
#
# 01_YAF.pm
#
# YAF - Yet Another Floorplan
# FHEM Projektgruppe Hochschule Karlsruhe, 2013
# Markus Mangei, Daniel Weisensee, Prof. Dr. Peter A. Henning
#
# $Id: 01_YAF.pm 2013-05 - pahenning $
#
########################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
########################################################################################
package main;
use JSON::XS;
use strict;
use warnings;
use lib qw(YAF);
use YAF::YAFWidgets;
use YAF::YAFConfig;
use vars qw(%data);
use vars qw(%_GET);
use vars qw(%defs);
use vars qw($FW_cname);
use vars qw($FW_RET);
use vars qw($FW_dir);
sub YAF_Request($@);
my $fhem_url;
my $yaf_version=0.41;
my $yafw_encoding = "UTF-8";
my $mp = AttrVal("global", "modpath", ".");
my $yaf_www_directory = $mp."/FHEM/YAF/www";
YAF_Config();
########################################################################################
#
# YAF_Initialize - register YAF with FHEM
#
# Parameter hash
#
########################################################################################
sub YAF_Initialize ($) {
my ($hash) = @_;
$hash->{DefFn} = "YAF_define";
my $name = "YAF";
$fhem_url = "/" . $name;
$data{FWEXT}{$fhem_url}{FUNC} = "YAF_Request";
$data{FWEXT}{$fhem_url}{LINK} = "YAF/www/global/yaf.htm";
$data{FWEXT}{$fhem_url}{NAME} = "YAF";
#-- load widgets
YAF_requireWidgets();
}
########################################################################################
#
# YAF_Print
#
# Parameter hash
#
########################################################################################
sub YAF_Print($@) {
if ($_[0]) {
$FW_RET .= $_[0];
}
}
########################################################################################
#
# YAF_Clean - clear output buffer
#
# no parameter
#
########################################################################################
sub YAF_Clean() {
$FW_RET = "";
}
########################################################################################
#
# YAF_LoadResource - Load a file from YAF directory
#
# Parameter hash
#
########################################################################################
sub YAF_LoadResource($@) {
my $absoluteFilePath = $_[0];
my $filebuffer = "";
my $fh;
# Filename
my @absoluteFilePathSplitted = split(/\//, $absoluteFilePath);
my $filename = $absoluteFilePathSplitted[scalar(@absoluteFilePathSplitted)-1];
# Extension
my @filenameSplitted = split(/\./, $filename);
my $extension = $filenameSplitted[scalar(@filenameSplitted)-1];
#Log 1,"YAF_LoadResource absoluteFilePath $absoluteFilePath filename $filename extension $extension";
# Datei laden
if ((-f $absoluteFilePath) && open($fh, "<", $absoluteFilePath)) {
binmode $fh;
my ($data, $n);
while (($n = read $fh, $data, 4) != 0) {
$filebuffer .= $data;
}
}
else {
# Datei nicht gefunden
Log 1,"YAF_LoadResource: file $filename not found";
return YAF_NotFound($absoluteFilePath);
}
close($fh);
if ($extension eq "htm" || $extension eq "html") {
if ($filename eq "yaf.htm") {
# replace:
# ###widget_css###
# ###widget_js###
my $widget_css = YAF_getWidgetsCss();
my $widget_js = YAF_getWidgetsJs();
$filebuffer =~ s/###widget_css###/$widget_css/g;
$filebuffer =~ s/###widget_js###/$widget_js/g;
}
YAF_Print($filebuffer);
return ("text/html; charset=$yafw_encoding", $FW_RET);
}
elsif ($extension eq "gif") {
YAF_Print($filebuffer);
return ("image/gif; charset=$yafw_encoding", $FW_RET);
}
elsif ($extension eq "jpg" || $extension eq "jpeg") {
YAF_Print($filebuffer);
return ("image/jpeg; charset=$yafw_encoding", $FW_RET);
}
elsif ($extension eq "png") {
YAF_Print($filebuffer);
return ("image/png; charset=$yafw_encoding", $FW_RET);
}
elsif ($extension eq "css") {
YAF_Print($filebuffer);
return ("text/css; charset=$yafw_encoding", $FW_RET);
}
elsif ($extension eq "js") {
YAF_Print($filebuffer);
return ("text/javascript; charset=$yafw_encoding", $FW_RET);
}
else {
YAF_Print($filebuffer);
return ("text/plain; charset=$yafw_encoding", $FW_RET);
}
}
########################################################################################
#
# YAF_define
#
# Parameter hash
#
########################################################################################
sub YAF_define ($@) {
my ($hash, $def) = @_;
return;
}
########################################################################################
#
# YAF_LoadView
#
# Parameter hash
#
########################################################################################
sub YAF_LoadView($@) {
my ($view) = @_;
YAF_Print("ddd");
return ("text/html; charset=$yafw_encoding", $FW_RET);
}
########################################################################################
#
# YAF_Request - http://fhemurl:fhemport/YAF is processed here
#
# Parameter hash, request-string
#
########################################################################################
sub YAF_Request ($@) {
my ($htmlarg) = @_;
# %20 durch Leerzeichen ersetzen
$htmlarg =~ s/%20/ /g;
# GET Parameter
my @params = split(/\?/, $htmlarg);
if (scalar(@params) > 1) {
my @attributesArray = split("&",$params[1]);
my @attributePair;
for (my $i = 0; $i < scalar(@attributesArray); $i++) {
@attributePair = split("=",$attributesArray[$i]);
$_GET{$attributePair[0]} = $attributePair[1];
}
}
@params = split(/\//, $params[0]);
#-- clean output buffer
YAF_Clean();
#-- take URI apart
my $controler_count = scalar(@params);
#Log 1,"YAF_Request: arguments $htmlarg params ".join(' ',@params);
#-- examples are
#/YAF/global/yaf.htm
#/YAF/global/js/yaf-dialogs.js
#/YAF/ajax/global/getRefreshTime
my $control_1 = $params[1];
my $control_2 = $params[2];
my $control_3 = $params[3];
if ($controler_count > 3) {
#-- either global, widget or ajax
if ($control_2 eq "global") {
my $request_file = $yaf_www_directory;
my $pos = 3;
for (; $pos < scalar(@params); $pos++) {
$request_file .= "/";
$request_file .= $params[$pos];
}
# Resource aus dem global www Verzeichnis laden
return YAF_LoadResource($request_file);
}
elsif ($control_2 eq "widget") {
return ("text/plain; charset=$yafw_encoding", $FW_RET);
}
elsif ($control_2 eq "ajax") {
if ($control_3 eq "global") {
if ($controler_count > 4) {
my $function = "";
$function = $params[4];
if ($function eq "getViews") {
my $views = encode_json(YAF_getViews());
YAF_Print($views);
}
#-- adds a View
elsif ($function eq "addView") {
if ($_GET{"name"} && (YAF_addView($_GET{"name"}) == 1)) {
YAF_Print("1");
}
else {
YAF_Print("0");
}
}
#-- deletes a View
elsif ($function eq "deleteView") {
if ($_GET{"id"} && (YAF_deleteView($_GET{"id"}) == 1)) {
YAF_Print("1");
}
else {
YAF_Print("0");
}
}
#-- returns all Widgets of a View
elsif ($function eq "getView") {
if ($_GET{"id"}) {
YAF_Print(encode_json(YAF_getView($_GET{"id"})));
}
else {
YAF_Print("0");
}
}
#-- changes the name of a View
elsif ($function eq "editView") {
if ($_GET{"id"} && $_GET{"name"}) {
YAF_Print(YAF_editView($_GET{"id"}, $_GET{"name"}));
}
else {
YAF_Print("0");
}
}
#-- modify position of a Widget
elsif ($function eq "setWidgetPosition") {
if ($_GET{"view_id"} && $_GET{"widget_id"} && $_GET{"x_pos"} && $_GET{"y_pos"}) {
YAF_setWidgetPosition($_GET{"view_id"}, $_GET{"widget_id"}, $_GET{"x_pos"}, $_GET{"y_pos"});
YAF_Print("1");
}
else {
YAF_Print("0");
}
}
#-- get Widgets
elsif ($function eq "getWidgets") {
my @widgets = YAF_getWidgetArray();
YAF_Print(encode_json(\@widgets));
}
#-- add Widget
elsif ($function eq "addWidget") {
if ($_GET{"view_id"} && $_GET{"widget"} && $_GET{"attributes"}) {
# %22 wieder durch " ersetzen!
# @TODO Probleme mit Sonderzeichen müssen noch behoben werden!
$_GET{"attributes"} =~ s/%22/"/g;
my @attributes_array = @{decode_json($_GET{"attributes"})};
my $widgetId = YAF_addWidget($_GET{"view_id"},$_GET{"widget"}, 28, 69, \@attributes_array);
YAF_Print($widgetId);
}
else {
YAF_Print("0");
}
}
#-- delete Widget
elsif($function eq "deleteWidget"){
if ($_GET{"view_id"} && $_GET{"widget_id"} && (YAF_deleteWidget($_GET{"view_id"}, $_GET{"widget_id"}) == 1)) {
YAF_Print("1");
}
else {
YAF_Print("0");
}
}
#-- get RefreshTime
elsif($function eq "getRefreshTime"){
my $refreshTime = YAF_getRefreshTime();
YAF_Print($refreshTime);
}
#-- set RefreshTime
elsif($function eq "setRefreshTime"){
if($_GET{"interval"}){
my $newRefreshTime = $_GET{"interval"};
YAF_setRefreshTime($newRefreshTime);
YAF_Print($newRefreshTime);
} else{
YAF_Print("0");
}
}
else {
YAF_Print("0");
}
}
else {
YAF_Print("1");
}
return ("text/plain; charset=$yafw_encoding", $FW_RET);
}
#-- evaluation of a widget function
elsif ($control_3 eq "widget") {
my $widget = $params[4];
my $function = $params[5];
if ($widget ne "") {
YAF_Print(eval($widget."_".$function."();")) or YAF_Print("0");
}
else {
YAF_Print("0");
}
#Log 1,"++++++++++++> Widget $widget called with function $function, length of return was ".length($FW_RET);
return ("text/plain; charset=$yafw_encoding", $FW_RET);
}
else {
Log 1,"YAF_Request: B response not found $control_1 $control_2";
return YAF_NotFound($htmlarg);
}
}
else {
Log 1,"YAF_Request: C response not found $control_1 $control_2";
return YAF_NotFound($htmlarg);
}
}
else {
Log 1,"YAF_Request: D response not found $control_1 $control_2";
return YAF_NotFound($htmlarg);
}
}
########################################################################################
#
# YAF_NotFound - Return a 404 Error
#
# Parameter hash, request-string
#
########################################################################################
sub YAF_NotFound{
my $file = $_[0];
YAF_Print("Error 404: $file");
YAF_Print("\n");
return ("text/html; charset=$yafw_encoding", $FW_RET);
}
1;

19
fhem/contrib/YAF/Makefile Executable file
View File

@ -0,0 +1,19 @@
VERS=0.41
DATE=2013-03-10
FHEMDIR=../../FHEM/fhem
all:
@echo "Use make install to install YAF"
install:
@echo "Installing YAF to FHEM installation in ${FHEMDIR}"
@echo "- copying files"
@cp 01_YAF.pm ${FHEMDIR}/FHEM
@cp -rp YAF ${FHEMDIR}/FHEM
@echo
@echo "Installation of YAF completed!"
@echo
@echo "Do not forget to configure YAF in fhem.cfg with"
@echo "define yaf YAF"
@echo

26
fhem/contrib/YAF/README Normal file
View File

@ -0,0 +1,26 @@
########################################################################################
#
# README
#
# YAF - Yet Another Floorplan
# FHEM Projektgruppe Hochschule Karlsruhe, 2013
# Markus Mangei, Daniel Weisensee
#
########################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
########################################################################################
Please notice the installation guide included in the documentation.

View File

@ -0,0 +1,507 @@
########################################################################################
#
# YAFConfig.pm - sub-module to read and interpret the configuration file
#
# YAF - Yet Another Floorplan
# FHEM Projektgruppe Hochschule Karlsruhe, 2013
# Markus Mangei, Daniel Weisensee, Prof. Dr. Peter A. Henning
#
########################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
########################################################################################
package main;
use strict;
use warnings;
use XML::LibXML;
use XML::LibXML::PrettyPrint;
my $yaf_version=0.41;
my $mp = AttrVal("global", "modpath", ".");
my $configurationFilepath = $mp."/FHEM/YAF/xml/yafConfig.xml";
my $schemaFilepath = $mp."/FHEM/YAF/xml/xmlSchema.xsd";
my $xmlSchema;
my $prettyPrinter;
my $config;
#######################################################################################
#
# YAF_Config - Initializes this module by creating the schema, pretty printer and
# loading the configuration from the filepath
#
# no parameter
#
########################################################################################
sub YAF_Config {
$xmlSchema = XML::LibXML::Schema->new(location => $schemaFilepath);
$prettyPrinter = XML::LibXML::PrettyPrint->new(indent_string => " ");
$config = XML::LibXML->load_xml(location => $configurationFilepath);
YAF_validate();
}
#######################################################################################
#
# YAF_validate - Validates the current state of the configuration instance
#
# no parameter
# Returns 1 if valid, otherwise 0.
#
########################################################################################
sub YAF_validate{
eval{ $xmlSchema->validate($config); };
if($@){
Log 1,"YAF: error validating configuration file";
return 0;
}
return 1;
}
#######################################################################################
#
# YAF_getViews - Assembles defined views from configuration file
#
# no parameter
# Returns pointer to array of views.
#
########################################################################################
sub YAF_getViews{
my @views = $config->findnodes('//view');
my @viewsArray;
my $index = 0;
foreach my $view (@views){
$viewsArray[$index][0] = $view->findvalue('@id');
$viewsArray[$index][1] = $view->findvalue('@name');
$index++;
}
return \@viewsArray;
}
#######################################################################################
#
# YAF_getView - Assembles parts of a view from configuration file
#
# viewId - The view id to search
# Returns Pointer to the view hash, hash may be empty
#
########################################################################################
sub YAF_getView{
my $viewId = $_[0];
my %viewHash = ();
#-- query view id
my $viewResult = $config->findnodes('//view[@id = '.$viewId.']');
if($viewResult->size() == 1){
my $view = $viewResult->get_node(0);
#-- prepare view hash and add simple key/value pairs (name)
$viewHash{'name'} = $view->findvalue('@name');
#-- collect all widgets and add them to an array which is then connected to the view hash
my @widgetsArray = ();
my @widgets = $view->findnodes('widgets/widget');
foreach my $widget (@widgets){
my @attributes = $widget->attributes();
my %widgetHash = ();
foreach my $attribute (@attributes){
$widgetHash{$attribute->nodeName} = $attribute->getValue();
}
#-- collect attr nodes in a hash and add to widget
my %attrHash = ();
my @attrs = $widget->getChildrenByTagName('attr');
foreach my $attr (@attrs){
my $key = $attr->findvalue('@name');
my $value = $attr->findvalue('@value');
$attrHash{$key} = $value;
}
$widgetHash{'attr'} = \%attrHash;
push(@widgetsArray, \%widgetHash);
}
$viewHash{'widgets'} = \@widgetsArray;
#-- collect all backgrounds and add them to an array which is then connected to the view hash
my @backgroundsArray = ();
my @backgrounds = $view->findnodes('backgrounds/background');
foreach my $background (@backgrounds){
my @attributes = $background->attributes();
my %backgroundHash = ();
foreach my $attribute (@attributes){
$backgroundHash{$attribute->nodeName} = $attribute->getValue();
}
push(@backgroundsArray, \%backgroundHash);
}
$viewHash{'backgrounds'} = \@backgroundsArray;
} else{
Log 1,"YAF_getView: view with id = ".$viewId." was not found";
}
return \%viewHash;
}
#######################################################################################
#
# YAF_editView - Edits the view with the given id
#
# viewId - The view id to search
# viewName The view name to be set
# @return 1 if successful, otherwise 0
#
########################################################################################
sub YAF_editView{
my $viewId = $_[0];
my $viewName = $_[1];
my $viewResult = $config->findnodes('//view[@id = '.$viewId.']');
if($viewResult->size() == 1){
my $view = $viewResult->get_node(0);
$view->setAttribute('name', $viewName);
YAF_saveConfiguration();
return 1;
} else {
Log 1,"YAF_editView: view with id = ".$viewId." was not found";
return 0;
}
}
#######################################################################################
#
# YAF_deleteView - Deletes the view with the given id
#
# viewId - The view id to search
# @return 1 if successful, otherwise 0
#
#######################################################################################
sub YAF_deleteView{
my $viewId = $_[0];
my $viewResult = $config->findnodes('//view[@id = '.$viewId.']');
if($viewResult->size() == 1){
my $view = $viewResult->get_node(0);
my $views = $view->parentNode;
$views->removeChild($view);
YAF_saveConfiguration();
return 1;
} else{
Log 1,"YAF_deleteView: view with id = ".$viewId." was not found";
return 0;
}
}
#######################################################################################
#
# YAF_addView - Add the view with the given id
#
# viewId - The view id to search
# @return 1 if successful, otherwise 0
#
#######################################################################################
sub YAF_addView{
my $viewName = $_[0];
#-- determine id for new element
my $newId = 0;
my @views = $config->findnodes('//view');
foreach my $view (@views){
my $tempId = $view->findvalue('@id');
if($newId < $tempId){
$newId = $tempId;
}
}
$newId++;
#-- initialize view and append to document
my $view = $config->createElement('view');
$view->setAttribute('id', $newId);
$view->setAttribute('name', $viewName);
#-- set default background
my $backgrounds = $config->createElement('backgrounds');
my $background = $config->createElement('background');
$background->setAttribute('img_url', "./img/eg.jpeg");
$background->setAttribute('x_pos', 1);
$background->setAttribute('y_pos', 1);
$backgrounds->appendChild($background);
$view->appendChild($backgrounds);
#-- initialize empty widgets node
my $widgets = $config->createElement('widgets');
$view->appendChild($widgets);
#-- add new view to configuration
my $parent = $config->findnodes('//views')->get_node(0);
$parent->appendChild($view);
YAF_saveConfiguration();
return 1;
}
#######################################################################################
#
# YAF_addWidget - Add widget the the view with the given id
#
# Parameters:
# widgetName The name of the new widget
# xPos The x coordinate of the widget position
# yPos The y coordinate of the widget position
# attributesArray The array of attribute elements
# @return The widget id if successful, otherwise 0
#
#########################################################################################
sub YAF_addWidget{
my $viewId = $_[0];
my $widgetName = $_[1];
my $xPos = $_[2];
my $yPos = $_[3];
my @attributesArray = @{$_[4]};
my $viewsResult = $config->findnodes('//view[@id = '.$viewId.']');
if($viewsResult->size() == 1){
my $view = $viewsResult->get_node(0);
#-- create a new widget with given properties
my $widget = $config->createElement('widget');
$widget->setAttribute('name', $widgetName);
$widget->setAttribute('x_pos', $xPos);
$widget->setAttribute('y_pos', $yPos);
my @widgets = $view->findnodes('widgets/widget');
my $newId = 0;
foreach my $currentWidget (@widgets){
my $tempId = $currentWidget->findvalue('@id');
if($newId < $tempId){
$newId = $tempId;
}
}
$newId++;
$widget->setAttribute('id', $newId);
#-- add widgets attribute nodes
foreach my $attribute (@attributesArray){
my $attr = $config->createElement('attr');
$attr->setAttribute('name', @$attribute[0]);
$attr->setAttribute('value', @$attribute[1]);
$widget->appendChild($attr);
}
#-- append the new widget to the configuration
my $widgetsNode = $view->findnodes('widgets')->get_node(0);
$widgetsNode->appendChild($widget);
YAF_saveConfiguration();
return $newId;
} else{
Log 1,"YAF_addWidget: view with id = ".$viewId." was not found";
return 0;
}
}
#######################################################################################
#
# YAF_deleteWidget - Delete the Widget
#
# Parameters
# viewId - The view id to search
# widgetId - The widget id
# @return 1 if successful, otherwise 0
#
#######################################################################################
sub YAF_deleteWidget{
my $viewId = $_[0];
my $widgetId = $_[1];
my $widgetResult = $config->findnodes('//view[@id = '.$viewId.']/widgets/widget[@id = '.$widgetId.']');
if($widgetResult->size() == 1){
my $widget = $widgetResult->get_node(0);
my $widgets = $widget->parentNode;
$widgets->removeChild($widget);
YAF_saveConfiguration();
return 1;
} else{
Log 1,"YAF_deleteWidget: widget with id = ".$widgetId." in view with id = ".$viewId." was not found";
return 0;
}
}
#######################################################################################
#
# YAF_isWidget - test, if a FHEM device name is already a widget
#
# viewId - The view id to search
# fhemname - the name of a FHEM device
#
########################################################################################
sub YAF_isWidget {
my $viewId = $_[0];
my $fhemname = $_[1];
my $ret = 0;
my $widgetResult = $config->findnodes('//view[@id = '.$viewId.']/widgets/widget/attr[@value = "'.$fhemname.'"]');
$ret = 1
if($widgetResult->size() != 0);
#Log 1,"YAF_isWidget: Checking with XPath //view[\@id = ".$viewId."]/widgets/widget/attr[\@value = \"".$fhemname."\"] => $ret";
return $ret;
}
#######################################################################################
#
# YAF_setWidgetPosition - Sets the position (x, y) of the widget to the given values
#
# Parameters
# viewId - The view id to search
# widgetId - The widget id
# @param xPos The new x coordinate of the widget position
# @param yPos The new y coordinate of the widget position
# @return 1 if successful, otherwise 0
#
#######################################################################################
sub YAF_setWidgetPosition{
my $viewId = $_[0];
my $widgetId = $_[1];
my $xPos = $_[2];
my $yPos = $_[3];
my $widgetResult = $config->findnodes('//view[@id = '.$viewId.']/widgets/widget[@id = '.$widgetId.']');
if($widgetResult->size() == 1){
my $widget = $widgetResult->get_node(0);
$widget->setAttribute('x_pos', $xPos);
$widget->setAttribute('y_pos', $yPos);
YAF_saveConfiguration();
return 1;
} else{
Log 1,"YAF_setWidgetPosition: widget with id = ".$widgetId." in view with id = ".$viewId." was not found";
return 0;
}
}
#######################################################################################
#
# YAF_getWidgetAttribute - Searches the widget attribute properties of the specified widget
#
# Parameters
# viewId - The view id to search
# widgetId - The widget id
# attributeName - name of the attribute properties to search for
#
# @return The value property if successful, otherwise 0
#
#######################################################################################
sub YAF_getWidgetAttribute{
my $viewId = $_[0];
my $widgetId = $_[1];
my $attributeName = $_[2];
my $attributes = $config->findnodes('//view[@id = '.$viewId.']/widgets/widget[@id = '.$widgetId.']/attr');
foreach my $attr (@{$attributes}){
if ($attr->getAttribute('name') eq $attributeName) {
return $attr->getAttribute('value');
}
}
Log 1,"YAF_getWidgetAttribute: attribute $attributeName was not found for widget with id = $widgetId";
return 0;
}
#######################################################################################
#
# YAF_getRefreshTime - Get refresh time interval
#
# @return time successful, otherwise 0
#
#######################################################################################
sub YAF_getRefreshTime{
my $refreshNodeResult = $config->findnodes('configuration/settings/refresh');
if($refreshNodeResult->size() == 1){
my $refreshNode = $refreshNodeResult->get_node(0);
my $refreshTime = $refreshNode->getAttribute('interval');
return $refreshTime;
} else{
Log 1,"YAF_getRefreshTime: refresh node was not found";
return 0;
}
}
#######################################################################################
#
# YAF_setRefreshTime - Set refresh time interval to the given value
# @return 1 if successful, otherwise 0
#
#######################################################################################
sub YAF_setRefreshTime{
my $newRefreshInterval = $_[0];
my $refreshNodeResult = $config->findnodes('configuration/settings/refresh');
if(($newRefreshInterval =~ /^\d+$/) && ($refreshNodeResult->size() == 1)){
my $refreshNode = $refreshNodeResult->get_node(0);
$refreshNode->setAttribute('interval', $newRefreshInterval);
YAF_saveConfiguration();
return 1;
} else{
Log 1,"YAF_setRefreshTime: no valid refresh value or refresh node was not found";
return 0;
}
}
#######################################################################################
#
# YAF_saveConfiguration - Save XML configuration file
#
# no parameter
# @return 1 if successful, otherwise 0
#
#######################################################################################
sub YAF_saveConfiguration{
my $state = 0;
if(YAF_validate() == 1){
$prettyPrinter->pretty_print($config);
$state = $config->toFile("$configurationFilepath");
}
return $state;
}
1;

View File

@ -0,0 +1,120 @@
########################################################################################
#
# YAFWidgets.pm
#
# YAF - Yet Another Floorplan
# FHEM Projektgruppe Hochschule Karlsruhe, 2013
# Markus Mangei, Daniel Weisensee, Prof. Dr. Peter A. Henning
#
########################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
########################################################################################
package main;
use strict;
use warnings;
my $yaf_version = 0.41;
my $mp = AttrVal("global", "modpath", ".");
my $yaf_dir = $mp."/FHEM/YAF/";
my @yaf_widgets;
#######################################################################################
#
# YAF_YAF_getWidgetArray
#
# no parameter
#
########################################################################################
sub YAF_getWidgetArray() {
@yaf_widgets = ();
my $widgets_directory = $yaf_dir."widgets/";
#-- open directory with widgets
if( !opendir(DIR, $widgets_directory) ){
Log 1,"YAF: directory with widgets not found";
return undef;
}
my $is_dir = 0;
#-- loop through all subdirectories
while (my $entry = readdir DIR) {
#-- check if it is really a directory
if (-d $widgets_directory.$entry) {
$is_dir = 1;
#-- check for proper file widgetname.pm
if (-e $widgets_directory.$entry."/".$entry.".pm") {
$yaf_widgets[scalar(@yaf_widgets)] = $entry;
}
}
}
#-- close directory
closedir DIR;
return @yaf_widgets;
}
#######################################################################################
#
# YAF_requireWidgets - load all widgets
#
# no parameter
#
########################################################################################
sub YAF_requireWidgets() {
YAF_getWidgetArray();
foreach (@yaf_widgets){
require($yaf_dir."widgets/".$_."/".$_.".pm");
}
return 1;
}
#######################################################################################
#
# YAF_getWidgetsCss - assemble the CSS code of all widgets
#
# no parameter
#
########################################################################################
sub YAF_getWidgetsCss() {
my $output_widget_css = "";
foreach (@yaf_widgets){
my $widget_css = "";
$widget_css = eval($_."_get_widgetcss();");
$output_widget_css .= $widget_css;
}
return $output_widget_css;
}
#######################################################################################
#
# YAF_getWidgetsJs - assemble the JavaScript code of all widgets
#
# no parameter
#
########################################################################################
sub YAF_getWidgetsJs() {
my $output_widget_js = "";
foreach (@yaf_widgets){
my $widget_js = "";
$widget_js = eval($_."_get_widgetjs();");
$output_widget_js .= $widget_js;
}
return $output_widget_js;
}
1;

View File

@ -0,0 +1,228 @@
########################################################################################
#
# fs20easylamp.pm
#
# YAF - Yet Another Floorplan
# FHEM Projektgruppe Hochschule Karlsruhe, 2013
# Markus Mangei, Daniel Weisensee, Prof. Dr. Peter A. Henning
#
########################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
########################################################################################
package main;
use strict;
use warnings;
my $yaf_version = 0.41;
use vars qw(%_GET);
use vars qw(%defs);
#######################################################################################
#
# fs20easylamp_get_widgetcss - Create the CSS code for this widget
#
# no parameter
#
########################################################################################
sub fs20easylamp_get_widgetcss() {
my $output = "
.widget_fs20easylamp {
width: 33px;
height: 33px;
background-repeat:no-repeat;
background-position:center center;
opacity:1 !important;
}
.widget_fs20easylamp_on {
background-image:url(./img/lamp_on.png) !important;
}
.widget_fs20easylamp_off {
background-image:url(./img/lamp_off.png) !important;
}
";
return $output;
}
########################################################################################
#
# fs20easylamp_get_widgetjs - Create the javascript code for this widget
#
# no parameter
#
########################################################################################
sub fs20easylamp_get_widgetjs() {
my $output = '
function fs20easylamp_on_click(view_id, widget_id) {
var widget = $("#widget_"+view_id+"_"+widget_id);
var newState;
if (widget.hasClass("widget_fs20easylamp_on")) {
newState = "off";
} else{
newState = "on";
}
$.ajax({
type: "GET",
async: true,
url: "../../ajax/widget/fs20easylamp/set_lamp_status",
data: "view_id="+view_id+"&widget_id="+widget_id+"&status="+newState,
context: document.body,
success: function(){
fs20easylamp_update_widget(view_id, widget_id);
}
});
}
function fs20easylamp_update_widget(view_id, widget_id) {
$.ajax({
type: "GET",
async: true,
url: "../../ajax/widget/fs20easylamp/get_lamp_status",
data: "view_id="+view_id+"&widget_id="+widget_id,
context: document.body,
success: function(lamp_status) {
var widget = $("#widget_"+view_id+"_"+widget_id);
if (lamp_status == "off") {
if (widget.hasClass("widget_fs20easylamp_on")) {
widget.removeClass("widget_fs20easylamp_on");
}
if (!widget.hasClass("widget_fs20easylamp_off")) {
widget.addClass("widget_fs20easylamp_off");
}
}
else if (lamp_status == "on") {
if (!widget.hasClass("widget_fs20easylamp_on")) {
widget.addClass("widget_fs20easylamp_on");
}
if (widget.hasClass("widget_fs20easylamp_off")) {
widget.removeClass("widget_fs20easylamp_off");
}
}
}
});
}
';
return $output;
}
########################################################################################
#
# fs20easylamp_getwidgethtml - HTML code for this widget
#
# no parameter
#
########################################################################################
sub fs20easylamp_get_widgethtml() {
my $output = "";
return $output;
}
########################################################################################
#
# fs20easylamp_get_addwidget_setup_html - Create the selection of devices for this widget
#
# no parameter
#
########################################################################################
sub fs20easylamp_get_addwidget_setup_html() {
my $output = "<script src='js/combobox.js'></script>
<select name='fs20_combobox' id='combobox'>";
my @list = (keys %defs);
foreach my $d (sort @list) {
my $type = $defs{$d}{TYPE};
my $name = $defs{$d}{NAME};
if( $type eq "FS20"){
$output = $output."<option value='$name'>$name</option>";
}
}
$output = $output."</select>";
return $output;
}
########################################################################################
#
# fs20easylamp_get_addwidget_prepare_attributes -
#
# no parameter
#
########################################################################################
sub fs20easylamp_get_addwidget_prepare_attributes() {
my $output = '
var temp_array = new Array();
temp_array[0] = "attribute";
temp_array[1] = $("#combobox option:selected").val()
attributes_array[0] = temp_array;
';
return $output;
}
########################################################################################
#
# fs20easylamp_getwidget_html - HTML code for this widget. DO WE NEED THIS ? SEE ABOVE
#
# no parameter
#
########################################################################################
sub fs20easylamp_getwidget_html() {
my $output = " ";
return $output;
}
########################################################################################
#
# fs20easylamp_get_lamp_status - return the state of the lamp
#
# no parameter
#
########################################################################################
sub fs20easylamp_get_lamp_status () {
my $attribute = YAF_getWidgetAttribute($_GET{"view_id"}, $_GET{"widget_id"}, "attribute");
my $d = $defs{$attribute};
return $d->{STATE};
}
########################################################################################
#
# fs20easylamp_set_lamp_status - set the state of the lamp
#
# no parameter
#
########################################################################################
sub fs20easylamp_set_lamp_status() {
my $attribute = YAF_getWidgetAttribute($_GET{"view_id"}, $_GET{"widget_id"}, "attribute");
my $d = $defs{$attribute};
Log 3, "set ".$d->{NAME}." ".$_GET{"status"};
fhem "set ".$d->{NAME}." ".$_GET{"status"};
}
1;

View File

@ -0,0 +1,231 @@
########################################################################################
#
# fs20st.pm - YAF widget for device FS20ST
#
# YAF - Yet Another Floorplan
# FHEM Projektgruppe Hochschule Karlsruhe, 2013
# Markus Mangei, Daniel Weisensee, Prof. Dr. Peter A. Henning
#
########################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
########################################################################################
package main;
use strict;
use warnings;
my $yaf_version = 0.41;
use vars qw(%_GET);
use vars qw(%defs);
#######################################################################################
#
# fs20st_get_widgetcss - Create the CSS code for this widget
#
# no parameter
#
########################################################################################
sub fs20st_get_widgetcss() {
my $output = "
.widget_fs20st {
width: 33px;
height: 33px;
background-repeat:no-repeat;
background-position:center center;
opacity:1 !important;
}
.widget_fs20st_on {
background-image:url(./img/lamp_on.png) !important;
}
.widget_fs20st_off {
background-image:url(./img/lamp_off.png) !important;
}
";
return $output;
}
########################################################################################
#
# fs20st_get_widgetjs - Create the JavaScript code for this widget
#
# no parameter
#
########################################################################################
sub fs20st_get_widgetjs() {
my $output = '
function fs20st_on_click(view_id, widget_id) {
var widget = $("#widget_"+view_id+"_"+widget_id);
var newState;
if (widget.hasClass("widget_fs20st_on")) {
newState = "off";
} else{
newState = "on";
}
$.ajax({
type: "GET",
async: true,
url: "../../ajax/widget/fs20st/set_state",
data: "view_id="+view_id+"&widget_id="+widget_id+"&state="+newState,
context: document.body,
success: function(){
fs20st_update_widget(view_id, widget_id);
}
});
}
function fs20st_update_widget(view_id, widget_id) {
$.ajax({
type: "GET",
async: true,
url: "../../ajax/widget/fs20st/get_state",
data: "view_id="+view_id+"&widget_id="+widget_id,
context: document.body,
success: function(state) {
var widget = $("#widget_"+view_id+"_"+widget_id);
if (state == "off") {
if (widget.hasClass("widget_fs20st_on")) {
widget.removeClass("widget_fs20st_on");
}
if (!widget.hasClass("widget_fs20st_off")) {
widget.addClass("widget_fs20st_off");
}
}
else if (state == "on") {
if (!widget.hasClass("widget_fs20st_on")) {
widget.addClass("widget_fs20st_on");
}
if (widget.hasClass("widget_fs20st_off")) {
widget.removeClass("widget_fs20st_off");
}
}
}
});
}
';
return $output;
}
########################################################################################
#
# fs20st_getwidgethtml - HTML code for this widget
#
# no parameter
#
########################################################################################
sub fs20st_get_widgethtml() {
my $output = "";
return $output;
}
########################################################################################
#
# fs20st_get_addwidget_setup_html - Create the selection of devices for this widget
#
# no parameter
#
########################################################################################
sub fs20st_get_addwidget_setup_html() {
my $output = "<script src='js/combobox.js'></script>
<select name='fs20_combobox' id='combobox'>";
my @list = (keys %defs);
foreach my $d (sort @list) {
my $type = $defs{$d}{TYPE};
my $name = $defs{$d}{NAME};
if( $type eq "FS20" ){
my $model = defined(AttrVal($name,"model",undef)) ? AttrVal($name,"model",undef) : "";
if( $model eq "fs20st" ){
#-- ignore those that are already defined in this view
$output = $output."<option value='$name'>$name</option>"
if( !YAF_isWidget($_GET{"view_id"},$name) );
}
}
}
$output = $output."</select>";
return $output;
}
########################################################################################
#
# fs20st_get_addwidget_prepare_attributes -
#
# no parameter
#
########################################################################################
sub fs20st_get_addwidget_prepare_attributes() {
my $output = '
var temp_array = new Array();
temp_array[0] = "fhemname";
temp_array[1] = $("#combobox option:selected").val()
attributes_array[0] = temp_array;
';
return $output;
}
########################################################################################
#
# fs20st_getwidget_html - HTML code for this widget. DO WE NEED THIS ? SEE ABOVE
#
# no parameter
#
########################################################################################
sub fs20st_getwidget_html() {
my $output = " ";
return $output;
}
########################################################################################
#
# fs20st_get_state - return the state of the switch
#
# no parameter
#
########################################################################################
sub fs20st_get_state () {
my $name = YAF_getWidgetAttribute($_GET{"view_id"}, $_GET{"widget_id"}, "fhemname");
my $d = $defs{$name};
return $d->{STATE};
}
########################################################################################
#
# fs20st_set_state - set the state of the switch
#
# no parameter
#
########################################################################################
sub fs20st_set_state() {
my $name = YAF_getWidgetAttribute($_GET{"view_id"}, $_GET{"widget_id"}, "fhemname");
Log 3, "set ".$name." ".$_GET{"state"};
fhem "set ".$name." ".$_GET{"state"};
}
1;

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1,461 @@
/*! jQuery UI - v1.9.1 - 2012-10-25
* http://jqueryui.com
* Includes: jquery.ui.core.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css
* To view and modify this theme, visit http://jqueryui.com/themeroller/
* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */
/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
.ui-helper-clearfix:after { clear: both; }
.ui-helper-clearfix { zoom: 1; }
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
.ui-accordion .ui-accordion-header { display: block; cursor: pointer; position: relative; margin-top: 2px; padding: .5em .5em .5em .7em; zoom: 1; }
.ui-accordion .ui-accordion-icons { padding-left: 2.2em; }
.ui-accordion .ui-accordion-noicons { padding-left: .7em; }
.ui-accordion .ui-accordion-icons .ui-accordion-icons { padding-left: 2.2em; }
.ui-accordion .ui-accordion-header .ui-accordion-header-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; overflow: auto; zoom: 1; }
.ui-autocomplete {
position: absolute;
top: 0; /* #8656 */
cursor: default;
}
/* workarounds */
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
.ui-button, .ui-button:link, .ui-button:visited, .ui-button:hover, .ui-button:active { text-decoration: none; }
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
.ui-button-icons-only { width: 3.4em; }
button.ui-button-icons-only { width: 3.7em; }
/*button text element */
.ui-button .ui-button-text { display: block; line-height: 1.4; }
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
/* no icon support for input elements, provide padding by default */
input.ui-button { padding: .4em 1em; }
/*button icon element(s) */
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
/*button sets*/
.ui-buttonset { margin-right: 7px; }
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
/* workarounds */
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
.ui-datepicker .ui-datepicker-prev { left:2px; }
.ui-datepicker .ui-datepicker-next { right:2px; }
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year { width: 49%;}
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
.ui-datepicker td { border: 0; padding: 1px; }
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi { width:auto; }
.ui-datepicker-multi .ui-datepicker-group { float:left; }
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
/* RTL support */
.ui-datepicker-rtl { direction: rtl; }
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
.ui-datepicker-cover {
position: absolute; /*must have*/
z-index: -1; /*must have*/
filter: mask(); /*must have*/
top: -4px; /*must have*/
left: -4px; /*must have*/
width: 200px; /*must have*/
height: 200px; /*must have*/
}.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
.ui-draggable .ui-dialog-titlebar { cursor: move; }
.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; outline: none; }
.ui-menu .ui-menu { margin-top: -3px; position: absolute; }
.ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1; width: 100%; }
.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; }
.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }
.ui-menu .ui-menu-item a.ui-state-focus,
.ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; }
.ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; }
.ui-menu .ui-state-disabled a { cursor: default; }
/* icon support */
.ui-menu-icons { position: relative; }
.ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; }
/* left-aligned */
.ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; }
/* right-aligned */
.ui-menu .ui-menu-icon { position: static; float: right; }
.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }.ui-resizable { position: relative;}
.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
.ui-slider { position: relative; text-align: left; }
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
.ui-slider-horizontal { height: .8em; }
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
.ui-slider-vertical { width: .8em; height: 100px; }
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
.ui-slider-vertical .ui-slider-range-max { top: 0; }.ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; }
.ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; }
.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; }
.ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */
.ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */
.ui-spinner-up { top: 0; }
.ui-spinner-down { bottom: 0; }
/* TR overrides */
.ui-spinner .ui-icon-triangle-1-s {
/* need to fix icons sprite */
background-position:-65px -16px;
}
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 0; margin: 1px .2em 0 0; border-bottom: 0; padding: 0; white-space: nowrap; }
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
.ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: -1px; padding-bottom: 1px; }
.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
.ui-tooltip {
padding: 8px;
position: absolute;
z-index: 9999;
max-width: 300px;
-webkit-box-shadow: 0 0 5px #aaa;
box-shadow: 0 0 5px #aaa;
}
/* Fades and background-images don't work well together in IE6, drop the image */
* html .ui-tooltip {
background-image: none;
}
body .ui-tooltip { border-width: 2px; }
/* Component containers
----------------------------------*/
.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
.ui-widget-content a { color: #222222; }
.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
.ui-widget-header a { color: #222222; }
/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
.ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #212121; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
.ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); } /* For IE8 - See #6059 */
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-on { background-position: -96px -144px; }
.ui-icon-radio-off { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
/* Overlays */
.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); }
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,100 @@
/*
* ########################################################################################
*
* yaf.css
*
* YAF - Yet Another Floorplan
* FHEM Projektgruppe Hochschule Karlsruhe, 2013
* Markus Mangei, Daniel Weisensee
*
* ########################################################################################
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ########################################################################################
*/
#menue {
width: 250px;
float: left;
height: 550px;
}
#content {
float: left;
height: 550px;
}
.tab {
height: 500px;
width: 600px;
}
.menue_button {
width: 240px
}
.menue_block {
margin-bottom: 10px;
}
#menue_button_editview {
margin-top: 10px;
}
#dialog_manageviews-table {
width: 100%;
}
#dialog_manageviews-table col.col1 { }
#dialog_manageviews-table col.col2 { width:20px; }
#dialog_manageviews-table col.col3 { width:20px; }
.loading_animation {
display: none;
position: fixed;
z-index: 1000;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: rgba( 255, 255, 255, .8 )
url('../img/loading.gif')
50% 50%
no-repeat;
}
.widgets {
padding: 0em;
position: absolute;
width: 33px;
height: 33px;
cursor: move;
opacity: 1;
border: 0px;
}
#widget_menue {
padding: 0em;
position: absolute;
width: 100px;
height: 33px;
border: 1px;
z-index: 999;
}
.widget_menue {
width: 33px;
height: 33px;
float: left;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 831 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1,128 @@
(function( $ ) {
$.widget( "ui.combobox", {
_create: function() {
var input,
that = this,
wasOpen = false,
select = this.element.hide(),
selected = select.children( ":selected" ),
value = selected.val() ? selected.text() : "",
wrapper = this.wrapper = $( "<span>" )
.addClass( "ui-combobox" )
.insertAfter( select );
function removeIfInvalid( element ) {
var value = $( element ).val(),
matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( value ) + "$", "i" ),
valid = false;
select.children( "option" ).each(function() {
if ( $( this ).text().match( matcher ) ) {
this.selected = valid = true;
return false;
}
});
if ( !valid ) {
// remove invalid value, as it didn't match anything
$( element )
.val( "" )
.attr( "title", value + " didn't match any item" )
.tooltip( "open" );
select.val( "" );
setTimeout(function() {
input.tooltip( "close" ).attr( "title", "" );
}, 2500 );
input.data( "ui-autocomplete" ).term = "";
}
}
input = $( "<input>" )
.appendTo( wrapper )
.val( value )
.attr( "title", "" )
.addClass( "ui-state-default ui-combobox-input" )
.autocomplete({
delay: 0,
minLength: 0,
source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( select.children( "option" ).map(function() {
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
label: text.replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<strong>$1</strong>" ),
value: text,
option: this
};
}) );
},
select: function( event, ui ) {
ui.item.option.selected = true;
that._trigger( "selected", event, {
item: ui.item.option
});
},
change: function( event, ui ) {
if ( !ui.item ) {
removeIfInvalid( this );
}
}
})
.addClass( "ui-widget ui-widget-content ui-corner-left" );
input.data( "ui-autocomplete" )._renderItem = function( ul, item ) {
return $( "<li>" )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
$( "<a>" )
.attr( "tabIndex", -1 )
.tooltip()
.appendTo( wrapper )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "ui-corner-right ui-combobox-toggle" )
.mousedown(function() {
wasOpen = input.autocomplete( "widget" ).is( ":visible" );
})
.click(function() {
input.focus();
// close if already visible
if ( wasOpen ) {
return;
}
// pass empty string as value to search for, displaying all results
input.autocomplete( "search", "" );
});
input.tooltip({
tooltipClass: "ui-state-highlight"
});
},
_destroy: function() {
this.wrapper.remove();
this.element.show();
}
});
})( jQuery );
$(function() {
$( "#combobox" ).combobox();
$( "#toggle" ).click(function() {
$( "#combobox" ).toggle();
});
});

9440
fhem/contrib/YAF/YAF/www/js/jquery-1.8.2.js vendored Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,160 @@
/*!
* jQuery UI Touch Punch 0.2.2
*
* Copyright 2011, Dave Furfero
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Depends:
* jquery.ui.widget.js
* jquery.ui.mouse.js
*/
(function ($) {
// Detect touch support
$.support.touch = 'ontouchend' in document;
// Ignore browsers without touch support
if (!$.support.touch) {
return;
}
var mouseProto = $.ui.mouse.prototype,
_mouseInit = mouseProto._mouseInit,
touchHandled;
/**
* Simulate a mouse event based on a corresponding touch event
* @param {Object} event A touch event
* @param {String} simulatedType The corresponding mouse event
*/
function simulateMouseEvent (event, simulatedType) {
// Ignore multi-touch events
if (event.originalEvent.touches.length > 1) {
return;
}
event.preventDefault();
var touch = event.originalEvent.changedTouches[0],
simulatedEvent = document.createEvent('MouseEvents');
// Initialize the simulated mouse event using the touch event's coordinates
simulatedEvent.initMouseEvent(
simulatedType, // type
true, // bubbles
true, // cancelable
window, // view
1, // detail
touch.screenX, // screenX
touch.screenY, // screenY
touch.clientX, // clientX
touch.clientY, // clientY
false, // ctrlKey
false, // altKey
false, // shiftKey
false, // metaKey
0, // button
null // relatedTarget
);
// Dispatch the simulated event to the target element
event.target.dispatchEvent(simulatedEvent);
}
/**
* Handle the jQuery UI widget's touchstart events
* @param {Object} event The widget element's touchstart event
*/
mouseProto._touchStart = function (event) {
var self = this;
// Ignore the event if another widget is already being handled
if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) {
return;
}
// Set the flag to prevent other widgets from inheriting the touch event
touchHandled = true;
// Track movement to determine if interaction was a click
self._touchMoved = false;
// Simulate the mouseover event
simulateMouseEvent(event, 'mouseover');
// Simulate the mousemove event
simulateMouseEvent(event, 'mousemove');
// Simulate the mousedown event
simulateMouseEvent(event, 'mousedown');
};
/**
* Handle the jQuery UI widget's touchmove events
* @param {Object} event The document's touchmove event
*/
mouseProto._touchMove = function (event) {
// Ignore event if not handled
if (!touchHandled) {
return;
}
// Interaction was not a click
this._touchMoved = true;
// Simulate the mousemove event
simulateMouseEvent(event, 'mousemove');
};
/**
* Handle the jQuery UI widget's touchend events
* @param {Object} event The document's touchend event
*/
mouseProto._touchEnd = function (event) {
// Ignore event if not handled
if (!touchHandled) {
return;
}
// Simulate the mouseup event
simulateMouseEvent(event, 'mouseup');
// Simulate the mouseout event
simulateMouseEvent(event, 'mouseout');
// If the touch interaction did not move, it should trigger a click
if (!this._touchMoved) {
// Simulate the click event
simulateMouseEvent(event, 'click');
}
// Unset the flag to allow other widgets to inherit the touch event
touchHandled = false;
};
/**
* A duck punch of the $.ui.mouse _mouseInit method to support touch events.
* This method extends the widget with bound touch event handlers that
* translate touch events to mouse events and pass them to the widget's
* original mouse event handling methods.
*/
mouseProto._mouseInit = function () {
var self = this;
// Delegate the touch handlers to the widget's element
self.element
.bind('touchstart', $.proxy(self, '_touchStart'))
.bind('touchmove', $.proxy(self, '_touchMove'))
.bind('touchend', $.proxy(self, '_touchEnd'));
// Call the original $.ui.mouse init method
_mouseInit.call(self);
};
})(jQuery);

View File

@ -0,0 +1,438 @@
/*
* ########################################################################################
*
* yaf-basics.js
*
* YAF - Yet Another Floorplan
* FHEM Projektgruppe Hochschule Karlsruhe, 2013
* Markus Mangei, Daniel Weisensee, Prof. Dr. Peter A. Henning
*
* ########################################################################################
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ########################################################################################
*/
function get_current_view_id() {
return current_view_id;
}
function get_current_widget_id() {
return current_widget_id;
}
// Ändert den Modus der Oberfläche
// mode: id des Modus
function switch_mode(new_mode) {
view_mode = new_mode;
if (new_mode == 0) {
// Live Modus
$(".widgets").draggable("disable");
} else if (new_mode == 1) {
// Positionierungsmodus
$(".widgets").draggable("enable");
}
}
// Timer für den Reload
// Wenn startIntervall = 1 ist, dann wird die Schleife gestartet,
// ansonsten ist es ein einmaliger aufruf
function refreshWidgets() {
$.each(widgets, function (index, widget) {
update_widget(widget[0], widget[1], widget[2])
});
setTimeout(function () {
refreshWidgets();
},
refreshTime * 1000);
}
function init_RefreshWidgets() {
$.ajax({
async: true,
url: "../../ajax/global/getRefreshTime",
context: document.body,
success: function (_refreshTime) {
refreshTime = _refreshTime;
refreshWidgets();
}
});
}
// Läd die Sichten über AJAX vom Server.
// callback: wird aufgerufen, wenn der Server geantwortet hat
function load_views(callback) {
console.log("called load_views()");
$.ajax({
async: true,
url: "../../ajax/global/getViews",
context: document.body,
success: function (jsondata) {
views = jQuery.parseJSON(jsondata);
console.log(views);
if (callback) {
callback();
}
}
});
return;
}
// Fügt eine neue Sicht zu den Tabs hinzu.
// id: Id der Sicht
// name: Name der Sicht
function add_tab(id, name) {
console.log("called add_tab()");
// Neues Div nur erzeugen, wenn es noch keins mit der entsprechenden Id gibt
if ($("#tabs-" + id).length <= 0) {
$("#tabs").append("<div id=\"tabs-" + id + "\" class=\"loaded tab\"></div>");
}
$("#views").append("<li id=\"tabs_li-" + id + "\"><a href=\"#tabs-" + id + "\">" + name + "</a></li>");
$("#tabs").tabs("refresh");
return;
}
// Löscht eine Sicht aus den Tabs.
// Das <div> sowie der <li> Eintrag werden gelöscht.
// id: Id der zu löschenden Sicht
function delete_tab(id) {
// Kann noch optimiert werden!
console.log("called delete_tab()");
$("#tabs-" + id).remove();
$("#tabs_li-" + id).remove();
load_views(show_views);
return;
}
// Zeigt alle Tabs neu an.
// Zuerst werden alle Tabs gelöscht und anschließend neu anzeigen.
function show_views() {
console.log("called show_views()");
$("#views").html("");
if (views.length == 0) {
$('#views').hide();
$('#tabs_error').html("Es wurden keine Sichten gefunden!");
$('#tabs_error').show();
} else {
$('#tabs_error').hide();
$('#views').show();
var selected_view_id = get_current_view_id();
var selected = 0;
var minId = 999;
$.each(views, function (index, view) {
add_tab(view[0], view[1]);
if (selected_view_id == view[0]) {
$('#tabs').tabs("select", "#tabs-" + view[0]);
selected = 1;
}
if (view[0] < minId) {
minId = view[0];
}
});
if (! selected) {
$('#tabs').tabs("select", "#tabs-" + minId);
}
}
return;
}
// Zeigt ein neues Hintergrundbild in einer bestimmten Sicht an.
// view_id: Die Sicht, in der das Hintergrundbild eingefügt werden soll
// file: Pfad und Dateiname der Grafik
// x_pos: x Positon
// y_pos: y Position
function add_background_image(view_id, file, x_pos, y_pos) {
$("#tabs-" + view_id).append("<img src=\"" + file + "\" />");
}
function update_widget(name, view_id, widget_id) {
console.log("update_widget " + name);
try {
eval(name + "_update_widget(" + view_id + ", " + widget_id + ")");
}
catch (exception) {
console.log("Error in update_widget()");
}
}
// Zeigt ein neues Widget in einer bestimmten Sicht an.
// view_id: Die Sicht, in der das Hintergrundbild eingefügt werden soll
// name: Typ des Widgets
// x_pos: x Positon
// y_pos: y Position
// attr_array: Ein Array mit den Attributen des Widgets.
function add_widget(view_id, widget_id, name, x_pos, y_pos, attr_array) {
var widget_html = "";
$.ajax({
type: "GET",
async: false,
url: "../../ajax/widget/" + name + "/getwidget_html",
context: document.body,
success: function (result) {
widget_html = result;
}
});
$("#tabs-" + view_id).append("<div id=\"widget_" + view_id + "_" + widget_id + "\" class=\"widgets widget_" + name + "\" style=\"left: " + x_pos + "px; top: " + y_pos + "px;\">" + widget_html + "</div>");
update_widget(name, view_id, widget_id);
$("#widget_" + view_id + "_" + widget_id).click(function () {
if (view_mode == 0) {
try {
eval(name + "_on_click(" + view_id + ", " + widget_id + ")");
}
catch (exception) {
console.log("Error in on_click()");
}
} else if (view_mode == 1) {
if (! widgetWasMoved) {
$("#widget_menue").show();
current_widget_id = widget_id;
var top = $("#widget_" + view_id + "_" + widget_id).position().top;
var left = $("#widget_" + view_id + "_" + widget_id).position().left;
// Nach links anzeigen
var offsetLeft = $("#widget_" + view_id + "_" + widget_id).width();
var positionLeft = left + offsetLeft - 10;
var positionTop = top - 23;
$("#widget_menue").css("top", positionTop);
$("#widget_menue").css("left", positionLeft);
setTimeout(function () {
if (close_widget_menue) {
$("#widget_menue").hide();
}
},
2500);
}
}
});
$("#widget_" + view_id + "_" + widget_id).draggable({
containment: "parent",
start: function (event, ui) {
close_widget_menue = true;
$("#widget_menue").hide();
},
stop: function (event, ui) {
widgetWasMoved = true;
setTimeout(function () {
widgetWasMoved = false;
},
500);
// Neue Position des Widget speichern. Kommastellen werden abgeschnitten.
x_pos = parseInt(ui.position.left);
y_pos = parseInt(ui.position.top);
widget_id = $(event.target).attr("id").split("_")[2];
view_id = $(event.target).attr("id").split("_")[1];
console.log("view-id: " + get_current_view_id() + " widget-id: " + widget_id + " x-pos: " + x_pos + " y-pos: " + y_pos);
$.ajax({
type: "GET",
async: true,
url: "../../ajax/global/setWidgetPosition",
data: "view_id=" + view_id + "&widget_id=" + widget_id + "&x_pos=" + x_pos + "&y_pos=" + y_pos,
context: document.body,
success: function (jsondata) {
console.log("Widget Position geändert: " + jsondata)
}
});
}
});
// widget in Widgetliste einfügen
var widget = new Array(name, get_current_view_id(), widget_id);
widgets[widgets.length] = widget;
}
// Behandelt das öffnen eines Tabs
// Entweder der Inhalt wurde bereits geladen, oder er muss über
// Ajax nachgeladen werden.
function activate_tab(view_id) {
if (! $("#tabs-" + view_id).hasClass("isLoaded")) {
current_view_id = view_id;
console.log("activate tab: " + view_id);
console.log("load widgets");
$("#tabs-" + view_id).html("");
// Speichern, dass view bereits geladen wurde
$("#tabs-" + view_id).addClass("isLoaded");
$("#tabs-" + view_id).html("");
$.ajax({
async: false,
url: "../../ajax/global/getView",
data: "id=" + view_id,
context: document.body,
success: function (jsondata) {
var view_data = jQuery.parseJSON(jsondata);
// background images laden
if (view_data.backgrounds) {
$.each(view_data.backgrounds, function (index, background) {
add_background_image(view_id, background.img_url, background.x_pos, background.y_pos);
});
} else {
console.log("keine Hintergrundbilder vorhanden!");
}
// widgets laden
if (view_data.widgets) {
$.each(view_data.widgets, function (index, widget) {
widget_x_pos = widget.x_pos;
widget_y_pos = widget.y_pos;
widget_name = widget.name;
widget_id = widget.id;
add_widget(view_id, widget_id, widget_name, widget_x_pos, widget_y_pos, 0);
});
// Aktueller View Mode für alle Widgets aktualisiert
switch_mode(view_mode);
} else {
console.log("keine widgets vorhanden!");
}
}
});
} else {
current_view_id = view_id;
console.log("switch to activated tab: " + view_id);
}
return;
}
// Initialisiert die Tabs. Diese Funktion muss nur einmal aufgerufen werden.
// Sobald das Tab gewechselt wird, wird die Funktion activate_tab(id)
// aufgerufen.
function init_tabs() {
$("#tabs").tabs({
activate: function (event, ui) {
activate_tab(ui.newPanel.selector.substr(6));
},
create: function (event, ui) {
//activate_tab(ui.panel.selector.substr(6));
}
});
$("#tabs").resizable({
containment: $(".widgets")
});
}
// Initialisiert das Menü.
function init_menue() {
$("#button_back").button({
icons: {
secondary: "ui-icon-circle-arrow-w"
}
});
$("#button_addview").button({
icons: {
secondary: "ui-icon-plusthick"
}
});
$("#button_manageviews").button({
icons: {
secondary: "ui-icon-plusthick"
}
});
$("#button_addwidget").button({
icons: {
secondary: "ui-icon-plusthick"
}
});
$("#button_managewidgets").button({
icons: {
secondary: "ui-icon-plusthick"
}
});
$("#button_settings").button({
icons: {
secondary: "ui-icon-pencil"
}
});
$("#widget_menue_edit").button({
icons: {
secondary: "ui-icon-pencil"
}
});
$("#widget_menue_delete").button({
icons: {
secondary: "ui-icon-trash"
}
});
$("#button_editview").buttonset();
}
// Initialisiert die Handler
function init_handlers() {
$("#button_back").click(function () {
window.location.href = "../../../../fhem";
return false;
});
$("#button_settings").click(function () {
$("#dialog_settings").dialog("open");
return false;
});
$("#button_addview").click(function () {
$("#dialog_addview").dialog("open");
return false;
});
$("#button_manageviews").click(function () {
$("#dialog_manageviews").dialog("open");
return false;
});
$("#button_addwidget").click(function () {
$("#dialog_addwidget").dialog("open");
return false;
});
$("#button_switchmode_0").click(function () {
if (view_mode != 0) {
switch_mode(0);
}
});
$("#button_switchmode_1").click(function () {
if (view_mode != 1) {
switch_mode(1);
}
});
$("#widget_menue_delete").click(function () {
$("#label_deletewidget").html("xy");
$("#dialog_deletewidget").dialog("open");
});
$("#widget_menue_edit").click(function () {
$("#label_editwidget").html("xy");
$("#dialog_editwidget").dialog("open");
$("#widget_menue").hide();
close_widget_menue = true;
});
$("#widget_menue").mouseenter(function () {
close_widget_menue = false;
});
$("#widget_menue").mouseleave(function () {
close_widget_menue = true;
$("#widget_menue").hide();
});
}

View File

@ -0,0 +1,371 @@
/*
* ########################################################################################
*
* yaf-dialogs.js
*
* YAF - Yet Another Floorplan
* FHEM Projektgruppe Hochschule Karlsruhe, 2013
* Markus Mangei, Daniel Weisensee, Prof. Dr. Peter A. Henning
*
* ########################################################################################
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ########################################################################################
*/
// Initialisiert die Dialoge
function init_dialogs() {
$("#dialog_addview").dialog({
autoOpen: false,
resizable: true,
height: 300,
width: 400,
modal: true,
buttons: {
"Hinzufügen": function (event) {
console.log("before: " + views);
$("#dialog_addview_loading").show();
$.ajax({
type: "GET",
async: true,
url: "../../ajax/global/addView",
data: "name=" + $("#dialog_addview_name").val(),
context: document.body,
success: function (jsondata) {
$("#dialog_addview").dialog("close");
load_views(show_views);
$("#dialog_addview_loading").hide();
console.log("after: " + views);
}
});
$(this).dialog("close");
},
"Abbrechen": function () {
$(this).dialog("close");
}
}
});
$("#dialog_deleteview").dialog({
autoOpen: false,
resizable: true,
height: 300,
width: 400,
modal: true,
buttons: {
"Löschen": function (ui) {
$.ajax({
type: "GET",
async: false,
url: "../../ajax/global/deleteView",
data: "id=" + delete_view_id,
context: document.body,
success: function (jsondata) {
delete_tab(delete_view_id);
$("#dialog_deleteview").dialog("close");
$("#manageviews_tr_" + delete_view_id).remove();
}
});
$(this).dialog("close");
},
"Abbrechen": function () {
$(this).dialog("close");
}
}
});
$("#dialog_editview").dialog({
autoOpen: false,
resizable: true,
height: 300,
width: 400,
modal: true,
buttons: {
"Speichern": function (ui) {
console.log("before: " + views);
$("#dialog_editview_loading").show();
$.ajax({
type: "GET",
async: true,
url: "../../ajax/global/editView",
data: "id=" + edit_view_id + "&name=" + $("#dialog_editview_name").val(),
context: document.body,
success: function (jsondata) {
load_views(show_views);
$($("#manageviews_tr_" + edit_view_id).children().get(0)).text($("#dialog_editview_name").val());
$("#dialog_editview_loading").hide();
$("#dialog_editview").dialog("close");
}
});
$(this).dialog("close");
},
"Abbrechen": function () {
$(this).dialog("close");
}
}
});
$("#dialog_addwidget").dialog({
autoOpen: false,
resizable: true,
height: 500,
width: 600,
modal: true,
buttons: {
"Schließen": function () {
$(this).dialog("close");
}
},
open: function (event, ui) {
$("#dialog_addwidget_loading").show();
$.ajax({
type: "GET",
async: true,
url: "../../ajax/global/getWidgets",
context: document.body,
success: function (jsondata) {
var widgets = jQuery.parseJSON(jsondata);
$("#dialog_addwidget_table").html("<colgroup><col class=\"col1\"><col class=\"col2\"><col class=\"col3\"></colgroup>");
if (widgets) {
$.each(widgets, function (index, widget) {
$("#dialog_addwidget_table").append("<tr><td>" + widget + "</td><td></td><td><button class=\"button_addwidget\" id=\"addwidget_" + widget + "\">&nbsp;</button></td></tr>");
});
$(".button_addwidget").button({
icons: {
primary: "ui-icon-circle-plus"
},
text: false
});
$(".button_addwidget").click(function (ui) {
add_widget_name = $(ui.currentTarget).attr("id").substr(10);
$("#dialog_addwidget_setup_widget").html(add_widget_name);
$("#dialog_addwidget_setup").dialog("open");
$("#dialog_addwidget_setup_loading").show();
$.ajax({
type: "GET",
async: true,
url: "../../ajax/widget/" + add_widget_name + "/get_addwidget_setup_html",
context: document.body,
success: function (html_result) {
if (html_result != 0) {
$("#dialog_addwidget_setup_form").html(html_result);
} else {
$("#dialog_addwidget_setup_form").html("Das Widget stellt keine Konfigurationsmöglichkeiten bereit!")
}
$("#dialog_addwidget_setup_loading").hide();
}
});
console.log("widget hinzufügen: " + add_widget_name)
return false;
});
} else {
console.log("keine Widgets vorhanden!")
}
$("#dialog_addwidget_loading").hide();
}
});
}
});
$("#dialog_addwidget_setup").dialog({
autoOpen: false,
resizable: true,
height: 350,
width: 400,
modal: true,
buttons: {
"Hinzufügen": function (event) {
$("#dialog_addwidget_setup_loading").show();
var attributes_array = new Array();
$.ajax({
type: "GET",
async: false,
url: "../../ajax/widget/" + add_widget_name + "/get_addwidget_prepare_attributes",
context: document.body,
success: function (js_result) {
try {
eval(js_result);
}
catch (exception) {
console.log("exception in dialog_addwidget_setup dialog event");
}
}
});
console.log(JSON.stringify(attributes_array));
$.ajax({
type: "GET",
async: false,
url: "../../ajax/global/addWidget",
data: "view_id=" + current_view_id + "&widget=" + add_widget_name + "&attributes=" + JSON.stringify(attributes_array),
context: document.body,
success: function (widgetId) {
// Position links oben x= 28 y = 69, muss auch in 01_YAF.pm in addWidget() Methode angepasst werden!
add_widget(current_view_id, widgetId, add_widget_name, 28, 69, attributes_array);
// Aktueller View Mode für alle Widgets aktualisiert
switch_mode(view_mode);
}
});
$("#dialog_addwidget_setup_loading").hide();
$(this).dialog("close");
},
"Abbrechen": function () {
$(this).dialog("close");
}
},
open: function (event, ui) {
console.log("dialog widget hinzufügen geöffnet => inhalt laden");
}
});
$("#dialog_deletewidget").dialog({
autoOpen: false,
resizable: true,
height: 300,
width: 400,
modal: true,
buttons: {
"Löschen": function (ui) {
var view_id = get_current_view_id();
var widget_id = get_current_widget_id();
console.log("delete view " + view_id + " widget " + widget_id);
$.ajax({
type: "GET",
async: false,
url: "../../ajax/global/deleteWidget",
data: "view_id=" + view_id + "&widget_id" + widget_id,
context: document.body,
success: function (jsondata) {
console.log("widget deleted");
$("#dialog_deletewidget").dialog("close");
$("#widget_menue").hide();
$("#widget_" + view_id + "_" + widget_id).remove();
}
});
$(this).dialog("close");
},
"Abbrechen": function () {
$(this).dialog("close");
}
}
});
$("#dialog_editwidget").dialog({
autoOpen: false,
resizable: true,
height: 300,
width: 400,
modal: true,
buttons: {
"Speichern": function (ui) {
$(this).dialog("close");
},
"Abbrechen": function () {
$(this).dialog("close");
}
}
});
$("#dialog_manageviews").dialog({
autoOpen: false,
resizable: true,
height: 500,
width: 600,
modal: true,
buttons: {
"Schließen": function () {
$(this).dialog("close");
}
},
open: function (event, ui) {
$("#dialog_manageviews-table").html("<colgroup><col class=\"col1\"><col class=\"col2\"><col class=\"col3\"></colgroup>");
$.each(views, function (index, view) {
$("#dialog_manageviews-table").append("<tr id=\"manageviews_tr_" + view[0] + "\"><td>" + view[1] + "</td><td><button id=\"button_edit_" + view[0] + "\" class=\"button_edit\">&nbsp;</button></td><td><button class=\"button_delete\" id=\"button_edit_" + view[0] + "\">&nbsp;</button></td></tr>");
});
$(".button_edit").button({
icons: {
primary: "ui-icon-pencil"
},
text: false
});
$(".button_delete").button({
icons: {
primary: "ui-icon-trash"
},
text: false
});
$(".button_delete").click(function (ui) {
var sichtName = $(ui.currentTarget.parentNode.parentNode.firstChild).html();
delete_view_id = $(ui.currentTarget).attr("id").substr(12);
$("#label_deleteview").html(sichtName);
$("#dialog_deleteview").dialog("open");
return false;
});
$(".button_edit").click(function (ui) {
edit_view_name = $(ui.currentTarget.parentNode.parentNode.firstChild).html();
edit_view_id = $(ui.currentTarget).attr("id").substr(12);
$("#dialog_editview_name").val(edit_view_name);
$("#dialog_editview").dialog("open");
return false;
});
}
});
$("#dialog_settings").dialog({
autoOpen: false,
resizable: true,
height: 500,
width: 600,
modal: true,
buttons: {
"Speichern": function () {
$("#dialog_settings_loading").show();
console.log("update widget refresh interval");
$.ajax({
type: "GET",
async: true,
url: "../../ajax/global/setRefreshTime",
data: "interval=" + $("#dialog_settings_intervall").val(),
context: document.body,
success: function () {
refreshTime = $("#dialog_settings_intervall").val();
$("#dialog_settings_loading").hide();
$("#dialog_settings").dialog("close");
}
});
$(this).dialog("close");
},
"Abbrechen": function () {
$(this).dialog("close");
}
},
open: function (event, ui) {
console.log("dialog settings opened");
$("#dialog_settings_loading").show();
$.ajax({
type: "GET",
async: true,
url: "../../ajax/global/getRefreshTime",
data: "interval=" + $("#dialog_settings_intervall").val(),
context: document.body,
success: function (refreshInterval) {
$("#dialog_settings_intervall").val(refreshInterval);
$("#dialog_settings_loading").hide();
}
});
}
});
}

181
fhem/contrib/YAF/YAF/www/yaf.htm Executable file
View File

@ -0,0 +1,181 @@
<!--
########################################################################################
#
# yaf.htm
#
# YAF - Yet Another Floorplan
# FHEM Projektgruppe Hochschule Karlsruhe, 2013
# Markus Mangei, Daniel Weisensee
#
########################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
########################################################################################
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="us" lang="us">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>YAF GUI</title>
<link type="text/css" href="css/smoothness/jquery-ui-1.9.1.custom.css" rel="stylesheet"/>
<link type="text/css" href="css/yaf.css" rel="stylesheet" />
<script type="text/javascript" src="js/jquery-1.8.2.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.9.1.custom.js"></script>
<script type="text/javascript" src="js/jquery.ui.touch-punch.min.js"></script>
<script type="text/javascript" src="js/yaf-dialogs.js"></script>
<script type="text/javascript" src="js/yaf-basics.js"></script>
<script>
// Array mit den Namen und den zugehörigen Id's der Sichten
var views = new Array();
var widgets = new Array();
var current_view_id = null;
var current_widget_id = null;
var refreshTime = null;
// Modus in der Sich YAF befindet
// modus=0: Live Modus
// modus=1: Positionierungs Modus
var view_mode = 0;
var widgetWasMoved = false;
var close_widget_menue = true;
// Speichert die Id der View, die gelöscht werden soll
var delete_view_id = null;
var edit_view_name = null;
var edit_view_id = null;
var add_widget_name = null;
// Initialisiert die Oberfläche
function init() {
init_tabs();
init_menue();
$("#widget_menue").hide();
init_dialogs();
init_handlers();
load_views(show_views);
init_RefreshWidgets();
return;
}
###widget_js###
$(document).ready(function() {
init();
});
</script>
<style>
###widget_css###
</style>
</head>
<body>
<div id="container">
<div id="menue">
<div class="menue_block">
<button id="button_back" class="menue_button">Zu FHEM</button>
</div>
<div class="menue_block">
<button id="button_settings" class="menue_button">Einstellungen</button>
</div>
<div class="menue_block">
<button id="button_addview" class="menue_button">Sicht hinzufügen</button>
<button id="button_manageviews" class="menue_button">Sichten verwalten</button>
</div>
<div class="menue_block">
<button id="button_addwidget" class="menue_button">Widget hinzufügen</button>
</div>
<div class="menue_block">
<div id="button_editview" class="menue_button">
<input type="radio" id="button_switchmode_0" name="radio" checked="checked"/><label for="button_switchmode_0" style="width: 118px;">Live</label>
<input type="radio" id="button_switchmode_1" name="radio"/><label for="button_switchmode_1" style="width: 118px;">Bearbeiten</label>
</div>
</div>
</div>
<div id="content">
<div id="tabs">
<div id="widget_menue">
<button id="widget_menue_edit" class="widget_menue"></button>
<button id="widget_menue_delete" class="widget_menue"></button>
</div>
<div id="tabs_error"></div>
<ul id="views">
</ul>
</div>
</div>
</div>
<div id="dialog_addview" title="Sicht hinzufügen">
<div class="loading_animation" id="dialog_addview_loading"></div>
<p>Hier können Sie YAF eine neue Sicht hinzufügen.</p>
<label>Name: </label><input id="dialog_addview_name" name="dialog_addview_name"/>
</div>
<div id="dialog_editview" title="Sicht bearbeiten">
<div class="loading_animation" id="dialog_addview_loading"></div>
<p>Hier können Sie die bestehende Sicht ändern.</p>
<label>Name: </label><input id="dialog_editview_name" name="dialog_editview_name" value="" />
</div>
<div id="dialog_deleteview" title="Sicht löschen">
<div class="loading_animation" id="dialog_deleteview_loading"></div>
<p>Sind Sie sicher, dass Sie die Sicht "<span><b id="label_deleteview"></b></span>" löschen Möchten? Es gehen alle Widgets verloren, die auf dieser Sicht verankert sind!</p>
</div>
<div id="dialog_manageviews" title="Sichten verwalten">
<div class="loading_animation" id="dialog_manageviews_loading"></div>
<p>Hier können Sie einzelne Sichten löschen oder bearbeiten. Gelöschte Sichten können nicht wiederhergestellt werden!</p>
<table id="dialog_manageviews-table">
</table>
</div>
<div id="dialog_addwidget" title="Widget hinzufügen">
<div class="loading_animation" id="dialog_addwidget_loading"></div>
<p>Hier können Sie Widgets zur ausgewählten Sicht hinzufügen.</p>
<table id="dialog_addwidget_table">
</table>
</div>
<div id="dialog_addwidget_setup" title="Widget hinzufügen">
<div class="loading_animation" id="dialog_addwidget_setup_loading"></div>
<p>Widget vom Typ <b id="dialog_addwidget_setup_widget"></b> hinzufügen: </p>
<div id="dialog_addwidget_setup_form" />
</div>
<div id="dialog_editwidget" title="Widget bearbeiten">
<div class="loading_animation" id="dialog_editwidget_loading"></div>
<p>Widget "<span><b id="label_editwidget"></b></span>" bearbeiten:</p>
</div>
<div id="dialog_deletewidget" title="Widget löschen">
<div class="loading_animation" id="dialog_deletewidget_loading"></div>
<p>Sind Sie sicher, dass Sie das Widget "<span><b id="label_deletewidget"></b></span>" löschen möchten?</p>
</div>
<div id="dialog_settings" title="Einstellungen">
<div class="loading_animation" id="dialog_settings_loading"></div>
<p>Einstellungen</p>
<label>Refresh-Intervall: </label><input id="dialog_settings_intervall" name="dialog_settings_intervall" value="" />
</div>
</body>
</html>

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
########################################################################################
#
# xmlSchema.xsd
#
# YAF - Yet Another Floorplan
# FHEM Projektgruppe Hochschule Karlsruhe, 2013
# Markus Mangei, Daniel Weisensee
#
########################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
########################################################################################
-->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- declaration of root -->
<xsd:element name="configuration" type="configuration-type" />
<xsd:complexType name="configuration-type">
<xsd:sequence>
<xsd:element name="settings" type="settings-type" minOccurs="1" maxOccurs="1" />
<xsd:element name="views" type="views-type" minOccurs="1" maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
<!-- settings -->
<xsd:complexType name="settings-type">
<xsd:sequence>
<xsd:element name="refresh" minOccurs="1" maxOccurs="1">
<xsd:complexType>
<xsd:attribute name="interval" type="xsd:int" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<!-- views -->
<xsd:complexType name="views-type">
<xsd:sequence>
<xsd:element name="view" type="view-type" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="view-type">
<xsd:sequence>
<xsd:element name="backgrounds" type="backgrounds-type" minOccurs="0" maxOccurs="1" />
<xsd:element name="widgets" type="widgets-type" minOccurs="1" maxOccurs="1" />
</xsd:sequence>
<xsd:attribute name="id" type="xsd:int" use="required" />
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
<xsd:complexType name="backgrounds-type">
<xsd:sequence>
<xsd:element name="background" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="img_url" type="xsd:string" use="required" />
<xsd:attribute name="x_pos" type="xsd:int" use="required" />
<xsd:attribute name="y_pos" type="xsd:int" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="widgets-type">
<xsd:sequence>
<xsd:element name="widget" type="widget-type" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="widget-type">
<xsd:sequence>
<xsd:element name="attr" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="value" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:int" use="required" />
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="x_pos" type="xsd:int" use="required" />
<xsd:attribute name="y_pos" type="xsd:int" use="required" />
</xsd:complexType>
</xsd:schema>

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
########################################################################################
#
# yafConfig.xml
#
# YAF - Yet Another Floorplan
# FHEM Projektgruppe Hochschule Karlsruhe, 2013
# Markus Mangei, Daniel Weisensee
#
########################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
########################################################################################
-->
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xmlSchema.xsd">
<settings>
<refresh interval="5"/>
</settings>
<views>
<view id="1" name="Erdgeschoss">
<backgrounds>
<background img_url="./img/eg.jpeg" x_pos="1" y_pos="1"/>
</backgrounds>
<widgets>
<widget name="fs20easylamp" x_pos="308" y_pos="202" id="1">
<attr name="fhemname" value="ez_LichtRegal"/>
</widget>
</widgets>
</view>
<view id="2" name="Obergeschoss">
<backgrounds>
<background img_url="./img/1og.jpeg" x_pos="1" y_pos="1"/>
</backgrounds>
<widgets>
<widget name="fs20easylamp" x_pos="151" y_pos="279" id="1">
<attr name="fhemname" value="ez_LichtRegal2"/>
</widget>
</widgets>
</view>
</views>
</configuration>

88
fhem/contrib/YAF/fhem.cfg Normal file
View File

@ -0,0 +1,88 @@
################################################################################
#
# fhem.cfg
# Exemplary fhem.cfg for demonstration purposes.
# Defines YAF and Floorplan and demonstrates the binding between the lamp widgets
# This file is not copied to /opt/fhem during the installation process!
#
# YAF - Yet Another Floorplan
# FHEM Projektgruppe Hochschule Karlsruhe, 2013
# Markus Mangei, Daniel Weisensee
#
################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
attr global logfile ./log/fhem-%Y-%m.log
attr global modpath . # where our FHEM directory is
attr global statefile ./log/fhem.save # where to save the state of the devices
attr global verbose 3 # "normal" verbosity (min 1, max 5)
attr global motd none
define telnetPort telnet 7072 global # our TCP/IP port
define WEB FHEMWEB 8083 global
define WEBphone FHEMWEB 8084 global
attr WEBphone smallscreen
define WEBtablet FHEMWEB 8085 global
attr WEBtablet touchpad
# Fake FileLog entry, to access the fhem log from FHEMWEB
define Logfile FileLog ./log/fhem-%Y-%m.log fakelog
define autocreate autocreate
attr autocreate autosave
attr autocreate device_room %TYPE
attr autocreate filelog ./log/%NAME-%Y.log
attr autocreate weblink
attr autocreate weblink_room Plots
# Disable this to avoid looking for new USB devices on startup
define initialUsbCheck notify global:INITIALIZED usb create
# If the above notify did not helped, then you probably have to enable some of
# the following lines. Verify first that /dev/xxx ist correct.
#define FHZ FHZ /dev/USB0
#define CUL CUL /dev/ttyACM0@9600 1234
#attr CUL rfmode HomeMatic
#define EUL TCM 310 /dev/ttyACM0@57600
#define BscBor TCM 120 /dev/ttyUSB0@9600
#define BscSmartConnect TCM 310 /dev/ttyUSB0@57600
################################################################################
# [YAF project] Configure YAF - Yet Another Floorplan
################################################################################
define yafVar YAF
################################################################################
# [YAF project] Configure Floorplan
################################################################################
define Erdgeschoss FLOORPLAN
attr Erdgeschoss fp_arrange 1
define ez_LichtRegal FS20 6969 01
attr ez_LichtRegal fp_Erdgeschoss 194,384,0,
attr ez_LichtRegal model fs20st
attr ez_LichtRegal room Schlafen
define ez_LichtRegal2 FS20 6969 02
attr ez_LichtRegal2 fp_Erdgeschoss 59,580,0,
attr ez_LichtRegal2 model fs20st
attr ez_LichtRegal2 room Bad

Binary file not shown.

Binary file not shown.