sso looks working
@@ -0,0 +1,447 @@
|
||||
<cfcomponent
|
||||
displayname="Application"
|
||||
output="true"
|
||||
hint="Handle the application.">
|
||||
|
||||
|
||||
<!--- Pseudoconstructor --->
|
||||
<!--- Set up the application. --->
|
||||
<cfset this.Name = "PAYG-REPORT" />
|
||||
<cfset this.applicationTimeout = createTimeSpan( 0, 0, 0, 30 ) />
|
||||
<cfset this.sessionmanagement="Yes"/>
|
||||
<cfset this.clientmanagement="No"/>
|
||||
<cfset this.sessiontimeout=CreateTimeSpan(0, 0, 0, 20)/>
|
||||
<cfset this.setclientcookies="No"/>
|
||||
<cfset this.mappings = structNew() />
|
||||
<cfset this.mappings["/mod"] = getDirectoryFromPath(getCurrentTemplatePath()) & "mod/" />
|
||||
<cfset this.customTagPaths = expandPath(getDirectoryFromPath(getCurrentTemplatePath()) & "mod")/>
|
||||
<cfset this.datasource = "billing"/>
|
||||
<!--- SSO --->
|
||||
<cfset this.client_id = "payg-report.deck.nubes.ru"/>
|
||||
<cfset this.auth_endpoint = "https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/auth" />
|
||||
<cfset this.access_token_endpoint = "https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/token" />
|
||||
<cfset this.idpCertUrl = "https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/certs" />
|
||||
<cfset this.client_secret = createObject("java", "java.lang.System").getEnv("IDP_CLIENT_SECRET")/>
|
||||
<!--- <cfset this.client_secret = this.client_secret ?: ""/> --->
|
||||
|
||||
<cfset this.defaultdatasource = this.datasource/>
|
||||
<cfset request.DS = "#this.datasource#">
|
||||
<!--- кажется, нужно инициализировать датасорцы в псевдоконструкторе - onRequest не получается --->
|
||||
<!--- <cfset this.datasources["#this.datasource#"]=getDS("#this.datasource#","ds_#this.datasource#")/> --->
|
||||
|
||||
|
||||
<cffunction
|
||||
name="OnApplicationStart"
|
||||
access="public"
|
||||
returntype="boolean"
|
||||
output="false"
|
||||
hint="Fires when the application is first created.">
|
||||
|
||||
<!--- *** мы не проверяем срок жизни сертификата и его отзыв--->
|
||||
Obtain idp certificate OnApplicationStart
|
||||
<cfset application.idpCertificate = getIdpCertificate(this.idpCertUrl)/>
|
||||
|
||||
<cfreturn true />
|
||||
</cffunction>
|
||||
|
||||
|
||||
<cffunction
|
||||
name="OnRequest"
|
||||
access="public"
|
||||
returntype="void"
|
||||
output="true"
|
||||
hint="Fires after pre page processing is complete.">
|
||||
|
||||
<cfargument name="template" type="string" required="true"/>
|
||||
|
||||
<cfset request.startTickCount=getTickCount()/>
|
||||
|
||||
<cfset setEncoding("FORM", "UTF-8")>
|
||||
<cfset setEncoding("URL", "UTF-8")>
|
||||
|
||||
<cfset request.PERMISSION_NONE=0/>
|
||||
<cfset request.PERMISSION_READ=1/>
|
||||
<cfset request.PERMISSION_WRITE=2/>
|
||||
|
||||
<!--- <cfset request.UNDEFINED_USR_ID=-1/>
|
||||
<cfset request.ANONYMOUS_USR_ID=2/>
|
||||
<cfset request.GUEST_USR_ID=3/> --->
|
||||
|
||||
<!--- global settings --->
|
||||
<cfset request.RECORDS_PER_PAGE=500/>
|
||||
<cfset request.APP_VERSION="0.00.000"/>
|
||||
<cfset request.STAND=getStand()/>
|
||||
|
||||
<!--- application constants --->
|
||||
|
||||
<!---<cfset request.SMTP_SERVER="172.16.16.16"/>
|
||||
<cfset request.MAIL_FROM_FOR_NOTIFICATION="Pipeline tracker <pipeline@mail.ru>"/>
|
||||
<cfset request.SUBJECT_PREFIX="[PIPELINE TRACKER] "/>--->
|
||||
<!---<cfset request.BASE_URL="https://smtest.dtln.local/pipeline/"/>*** сделать нормально. Внимание! При наличии прокси CGI.SERVER_NAME может быть заменено --->
|
||||
|
||||
<cfset local = {} />
|
||||
|
||||
<cfset local.basePath = getDirectoryFromPath(
|
||||
getCurrentTemplatePath()
|
||||
) />
|
||||
|
||||
<cfset local.targetPath = getDirectoryFromPath(
|
||||
expandPath( arguments.template )
|
||||
) />
|
||||
|
||||
<cfset local.requestDepth = (
|
||||
listLen( local.targetPath, "\/" ) -
|
||||
listLen( local.basePath, "\/" )
|
||||
) />
|
||||
|
||||
<cfset request.webRoot = repeatString(
|
||||
"../",
|
||||
local.requestDepth
|
||||
) />
|
||||
|
||||
<!---
|
||||
While we wouldn't normally do this for every page
|
||||
request (it would normally be cached in the
|
||||
application initialization), I'm going to calculate
|
||||
the site URL based on the web root.
|
||||
--->
|
||||
<cfset request.siteUrl = (
|
||||
IIF(
|
||||
(CGI.server_port_secure <!--- CGI.https EQ "On" does not work with apache+tomcat and nginx+tomcat --->),
|
||||
DE( "https://" ),
|
||||
DE( "http://" )
|
||||
) &
|
||||
cgi.http_host &
|
||||
reReplace(
|
||||
getDirectoryFromPath( arguments.template ), "([^\\/]+[\\/]){#local.requestDepth#}$",
|
||||
"",
|
||||
"one"
|
||||
)
|
||||
) />
|
||||
|
||||
<cfset request.thisPage=Replace(ReplaceNoCase(expandPath(ARGUMENTS.template), local.basePath, ""), "\", "/")/>
|
||||
<!--- <cfset request.thisUrl="#request.thisPage##len(CGI.queryString)#"/> чревато циклом --->
|
||||
|
||||
<!--- получение сертификата может занимать длительное время.
|
||||
Блокировать на это время приложение или сессию не следует.
|
||||
Вообще не следует ничего блокировать на время сетевого взаимодействия
|
||||
Нижеследующая, на первый взгляд, странная конструкция ровно для этого придумана
|
||||
--->
|
||||
<cfoutput>onRequest:check for cert started #(getTickCount()-request.startTickCount)#</cfoutput>
|
||||
<cfset var idpCertificateExists = false/>
|
||||
<cflock scope="application" type="readonly" timeout=1>
|
||||
<cfset request.APP_NAME=this.Name/>
|
||||
<cfset idpCertificateExists = structKeyExists(application,"idpCertificate")/>
|
||||
</cflock>
|
||||
<cfif NOT idpCertificateExists>
|
||||
Obtain IDP Certificate (onRequest)
|
||||
<cfset var idpCertificate = getIdpCertificate(this.idpCertUrl) />
|
||||
<cflock scope="application" type="exclusive" timeout=1>
|
||||
<cfset application.idpCertificate = idpCertificate/>
|
||||
</cflock>
|
||||
</cfif>
|
||||
<cfoutput>onRequest:check for cert finished #(getTickCount()-request.startTickCount)#</cfoutput>
|
||||
|
||||
|
||||
<cfset this.redirect_uri = "https://#CGI.SERVER_NAME#/#CGI.SCRIPT_NAME#" />
|
||||
|
||||
<cfinclude template="inc/functions.cfm"/>
|
||||
|
||||
<cfcookie name="CFID" value="#session.CFID#"/>
|
||||
<cfcookie name="CFTOKEN" value="#session.CFTOKEN#"/>
|
||||
|
||||
<!--- SSO --->
|
||||
<cflock scope="session" type="exclusive" timeout="3">
|
||||
<!--- --->
|
||||
<cfdump var=#session#/>
|
||||
<cfoutput>#(getTickCount()-request.startTickCount)#</cfoutput>
|
||||
<!---
|
||||
Это первая проба, с сессией
|
||||
Когда протухнет сессия, мы можем пойти к IDP и повторно аутентифицироваться. Поскольку у нас сохраняются куки IDP, его сессия, возможно, будет жива. Если мы обновляли сессию IDP в другом приложении SSO, по всей видимости, она будет продолжаться. Если мы видим, что сессия IDP состарилась и хочет протухнуть, мы можем ее освежить и получить новый access token (который мы пока не используем - мы пользуемся ответом IDP) Наверное, правильно обходиться для этих целей вообще без сессии *** --->
|
||||
<!---
|
||||
сделать логаут
|
||||
сделать отображение ошибки IDP?
|
||||
+сделать получение сертификата
|
||||
сделать рефреш
|
||||
--->
|
||||
<cfif structKeyExists(session, "auth")>
|
||||
<cfset request.auth = structCopy(session.auth)/>
|
||||
<!--- тут нужно сделать проверку и рефреш токена --->
|
||||
сессия есть
|
||||
<cfelse>
|
||||
сессии нет
|
||||
<cfset session.auth_state=createGUID().toString()/>
|
||||
|
||||
<cfscript>
|
||||
jwt = new lib.jwt(this.client_secret);
|
||||
idp = new lib.oauth2(this.client_id, this.client_secret, this.auth_endpoint, this.access_token_endpoint, this.redirect_uri);
|
||||
|
||||
/*
|
||||
часто появляется ошибка: после неудачного запроса к IDP
|
||||
в адресной строке браузера остается все, с чем его редиректил IDP,
|
||||
а повторный запрос с этим контентом уже не работает. Получаем 400 Bad Request -
|
||||
может быть, KeyCloak так защищается от циклических редиректов
|
||||
Не очень понятно, как предотвратить повторный запрос (можно, конечно, использовать сессию, но странно)
|
||||
*/
|
||||
writeOutput(getTickCount()-request.startTickCount);
|
||||
if(structKeyExists(url, "code")) { //обрабатываем редирект от IDP *** наличие поля code в URL введет нас в заблуждение, но эvar = data, label =то только без валидной сессии
|
||||
dump(var = url.code, label = "URL.code");
|
||||
// Request access token from idp with the
|
||||
// authorization code that we got via the URL
|
||||
//aFormFields = [];
|
||||
//data = idp.makeAccessTokenRequest((url.code).content, aFormFields);
|
||||
try {
|
||||
writeOutput("idp.makeAccessTokenRequest");
|
||||
writeOutput(getTickCount()-request.startTickCount);
|
||||
resp = idp.makeAccessTokenRequest(url.code/*, aFormFields*/);
|
||||
writeOutput("idp.makeAccessTokenRequest Done");
|
||||
writeOutput(getTickCount()-request.startTickCount);
|
||||
dump(resp);
|
||||
data = deserializeJson(resp.content);
|
||||
//writedump(data);
|
||||
// Print full response from idp
|
||||
dump(var = data, label = "makeAccessTokenRequest - Response from idp");
|
||||
|
||||
echo('<a href="./index.cfm?refresh=#data.refresh_token#">Refresh token #data.refresh_token#</a>');
|
||||
|
||||
session.auth.expires_in = data.expires_in;
|
||||
session.auth.refresh_expires_in = data.refresh_expires_in;
|
||||
session.auth.access_token = data.access_token;
|
||||
session.auth.refresh_token = data.refresh_token;
|
||||
session.auth.id_token = data.id_token;
|
||||
session.auth.token_type = data.token_type;
|
||||
session.idp_response_content = structCopy(data);
|
||||
|
||||
//flush()
|
||||
lock scope="application" type="readonly" timeout="1" {
|
||||
token_data = (jwt.decode(data.access_token, application.idpCertificate,"RS256"));
|
||||
}
|
||||
writeOutput("jwt.decode Done");
|
||||
writeOutput(getTickCount()-request.startTickCount);
|
||||
writedump(token_data);
|
||||
session.auth.login = token_data.preferred_username;
|
||||
session.auth.wz = token_data.ClientID;
|
||||
session.auth.fullname = token_data.name;
|
||||
session.auth.groups = token_data.groups;
|
||||
session.auth.session_state = token_data.session_state;
|
||||
session.auth.sid = token_data.sid;
|
||||
session.auth.auth_time = token_data.auth_time;
|
||||
session.auth.exp = token_data.exp;
|
||||
session.auth.iat = token_data.iat;
|
||||
//session.sid = token_data.sid;
|
||||
session.token_data = structCopy(token_data);
|
||||
|
||||
location(this.redirect_uri,false);
|
||||
} catch (e) {echo('<br>****************** #e.message# : #e.detail# **********');}
|
||||
|
||||
} else {
|
||||
strURL = idp.buildRedirectToAuthURL({"scope":'openid profile email',"state":session.auth_state,"allow_signup":false});
|
||||
echo('<a href="#strURL#">self-made Auth link (idp) #strURL#</a> <br> <br>');
|
||||
location(strUrl,false);
|
||||
}
|
||||
</cfscript>
|
||||
</cfif>
|
||||
|
||||
</cflock><!--- session exclusive --->
|
||||
|
||||
|
||||
|
||||
|
||||
<cfif structKeyExists(request, "auth")>
|
||||
<cfinclude template="#ARGUMENTS.template#"/>
|
||||
<cfelse>
|
||||
<cfset currentDir = (
|
||||
lCase(
|
||||
replace(
|
||||
getDirectoryFromPath(
|
||||
replaceNoCase(
|
||||
expandPath(
|
||||
ARGUMENTS.template
|
||||
),
|
||||
getDirectoryFromPath(
|
||||
getCurrentTemplatePath()
|
||||
),
|
||||
""
|
||||
)
|
||||
), "\", "/", "ALL"
|
||||
)
|
||||
)
|
||||
)/>
|
||||
<!--- <cfif currentDir EQ "saml/"><!--- note traling slash --->
|
||||
<cfinclude template="#ARGUMENTS.template#"/>
|
||||
<cfelse>
|
||||
<cfinclude template="login.cfm" />
|
||||
</cfif> --->
|
||||
</cfif>
|
||||
|
||||
|
||||
|
||||
<cfreturn />
|
||||
</cffunction>
|
||||
|
||||
|
||||
<cffunction
|
||||
name="OnRequestEnd"
|
||||
access="public"
|
||||
returntype="void"
|
||||
output="true"
|
||||
hint="Fires after the page processing is complete.">
|
||||
<!--- Attention! Before CF9, OnrequestEnd is not executed in case of redirect. That is why we use session.save_login --->
|
||||
|
||||
<cfif structKeyExists(session, "save_login")>
|
||||
<cfif session.save_login EQ "">
|
||||
<!--- unset (expire) cookie --->
|
||||
<cfcookie expires="-1" name="portalUser" value="">
|
||||
<cfelse>
|
||||
<!--- set persistent cookie with no expiration --->
|
||||
<cfcookie expires="NEVER" name="portalUser" value="#encrypt(session.save_login,COOKIEENCKEY)#">
|
||||
</cfif>
|
||||
<cfset structDelete(session, "save_login")>
|
||||
</cfif>
|
||||
|
||||
<cfreturn />
|
||||
</cffunction>
|
||||
|
||||
<cffunction
|
||||
name="getStand"
|
||||
access="private"
|
||||
returntype="string"
|
||||
output="true"><!--- *** duplicated in svc-api --->
|
||||
|
||||
<cftry>
|
||||
<cfquery name=qConfig>
|
||||
select value as stand from config
|
||||
where name='STAND'
|
||||
</cfquery>
|
||||
<cfreturn qConfig.stand/>
|
||||
|
||||
<cfcatch type="ANY">
|
||||
<!--- do nothing, default will be returned --->
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
<cfreturn ""/>
|
||||
</cffunction>
|
||||
|
||||
|
||||
<cffunction
|
||||
name="getDS"
|
||||
access="private"
|
||||
returntype="struct"
|
||||
output="true"
|
||||
hint="Configure data source from environment variables. Convention: data source name is an environment varialble prefix">
|
||||
|
||||
<cfargument name="dsname" type="string" required="true"/>
|
||||
<cfargument name="prefix" type="string" default=#dsname#/>
|
||||
|
||||
<cfset system = createObject("java", "java.lang.System")/>
|
||||
<cfset var ds={}/>
|
||||
|
||||
<cfloop list="class,connectionString,database,driver,dbdriver,host,port,type,url,username,password,bundleName,bundleVersion,connectionLimit,liveTimeout,validate" item="field"><!--- driver vs dbdriver --->
|
||||
<cfset var value=system.getEnv("#arguments.prefix#_#field#")/>
|
||||
<cfif isDefined("value") AND len(value)>
|
||||
<cfset structInsert(ds,field,value)/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
<cfif structIsEmpty(ds)>
|
||||
<cfthrow type="application" message="Datasource not configured" detail="Datasource not defined in the environment. Expected prefix is #arguments.prefix#"/>
|
||||
</cfif>
|
||||
|
||||
<!--- test datasource (just to get exception if invalid) --->
|
||||
<cftry>
|
||||
<cfquery name="qTestDs" datasource=#ds#>
|
||||
select 1;
|
||||
</cfquery>
|
||||
|
||||
<cfcatch type="any">
|
||||
<!--- <cfdump var=#ds#/><cfabort/> --->
|
||||
<cfrethrow/>
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
|
||||
<cfreturn ds/>
|
||||
</cffunction>
|
||||
|
||||
<cfscript>
|
||||
//https://keycloak.nubes.ru/admin
|
||||
//https://keycloak.nubes.ru/realms/SSH_CA/account //smishchuk@mgmt.nubes.ru
|
||||
//https://stackoverflow.com/questions/28658735/what-are-keycloaks-oauth2-openid-connect-endpoints
|
||||
//http://https://keycloak.nubes.ru/realms/SSH_CA/.well-known/openid-configuration
|
||||
|
||||
//https://keycloak.nubes.ru/realms/cloud/.well-known/openid-configuration тут ссылка
|
||||
//https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/certs тут серт
|
||||
//только надо его обрамить -----BEGIN CERTIFICATE-----
|
||||
function getIdpCertificate(certUrl) {
|
||||
|
||||
var httpService = new http();
|
||||
httpService.setMethod( "get" );
|
||||
httpService.setCharset( "utf-8" );
|
||||
httpService.setUrl(arguments.certUrl);
|
||||
|
||||
var result = httpService.send().getPrefix();
|
||||
var status_code = result.ResponseHeader['Status_Code'];
|
||||
|
||||
if ('200' == status_code) {
|
||||
var content = deserializeJson(result.FileContent);
|
||||
//мы подразумеваем структуру конкретно KeyCloak
|
||||
var key = "";
|
||||
for (key in content.keys) {
|
||||
if ("RSA" == key.kty AND "sig" == key.use) {
|
||||
return "-----BEGIN CERTIFICATE-----" & key.x5c[1] & "-----END CERTIFICATE-----";
|
||||
}
|
||||
}
|
||||
throw(message="RSA cetificate not found");
|
||||
} else {
|
||||
throw (message="Cannot obtain IDP certificate, request failed", detail="Status_Code #status_code#");
|
||||
}
|
||||
}
|
||||
|
||||
function auth() {
|
||||
client_id = "payg-report.deck.nubes.ru"
|
||||
client_secret = "********"
|
||||
auth_endpoint = "https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/auth"
|
||||
access_token_endpoint = "https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/token"
|
||||
redirect_uri = "https://localhost/payg-report/"
|
||||
|
||||
jwt = new lib.jwt(client_secret);
|
||||
idp = new lib.oauth2(client_id, client_secret, auth_endpoint, access_token_endpoint, redirect_uri);
|
||||
|
||||
// Get URL that the user will click on and grant our application all necessary permissions
|
||||
strURL = idp.buildRedirectToAuthURL({"scope":'openid profile email',"state":createGUID().toString(),"allow_signup":true});
|
||||
echo('<a href="#strURL#">self-made Auth link (idp) #strURL#</a> <br> <br>');
|
||||
|
||||
//redreshURL = github.refreshAccessTokenRequest();
|
||||
|
||||
if(structKeyExists(url, "code")) {
|
||||
writedump(url.code);
|
||||
// Request access token from idp with the authorization code that we got via the URL
|
||||
data = deserializeJson(idp.makeAccessTokenRequest(url.code/*, aFormFields*/).content);
|
||||
// Print full response from idp
|
||||
dump(var = data, label = "makeAccessTokenRequest - Response from idp");
|
||||
|
||||
try {
|
||||
//parsed=getParamsFromUrlString(data);
|
||||
writedump(data);
|
||||
echo('<a href="./index.cfm?refresh=#data.refresh_token#">Refresh token #data.refresh_token#</a>');
|
||||
//https://keycloak.nubes.ru/realms/cloud/.well-known/openid-configuration тут ссылка
|
||||
//https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/certs тут серт
|
||||
//только надо его обрамить -----BEGIN CERTIFICATE-----
|
||||
|
||||
writedump(jwt.decode(data.access_token,"-----BEGIN CERTIFICATE-----
|
||||
MIICmTCCAYECBgGG7361eDANBgkqhkiG9w0BAQsFADAQMQ4wDAYDVQQDDAVjbG91ZDAeFw0yMzAzMTcxMjEzMjRaFw0zMzAzMTcxMjE1MDRaMBAxDjAMBgNVBAMMBWNsb3VkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn2segSPrciUFaD7Fa+brR9JdZknQr0F8zCzYQdTPsZJMtYnVPuE7MdZlbtGQ9n/HjcUst8FINjMONhzzbwVQSRZHH57pbAEm4r7fM3QDEAKXGERtDXhVLJGQSkg17X9zSWZs4RwkbxNsG6r+3/GT+U75lTG+/LKKzdG5OHK7Wwnrsiqy7sg3wAPFtlSwbebMdXJ70FosEI1SVhPRDn+LuVH3WINvijQU1GV2srWPwZl16fdXDele6NkvnC032l00pTbkVbgBLgySR0sPsI1s5AuMTT//nA0Xm5Ss40SwLJX2BYWyEALvEYdVt9wUZU2QXcZLLgmsCcFye4HjXa2CAwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBlvkOLPRG6+tB30ZElwKSh/xrptnxgTf93RnS4IUDZebSolR5V/77PFAuqw4DTIlBNtJ6i1ffmyvtZIAMlm3sMZK0GuQ+SFq72DHxYzSmZ61cSS5YFKKyHcX3JIFMXYLmrw11GXt69V3xB8/Y0+BnBBpDD7ZKDdXdQa+9IWsERdTAIFk7ucwiG3BuTOJbzU1d+m8hNIVL4+dYR1TAnA9QPaJaQj0kUD0DYgXcIrrTFIQF0IPeB9I+eOyJ0FxJkukffX7QLVGFrc3+dVRHSSWmMpXi0B/VXT5DlsFDstEldH+/r3XnXAY6qadciyksSBRSXR4Rm9ZEq/xk+VmcxomWc
|
||||
-----END CERTIFICATE-----","RS256"));
|
||||
} catch (e) {echo('<br>****************** #e.message# : #e.detail# **********');}
|
||||
|
||||
}
|
||||
|
||||
if(structKeyExists(url, "refresh")) {
|
||||
|
||||
// With the refresh_token we can easly request a new access token
|
||||
refreshedToken = deserializeJson(idp.refreshAccessTokenRequest(url.refresh).content);
|
||||
dump(var = refreshedToken, label = "refreshAccessTokenRequest - Response from IDP");
|
||||
|
||||
echo('<br> <a href="./index.cfm?refresh=#refreshedToken.refresh_token#">Refresh token #refreshedToken.refresh_token#</a>')
|
||||
writedump(jwt.decode(refreshedToken.access_token));
|
||||
}
|
||||
}
|
||||
</cfscript>
|
||||
</cfcomponent>
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"ds_dwh_class": "org.postgresql.Driver",
|
||||
"ds_dwh_connectionString": "jdbc:postgresql://db-services.adl.nubes.ru:5432/dwh",
|
||||
"ds_dwh_username": "smishchuk",
|
||||
"ds_dwh_password": "encrypted:********",
|
||||
"ds_dwh_connectionLimit": "5",
|
||||
"IDP_CLIENT_SECRET": "********",
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
REM set Windows env
|
||||
setx ds_dwh_class org.postgresql.Driver /M
|
||||
setx ds_dwh_connectionString jdbc:postgresql://db-services.adl.nubes.ru:5432/dwh /M
|
||||
setx ds_dwh_username smishchuk /M
|
||||
setx ds_dwh_password encrypted:******** /M
|
||||
setx ds_dwh_connectionLimit 5 /M
|
||||
|
||||
setx IDP_CLIENT_SECRET ******** /M
|
||||
|
||||
pause
|
||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW X8 -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="78.6273mm" height="70.4009mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
|
||||
viewBox="0 0 37746 33797"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
.fil3 {fill:none}
|
||||
.fil2 {fill:#D7F372}
|
||||
.fil4 {fill:#FEFEFE;fill-rule:nonzero}
|
||||
.fil5 {fill:#638328;fill-rule:nonzero}
|
||||
.fil1 {fill:url(#id1)}
|
||||
.fil0 {fill:url(#id2)}
|
||||
]]>
|
||||
</style>
|
||||
<clipPath id="id0">
|
||||
<path d="M20432 0c8718,-38 15581,2266 15458,9209 -25,787 -197,745 -1206,434 -5376,-1662 -8578,-3016 -12410,-6248 -1067,-900 -1945,-1797 -2743,-2837 -478,-648 -8,-545 901,-558zm-18416 19428c1785,-4186 2803,-6725 6956,-9214 1814,-1088 3728,-1795 5744,-2401 5011,-1469 9917,-953 14495,540 1697,562 2833,1208 4123,2158 602,450 989,178 1872,-71 402,-113 1572,-529 1912,-305 933,615 -675,1120 -1291,1389 -1798,785 -1256,251 -1265,1780 -43,7030 -7302,11174 -13250,12374 -3409,688 -7029,1146 -9343,1499 -5916,900 -5060,-1185 -9071,-2819 -937,-381 -2531,-341 -2879,-1361 -223,-655 1540,-2751 1997,-3569z"/>
|
||||
</clipPath>
|
||||
<linearGradient id="id1" gradientUnits="userSpaceOnUse" x1="-740.954" y1="15224.8" x2="37478.6" y2="11458.4">
|
||||
<stop offset="0" style="stop-opacity:1; stop-color:#C6C517"/>
|
||||
<stop offset="1" style="stop-opacity:1; stop-color:#E7D900"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="id2" gradientUnits="userSpaceOnUse" x1="-442.19" y1="20004.6" x2="37830.6" y2="16055.8">
|
||||
<stop offset="0" style="stop-opacity:1; stop-color:#89A423"/>
|
||||
<stop offset="1" style="stop-opacity:1; stop-color:#638429"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="Layer_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<path class="fil0" d="M22767 31689l-14060 2085c-2226,330 -4572,-2956 -6349,-3695 -1559,-649 -1653,-822 -1915,-2004 -266,-1196 -259,-3137 -401,-4460 -150,-1391 203,-1130 973,-2123 591,-795 964,-1292 1359,-2228 1413,-3396 2313,-5352 5285,-7695 3781,-2753 8236,-4067 12877,-4299 774,-89 484,-275 112,-747 -812,-1079 -1165,-2747 -1381,-4068 -68,-416 -308,-2197 198,-2372 228,-79 1093,72 1388,100 101,9 200,16 301,22 1094,51 2280,-41 2615,-17 4852,417 10503,1550 11899,7016 226,935 209,1325 200,2255 -2,142 -8,1026 126,1086 215,97 947,-1057 1467,133 110,344 145,764 169,1126 8,120 17,237 29,356 91,880 115,1755 53,2638 -23,319 -23,817 -223,1077 -611,795 -1576,1292 -2268,2065 -435,506 -635,1974 -834,2703 -720,2633 -1869,4361 -3594,4590l-7936 1054 -90 5402z"/>
|
||||
<path class="fil1" d="M20432 0c8718,-38 15581,2266 15458,9209 -25,787 -197,745 -1206,434 -5376,-1662 -8578,-3016 -12410,-6248 -1067,-900 -1945,-1797 -2743,-2837 -478,-648 -8,-545 901,-558zm-18416 19428c1785,-4186 2803,-6725 6956,-9214 1814,-1088 3728,-1795 5744,-2401 5011,-1469 9917,-953 14495,540 1697,562 2833,1208 4123,2158 602,450 989,178 1872,-71 402,-113 1572,-529 1912,-305 933,615 -675,1120 -1291,1389 -1798,785 -1256,251 -1265,1780 -43,7030 -7302,11174 -13250,12374 -3409,688 -7029,1146 -9343,1499 -5916,900 -5060,-1185 -9071,-2819 -937,-381 -2531,-341 -2879,-1361 -223,-655 1540,-2751 1997,-3569z"/>
|
||||
<g style="clip-path:url(#id0)">
|
||||
<g id="_3107826610240">
|
||||
<path id="1" class="fil2" d="M32620 15645c91,-46 98,-37 3,-91 -66,80 -20,59 -3,91zm-9180 173l399 13 94 3 24 -102c121,-34 39,27 76,-81l-104 -24c-76,-2 -129,-55 -130,-59 -3,-10 -11,-11 -18,-15l-68 -4c-94,14 -151,38 -213,69l-167 12 -8 120 12 65 103 3zm3362 -16369c31,57 -35,35 43,50 123,23 4,11 64,-18 -27,-64 39,-43 -41,-56 -131,-22 -7,-12 -66,24zm10290 3584c-14,-80 10,-36 -56,-77 -2,4 -94,5 -19,84 51,53 74,-7 75,-7zm2277 11808c100,-46 108,-71 4,-122 -65,81 -40,56 -4,122zm-598 -13384c72,-96 70,-72 -25,-113 -75,90 -74,70 25,113zm-486 7658c-47,-62 -81,7 -83,7 65,99 -66,22 64,80 3,-6 100,22 19,-87zm-14361 -9918c35,-131 44,-89 -39,-138 -4,7 -53,-26 -31,67 27,121 -23,26 70,71zm13953 15010c7,-87 -6,-35 -58,-63 -74,84 -46,57 -4,129 45,-22 53,54 62,-66zm1320 -15163c106,-113 26,-91 4,-126 -51,29 -67,-45 -62,71 4,73 20,40 58,55zm2646 15025c-2,-2 9,-68 -88,-57 -109,12 -37,7 -73,64 105,50 64,60 161,-7zm-292 -3726c48,-52 47,-33 49,-171 -84,-2 -93,-38 -195,78 -83,11 -33,-18 -92,47l115 91c47,-29 48,-35 123,-45zm-2986 3302c-113,22 -40,12 -65,57 182,135 184,-23 184,-24 -10,-6 19,-60 -119,-33zm-1300 1033c-76,-44 -26,-43 -193,-4 18,157 33,163 111,169 166,12 14,18 79,-36l3 -129zm-28 818c-15,-28 43,-120 -226,-46 35,72 -28,65 93,92 164,37 124,-39 133,-46zm-7887 -16516l182 4c21,-158 -15,-177 -161,-176l-21 172zm1556 1675l148 114c99,86 124,57 174,-16 -50,-145 -12,-36 -146,-105 -44,-243 65,-253 -76,-325 -82,93 -25,15 -43,187 -15,145 -10,6 -57,145zm-16717 6826c58,-32 47,42 53,-46 7,-83 4,-30 -50,-59l-24 38c3,61 -11,24 21,67zm-1336 -2651c25,-6 44,9 63,-22 77,-123 10,-42 -8,-80 -80,40 -47,5 -55,102zm-4579 -6954l-112 -3 26 95c101,-38 42,50 86,-92zm7494 3833c33,-24 94,21 33,-122 -79,33 -49,-52 -62,48 -20,150 -16,19 29,74zm14390 12465c-110,-30 -18,-3 -62,20 24,35 -18,154 116,33 -22,-35 -5,-40 -54,-53zm-16336 1107c44,-72 -19,-62 -22,-69 -108,42 -55,-27 -72,102 120,-4 51,36 94,-33zm-15555 -8727c0,-1 54,27 19,-104 -41,1 -53,-32 -83,34 -36,76 49,66 64,70zm29578 -7130c115,91 90,22 123,-26 -55,-41 62,-61 -72,-36 -85,16 -30,37 -51,62zm-15613 10133c8,-12 163,46 3,-107 -158,125 -4,106 -3,107zm19829 6238c-113,-3 -59,-5 -148,25 75,104 35,82 146,96l2 -121zm-1810 -750c-9,127 22,73 56,93 13,-18 98,-37 6,-177 -40,23 -55,-4 -62,84zm-22909 -1701c110,-49 103,-21 88,-170l-170 17 -8 103 29 61 61 -11zm17260 -7459c57,-32 46,52 67,-70 25,-145 -10,-61 -33,-93 -62,23 -49,-63 -69,61 -24,151 20,79 35,102zm6292 8218c-86,10 -54,14 -87,55 20,17 25,52 112,48 130,-7 69,-26 89,-71 -34,-23 -5,-44 -114,-32zm-18726 -12582l138 126c48,-78 33,-47 37,-156 -115,-27 -88,-44 -175,30zm5425 2089c112,8 43,39 121,-26l69 -111c-57,-38 50,-12 -63,-36 -108,-23 -8,-17 -111,3l-16 170zm199 -5155c68,-15 102,32 91,-91 -10,-106 -55,-86 -91,-103 -91,200 -13,173 0,194zm-4498 9344c44,-116 -2,-63 -8,-78 -188,-98 -154,47 -70,159 12,-9 44,9 78,-81zm-14595 -8298l-37 -85 -225 -25c13,84 -5,39 37,90 11,13 11,8 29,27 101,111 -29,62 100,79 134,17 77,-16 96,-28l0 -58zm16516 14224c-51,-40 -1,-28 -113,-50 -41,-8 -243,-20 -290,67 61,129 108,18 237,86 55,29 -10,50 104,69 198,32 132,-42 146,-52 -49,-181 23,-57 -89,-111l5 -9zm-15097 58c48,-69 44,-72 16,-145 -273,51 -22,42 -250,167 31,-165 -35,-99 -48,-114l-10 228 209 8 83 -144zm10508 -4775c26,-191 49,60 -34,-54 -80,69 -76,58 -4,123 52,-55 25,22 38,-69zm2333 -7579c33,-5 125,10 56,-109 -99,52 -45,-60 -56,109zm-3430 -2611c31,53 -29,36 45,50 112,21 9,9 62,-17 -23,-52 62,-39 -40,-56 -76,-13 -10,-11 -67,23zm-5194 1548c20,-171 28,-57 -48,-102 -23,40 -71,-39 -25,67 24,53 -2,25 73,35zm2622 14176c16,-129 5,-16 -32,-67 -96,48 -105,68 -4,128 34,-41 21,52 36,-61zm20631 -662c17,-119 -2,-25 -34,-66 -97,47 -110,67 -4,121 35,-34 24,49 38,-55zm-26456 -15122c101,69 78,57 133,-25 -30,-22 47,-55 -72,-37 -124,19 -29,27 -61,62zm-3047 11843c12,19 -43,82 103,51 57,-13 47,-31 63,-80 -75,-40 -83,-41 -168,-21l2 50zm590 1476c-68,85 -67,86 -5,161 100,-47 96,-110 5,-161zm9676 2249c132,-45 120,-6 96,-144 -185,-46 -50,-16 -91,31 11,22 4,32 23,36 49,12 16,9 52,-9 -39,-41 -1,-18 -75,-27 -8,6 -42,26 -44,28 -15,11 -32,39 -36,33 -3,-7 -12,13 -19,19l7 24c-83,-5 -17,-34 -119,21l-151 150c-7,14 -26,96 -30,118 184,-1 47,-2 195,-98 58,-38 107,-51 184,-77l17 -88 -9 -17zm-10949 -16354c55,-82 68,-123 -24,-178 -4,5 -49,-31 -45,89 4,131 35,74 69,89zm5381 2060c95,56 114,57 192,-23 -73,-75 -188,-91 -192,23zm4150 14183c1,-1 64,-22 50,-106 -19,-117 0,-36 -73,-72 -30,39 -121,103 23,178zm17483 -2004c-59,-80 -103,-72 -188,-35 18,24 -70,68 84,81 141,12 94,-39 104,-46zm-13680 -1675c141,42 169,46 247,-29 -37,-39 -45,-69 -145,-59 -99,10 -73,22 -102,88zm-8064 1221l-36 23c-90,81 -54,49 -56,120 261,25 188,-170 188,-171 -115,-7 34,-13 -60,2l-36 26c7,17 -3,42 39,48 3,1 16,-4 19,-4 5,0 15,-7 23,-10 -39,-35 6,-19 -81,-34zm8633 -1952c-7,-10 54,-79 -137,-26 9,87 13,131 90,196 33,-28 19,-1 55,-52 24,-33 -22,88 23,-39 49,-141 4,-71 -31,-79l-78 -1 25 81 53 -80zm-7088 2769c-11,-74 -88,-139 -148,-163l-43 119 162 129c15,-21 48,44 29,-85zm-7692 303l-2 61 261 28c11,-216 -161,-128 -259,-89zm39584 -10253c14,28 -26,64 65,64 135,1 27,20 78,-60 -44,-33 11,-44 -75,-39 -129,8 -18,-2 -68,35zm419 750c28,-36 34,52 41,-69 10,-164 -9,-60 -36,-101 -30,17 -56,-27 -71,73 -20,138 30,78 66,97zm3066 2473c55,-72 68,-95 66,-198 -92,-19 -136,-38 -155,50 -18,87 89,148 89,148zm2396 -3620c57,42 -52,30 106,49 159,20 20,7 113,-14 -22,-95 28,-126 -112,-132 -102,-5 -86,13 -107,97zm-718 4372l-51 -56c213,-116 92,-238 -70,-239 -152,-1 -176,38 -165,195l14 39c15,128 95,141 227,140l45 -79zm-11882 -7680c96,59 33,27 76,3l-58 -18c-3,-8 -12,11 -18,15zm-21198 15445c35,43 20,47 60,29 5,-2 14,-15 22,-22l-82 -7zm5007 1132l97 3 -6 -58c-40,-60 5,-36 -76,-65 -35,-12 -55,0 -88,1l5 117 68 2zm19326 -14421l-61 0c-35,54 -28,-70 -32,67 -4,136 11,60 30,93 73,-19 31,14 65,-50 146,-35 47,16 96,-68 -57,-55 15,-32 -98,-42zm-8429 13335c39,-6 206,-169 -164,-173 -70,95 -80,76 -102,170l266 3zm14571 -9261c47,74 57,123 127,4 -116,-124 -105,-20 -127,-4zm909 -1194c55,84 170,131 199,-23 -26,-14 -10,-39 -115,-26 -57,8 -60,10 -84,49zm271 2163c-1,-1 34,-56 -85,-37 -107,17 -28,-8 -84,61 38,68 -52,70 107,81 68,5 70,-17 106,-46 -12,-97 2,-33 -44,-59l-117 15 83 62c43,-50 20,-9 34,-77zm2227 -30c105,19 81,28 165,-11 -16,-86 -60,-131 -144,-155 -48,81 -43,60 -21,166zm-680 -1938c36,-37 13,13 35,-54 59,-184 69,-195 19,-219 -7,-2 -19,-13 -22,-4 -3,7 -75,-30 -95,109 -15,102 -6,135 63,168zm-7887 -1031c174,9 174,-15 198,-181l-195 0 -3 181zm-434 -3677c0,-132 -97,-207 -219,-204 -14,163 61,224 219,204zm9067 10670l-228 -20c15,143 32,200 191,182 20,-35 15,-15 29,-68 0,-1 7,-80 8,-94zm-11458 -8654l180 15c41,-77 53,-78 67,-187l-240 -2 -7 174zm-13484 -1787c67,65 -100,40 38,31 70,-5 24,3 66,-28 -77,-64 98,-40 -43,-30 -87,6 4,-25 -61,27zm15318 6420c8,8 -37,96 94,3 -76,-59 111,-37 -40,-27 -71,5 -10,-11 -54,24zm-4361 -5494c0,-176 44,-57 -80,-98 19,109 -24,65 80,98zm5777 11913c-52,-67 -18,-71 -104,-32 75,108 -101,-50 19,46 3,3 11,10 15,12 122,59 35,-5 70,-26zm452 -9192c-16,-105 17,-46 -64,-89 -51,58 -31,28 -37,112l0 24c139,141 57,117 171,135l19 -142 -89 -40zm1300 -184c26,36 -55,67 176,58 3,-16 70,-189 -107,-115 -68,28 -31,-2 -69,57zm-6645 5321c35,-145 -23,-89 -32,-106 -123,17 -84,-60 -108,72 -22,127 47,87 73,100 61,-30 38,56 67,-66zm12539 -5533c161,1 121,36 140,-122 -54,-35 -31,-46 -160,-30 -8,73 -19,77 20,152zm-7898 4642l158 -3 13 -151 -160 -4 -11 158zm-17042 -7038c56,111 45,115 104,4 -52,-38 -53,-32 -104,-4zm9439 14921c154,-74 34,-104 32,-108 -148,63 -33,108 -32,108zm-15492 -14617c77,-131 38,-84 -75,-106 31,146 -22,74 75,106zm2595 5412c115,-55 112,-64 4,-122 -16,20 -39,-42 -33,60 3,61 1,30 29,62zm3716 -5475c14,118 -32,80 92,86 38,-95 6,-127 -92,-86zm-11754 7101c6,-101 5,-86 -98,-105 -13,127 -2,118 98,105zm5801 -8233c54,-27 68,45 62,-68 -3,-75 -27,-45 -58,-61 -2,3 -85,14 -4,129zm-10835 7881c-39,-69 -44,-121 -135,-4 60,52 -67,23 67,40 113,15 27,-3 68,-36zm25397 -740c-39,10 -173,13 -98,95 96,105 86,-47 98,-95zm-2065 8351c-44,-72 23,-10 -75,-89 -65,-51 0,-9 -75,-42l-42 107 31 161c92,9 87,6 142,-32l19 -105zm-14954 -14214c87,52 55,48 150,6 -45,-139 -121,-139 -150,-6zm2674 8592c-160,2 -83,47 -93,81l164 16c3,-66 28,-97 -71,-97zm-12857 -11651c60,116 145,73 198,6 -88,-66 -119,-55 -198,-6zm14730 9603c8,31 -35,70 85,81 110,11 71,-14 85,-76 -83,-43 -68,-37 -170,-5zm-1945 -4959c-114,-51 -60,-57 -140,3l-4 58c93,64 166,73 228,-21 -41,-48 23,-26 -84,-40l-116 0c37,83 -28,35 83,68 54,-39 15,12 33,-68zm1791 10456c-76,-57 -141,-72 -205,22 16,13 16,57 118,48 109,-8 68,-30 87,-70zm6791 -1117c36,-46 36,70 46,-94 8,-128 -24,-68 -40,-87 -41,17 -64,-27 -71,84 -7,141 28,77 65,97zm-19845 -1831c156,4 126,-56 115,-191 -148,46 -119,6 -115,191zm28588 2560c110,14 138,-57 145,-166l-129 10c-85,158 -16,155 -16,156zm-24535 1960c-95,25 -67,45 -80,133 123,4 100,21 190,-35 -15,-82 23,-133 -110,-98zm-1340 -12555c34,-29 35,29 35,-82 -176,-85 -220,125 -198,245 233,90 139,21 170,-18l-9 -56 2 -89zm-138 10191c7,-3 15,-9 19,-11 187,-98 143,-30 160,-133 -81,-49 -97,-61 -235,49 -9,7 -14,11 -18,14l-10 -4 3 8c-6,4 -7,6 -36,40 48,43 -12,16 62,44 104,41 37,-1 55,-7zm8367 -12746l142 -3 17 -140c-107,-42 -56,-44 -174,-39 -39,107 -19,70 15,182zm13541 9864c19,-155 31,-118 -58,-202l-114 -68 -18 135c5,4 38,33 47,42 111,117 -30,57 143,93zm988 4753c45,-102 30,10 23,-135l-34 -127c-82,44 -10,4 -55,41l-47 40c-59,65 -45,-8 -44,128 63,55 64,54 157,53zm12225 -12623c69,-36 48,37 60,-51 11,-77 1,-29 -27,-74 -74,34 -47,-58 -61,47 -12,85 -16,23 28,78zm-541 532c79,-38 56,43 72,-73 18,-134 -33,-95 -37,-102 -62,28 -51,-64 -71,68 -26,164 18,78 36,107zm3249 -2408c42,-47 40,67 48,-70 9,-158 -18,-67 -43,-99 -62,25 -63,-61 -81,69 -20,138 47,86 76,100zm1303 9111c11,10 -39,54 99,53 166,-1 78,-27 103,-76 -9,-7 35,-50 -103,-50 -165,1 -70,41 -99,73zm-491 -3647c91,-9 105,-16 198,-88 -55,-161 -128,-160 -199,-171 8,167 44,104 1,259zm-24692 -3316c89,44 53,43 105,-26 -38,-27 54,-78 -66,-29 -4,1 -13,8 -16,10l-23 45zm13671 13200c-34,-129 31,-90 -104,-104 13,123 -20,66 104,104zm-2531 -392c-27,-46 15,-108 -118,-32 19,31 -50,43 47,68 133,33 20,3 71,-36zm7334 520c-76,-6 -56,36 -71,58 59,45 -67,20 67,36 129,15 17,4 69,-31 -26,-54 52,-54 -65,-63zm-2346 -1174c-22,-102 14,-11 -61,-51 -44,43 -78,-66 -39,94 19,78 18,22 64,42 41,-48 53,-4 36,-85zm-2672 1531c-126,3 -69,18 -100,66 34,27 41,99 222,7 -23,-40 -10,-76 -122,-73zm2389 -1391c-144,-10 -215,11 -139,175l166 10 -27 -185zm-13510 -6878c31,-55 21,-40 3,-86 -56,59 -65,-88 -32,42 34,130 -97,-14 29,44zm11036 7899c51,38 -7,20 62,28 135,17 -25,23 42,-24 -37,-35 4,-24 -62,-33 -161,-23 46,-43 -42,29zm-26597 -10879c62,73 10,58 96,32 -17,-44 72,-25 -23,-45 -72,-14 -23,-8 -73,13zm24877 10019c-13,-82 1,-14 -47,-36 -75,86 -26,63 26,92 24,-39 30,7 21,-56zm-13301 -13607c15,-24 58,33 23,-60 -25,-65 14,-8 -49,-43 -39,74 -63,63 26,103zm-1474 10770c72,-89 63,-70 -26,-109 -101,108 -21,86 26,109zm2490 -9768c5,-7 104,11 5,-148 -44,51 -53,-76 -44,73 6,81 4,33 39,75zm-455 582l45 -26c-21,-110 32,-69 -101,-93 -6,111 -40,72 56,119zm-2645 4875c5,-126 -3,-96 -98,-104 -11,117 -39,123 98,104zm-15387 -7335c18,35 -39,43 62,61 137,25 73,-13 98,-27 -5,-10 32,-155 -160,-34zm3775 14905c-5,113 34,83 37,87 96,-48 93,-123 5,-181 -22,29 -35,-53 -42,94zm16124 -7293c1,0 19,130 175,5 -14,-31 12,-58 -77,-63 -125,-7 -71,37 -98,58zm4169 4706c36,-17 59,39 73,-89 14,-124 -31,-78 -39,-88 -47,21 -58,-27 -69,83 -13,129 26,80 35,94zm-14149 1449c-78,-12 -84,28 -88,128l195 -3c-12,-79 -17,-110 -107,-125zm-10285 -377c144,13 156,25 270,-28 -59,-65 -141,-121 -249,-121l-21 149zm30877 -12750c85,40 49,47 105,-26 -20,-16 24,-117 -105,26zm-4545 -547c57,-82 74,-71 -25,-119 -65,93 -66,76 25,119zm6390 36c29,-122 42,-90 -84,-116 14,175 -38,71 84,116zm5154 2987c-1,45 -19,42 30,111 107,-34 39,71 81,-92 -1,-4 -13,-87 -13,-87 -16,-49 -13,-36 -31,-65 -83,37 -49,-29 -67,133zm-7078 -529c164,-26 122,59 107,-100 -108,-4 -71,-31 -107,100zm1289 -911c4,-125 47,-86 -67,-119 -93,100 -38,96 67,119zm2389 12606c-126,16 -58,-23 -117,61 78,102 120,95 117,-61zm-6679 -14484c93,-49 101,-26 33,-126 -50,15 -41,-45 -66,34 -45,140 4,62 33,92zm-6632 -463c15,26 -10,57 69,74 138,32 72,-15 95,-30 -35,-82 47,-48 -65,-68 -29,-6 -93,19 -99,24zm9162 3323c39,-11 64,56 82,-82 14,-103 -25,-89 -47,-113 -98,45 -81,123 -35,195zm11121 7323c77,-41 52,57 68,-98 6,-49 -11,-65 -20,-97 -60,22 -76,-44 -92,91 -17,134 36,91 44,104zm-6944 6433l64 2c35,-109 52,-107 -11,-201 -29,8 -65,-56 -82,91 -8,64 4,48 29,108zm-9851 -12707c33,-80 14,-192 -50,-252 -80,-76 -14,-26 -117,-47 51,222 26,39 90,163 44,86 -28,59 77,136zm17007 11129c-5,-4 -12,-10 -18,-14l-82 -58c-96,106 -9,225 150,201 10,-144 19,-76 -50,-129zm-14523 -7357l6 118 177 17 4 -157c-119,-17 -93,-25 -187,22zm1634 621c122,-10 52,43 137,-39 82,-80 30,-20 53,-141l-179 10 -11 170zm4069 -5651l169 46c4,-99 16,-85 -35,-146 -85,-102 -17,-50 -154,-73l20 173zm10176 12053c-10,-85 13,-6 -49,-52 -38,41 -37,-9 -30,69 9,97 -12,14 55,43 37,-56 37,58 24,-60zm-8682 -13172c37,61 -40,39 51,54 69,12 24,3 66,-21 -13,-32 49,-134 -117,-33zm2107 1274c32,-19 113,33 33,-122 -78,35 -50,-47 -63,48 -17,129 -11,23 30,74zm-2180 -3663l-108 -3c2,174 -2,49 42,106 98,-52 42,59 66,-103zm10237 6623c21,-30 58,43 35,-71 -21,-101 17,-22 -68,-66 -52,93 -66,71 33,137zm-4681 8279c36,-113 -28,-91 -30,-94 -79,34 -36,-30 -61,65 -8,29 10,72 15,95 50,-25 47,25 76,-66zm1712 -10475c91,-11 72,27 106,-40 54,-109 -37,-81 -62,-94l-37 44c-16,57 -18,8 -7,90zm-2158 653c14,19 -16,66 79,65 118,-2 32,5 75,-60 -18,-16 33,-129 -154,-5zm-9161 -4516c140,63 104,33 149,-46 -10,-8 40,-74 -77,-47 -186,44 -11,10 -72,93zm14791 10390c-148,-15 -74,13 -105,64 54,49 -82,47 102,53 102,4 98,-46 99,-47 -19,-29 7,-60 -96,-70zm-7396 -6688c36,71 -84,46 67,61 7,-6 18,-26 21,-20l74 -89c49,-90 34,-58 -1,-120 -66,20 -27,3 -73,42 -4,4 -10,10 -14,14 -4,4 -10,10 -14,14 -5,5 -12,11 -16,16l-35 33 -9 49zm3325 -2979c18,41 -50,73 94,76 129,2 71,-21 95,-70 -6,-6 38,-52 -90,-53 -164,-1 -55,12 -99,47zm-4326 1161l115 0c21,-126 29,-84 -30,-190 -116,49 -118,87 -85,190zm5264 1728c3,-4 48,17 51,-93 3,-169 -3,-47 -45,-100 -39,16 -76,-51 -89,107 -7,77 16,64 83,86zm3737 8908c127,-174 17,-185 6,-201 -65,17 -98,-21 -96,100 3,114 51,86 90,101zm-578 -7651c-69,-84 28,-32 -83,-63 -47,-14 -89,-4 -137,1 12,162 117,193 220,62zm-10792 -2729c100,-7 112,56 202,-184l-175 3 -27 181zm11216 4612c69,-72 57,-54 46,-178l-200 -7c-4,7 -10,9 -11,18l-76 95c135,22 67,-7 160,87l81 -15zm-25274 1701c77,60 7,56 87,3 -48,-47 101,-40 -34,-29 -73,6 -3,-17 -53,26zm-2320 -4177c8,14 14,124 93,3 -55,-40 95,-28 -36,-22 -55,3 -22,-1 -57,19zm3531 6166c27,41 -51,47 54,45 61,-2 16,-6 40,-42 -34,-25 -1,-17 -55,-23 -3,0 -17,14 -19,7 -3,-7 -13,9 -20,13zm9742 -9188c141,-30 64,23 96,-75 -192,-10 -27,10 -96,75zm-816 7909c14,-101 12,5 -30,-35 -126,99 -4,94 -3,96 46,-55 21,17 33,-61zm4718 4713c-57,112 -6,23 20,71 19,-13 146,-53 23,-91 -70,-21 -30,-5 -43,20zm-8122 -431c-16,-86 16,-10 -58,-43 -83,124 13,93 34,107 35,-58 47,63 24,-64zm17489 -3007c175,99 121,19 148,5 -163,-141 -131,-17 -148,-5zm-22342 4930c132,-4 153,38 191,-77l-183 -33c-126,37 -56,-3 -107,63 48,51 -83,44 99,47zm12980 -12068c-5,14 -15,15 -16,31 -2,16 -12,19 -13,27 -6,30 -6,60 -4,92l176 14 5 -153 -148 -11zm3361 -432c36,-54 25,-37 3,-87 -60,72 -60,-95 -28,43 33,144 -77,-37 25,44zm-4106 70c11,-16 62,31 29,-65 -27,-79 22,-7 -54,-51 -28,44 -74,-63 -27,70 23,65 -11,17 52,46zm4107 -1014c84,-42 48,57 62,-54 19,-151 13,-10 -29,-78 -90,38 -52,-66 -66,48 -12,105 -22,20 33,84zm5309 -1291c25,-37 79,60 36,-83 -31,-104 27,-9 -60,-59 -32,47 -83,-71 -36,83 27,91 -22,17 60,59zm1248 6583c63,-42 37,35 61,-54 36,-132 -10,-66 -27,-91 -56,21 -39,-53 -66,42 -50,177 2,67 32,103zm-3412 -2551c58,-28 78,64 72,-75 -4,-112 -22,-47 -68,-70 0,1 -117,-7 -4,145zm-290 -1225c21,58 -53,43 42,70 192,56 47,8 103,-36 -35,-66 28,-44 -52,-65 -126,-33 -82,23 -93,31zm-5356 -3095l-18 46c15,128 58,97 106,82 112,-34 73,-59 86,-77 -19,-13 -52,-43 -84,-53l-90 2zm8115 7257c60,-74 70,111 51,-115 -8,-93 -53,-79 -74,-92 -6,7 -48,-10 -51,93 -7,206 -25,60 74,114zm-358 -3417c71,-45 53,62 74,-83 25,-183 -18,-80 -39,-116 -80,37 -60,-87 -83,79 -26,191 22,83 48,120zm-17157 14c84,70 -122,41 42,30 72,-5 22,6 65,-27 -62,-52 99,-38 -41,-29 -76,5 -12,-10 -66,26zm5328 -1528c64,-38 48,39 53,-51 7,-103 14,-24 -49,-60 -33,49 -32,66 -4,111zm-27615 8986c78,-37 55,63 54,-88 -92,2 -45,-22 -73,27 -47,84 8,41 19,61zm32764 3684c-10,-69 1,-14 -45,-37 -107,108 -16,75 26,101 17,-36 27,-9 19,-64zm-6438 -13319c1,0 47,9 52,-34 12,-113 25,-18 -49,-67 -15,24 -88,9 -3,101zm-2549 -1315c-17,8 -170,44 -28,87 58,17 34,0 42,-20 45,-117 9,-15 -14,-67zm4500 3122c50,-16 41,47 55,-34 13,-73 3,-24 -22,-71 -54,37 -107,11 -33,105zm100 11390c59,41 -62,18 67,32 141,16 7,10 72,-28 -141,-125 -131,-11 -139,-4zm5906 333c26,-38 129,23 33,-116 -108,38 -98,26 -33,116zm-36586 -127c129,-18 2,10 67,-35 -65,-124 -157,-104 -185,26 57,9 59,18 118,9zm29127 1316c73,-30 40,-35 106,4 -33,22 14,19 -51,22 -116,5 -14,2 -55,-26zm-38 58l179 5 2 -117 -181 -1 0 113zm-23361 -15949c1,-1 61,10 45,-97 -16,-103 8,-32 -68,-78 -13,20 -65,-31 -41,104 21,124 2,35 64,71zm7079 11660c-101,8 -43,-8 -107,52 -56,54 -46,20 -62,107l176 18 -7 -177zm27110 -785c-83,-43 -52,-52 -103,26 49,34 -62,39 59,24 76,-9 15,3 44,-50zm-1211 -2487c86,-45 122,22 33,-115 -52,20 -45,-52 -59,40 -13,86 -25,15 26,75zm849 -5816c135,-10 77,32 107,-104 -166,22 -89,-39 -107,104zm-8045 -1393l59 -2c61,-97 37,-142 -53,-191 -5,7 -123,39 -6,193zm-12585 2344c3,-126 9,-31 -32,-70 -25,25 -18,13 -37,64l39 57 30 -51zm21445 8401c-173,28 -5,162 -5,162 17,-23 34,53 35,-88 2,-133 2,-16 -30,-74zm-7726 -10714c54,-16 48,46 60,-34 14,-86 9,-15 -27,-73 -49,31 -121,-28 -33,107zm2226 -437c29,-40 52,53 35,-69 -15,-105 -2,-34 -59,-73 -14,17 -58,-43 -43,72 17,126 -14,33 67,70zm-13381 14473c-108,-44 -32,2 -69,25 153,144 93,45 120,32 -37,-65 17,-30 -51,-57zm-16107 -2399c103,-46 70,-13 61,-117 -96,10 -54,-27 -90,34 -46,78 29,83 29,83zm6804 -10029c-8,-5 -18,-24 -24,-15l-95 -9c0,144 -25,145 119,124l0 -100c-90,37 -68,-13 -76,69 108,-5 13,38 76,-69zm-11048 7103c11,-112 26,21 -39,-41l8 93c60,-55 22,37 31,-52zm6 -5040c76,71 -99,41 38,30 70,-5 11,13 56,-27 -53,-44 90,-32 -36,-25 -65,4 -11,-8 -58,22zm701 2991c38,31 32,40 85,3 -102,-100 -85,-3 -85,-3zm38576 5668c152,93 87,13 102,3 -42,-43 17,-22 -57,-32l-45 29z"/>
|
||||
<path class="fil2" d="M22443 33531c91,-46 99,-37 3,-91 -65,80 -19,59 -3,91zm-9179 174l399 12 94 3 23 -102c121,-33 40,27 77,-81l-104 -24c-77,-2 -129,-55 -130,-59 -3,-10 -12,-11 -18,-15l-68 -4c-94,14 -152,38 -213,70l-167 11 -9 121 13 64 103 4zm3362 -16370c31,57 -35,35 43,50 123,23 4,11 64,-17 -27,-65 39,-44 -41,-57 -132,-21 -7,-12 -66,24zm10290 3584c-14,-80 9,-36 -56,-77 -3,4 -94,6 -19,84 51,53 74,-6 75,-7zm2277 11808c100,-46 108,-71 3,-122 -64,81 -39,56 -3,122zm-598 -13384c72,-96 69,-72 -26,-113 -75,90 -73,70 26,113zm-487 7658c-46,-62 -80,7 -82,7 65,99 -67,22 63,80 4,-5 100,22 19,-87zm-14360 -9918c34,-131 44,-88 -39,-138 -4,7 -53,-26 -32,67 28,121 -23,26 71,71zm13953 15010c6,-87 -6,-35 -58,-63 -75,84 -46,57 -4,130 44,-23 53,54 62,-67zm1319 -15162c106,-114 26,-92 4,-127 -51,29 -67,-45 -61,71 4,73 20,40 57,56zm2647 15024c-2,-2 8,-68 -88,-57 -109,12 -38,7 -73,64 105,50 64,60 161,-7zm-293 -3726c49,-51 48,-33 50,-171 -85,-2 -93,-38 -195,78 -83,12 -33,-18 -93,47l116 91c47,-29 48,-34 122,-45zm-2986 3302c-112,22 -39,12 -64,57 182,135 183,-23 184,-23 -10,-7 18,-61 -120,-34zm-1299 1033c-77,-44 -27,-43 -194,-4 19,157 34,164 112,169 166,12 14,18 78,-36l4 -129zm-29 818c-14,-28 44,-120 -225,-46 34,72 -28,65 93,92 164,37 124,-39 132,-46zm-7886 -16516l181 4c22,-158 -15,-177 -160,-176l-21 172zm1555 1675l149 114c98,86 124,57 174,-16 -50,-145 -13,-36 -146,-105 -44,-243 65,-253 -76,-325 -82,93 -26,15 -43,187 -15,145 -11,7 -58,145zm-16716 6826c57,-32 46,42 53,-46 6,-83 4,-30 -50,-59l-24 38c3,61 -12,24 21,67zm-1337 -2651c26,-6 45,9 64,-22 76,-123 9,-42 -9,-80 -79,40 -46,5 -55,102zm-4578 -6954l-112 -3 26 95c100,-38 42,50 86,-92zm7494 3833c33,-24 94,21 33,-122 -79,33 -50,-52 -63,48 -20,150 -15,19 30,74zm14390 12465c-111,-30 -19,-3 -63,20 25,35 -17,155 117,33 -23,-35 -5,-39 -54,-53zm-16337 1107c45,-72 -18,-62 -21,-68 -108,41 -55,-28 -72,101 119,-4 51,36 93,-33zm-15554 -8727c0,0 54,27 19,-104 -42,1 -53,-32 -84,34 -35,76 50,66 65,70zm29578 -7130c115,91 90,22 123,-26 -55,-41 62,-61 -72,-36 -85,16 -31,37 -51,62zm-15614 10133c9,-12 164,46 4,-107 -159,125 -4,106 -4,107zm19830 6238c-114,-3 -59,-5 -148,25 75,104 35,82 145,96l3 -121zm-1810 -750c-9,127 22,73 56,93 12,-18 98,-37 5,-177 -39,23 -54,-4 -61,84zm-22909 -1701c109,-48 103,-21 88,-170l-170 17 -8 103 28 61 62 -11zm17260 -7459c57,-31 46,52 67,-70 25,-145 -11,-61 -33,-93 -63,23 -49,-63 -69,61 -24,151 20,79 35,102zm6292 8218c-87,10 -54,14 -87,55 20,17 25,52 112,48 129,-7 69,-26 89,-70 -34,-24 -5,-45 -114,-33zm-18726 -12582l138 126c48,-78 33,-47 37,-155 -115,-28 -88,-44 -175,29zm5425 2089c111,8 43,39 121,-26l69 -111c-57,-37 50,-12 -63,-36 -108,-23 -9,-17 -111,3l-16 170zm198 -5155c69,-15 103,32 92,-91 -10,-106 -55,-86 -92,-103 -90,200 -13,173 0,194zm-4497 9344c43,-116 -3,-63 -8,-78 -188,-98 -155,47 -70,159 12,-9 44,9 78,-81zm-14595 -8298l-38 -84 -224 -26c12,84 -6,39 36,90 11,13 12,8 29,28 102,110 -28,62 101,78 134,18 76,-16 96,-27l0 -59zm16516 14224c-52,-40 -1,-28 -113,-50 -42,-8 -243,-19 -291,67 61,129 109,18 238,86 55,29 -10,50 104,69 197,32 132,-42 145,-52 -48,-181 24,-57 -88,-111l5 -9zm-15098 58c48,-69 45,-72 17,-145 -274,51 -23,42 -250,167 30,-165 -35,-99 -48,-113l-11 227 209 8 83 -144zm10508 -4775c27,-191 50,60 -34,-54 -79,69 -75,58 -4,123 52,-55 26,22 38,-69zm2333 -7579c33,-5 126,10 57,-109 -99,52 -45,-60 -57,109zm-3429 -2611c31,53 -29,36 45,50 112,21 8,9 62,-17 -23,-52 62,-39 -41,-56 -76,-13 -10,-11 -66,23zm-5194 1548c20,-171 28,-57 -49,-102 -23,40 -71,-39 -24,67 24,53 -2,25 73,35zm2621 14176c16,-129 6,-16 -31,-67 -97,48 -106,68 -4,128 34,-41 21,52 35,-61zm20632 -662c16,-119 -2,-25 -34,-66 -97,47 -111,67 -4,122 35,-34 23,48 38,-56zm-26456 -15122c101,69 77,57 133,-25 -31,-22 47,-55 -73,-37 -124,19 -29,27 -60,62zm-3048 11843c12,19 -42,82 104,51 57,-12 47,-31 63,-80 -76,-39 -83,-41 -168,-21l1 50zm591 1476c-69,86 -68,86 -5,161 100,-47 96,-110 5,-161zm9675 2249c133,-45 121,-5 97,-144 -185,-45 -50,-16 -91,31 11,22 3,32 23,36 48,12 16,9 52,-9 -40,-40 -1,-18 -75,-27 -8,6 -43,27 -44,28 -15,11 -33,39 -36,33 -3,-7 -13,13 -19,19l7 24c-84,-5 -18,-34 -119,21l-151 150c-8,14 -26,96 -31,118 184,-1 48,-2 196,-98 58,-38 107,-51 184,-77l16 -87 -9 -18zm-10948 -16354c55,-82 67,-123 -24,-178 -4,5 -50,-31 -46,89 4,132 36,74 70,89zm5381 2060c95,56 114,57 192,-23 -74,-75 -188,-91 -192,23zm4150 14183c1,-1 63,-22 50,-106 -19,-117 0,-36 -74,-72 -29,39 -120,103 24,178zm17482 -2004c-59,-80 -103,-72 -188,-35 18,24 -69,68 85,81 140,12 94,-39 103,-46zm-13680 -1675c142,42 170,46 247,-29 -36,-39 -44,-68 -144,-58 -99,9 -73,21 -103,87zm-8064 1221l-36 23c-90,81 -54,49 -55,120 261,25 188,-170 188,-171 -115,-6 33,-13 -60,2l-37 26c8,17 -2,42 39,48 4,1 17,-4 20,-4 4,0 15,-7 22,-10 -39,-35 7,-19 -81,-34zm8634 -1952c-7,-10 54,-79 -138,-26 10,87 13,131 91,196 33,-28 19,-1 54,-52 25,-33 -21,88 23,-39 49,-141 5,-71 -30,-79l-79 -1 26 81 53 -80zm-7088 2769c-11,-74 -89,-139 -148,-163l-44 119 162 129c15,-21 49,45 30,-85zm-7692 303l-2 61 260 28c12,-216 -160,-128 -258,-89zm39584 -10253c14,28 -26,64 64,64 136,1 28,20 79,-60 -44,-33 10,-44 -75,-38 -129,7 -19,-3 -68,34zm419 750c28,-36 34,52 41,-69 10,-164 -9,-60 -36,-101 -30,17 -56,-27 -71,73 -20,138 30,78 66,97zm3065 2473c56,-72 68,-95 66,-198 -91,-19 -135,-38 -154,50 -19,87 88,148 88,148zm2397 -3620c57,42 -53,30 105,50 159,19 21,7 114,-15 -23,-95 27,-126 -112,-132 -103,-5 -87,13 -107,97zm-719 4372l-51 -56c213,-116 93,-238 -69,-239 -152,-1 -176,38 -165,195l14 39c14,128 95,141 226,140l45 -79zm-11881 -7680c95,59 33,27 75,3l-58 -18c-2,-8 -11,11 -17,15zm-21198 15445c35,43 20,47 60,29 5,-2 14,-15 21,-22l-81 -7zm5007 1132l96 3 -5 -58c-40,-60 5,-36 -76,-65 -36,-12 -55,0 -88,1l4 117 69 2zm19325 -14421l-61 0c-35,54 -27,-70 -32,67 -4,136 12,61 31,94 73,-20 31,13 65,-51 145,-35 46,16 95,-68 -56,-55 16,-32 -98,-42zm-8429 13335c40,-6 207,-169 -164,-173 -69,95 -80,76 -101,170l265 3zm14572 -9261c47,74 56,123 127,4 -117,-124 -105,-20 -127,-4zm909 -1194c54,84 169,131 199,-23 -27,-13 -10,-39 -116,-25 -56,7 -60,9 -83,48zm271 2163c-1,-1 33,-56 -85,-37 -108,17 -29,-7 -85,61 38,68 -51,70 108,81 68,5 70,-17 106,-46 -12,-97 2,-33 -44,-59l-117 16 83 62c42,-51 19,-10 34,-78zm2226 -30c105,20 81,29 165,-11 -16,-86 -60,-131 -144,-155 -47,81 -42,60 -21,166zm-680 -1938c37,-37 13,14 35,-54 59,-183 70,-195 20,-219 -8,-1 -19,-13 -23,-4 -2,7 -74,-30 -94,109 -15,102 -7,135 62,168zm-7886 -1031c174,9 174,-15 198,-181l-195 0 -3 181zm-435 -3677c1,-132 -96,-207 -218,-204 -14,163 61,224 218,204zm9068 10670l-229 -20c16,143 33,200 192,182 19,-35 15,-15 28,-68 1,-1 7,-80 9,-94zm-11458 -8654l179 16c42,-78 53,-79 68,-188l-240 -2 -7 174zm-13484 -1787c67,65 -101,40 38,31 69,-5 24,3 66,-28 -78,-63 97,-40 -43,-30 -88,6 4,-25 -61,27zm15318 6420c8,8 -38,96 94,3 -76,-59 111,-37 -40,-27 -71,5 -10,-11 -54,24zm-4361 -5494c0,-176 44,-57 -80,-98 19,110 -24,65 80,98zm5776 11913c-52,-67 -17,-71 -103,-32 75,108 -101,-50 18,46 3,3 12,10 15,12 123,59 36,-5 70,-26zm452 -9192c-15,-105 18,-46 -63,-89 -52,58 -31,28 -37,112l0 24c138,141 57,117 171,135l18 -141 -89 -41zm1300 -184c26,36 -55,67 177,58 3,-16 69,-189 -108,-115 -67,28 -30,-2 -69,57zm-6644 5321c34,-145 -23,-89 -32,-106 -123,17 -85,-60 -108,72 -22,127 47,87 73,100 61,-30 38,56 67,-66zm12539 -5533c161,1 121,36 140,-122 -54,-35 -31,-46 -161,-30 -7,73 -19,77 21,152zm-7899 4642l158 -3 14 -151 -161 -4 -11 158zm-17041 -7038c56,111 45,115 103,4 -51,-38 -52,-32 -103,-4zm9438 14921c155,-74 35,-103 33,-108 -148,63 -33,108 -33,108zm-15491 -14617c76,-131 38,-84 -75,-106 30,146 -22,74 75,106zm2595 5412c114,-55 112,-64 4,-122 -17,20 -39,-42 -33,60 3,62 0,30 29,62zm3715 -5475c14,118 -32,80 93,86 37,-95 5,-127 -93,-86zm-11753 7101c5,-101 4,-86 -99,-104 -13,126 -1,117 99,104zm5801 -8233c54,-27 68,45 62,-68 -4,-75 -27,-45 -58,-61 -3,3 -85,14 -4,129zm-10835 7881c-39,-69 -44,-121 -135,-4 59,52 -68,23 66,40 114,15 28,-3 69,-36zm25397 -740c-39,10 -173,13 -98,95 96,105 85,-47 98,-95zm-2065 8351c-44,-72 23,-10 -75,-89 -65,-51 0,-9 -75,-42l-43 107 31 161c93,9 88,6 142,-32l20 -105zm-14954 -14214c87,52 55,48 150,6 -45,-139 -121,-139 -150,-6zm2674 8593c-160,1 -84,46 -93,80l164 16c3,-66 28,-97 -71,-96zm-12857 -11652c59,116 145,73 198,6 -89,-66 -119,-55 -198,-6zm14729 9603c9,31 -34,70 86,81 110,11 71,-13 85,-75 -84,-44 -68,-38 -171,-6zm-1945 -4959c-113,-51 -59,-57 -140,3l-3 59c93,63 166,72 228,-22 -42,-48 23,-26 -85,-40l-115 0c37,83 -28,35 82,68 55,-38 15,12 33,-68zm1792 10456c-77,-56 -141,-72 -205,23 16,12 15,56 118,47 109,-8 68,-30 87,-70zm6791 -1117c36,-46 36,70 46,-94 7,-128 -25,-68 -41,-87 -41,17 -64,-27 -70,84 -8,141 28,77 65,97zm-19845 -1831c156,4 126,-56 115,-191 -148,47 -119,6 -115,191zm28588 2560c110,14 138,-57 145,-166l-129 10c-85,158 -17,155 -16,156zm-24536 1960c-95,25 -67,45 -79,133 122,4 100,21 190,-35 -16,-82 22,-133 -111,-98zm-1339 -12555c34,-29 35,29 35,-82 -176,-85 -220,125 -198,245 232,90 139,21 169,-18l-8 -56 2 -89zm-138 10191c6,-3 15,-9 19,-11 187,-98 143,-30 160,-133 -81,-49 -97,-61 -235,49 -9,7 -15,11 -19,14l-10 -4 4 8c-6,4 -7,6 -36,41 47,43 -13,15 61,44 105,40 38,-2 56,-8zm8367 -12746l142 -3 16 -140c-106,-42 -55,-43 -174,-39 -38,108 -18,70 16,182zm13540 9864c20,-155 32,-118 -57,-201l-114 -69 -18 135c4,4 38,33 46,42 112,117 -30,57 143,93zm988 4753c45,-102 30,10 24,-135l-34 -127c-82,44 -11,4 -56,41l-47 40c-58,65 -44,-8 -43,128 63,55 64,54 156,53zm12226 -12623c69,-36 48,37 60,-51 10,-77 0,-29 -27,-74 -74,34 -47,-58 -62,47 -11,85 -16,23 29,78zm-541 532c79,-38 56,43 72,-73 18,-134 -33,-95 -37,-102 -62,28 -51,-64 -72,68 -25,164 18,78 37,107zm3249 -2408c42,-47 39,67 47,-70 10,-158 -17,-67 -42,-99 -63,25 -63,-60 -82,69 -19,138 47,86 77,100zm1303 9111c11,10 -39,54 99,53 165,-1 78,-27 103,-76 -9,-7 34,-50 -103,-50 -165,1 -71,41 -99,73zm-492 -3647c92,-9 106,-16 198,-88 -55,-161 -128,-160 -198,-171 8,167 44,104 0,259zm-24691 -3316c88,44 53,43 105,-26 -39,-27 54,-78 -66,-29 -4,1 -13,8 -16,10l-23 45zm13670 13200c-33,-129 32,-90 -103,-104 13,123 -21,66 103,104zm-2530 -391c-27,-47 15,-109 -119,-33 20,31 -50,44 47,68 133,33 20,3 72,-35zm7333 519c-75,-6 -55,36 -70,58 59,45 -67,20 67,36 128,15 17,5 68,-31 -26,-54 53,-54 -65,-63zm-2346 -1174c-21,-102 14,-11 -60,-51 -44,43 -78,-66 -39,94 19,78 18,22 64,42 41,-48 52,-4 35,-85zm-2671 1531c-126,3 -69,18 -100,67 33,26 41,98 222,6 -23,-40 -11,-75 -122,-73zm2389 -1391c-144,-10 -216,11 -140,175l167 10 -27 -185zm-13510 -6878c31,-55 21,-40 2,-86 -55,59 -65,-88 -31,42 34,130 -97,-14 29,44zm11036 7899c51,38 -7,20 62,28 135,17 -26,24 42,-24 -37,-35 3,-24 -62,-33 -162,-23 46,-43 -42,29zm-26597 -10879c61,73 10,58 96,32 -17,-44 72,-25 -24,-45 -72,-14 -22,-8 -72,13zm24876 10019c-12,-82 2,-14 -47,-36 -75,86 -25,63 27,92 24,-39 30,7 20,-56zm-13300 -13607c15,-24 58,33 23,-60 -25,-65 14,-8 -49,-43 -39,74 -64,63 26,103zm-1474 10770c72,-89 63,-70 -26,-109 -102,108 -21,86 26,109zm2490 -9768c5,-7 104,11 5,-148 -45,51 -53,-76 -44,73 5,81 3,34 39,75zm-455 582l45 -26c-21,-109 31,-69 -102,-93 -6,111 -39,73 57,119zm-2646 4875c5,-126 -2,-96 -98,-104 -10,117 -38,124 98,104zm-15387 -7335c19,35 -38,43 63,61 137,25 73,-13 97,-27 -4,-10 32,-155 -160,-34zm3776 14905c-5,113 33,83 36,87 97,-48 94,-123 6,-180 -22,28 -35,-54 -42,93zm16124 -7293c1,0 19,130 175,5 -14,-31 11,-58 -77,-63 -125,-7 -71,37 -98,58zm4168 4706c37,-17 60,39 74,-88 13,-125 -31,-79 -39,-89 -47,21 -58,-27 -69,83 -13,129 25,80 34,94zm-14149 1449c-77,-12 -83,28 -88,128l196 -3c-13,-79 -18,-110 -108,-125zm-10285 -377c145,13 156,25 271,-27 -60,-66 -141,-122 -250,-121l-21 148zm30878 -12750c85,40 49,48 105,-26 -21,-16 24,-117 -105,26zm-4545 -547c57,-82 74,-71 -26,-119 -64,93 -65,76 26,119zm6389 36c29,-122 43,-90 -83,-116 14,175 -39,72 83,116zm5155 2988c-2,44 -19,42 29,111 108,-35 40,70 81,-93 0,-4 -13,-87 -13,-87 -15,-49 -13,-36 -31,-65 -82,38 -49,-29 -66,134zm-7078 -530c164,-26 121,59 106,-100 -107,-4 -71,-31 -106,100zm1288 -911c5,-125 48,-86 -66,-119 -93,100 -38,96 66,119zm2390 12606c-127,16 -58,-23 -117,61 77,102 120,95 117,-61zm-6680 -14484c93,-49 102,-26 33,-126 -50,15 -40,-45 -66,34 -44,140 5,62 33,92zm-6631 -463c15,26 -10,57 69,75 138,31 72,-16 95,-31 -35,-82 47,-48 -66,-68 -28,-5 -93,19 -98,24zm9161 3323c39,-11 65,56 83,-82 13,-103 -26,-89 -48,-112 -98,44 -81,122 -35,194zm11122 7323c77,-41 52,57 68,-98 5,-49 -11,-64 -20,-96 -60,21 -77,-45 -93,90 -16,134 36,91 45,104zm-6944 6433l64 2c34,-109 52,-107 -11,-201 -30,8 -66,-56 -83,91 -7,64 4,48 30,108zm-9852 -12707c33,-80 15,-192 -49,-252 -81,-76 -14,-26 -117,-47 50,222 25,40 89,163 45,86 -28,59 77,136zm17007 11129c-5,-4 -12,-10 -17,-14l-83 -58c-95,106 -8,225 151,201 10,-144 18,-76 -51,-129zm-14522 -7357l6 118 177 17 4 -157c-119,-17 -94,-25 -187,22zm1633 621c122,-9 53,43 137,-39 83,-80 31,-20 54,-141l-180 10 -11 170zm4070 -5651l169 46c4,-99 16,-85 -35,-146 -85,-102 -17,-49 -154,-73l20 173zm10175 12053c-9,-85 14,-6 -49,-52 -37,41 -36,-9 -29,69 9,97 -12,14 55,43 36,-56 37,58 23,-60zm-8682 -13171c38,60 -39,38 51,53 70,12 25,3 66,-21 -12,-32 50,-133 -117,-32zm2108 1273c32,-19 113,33 33,-122 -78,35 -51,-47 -63,49 -17,128 -11,22 30,73zm-2180 -3663l-109 -3c3,174 -2,49 43,106 98,-52 42,59 66,-103zm10237 6624c21,-31 58,42 35,-72 -21,-101 16,-22 -69,-66 -51,93 -65,71 34,138zm-4681 8278c35,-113 -29,-91 -30,-94 -79,35 -36,-30 -61,65 -8,30 9,72 15,95 49,-25 47,25 76,-66zm1712 -10475c90,-11 72,27 105,-40 54,-109 -36,-81 -61,-94l-37 44c-16,57 -18,8 -7,90zm-2159 653c14,19 -15,66 80,65 117,-2 32,5 75,-60 -19,-16 33,-129 -155,-5zm-9160 -4516c140,63 103,33 149,-46 -10,-8 40,-74 -77,-47 -186,44 -11,10 -72,93zm14791 10390c-149,-15 -74,13 -105,64 54,49 -82,47 102,53 102,4 97,-46 99,-47 -19,-29 7,-60 -96,-70zm-7396 -6688c36,71 -84,46 66,62 8,-7 18,-27 22,-21l74 -89c49,-90 34,-58 -1,-120 -66,20 -27,3 -73,42 -5,4 -10,10 -14,14 -5,4 -11,10 -15,14 -4,5 -11,12 -16,16l-35 34 -8 48zm3324 -2979c19,41 -49,73 95,76 129,2 70,-21 95,-70 -7,-6 38,-52 -90,-53 -165,-1 -56,12 -100,47zm-4325 1161l115 0c20,-126 28,-84 -30,-190 -117,49 -118,87 -85,190zm5264 1728c2,-3 48,17 50,-92 4,-170 -3,-48 -44,-101 -39,16 -77,-51 -90,107 -6,77 17,64 84,86zm3736 8908c128,-174 17,-185 7,-200 -65,16 -98,-21 -96,99 2,114 50,86 89,101zm-577 -7651c-69,-84 28,-31 -83,-63 -48,-14 -90,-4 -138,1 13,162 117,193 221,62zm-10793 -2729c100,-7 113,56 202,-184l-174 3 -28 181zm11216 4612c69,-72 58,-54 46,-178l-199 -7c-4,7 -10,9 -12,18l-76 95c135,22 68,-7 161,87l80 -15zm-25273 1701c76,60 6,56 86,3 -47,-47 102,-40 -34,-29 -72,6 -2,-17 -52,26zm-2321 -4177c9,14 14,125 94,3 -55,-40 95,-28 -36,-22 -55,3 -22,-1 -58,19zm3532 6166c27,41 -52,47 54,45 61,-2 15,-6 40,-42 -34,-25 -1,-17 -55,-23 -4,0 -17,14 -19,7 -3,-7 -13,9 -20,13zm9741 -9188c141,-29 65,23 97,-75 -192,-10 -27,11 -97,75zm-816 7909c15,-101 13,5 -29,-35 -126,99 -5,94 -3,96 46,-55 21,17 32,-61zm4719 4713c-57,112 -6,24 19,71 20,-12 147,-53 24,-91 -71,-21 -31,-5 -43,20zm-8123 -431c-15,-86 16,-10 -58,-43 -82,124 13,93 35,107 35,-58 46,63 23,-64zm17490 -3007c175,100 121,20 148,5 -164,-141 -131,-17 -148,-5zm-22342 4930c132,-4 153,38 190,-77l-182 -33c-126,37 -57,-3 -107,63 47,51 -83,44 99,47zm12980 -12068c-5,14 -15,15 -17,31 -2,16 -11,19 -13,27 -5,31 -5,60 -3,92l176 14 5 -153 -148 -11zm3361 -432c36,-54 25,-37 3,-87 -60,72 -60,-95 -28,43 33,144 -77,-37 25,44zm-4106 70c11,-16 62,31 29,-65 -28,-79 21,-7 -55,-51 -27,44 -74,-63 -27,70 23,65 -11,17 53,46zm4107 -1014c83,-42 48,57 62,-54 19,-151 12,-10 -29,-78 -91,38 -53,-66 -66,49 -13,104 -23,19 33,83zm5309 -1291c25,-37 79,60 36,-83 -31,-103 26,-8 -61,-59 -32,47 -82,-71 -36,83 28,92 -21,17 61,59zm1248 6583c63,-42 37,35 61,-54 35,-132 -11,-66 -27,-91 -56,21 -40,-53 -67,42 -50,177 3,67 33,103zm-3413 -2551c58,-28 79,64 73,-75 -5,-112 -22,-47 -68,-70 -1,1 -117,-7 -5,145zm-289 -1224c21,57 -53,42 41,69 192,56 47,8 104,-36 -35,-66 27,-44 -52,-65 -126,-33 -82,23 -93,32zm-5357 -3096l-17 46c15,129 58,97 106,82 112,-34 72,-59 86,-77 -20,-13 -52,-43 -84,-53l-91 2zm8116 7257c60,-74 70,111 51,-114 -8,-94 -53,-80 -74,-93 -6,8 -48,-10 -52,93 -7,206 -24,60 75,114zm-359 -3417c72,-45 54,62 74,-83 26,-183 -17,-80 -38,-116 -80,37 -61,-87 -83,79 -26,191 21,83 47,120zm-17157 14c85,70 -121,41 43,30 71,-4 21,6 65,-27 -62,-52 98,-38 -42,-29 -76,5 -12,-10 -66,26zm5329 -1528c63,-38 47,39 53,-51 6,-102 14,-24 -50,-60 -32,49 -31,66 -3,111zm-27615 8986c78,-36 55,63 54,-88 -92,3 -46,-22 -73,28 -47,83 8,40 19,60zm32764 3684c-10,-69 0,-14 -45,-36 -107,107 -16,74 26,100 17,-35 26,-9 19,-64zm-6439 -13319c1,0 48,9 52,-33 12,-114 25,-19 -48,-68 -16,24 -89,9 -4,101zm-2549 -1315c-16,8 -169,44 -28,87 59,17 35,0 43,-20 45,-117 8,-15 -15,-67zm4501 3122c50,-16 41,47 55,-34 13,-73 3,-24 -23,-71 -53,37 -106,11 -32,105zm100 11390c59,41 -62,18 66,32 141,16 8,10 73,-28 -142,-125 -131,-11 -139,-4zm5906 333c25,-38 129,23 33,-116 -109,38 -98,26 -33,116zm-36586 -127c129,-18 2,10 67,-34 -65,-125 -157,-104 -185,25 57,9 59,18 118,9zm29127 1317c73,-31 40,-35 105,3 -33,22 15,19 -51,22 -115,5 -13,3 -54,-25zm-38 57l179 5 2 -117 -181 -1 0 113zm-23361 -15949c1,-1 61,10 45,-96 -16,-104 8,-33 -69,-78 -13,19 -64,-32 -40,103 21,124 1,35 64,71zm7078 11660c-100,8 -43,-8 -106,52 -56,54 -46,20 -62,107l175 18 -7 -177zm27110 -785c-82,-43 -51,-52 -102,26 49,34 -62,39 58,24 76,-9 15,3 44,-50zm-1210 -2487c86,-45 122,22 32,-114 -51,19 -45,-53 -58,39 -14,86 -25,15 26,75zm849 -5816c135,-10 76,32 106,-104 -166,22 -89,-39 -106,104zm-8045 -1393l58 -2c62,-97 37,-142 -52,-191 -5,7 -124,39 -6,193zm-12585 2344c3,-126 9,-31 -32,-70 -26,25 -18,13 -37,64l38 57 31 -51zm21445 8402c-173,27 -5,161 -5,161 16,-23 33,53 35,-88 2,-133 2,-16 -30,-73zm-7726 -10715c54,-16 48,46 60,-34 13,-86 8,-15 -27,-73 -49,31 -122,-28 -33,107zm2226 -437c29,-40 52,53 35,-69 -16,-105 -3,-34 -60,-73 -13,17 -57,-43 -42,72 16,126 -15,33 67,70zm-13381 14473c-109,-44 -32,2 -69,25 153,144 93,45 120,33 -37,-65 17,-30 -51,-58zm-16107 -2399c103,-46 70,-13 61,-117 -97,10 -54,-27 -90,34 -46,78 29,83 29,83zm6804 -10029c-8,-5 -18,-24 -24,-15l-96 -9c1,144 -24,145 120,124l0 -100c-90,37 -68,-13 -76,69 108,-5 13,38 76,-69zm-11049 7103c12,-112 26,21 -38,-41l7 93c60,-55 22,37 31,-52zm7 -5040c76,71 -99,41 37,30 71,-5 11,13 56,-27 -52,-44 90,-32 -35,-25 -65,4 -11,-8 -58,22zm700 2992c39,30 32,39 86,2 -102,-100 -86,-3 -86,-2zm38577 5667c152,93 87,13 102,3 -42,-43 16,-22 -58,-32l-44 29z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path class="fil3" d="M20432 0c8718,-38 15581,2266 15458,9209 -25,787 -197,745 -1206,434 -5376,-1662 -8578,-3016 -12410,-6248 -1067,-900 -1945,-1797 -2743,-2837 -478,-648 -8,-545 901,-558zm-18416 19428c1785,-4186 2803,-6725 6956,-9214 1814,-1088 3728,-1795 5744,-2401 5011,-1469 9917,-953 14495,540 1697,562 2833,1208 4123,2158 602,450 989,178 1872,-71 402,-113 1572,-529 1912,-305 933,615 -675,1120 -1291,1389 -1798,785 -1256,251 -1265,1780 -43,7030 -7302,11174 -13250,12374 -3409,688 -7029,1146 -9343,1499 -5916,900 -5060,-1185 -9071,-2819 -937,-381 -2531,-341 -2879,-1361 -223,-655 1540,-2751 1997,-3569z"/>
|
||||
<path class="fil4" d="M10113 32164l548 -85c566,-87 655,-815 655,-1696 0,-1108 -152,-1559 -630,-1485l-573 89 0 3177zm-872 -3711l1541 -239c770,-120 1425,167 1425,1818l0 225c0,1013 -203,2283 -1374,2464l-1592 246 0 -4514z"/>
|
||||
<path class="fil4" d="M14753 30269l-349 -2047 -421 2167 770 -120zm-922 -2527l1171 -182 1019 4358 -943 146 -216 -1141 -987 152 -274 1218 -935 145 1165 -4696z"/>
|
||||
<polygon class="fil4" points="17968,31617 17096,31752 17096,27924 16014,28092 16014,27404 19050,26934 19050,27622 17968,27790 "/>
|
||||
<path class="fil5" d="M24269 30700l88 -3885 -824 115 -106 4640 2357 -329 17 -755 -1532 214zm2552 396l105 -4640 -824 115 -106 4640 825 -115zm3488 -5112l-525 1811c-157,575 -298,1154 -410,1687l-17 3c-83,-518 -193,-1044 -319,-1586l-423 -1679 -1020 143 -395 4680 752 -105 124 -1798c41,-577 85,-1269 109,-1855l17 -3c87,553 207,1162 334,1668l432 1780 624 -87 566 -1950c157,-539 327,-1176 462,-1748l17 -3c-16,472 -6,1216 3,1822l37 1793 785 -109 -139 -4606 -1014 142zm2380 3547l29 -1291 1399 -196 16 -730 -1398 196 25 -1123 1483 -207 17 -748 -2307 322 -106 4640 2396 -334 17 -749 -1571 220z"/>
|
||||
<path class="fil4" d="M21036 29298l-350 -2048 -420 2166 770 -118zm-923 -2529l1172 -182 1019 4359 -943 145 -217 -1141 -986 152 -274 1218 -936 145 1165 -4696z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 69 B |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 174 B |
|
After Width: | Height: | Size: 173 B |
|
After Width: | Height: | Size: 173 B |
|
After Width: | Height: | Size: 180 B |
|
After Width: | Height: | Size: 179 B |
|
After Width: | Height: | Size: 180 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 255 B |
|
After Width: | Height: | Size: 8.9 KiB |
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#555555;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M476.7,88.3h-88.3c0-48.8-39.5-88.3-88.3-88.3s-88.3,39.5-88.3,88.3h-88.3c-19.5,0-35.3,15.8-35.3,35.3v88.3
|
||||
C39.5,211.9,0,251.4,0,300.1s39.5,88.3,88.3,88.3v88.3c0,19.5,15.8,35.3,35.3,35.3h123.6v-35.3c0-29.3,23.7-53,53-53s53,23.7,53,53
|
||||
V512h123.6c19.5,0,35.3-15.8,35.3-35.3V353.1h-35.3c-29.3,0-53-23.7-53-53s23.7-53,53-53H512V123.6
|
||||
C512,104.1,496.2,88.3,476.7,88.3z M388.4,300.1c0,48.8,39.5,88.3,88.3,88.3v88.3h-88.3c0-31.5-16.8-60.7-44.1-76.5
|
||||
c-27.3-15.8-61-15.8-88.3,0c-27.3,15.8-44.1,44.9-44.1,76.5h-88.3V353.1H88.3c-29.3,0-53-23.7-53-53s23.7-53,53-53h35.3V123.6
|
||||
h123.6V88.3c0-29.3,23.7-53,53-53s53,23.7,53,53v35.3h123.6v88.3C427.9,211.9,388.4,251.4,388.4,300.1z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 141 B |
|
After Width: | Height: | Size: 222 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1023 B |
|
After Width: | Height: | Size: 889 B |
|
After Width: | Height: | Size: 81 B |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,16 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z" />
|
||||
<polyline points="14 2 14 8 20 8" />
|
||||
<path d="M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1" />
|
||||
<path d="M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 498 B |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 431 B |
|
After Width: | Height: | Size: 725 B |
|
After Width: | Height: | Size: 996 B |
|
After Width: | Height: | Size: 743 B |
|
After Width: | Height: | Size: 972 B |
|
After Width: | Height: | Size: 517 B |
|
After Width: | Height: | Size: 665 B |
|
After Width: | Height: | Size: 692 B |
|
After Width: | Height: | Size: 271 B |
|
After Width: | Height: | Size: 691 B |
|
After Width: | Height: | Size: 71 B |
|
After Width: | Height: | Size: 71 B |
|
After Width: | Height: | Size: 537 B |
|
After Width: | Height: | Size: 305 B |
|
After Width: | Height: | Size: 350 B |
|
After Width: | Height: | Size: 346 B |
|
After Width: | Height: | Size: 1000 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 54 B |
|
After Width: | Height: | Size: 54 B |
|
After Width: | Height: | Size: 103 B |
|
After Width: | Height: | Size: 241 B |
|
After Width: | Height: | Size: 362 B |
|
After Width: | Height: | Size: 243 B |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 51 B |
|
After Width: | Height: | Size: 84 B |
|
After Width: | Height: | Size: 990 B |
@@ -0,0 +1,356 @@
|
||||
<cfscript>
|
||||
/* Все глобальные функции экспортированы в request scope */
|
||||
function plain2htm(s) {
|
||||
return replace(replace(s, chr(13),'',"ALL"),chr(10),'<br/>', "ALL");
|
||||
}
|
||||
request.plain2htm = plain2htm;
|
||||
|
||||
function htm2plain(s) {
|
||||
return replaceNoCase(s, '<br/>', '#chr(13)##chr(10)#', "ALL");
|
||||
}
|
||||
request.htm2plain = htm2plain;
|
||||
|
||||
function cleanHtm(s) {
|
||||
return replaceList(s, '<,>,"', '<,>,"');
|
||||
}
|
||||
request.cleanHtm = cleanHtm;
|
||||
|
||||
function clean4CDATA(s) {
|
||||
LF = chr(10);
|
||||
return replaceNoCase(replaceList(s, '[,]', '&91;,&93;'),"<br>",LF,"ALL");
|
||||
}
|
||||
request.clean4CDATA = clean4CDATA;
|
||||
|
||||
function numFmt(num, decimalPlaces = 0){
|
||||
var sFormat = ",";
|
||||
if (decimalPlaces GT 0) {sFormat = sFormat & "." & repeatString("0", decimalPlaces);}
|
||||
return replace(NumberFormat(num, sFormat), ",", " ", "ALL");
|
||||
}
|
||||
request.numFmt = numFmt;
|
||||
|
||||
function nFmt(num, decimalPlaces = 2){
|
||||
if (num EQ 0) return "";
|
||||
return numFmt(num, decimalPlaces);
|
||||
}
|
||||
request.nFmt = nFmt;
|
||||
|
||||
function dateFmt(date, sFormat = 'YYYY-MM-DD'){
|
||||
return dateFormat(date, sFormat);
|
||||
}
|
||||
request.dateFmt = dateFmt;
|
||||
|
||||
function dateTimeFmt(date, sDateFormat = 'YYYY-MM-DD', sTimeFormat='HH:MM'){
|
||||
return dateFormat(date, sDateFormat) & ' ' & timeFormat(date, sTimeFormat);
|
||||
}
|
||||
request.dateTimeFmt = dateTimeFmt;
|
||||
|
||||
function timeFmt(date, sFormat = 'HH:MM'){
|
||||
return timeFormat(date, sFormat);
|
||||
}
|
||||
request.timeFmt = timeFmt;
|
||||
|
||||
function usrAuthenticated() {
|
||||
return request.usr_id GT 0 AND NOT (request.usr_id EQ request.ANONYMOUS_USR_ID);
|
||||
}
|
||||
request.usrAuthenticated = usrAuthenticated;
|
||||
|
||||
function filterOn(filter) {
|
||||
return (isStruct(filter) AND NOT structIsEmpty(filter));
|
||||
}
|
||||
request.filterOn = filterOn;
|
||||
|
||||
function stripWhiteSpace(sNumber) {
|
||||
return reReplace(sNumber, "[[:space:]]", "", "ALL");
|
||||
}
|
||||
request.stripWhiteSpace = stripWhiteSpace;
|
||||
/*
|
||||
// never used
|
||||
function cleanNumber(sNumber) {
|
||||
var s = reReplace(sNumber, "[[:space:]]", "", "ALL");
|
||||
if ( find(",", s) ) { //watch argument order!!!
|
||||
// assume Russian format with decimal comma and spaces for thousand separator
|
||||
return replace(s, ",", ".");
|
||||
} else {
|
||||
// assume English format with decimal point and commas for thousand separator
|
||||
return replace(s, ",", "", "ALL");
|
||||
}
|
||||
}
|
||||
request.cleanNumber = cleanNumber;
|
||||
*/
|
||||
|
||||
/*https://cflib.org/udf/queryColumnToArray*/
|
||||
/**
|
||||
* Takes a selected column of data from a query and converts it into an array.
|
||||
*
|
||||
* @param query The query to scan. (Required)
|
||||
* @param column The name of the column to return data from. (Required)
|
||||
* @return Returns an array.
|
||||
* @author Peter J. Farrell (pjf@maestropublishing.com)
|
||||
* @version 1, July 22, 2005
|
||||
*/
|
||||
function queryColumnToArray(qry, column) {
|
||||
var arr = arrayNew(1);
|
||||
var ii = "";
|
||||
var loop_len = arguments.qry.recordcount;
|
||||
for (ii=1; ii lte loop_len; ii=ii+1) {
|
||||
arrayAppend(arr, arguments.qry[arguments.column][ii]);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
request.queryColumnToArray = queryColumnToArray;
|
||||
|
||||
/* ************************************* */
|
||||
|
||||
function loginPasswordPolicyCheck(usr_id, login, passwd, passwd2) {
|
||||
msg = "";
|
||||
// для старого логина длина не проверяется, все равно ничего не поделаешь
|
||||
if (NOT(usr_id GT 0) AND len(login) LE 3) {
|
||||
msg="Слишком короткий логин (минимальная длина логина 3 символа)";
|
||||
} else {
|
||||
if (passwd NEQ passwd2) {
|
||||
msg="Пароль и подтверждение не совпадают";
|
||||
} else {
|
||||
if (len(passwd) LT "8") msg="Слишком короткий пароль (минимальная длина пароля 8 символов)";
|
||||
}
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
request.loginPasswordPolicyCheck = loginPasswordPolicyCheck;
|
||||
|
||||
function i18(label,label_en=label) {
|
||||
//примитивная 2-язычная версия
|
||||
if (request.language EQ 'en') {
|
||||
return label_en;
|
||||
} else {
|
||||
return label;
|
||||
};
|
||||
}
|
||||
request.i18 = i18;
|
||||
|
||||
function passwordHashCreate(password) {
|
||||
return GenerateArgon2Hash('#ARGUMENTS.password#', 'argon2id', 1, 16000, 2);
|
||||
}
|
||||
request.passwordHashCreate = passwordHashCreate;
|
||||
|
||||
function passwordHashCheck(password, passwordHash) {
|
||||
return Argon2CheckHash('#ARGUMENTS.password#', ARGUMENTS.passwordHash, 'argon2id');
|
||||
}
|
||||
request.passwordHashCheck = passwordHashCheck;
|
||||
/*
|
||||
function skuCode(area_code="", abstract_service_code="") {
|
||||
var s="#arguments[1]#.#arguments[2]#";
|
||||
if (arrayLen(arguments) GE 3) {
|
||||
if (len(arguments[3]) GT 0) {
|
||||
s="#s#.#arguments[3]#";
|
||||
} else {
|
||||
s="#s#.0";
|
||||
};
|
||||
};
|
||||
if (arrayLen(arguments) GE 4) {
|
||||
if (len(arguments[4]) GT 0) {
|
||||
s="#s#.#arguments[4]#"
|
||||
}
|
||||
};
|
||||
if (arrayLen(arguments) GE 5) {
|
||||
var pricingModelSuffix=arguments[5];
|
||||
s="#s#-#pricingModelSuffix#";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
request.skuCode = skuCode;
|
||||
*/
|
||||
function roundSafe(a, precision) {
|
||||
return (isNumeric(a) AND isNumeric(precision)) ? round(a,precision) : a;
|
||||
}
|
||||
request.roundSafe = roundSafe;
|
||||
|
||||
function timeUnitLabel(n, value=0, locale="ru") {
|
||||
var labels = ["сек.","мин.","ч.","д.","мес."];
|
||||
if (n LE 5 AND n GE 1) {return labels[n];}
|
||||
else if (n EQ 6) { // в зависимости от числа - "год" г. или "лет" л.
|
||||
var m = value MOD 100;
|
||||
if (m GE 11 AND m LE 20) {
|
||||
return "л.";
|
||||
}
|
||||
m = m MOD 10;
|
||||
if (m GE 1 AND m LE 4) {
|
||||
return "г.";
|
||||
}
|
||||
return "л.";
|
||||
}
|
||||
throw (message="timeUnitLabelRu: index out of bounds", detail="Index must be from 1 to 6");
|
||||
}
|
||||
request.timeUnitLabel = timeUnitLabel;
|
||||
|
||||
function dateDiffVerbose(dateFrom, dateTo, maxParts=6, maxPrecision=1, locale="ru") {
|
||||
// returns formatted datetime interval duration, e.g. 1 hour 5 minutes or 3 years 0 months 12 days
|
||||
//(currently, only Russian supported)
|
||||
//
|
||||
//maxParts specifies, how many parts to display
|
||||
//maxPrecision starts froms seconds: 1=seconds, 2=minutes, 3=hours, 4=days, 5=months, 6=years
|
||||
//if maxPrecision specified is greater than given time interval, output is nothing
|
||||
//locale=ru just for interface, not used
|
||||
//attention: truncates the tail, not rounds
|
||||
//example: request.dateDiffVerbose(Now(),Now()+373.1234567, 3, 1) produces 1 г. 0 мес. 8 д.
|
||||
//example: request.dateDiffVerbose(Now(),Now()+373.1234567, 6, 1) produces 1 г. 0 мес. 8 д. 2 ч. 57 мин. 46 сек.
|
||||
//intended common usage: request.dateDiffVerbose(dateFrom, dateTo, 2, 1) - prints 2 senior parts of the interval,
|
||||
//with presision not better than second
|
||||
//
|
||||
// this is not the same task as converting number of seconds to days-hours-minutes-seconds,
|
||||
// because months contain different number of days, and days number of february depends on year
|
||||
try {
|
||||
if (NOT (isDate(dateFrom) AND isDate(dateTo))) return "";
|
||||
var UNIT_CODES = ["s","n","h","d","m","yyyy"];
|
||||
var start = dateFrom;
|
||||
var finish = dateTo;
|
||||
|
||||
var sOut = "";
|
||||
var nUnits = 0;
|
||||
var nPrintedPositions = 0;
|
||||
var printStart = false;
|
||||
|
||||
for (i=ArrayLen(UNIT_CODES); i GT 0; i=i-1) {
|
||||
nUnits = dateDiff(UNIT_CODES[i], start, finish);
|
||||
start = dateAdd(UNIT_CODES[i], nUnits, start);
|
||||
if (nPrintedPositions GT 0) {nPrintedPositions=nPrintedPositions+1;} //print started, so increment position
|
||||
if (nPrintedPositions GT maxParts) {break;}
|
||||
if (i LT maxPrecision) {break;}
|
||||
if (nUnits NEQ 0 AND nPrintedPositions EQ 0) {nPrintedPositions=1;}
|
||||
if (nPrintedPositions GT 0) {
|
||||
if (len(sOut)) {sOut=sOut & " ";}
|
||||
sOut=sOut & nUnits & " " & request.timeUnitLabel(i, nUnits, "ru");
|
||||
}
|
||||
}
|
||||
return sOut;
|
||||
} catch(e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
request.dateDiffVerbose = dateDiffVerbose;
|
||||
|
||||
/*
|
||||
function secondsToDHMS(nSeconds,partsToKeep) {
|
||||
//format seconds to days-hours-minutes-seconds and truncate to specified precision
|
||||
{
|
||||
days = n / (24 * 3600);
|
||||
|
||||
n = n % (24 * 3600);
|
||||
hours = n / 3600;
|
||||
|
||||
n %= 3600;
|
||||
minutes = n / 60 ;
|
||||
|
||||
n %= 60;
|
||||
seconds = n;
|
||||
|
||||
return days & " " & "days "
|
||||
& hours & " " & "hours "
|
||||
& minutes & " " & "minutes "
|
||||
& seconds & " " & "seconds ");
|
||||
}
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* Formats a JSON string with indents and new lines.
|
||||
* v1.0 by Ben Koshy (modified)
|
||||
*
|
||||
* @param str JSON string (Required)
|
||||
* @return Returns a string of indent-formated JSON
|
||||
* @author Ben Koshy (cf@animex.com)
|
||||
* @version 0, September 16, 2012
|
||||
*/
|
||||
// formatJson() :: formats and indents JSON string
|
||||
// based on blog post @ http://ketanjetty.com/coldfusion/javascript/format-json/
|
||||
// modified for CFScript By Ben Koshy @animexcom
|
||||
// usage: result = formatJson('STRING TO BE FORMATTED') OR result = formatJson(StringVariableToFormat);
|
||||
|
||||
// генерирует html разметку, чтобы не использовать <pre> и выровнять пробелы
|
||||
// содержит ошибку: делает перевод строки после запятой в строке в кавычках
|
||||
public string function formatJsonString(str) {
|
||||
var fjson = '';
|
||||
var pos = 0;
|
||||
var strLen = len(arguments.str);
|
||||
var indentStr = ' '; // Adjust Indent Token If you Like (замыкающий пробел - для выравнивания при пробелах после запятой)
|
||||
var newLine = '<br/>'; // Adjust New Line Token If you Like <BR>
|
||||
|
||||
for (var i=1; i<=strLen; i++) { //fix: <=
|
||||
var char = mid(arguments.str,i,1);
|
||||
|
||||
if (char == '}' || char == ']') {
|
||||
fjson &= newLine;
|
||||
pos = pos - 1;
|
||||
|
||||
for (var j=1; j <= pos; j++) {
|
||||
fjson &= indentStr;
|
||||
}
|
||||
}
|
||||
|
||||
fjson &= char;
|
||||
|
||||
if (char == '{' || char == '[' || char == ',') {
|
||||
fjson &= newLine;
|
||||
|
||||
if (char == '{' || char == '[') {
|
||||
pos = pos + 1;
|
||||
}
|
||||
|
||||
for (var k=1; k <= pos; k++) {
|
||||
fjson &= indentStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fjson;
|
||||
}
|
||||
request.formatJsonString = formatJsonString;
|
||||
//нужна еще функция, которая сериализует структуру как pretty printed json. См. https://github.com/bennadel/JsonSerializer.cfc (все не совсем просто, например, не заранее не определен формат даты)
|
||||
</cfscript>
|
||||
|
||||
<cffunction name=structGetKey>
|
||||
<cfargument name="struct" type="struct"/>
|
||||
<cfargument name="key" type="string"/>
|
||||
<cfargument name="default" type="string" default=""/>
|
||||
|
||||
<cftry>
|
||||
<cfif StructKeyExists(ARGUMENTS.struct, ARGUMENTS.key)>
|
||||
<cfreturn structFind(ARGUMENTS.struct, ARGUMENTS.key)/>
|
||||
<cfelse>
|
||||
<cfreturn ARGUMENTS.default/>
|
||||
</cfif>
|
||||
<cfcatch type="any">
|
||||
<cfreturn ARGUMENTS.default/>
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
<!--- можно проще - просто обработать исключение. вряд ли будет сильно хуже --->
|
||||
</cffunction>
|
||||
<cfset request.structGetKey = structGetKey/>
|
||||
|
||||
<cffunction name="setError">
|
||||
<cfargument name="container" type="struct"/>
|
||||
<cfargument name="message" type="string"/>
|
||||
|
||||
<cfset arguments.container.errorState=true/>
|
||||
<cfset arguments.container.errorMessage=arguments.message/>
|
||||
</cffunction>
|
||||
<cfset request.setError = setError/>
|
||||
|
||||
<cffunction name="snake2camel"
|
||||
access="public"
|
||||
returntype="any"
|
||||
output="false"
|
||||
hint="convert snake style name to camel style name">
|
||||
<cfargument name="snake" type="string" required="true" />
|
||||
<cfreturn #reReplace(ARGUMENTS.snake,"_([a-z])","\u\1","ALL")#/>
|
||||
</cffunction>
|
||||
<cfset request.snake2camel = snake2camel/>
|
||||
|
||||
<cffunction name="camel2snake"
|
||||
access="public"
|
||||
returntype="any"
|
||||
output="false"
|
||||
hint="convert camel style name to snake style name">
|
||||
<cfargument name="snake" type="string" required="true" />
|
||||
<cfreturn #reReplace(ARGUMENTS.snake,"([A-Z])","_\l\1","ALL")#/>
|
||||
</cffunction>
|
||||
<cfset request.camel2snake = camel2snake/>
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
<cfimport prefix="m" taglib="../lib"/>
|
||||
<cfimport prefix="c" taglib="../lib/controls"/>
|
||||
<cfparam name="ATTRIBUTES.fwx" default=""/>
|
||||
<cfparam name="ATTRIBUTES.thisUrl" default=""/>
|
||||
|
||||
<cfset i18=request.i18/>
|
||||
|
||||
<!---<style>ul#mainmenu li.menu-item-noaction a.inline{display:inline;}</style>--->
|
||||
<cfoutput>
|
||||
<ul id="mainmenu">
|
||||
<cfif request.usrAuthenticated()></cfif>
|
||||
|
||||
<li class="menu-title">Реестры</li>
|
||||
|
||||
<c:menu_item acl="" page="deal_ls.cfm" label="Сделки"/>
|
||||
<c:menu_item acl="" page="contract_ls.cfm" label="Договоры"/>
|
||||
<c:menu_item acl="" page="additional_agreement_ls.cfm" label="Доп. соглашения"/>
|
||||
|
||||
<!---
|
||||
<c:menu_item acl="" page="specification_ls.cfm" label="Спецификации"/>
|
||||
<c:menu_item acl="" page="agreement_ls.cfm" label="Сделки"/>
|
||||
<c:menu_item acl="" page="specification_item_ls.cfm" label="Экземпляры услуг"/>--->
|
||||
<li class="menu-title">Отчеты</li>
|
||||
<c:menu_item acl="" page="payg.cfm" label="PAYG"/>
|
||||
<!--- <c:menu_item acl="" page="detail_daily_rpt.cfm" label="Детализация по дням"/>
|
||||
<c:menu_item acl="" page="income_daily_rpt.cfm" label="Выручка по дням"/>
|
||||
<c:menu_item acl="" page="income_monthly_rpt.cfm" label="Выручка по месяцам"/> --->
|
||||
|
||||
<li class="menu-title">Справочники</li>
|
||||
|
||||
<!--- <c:menu_item acl="" page="svc_ls.cfm" label="Сервисы"/> --->
|
||||
<c:menu_item acl="" page="contragent_ls.cfm" label="Контрагенты"/>
|
||||
<!--- <c:menu_item acl="" page="measure_ls.cfm" label="Единицы измерения"/>
|
||||
|
||||
<c:menu_item acl="" page="usr_ls.cfm" label="Пользователи"/>
|
||||
--->
|
||||
<!--- <li class="menu-title">Пользователь</li>
|
||||
|
||||
<cfif request.usrAuthenticated()>
|
||||
<cfquery name="qUsr" datasource="#request.DS#">
|
||||
select shortname/*, login, firstname, middlename, lastname*/
|
||||
from usr
|
||||
where usr_id=<cfqueryparam cfsqltype="CF_SQL_INTEGER" value=#request.usr_id#/>
|
||||
</cfquery>
|
||||
<li class="menu-item-noaction">#qUsr.shortname#</li> <!---#request.usr_id#--->
|
||||
<c:menu_item acl="" page="password.cfm" queryString="#ATTRIBUTES.fwx#" label="Смена пароля"/>
|
||||
<c:menu_item acl="" page="logout.cfm" queryString="target_page=#URLEncodedFormat(ATTRIBUTES.thisUrl)#" label="Выход"/>
|
||||
|
||||
<cfelse>
|
||||
<c:menu_item acl="" page="saml/login.cfm" queryString="target_page=#URLEncodedFormat(ATTRIBUTES.thisUrl)#" label="Вход через WebSSO"/>
|
||||
<c:menu_item acl="" page="login.cfm" queryString="#ATTRIBUTES.fwx#" label="Вход"/>
|
||||
<c:menu_item acl="" page="logout.cfm" queryString="target_page=#URLEncodedFormat(ATTRIBUTES.thisUrl)#" label="Выход"/>
|
||||
</cfif> --->
|
||||
|
||||
|
||||
</ul>
|
||||
</cfoutput>
|
||||
<cfexit method="exittag"/>
|
||||
@@ -0,0 +1,7 @@
|
||||
<h1>PAYG REPORT</h1>
|
||||
Установление сессии.
|
||||
Если валидной сессии нет, отправляем браузер за аутентификацией к IDP.
|
||||
Получаем в токене данные пользователя и время жизни, кладем в сессию.
|
||||
По истечении установленного времени (скажем, половины срока жизни токена) идем к IDP за рефрешем
|
||||
Сертификат открытого ключа можно каждый раз получать от IDP.
|
||||
Запрос к IDP идет только для освежения сессии, а не на каждый запрос. Логаут на IDP не проверяется при каждом запросе.
|
||||
@@ -0,0 +1,4 @@
|
||||
/*! jQuery v1.7.1 jquery.com | jquery.org/license */
|
||||
(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
|
||||
f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()
|
||||
{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
|
||||
@@ -0,0 +1,3 @@
|
||||
/* JQuery Searchable DropDown Plugin | Copyright (c) 2012 xhaggi */
|
||||
/*modidfed 14.11.2016|18.01.2018 by msyu - display:inline-block, padding-top: 0 for chrome; BUG: maxListSize IS IGNORED, use instead maxMultiMatch; chrome highlighted position correction;*/
|
||||
(function($){var B=register("searchable");B.defaults={maxListSize:100,maxMultiMatch:50,exactMatch:false,wildcards:true,ignoreCase:true,warnMultiMatch:"top {0} matches ...",warnNoMatch:"no matches ...",latency:200,zIndex:"auto"};B.execute=function(g,h){var j=null;var k=null;var l=null;if($.browser.msie&&parseInt(jQuery.browser.version)<7)return this;if(this.nodeName!="SELECT"||this.size>1)return this;var m=$(this);var n={index:-1,options:null};var o="lang";var p=false;$.browser.chrome=/chrome/.test(navigator.userAgent.toLowerCase());if($.browser.chrome)$.browser.safari=false;if($.meta){g=$.extend({},options,m.data())}var q=$("<div/>");var r=$("<div/>");var t=$("<input/>");var u=$("<select/>");var x=$("<option>"+g.warnMultiMatch.replace(/\{0\}/g,g.maxMultiMatch)+"</option>").attr("disabled","true");var y=$("<option>"+g.warnNoMatch+"</option>").attr("disabled","true");var z={option:function(a){return $(u.get(0).options[a])},selected:function(){return u.find(":selected")},selectedIndex:function(a){if(a>-1)u.get(0).selectedIndex=a;return u.get(0).selectedIndex},size:function(a){u.attr("size",Math.max(2,Math.min(a,20)))},reset:function(){if((m.get(0).selectedIndex-1)==m.data("index"))return;var a=m.get(0).selectedIndex;var b=m.get(0).length;var c=Math.floor(g.maxMultiMatch/2);var d=Math.max(1,(a-c));var e=Math.min(b,Math.max(g.maxMultiMatch,(a+c)));var f=a-d;u.empty();this.size(e-d);for(var i=d;i<e;i++)u.append($(m.get(0).options[i]).clone().attr(o,i-1));if(e>g.maxMultiMatch)u.append(x);u.get(0).selectedIndex=f}};draw();var A=false;r.mouseover(function(){A=true});r.mouseout(function(){A=false});u.mouseover(function(){A=true});u.mouseout(function(){A=false});t.click(function(e){if(!p)enable(e,true);else disable(e,true)});t.blur(function(e){if(!A&&p)disable(e,true)});m.keydown(function(e){if(e.keyCode!=9&&!e.shiftKey&&!e.ctrlKey&&!e.altKey)t.click()});m.click(function(e){u.focus()});u.click(function(e){if(z.selectedIndex()<0)return;disable(e)});u.focus(function(e){t.focus()});u.blur(function(e){if(!A)disable(e,true)});u.mousemove(function(e){if($.browser.opera&&parseFloat(jQuery.browser.version)>=9.8)return true;var a=Math.floor(parseFloat(/([0-9\.]+)px/.exec(z.option(0).css("font-size"))));var b=4;if($.browser.opera)b=2.5;if($.browser.safari)b=3;if($.browser.chrome)b=3.4;a+=a/b;z.selectedIndex(Math.floor((e.pageY-u.offset().top+this.scrollTop)/a))});r.click(function(e){t.click()});t.keyup(function(e){if(jQuery.inArray(e.keyCode,new Array(9,13,16,33,34,35,36,38,40))>-1)return true;l=$.trim(t.val().toLowerCase());clearSearchTimer();j=setTimeout(searching,g.latency)});t.keydown(function(e){if(e.keyCode==9){disable(e)}if(e.shiftKey||e.ctrlKey||e.altKey)return;switch(e.keyCode){case 13:disable(e);m.focus();break;case 27:disable(e,true);m.focus();break;case 33:if(z.selectedIndex()-u.attr("size")>0){z.selectedIndex(z.selectedIndex()-u.attr("size"))}else{z.selectedIndex(0)}synchronize();break;case 34:if(z.selectedIndex()+u.attr("size")<u.get(0).options.length-1){z.selectedIndex(z.selectedIndex()+u.attr("size"))}else{z.selectedIndex(u.get(0).options.length-1)}synchronize();break;case 38:if(z.selectedIndex()>0){z.selectedIndex(z.selectedIndex()-1);synchronize()}break;case 40:if(z.selectedIndex()<u.get(0).options.length-1){z.selectedIndex(z.selectedIndex()+1);synchronize()}break;default:return true}return false});function draw(){m.css("text-decoration","none");m.width(m.outerWidth());m.height(m.outerHeight());q.css("position","relative");/*msyu*/q.css("display","inline-block");q.css("margin","0");/*/msyu*/q.css("width",m.outerWidth());if($.browser.msie)q.css("z-index",h);r.css({"position":"absolute","top":0,"left":0,"width":m.outerWidth(),"height":m.outerHeight(),/*msyu*/"background-color":"#BBEE55","opacity":"0.2"/*/msyu*/});t.attr("type","text");t.hide();t.height(m.outerHeight());t.css({"position":"absolute","top":0,"left":0,"margin":"0px","padding":"0px","outline-style":"none","border-style":"solid","border-bottom-style":"none","border-color":"transparent","background-color":"transparent"});var a=new Array();a.push("border-left-width");a.push("border-top-width");a.push("font-size");a.push("font-stretch");a.push("font-variant");a.push("font-weight");a.push("color");a.push("text-align");a.push("text-indent");a.push("text-shadow");a.push("text-transform");a.push("padding-left");a.push("padding-top");for(var i=0;i<a.length;i++)t.css(a[i],m.css(a[i]));if($.browser.msie&&parseInt(jQuery.browser.version)<8){t.css("padding","0px");t.css("padding-left","3px");t.css("border-left-width","2px");t.css("border-top-width","3px")}else if($.browser.chrome){t.height(m.innerHeight());t.css("text-transform","none");t.css("padding-left",parseFloatPx(t.css("padding-left"))+3);t.css("padding-top",/*2*/0)}else if($.browser.safari){t.height(m.innerHeight());t.css("padding-top",2);t.css("padding-left",3);t.css("text-transform","none")}else if($.browser.opera){t.height(m.innerHeight());var b=parseFloatPx(m.css("padding-left"));t.css("padding-left",b==1?b+1:b);t.css("padding-top",0)}else if($.browser.mozilla){t.css("padding-top","0px");t.css("border-top","0px");t.css("padding-left",parseFloatPx(m.css("padding-left"))+3)}else{t.css("padding-left",parseFloatPx(m.css("padding-left"))+3);t.css("padding-top",parseFloatPx(m.css("padding-top"))+1)}var c=parseFloatPx(m.css("padding-left"))+parseFloatPx(m.css("padding-right"))+parseFloatPx(m.css("border-left-width"))+parseFloatPx(m.css("border-left-width"))+23;t.width(m.outerWidth()-c);var w=m.css("width");var d=m.outerWidth();m.css("width","auto");d=d>m.outerWidth()?d:m.outerWidth();m.css("width",w);u.hide();z.size(m.get(0).length);u.css({"position":"absolute","top":m.outerHeight(),"left":0,"width":d,"border":"1px solid #333","font-weight":"normal","padding":0,"background-color":m.css("background-color"),"text-transform":m.css("text-transform")});var e=/^\d+$/.test(m.css("z-index"))?m.css("z-index"):1;if(g.zIndex&&/^\d+$/.test(g.zIndex))e=g.zIndex;r.css("z-index",(e).toString(10));t.css("z-index",(e+1).toString(10));u.css("z-index",(e+2).toString(10));m.wrap(q);m.after(r);m.after(t);m.after(u)};function enable(e,s,v){if(m.attr("disabled"))return false;m.prepend("<option />");if(typeof v=="undefined")p=!p;z.reset();synchronize();store();if(s)u.show();t.show();t.focus();t.select();m.get(0).selectedIndex=0;if(typeof e!="undefined")e.stopPropagation()};function disable(e,a){p=false;m.find(":first").remove();clearSearchTimer();t.hide();u.hide();if(typeof a!="undefined")restore();populate();if(typeof e!="undefined")e.stopPropagation()};function clearSearchTimer(){if(j!=null)clearTimeout(j)};function populate(){if(z.selectedIndex()<0||z.selected().get(0).disabled)return;m.get(0).selectedIndex=parseInt(u.find(":selected").attr(o));m.change();m.data("index",new Number(m.get(0).selectedIndex))};function synchronize(){if(z.selectedIndex()>-1&&!z.selected().get(0).disabled)t.val(u.find(":selected").text());else t.val(m.find(":selected").text())};function store(){n.index=z.selectedIndex();n.options=new Array();for(var i=0;i<u.get(0).options.length;i++)n.options.push(u.get(0).options[i])};function restore(){u.empty();for(var i=0;i<n.options.length;i++)u.append(n.options[i]);z.selectedIndex(n.index);z.size(n.options.length)};function escapeRegExp(a){var b=["/",".","*","+","?","|","(",")","[","]","{","}","\\","^","$"];var c=new RegExp("(\\"+b.join("|\\")+")","g");return a.replace(c,"\\$1")};function searching(){if(k==l){j=null;return}var a=0;k=l;u.hide();u.empty();var b=escapeRegExp(l);if(g.exactMatch)b="^"+b;if(g.wildcards){b=b.replace(/\\\*/g,".*");b=b.replace(/\\\?/g,".")}var c=null;if(g.ignoreCase)c="i";l=new RegExp(b,c);for(var i=1;i<m.get(0).length&&a<g.maxMultiMatch;i++){if(l.length==0||l.test(m.get(0).options[i].text)){var d=$(m.get(0).options[i]).clone().attr(o,i-1);if(m.data("index")==i)d.text(m.data("text"));u.append(d);a++}}if(a>=1){z.selectedIndex(0)}else if(a==0){u.append(y)}if(a>=g.maxMultiMatch){u.append(x)}z.size(a);u.show();j=null};function parseFloatPx(a){try{a=parseFloat(a.replace(/[\s]*px/,""));if(!isNaN(a))return a}catch(e){}return 0};return};function register(d){var e=$[d]={};$.fn[d]=function(b){b=$.extend(e.defaults,b);var c=this.size();return this.each(function(a){e.execute.call(this,b,c-a)})};return e}})(jQuery);
|
||||
@@ -0,0 +1,79 @@
|
||||
<!---
|
||||
Access check aka проверка доступа.
|
||||
Если доступа нет, код, заключенный внутри тега, не выполняется, текст не выводится.
|
||||
|
||||
Два варианта использования.
|
||||
1. При заданном значении действия проверяется наличие этого доступа к объекту, ответ да-нет
|
||||
2. Проверяется уровень доступа к заданному объекту
|
||||
|
||||
Для пустого объекта
|
||||
|
||||
Если задать строковый атрибут output, в переменную с таким именем запишется
|
||||
TRUE(доступ разрешен)/FALSE(доступ запрещен).
|
||||
Тег обязательно должен быть закрыт.
|
||||
---><cfsilent>
|
||||
<!--- проверка на закрытость тега - без закрытия возможна неоднозначность со вложенными тегами --->
|
||||
<cfif NOT thisTag.hasEndTag>
|
||||
<cfthrow
|
||||
type="custom" message="Unclosed AC.CFM tag found."
|
||||
detail="AC.CFM tag must be closed. Self-closed tag is acceptable, e.g.: <cfmodule template=""mod/ac.cfm"" />.">
|
||||
</cfif>
|
||||
|
||||
<cfif thisTag.ExecutionMode is 'start'>
|
||||
|
||||
<cfparam name="ATTRIBUTES.obj" type="string" default=""/><!---
|
||||
объект, к которому проверяется доступ --->
|
||||
<cfparam name="ATTRIBUTES.act" type="numeric" default="#request.PERMISSION_READ#"/><!---
|
||||
действие, которое проверяется --->
|
||||
<cfparam name="ATTRIBUTES.output" type="string" default=""/>
|
||||
<cfparam name="ATTRIBUTES.permissionOut" type="string" default=""/>
|
||||
|
||||
|
||||
|
||||
<cfset permission=request.PERMISSION_NONE/>
|
||||
|
||||
<cfif ATTRIBUTES.obj EQ "">
|
||||
<cfif #request.usrAuthenticated()#>
|
||||
<cfset permission=request.PERMISSION_WRITE/>
|
||||
<cfelse>
|
||||
<cfset permission=request.PERMISSION_READ/>
|
||||
</cfif>
|
||||
|
||||
<cfset permitted=(ATTRIBUTES.act EQ #request.PERMISSION_READ# OR #request.usrAuthenticated()#)/>
|
||||
|
||||
<cfelse>
|
||||
|
||||
<cftry>
|
||||
<cfset permitted=(len(ATTRIBUTES.obj) GT 0)>
|
||||
|
||||
<!---*** Максимальный доступ для перечисленных объектов и ролей
|
||||
Можно подумать о минимальном--->
|
||||
<cfquery name="qACL" datasource="#request.DS#">
|
||||
select coalesce(max(permission),0) as permission
|
||||
from usr_role ur
|
||||
join acl on acl.role_id=ur.role_id
|
||||
where ur.usr_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#request.usr_id#">
|
||||
and acl.obj in (<cfqueryparam cfsqltype="cf_sql_varchar" value="#ATTRIBUTES.obj#" list="true">)
|
||||
</cfquery>
|
||||
|
||||
<cfset permitted=(qACL.permission GE ATTRIBUTES.act)>
|
||||
<cfset permission=#qACL.permission#/>
|
||||
|
||||
<cfcatch type="database">
|
||||
<cfset permitted="Yes"/><!---***--->
|
||||
<cfrethrow/>
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
|
||||
</cfif>
|
||||
|
||||
<cfif len(ATTRIBUTES.output)>
|
||||
<cfset setVariable("CALLER.#ATTRIBUTES.output#", permitted)><!---boolean--->
|
||||
</cfif>
|
||||
<cfif len(ATTRIBUTES.permissionOut)>
|
||||
<cfset setVariable("CALLER.#ATTRIBUTES.permissionOut#", permission)><!---integer 0 1 2--->
|
||||
</cfif>
|
||||
|
||||
<cfif NOT permitted><cfexit method="EXITTAG"></cfif>
|
||||
</cfif><!---thisTag.ExecutionMode is 'start'--->
|
||||
</cfsilent>
|
||||
@@ -0,0 +1,12 @@
|
||||
<!---v0.2 19:01 06.10.2020
|
||||
---><cfparam name="ATTRIBUTES.contenttype"/>
|
||||
<cfswitch expression=#ATTRIBUTES.contenttype#>
|
||||
<cfcase value="text/plain"><img src="img/mimetype/text.png"/></cfcase>
|
||||
<cfcase value="text/html"><img src="img/mimetype/html.png"/></cfcase>
|
||||
<cfcase value="application/pdf"><img src="img/mimetype/pdf.png"/></cfcase>
|
||||
<cfcase value="image/gif,image/png,image/jpeg"><img src="img/mimetype/image.png"/></cfcase>
|
||||
<cfcase value="application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"><img src="img/mimetype/excel.png"/></cfcase>
|
||||
<cfcase value="application/vnd.ms-powerpoint"><img src="img/mimetype/powerpoint.png"/></cfcase>
|
||||
<cfcase value="application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"><img src="img/mimetype/word.png"/></cfcase>
|
||||
<cfdefaultcase><img src="img/mimetype/document.png"/></cfdefaultcase>
|
||||
</cfswitch><cfexit method="exittag"/>
|
||||
@@ -0,0 +1,23 @@
|
||||
<cfsilent>
|
||||
<cfparam name="ATTRIBUTES.name"/>
|
||||
<cfparam name="ATTRIBUTES.value" default="1"/>
|
||||
|
||||
<cfif structKeyExists(ATTRIBUTES,"checked")>
|
||||
<cfset checked=!(ATTRIBUTES.checked EQ "0" OR ATTRIBUTES.checked EQ "")/>
|
||||
<cfelse>
|
||||
<cfset checked=!(ATTRIBUTES.container[ATTRIBUTES.name] EQ "0" OR ATTRIBUTES.container[ATTRIBUTES.name] EQ "")/>
|
||||
</cfif>
|
||||
|
||||
<cfparam name="ATTRIBUTES.suffix" default=""/>
|
||||
<cfparam name="ATTRIBUTES.id" default="#ATTRIBUTES.name##ATTRIBUTES.suffix#"/>
|
||||
<cfparam name="ATTRIBUTES.disabled" type="boolean" default="No"/>
|
||||
<cfset attributeList="name,value,checked,container,suffix,id,disabled"/>
|
||||
|
||||
</cfsilent><cfoutput><input type="checkbox" name="#ATTRIBUTES.name#"<!---
|
||||
---><cfif len(ATTRIBUTES.id)> id=#ATTRIBUTES.id#</cfif> value="#ATTRIBUTES.value#"<!---
|
||||
---><cfif checked> checked="checked"</cfif><!---
|
||||
---><cfif ATTRIBUTES.disabled> disabled="disabled"</cfif><!---
|
||||
passthrough additional attributes
|
||||
---><cfloop collection=#ATTRIBUTES# item="attr"><!---
|
||||
---><cfif NOT listFindNoCase(attributeList,attr)> #attr#="#structFind(ATTRIBUTES,attr)#"</cfif><!---
|
||||
---></cfloop>/></cfoutput><cfexit method="exittag"/>
|
||||
@@ -0,0 +1,30 @@
|
||||
<cfparam name="ATTRIBUTES.lang" type="string" default=""/>
|
||||
<cfparam name="request.language" type="string" default=""/>
|
||||
<cfif len(ATTRIBUTES.lang) AND #ATTRIBUTES.lang# NEQ #request.language#>
|
||||
<cfexit method="exittag"/>
|
||||
</cfif>
|
||||
|
||||
<cfif thisTag.executionMode IS "end">
|
||||
|
||||
<!--- <cfloop collection=#CALLER# item="item">
|
||||
<cfset structInsert(variables, item, CALLER[item], false)/>
|
||||
</cfloop> --->
|
||||
|
||||
<cfassociate basetag="cf_table" datacollection="columns"/>
|
||||
<cfset attributeList=""/> <!--- *** сделать проброс атрибутов --->
|
||||
<cfparam name="thisTag.th" type="array" default=#[{content="",field=""}]#/><!---контейнер для данных вложенного элемента TH. Предусмотрен только один элемент массива, остальные игнорируются--->
|
||||
<!---<cfparam name="thisTag.td" type="array" default=#[{content="",field=""}]#/>--->
|
||||
<cfparam name="thisTag.td" type="array" default=#thisTag.th#/><!---контейнер для данных вложенного элемента TD. Предусмотрен только один элемент массива, остальные игнорируются--->
|
||||
<!---Зачем массив? - потому что массив вложенных тегов, а у нас считается только первый вложенный тег TD--->
|
||||
|
||||
<cfset ATTRIBUTES.td=#thisTag.td#/><!---поле, видное включающему тегу table в коллекции columns--->
|
||||
<cfset ATTRIBUTES.th=#thisTag.th#/><!---поле, видное включающему тегу table в коллекции columns--->
|
||||
<cfset ATTRIBUTES.content=thisTag.generatedContent/>
|
||||
|
||||
<cfparam name="ATTRIBUTES.field" default="#thisTag.td[1].field#"/><!---***---><!---настоящий атрибут - имя поля запроса (query) для ВЫВОДА, может задаваться как атрибут тега--->
|
||||
<cfparam name="ATTRIBUTES.formatter" type="function" default=#function (x) {return x;}#/>
|
||||
<cfparam name="ATTRIBUTES.sortable" type="boolean" default=true/>
|
||||
<cfparam name="ATTRIBUTES.visible" type="boolean" default=true/>
|
||||
<cfparam name="ATTRIBUTES.columnOrder" type="integer" default=0/>
|
||||
<!--- Желательное поведение сортировки колонок: для некоторых колонок указан порядок, на этом месте они и оказываются. Не указан - идут в порядке появления в коде. Если 2 колонки с одним порядком сортировки, первой выводится та, которая первая по тексту. --->
|
||||
</cfif>
|
||||
@@ -0,0 +1,46 @@
|
||||
<cfsilent>
|
||||
<cfimport prefix="c" taglib="."/>
|
||||
|
||||
|
||||
<!---*** идея включить титул в метаданные была не совсем пустой, но когда титул определяется в селекте, это не слишком удобно --->
|
||||
<cfassociate basetag="cf_grid_head" datacollection="headersArray"/>
|
||||
<cfset envelope=getBaseTagData('cf_grid_head',1)/>
|
||||
|
||||
<cfparam name="ATTRIBUTES.title" type="string" default="#envelope.ATTRIBUTES.titleMap[ATTRIBUTES.name].title#"/>
|
||||
<cfparam name="ATTRIBUTES.name" type="string"/><!--- Заголовок указвается на том поле, по которому будет сортировка, а не на том, которе отображается --->
|
||||
<cfparam name="ATTRIBUTES.arrows" type="boolean" default="Yes"/>
|
||||
|
||||
|
||||
|
||||
<cfset attributeList="name,arrows,title"/>
|
||||
|
||||
<!--- В данном случае реализован подход: дополнительные атрибуты передаются вниз.
|
||||
Другой вариант - создавать атрибут extra, в который писать суффикс QueryString.
|
||||
Первый подход, использованный здесь, позволяет иметь доступ к дополнительным атрибутам, но непонятно, зачем - ведь их имена все равно неизвестны.
|
||||
Очевидный минус этого подхода - возможный конфликт имен с именами существующих атрибутов --->
|
||||
<cfset extraAttributes=structNew()/>
|
||||
|
||||
<!--- дополнительные атрибуты родительского тега--->
|
||||
<cfif StructKeyExists(envelope, "extraAttributes") AND isStruct(envelope.extraAttributes)>
|
||||
<cfloop collection=#envelope.extraAttributes# item="attr">
|
||||
<cfif NOT listFindNoCase(attributeList, attr)><!--- проверка относительно локальных атрибутов, чтобы их не перетереть--->
|
||||
<cfset val="#structFind(envelope.extraAttributes, attr)#"/>
|
||||
<cfif IsSimpleValue(val)>
|
||||
<cfset structInsert(extraAttributes, attr, val)/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<cfloop collection=#ATTRIBUTES# item="attr">
|
||||
<cfif NOT listFindNoCase(attributeList, attr)>
|
||||
<cfset val="#structFind(ATTRIBUTES, attr)#"/>
|
||||
<cfif IsSimpleValue(val)>
|
||||
<cfset structInsert(extraAttributes, attr, val, "Yes")/><!--- локальные атрибуты перетрут родительские --->
|
||||
</cfif>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
|
||||
|
||||
</cfsilent><cfif thisTag.executionMode is "end"><cfoutput>#ATTRIBUTES.title#
|
||||
<cfif ATTRIBUTES.arrows><c:order_arrows sortArray=#envelope.ATTRIBUTES.sortArray# n=#envelope.ATTRIBUTES.titleMap[ATTRIBUTES.name].ordinal# attributeCollection=#extraAttributes#/></cfif></cfoutput></cfif>
|
||||
@@ -0,0 +1,178 @@
|
||||
<!--- combobox
|
||||
v3.1 23.10.2020 support of list in multiple selection
|
||||
v3.0 12.08.2016 ATTRIBUTES.readonly
|
||||
v2.1 04.05.2016 ATTRIBUTES.disabled
|
||||
v2 с форматным выводом
|
||||
|
||||
---><cfprocessingdirective suppresswhitespace="true">
|
||||
<!---
|
||||
<cfparam name="ATTRIBUTES.query" type="query"/>
|
||||
<cfparam name="ATTRIBUTES.queryString" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.list" type="string"/>
|
||||
--->
|
||||
<cfparam name="ATTRIBUTES.DS" type="string" default="#request.DS#"/>
|
||||
<cfparam name="ATTRIBUTES.combo"/><!--- имя контрола (name)--->
|
||||
<cfparam name="ATTRIBUTES.key"/><!--- Имя ключевого поля---><!--- ограничение: не поддерживаем составные ключи --->
|
||||
<cfparam name="ATTRIBUTES.display" default=""/><!--- имя поля резалтсета --->
|
||||
<cfparam name="ATTRIBUTES.displayf" default=""/><!--- форматный вывод, поля резалтсета писать: ##field##, например "*##field1##:##field2##*" --->
|
||||
<cfparam name="ATTRIBUTES.selected" default=""/><!--- в случае base64 - завернуто в base64--->
|
||||
<cfparam name="ATTRIBUTES.base64" default="No"/><!---*** это архитектурная ошибка. Base64 is url unsafe. Но поскольку все передается POST-ом, обычно не проявляется --->
|
||||
<cfparam name="ATTRIBUTES.disabled" type="boolean" default="No"/>
|
||||
<cfparam name="ATTRIBUTES.style_selector" default=""/>
|
||||
<cfparam name="ATTRIBUTES.style_spec" type="struct" default=#structNew()#/>
|
||||
<cfparam name="ATTRIBUTES.class_selector" default=""/>
|
||||
<cfparam name="ATTRIBUTES.class_spec" type="struct" default=#structNew()#/>
|
||||
<cfparam name="ATTRIBUTES.flag_disabled" type="string" default=""/><!--- проверяется на > 0. Возможно, не следует отключать выбранное значение --->
|
||||
<cfparam name="ATTRIBUTES.readonly" type="boolean" default="false"/><!--- в случае readonly выводится текст и скрытое поле с ID, если множественное выделение, то надо наверно выводить все выделенные элементы? --->
|
||||
<cfparam name="ATTRIBUTES.extra" type="string" default=""/><!--- --->
|
||||
|
||||
|
||||
<cfset attributeList="template,query,queryString,combo,key,display,displayf,selected,empty,DS,base64,disabled,style_selector,style_spec,class_selector,class_spec,flag_disabled,readonly,extra"/>
|
||||
|
||||
<cffunction name="escape64" returnType="string">
|
||||
<cfargument name="val" type="string">
|
||||
<cfif #ATTRIBUTES.base64#>
|
||||
<cfreturn ToBase64(val)>
|
||||
<cfelse>
|
||||
<cfreturn val>
|
||||
</cfif>
|
||||
</cffunction>
|
||||
|
||||
<cffunction name="isSelected" returnType="boolean">
|
||||
<!--- tests for presense of key (second arg) in passed array (first arg) or, if sel is simple value just compares key and sel.
|
||||
Used for checking against multiple alternatives like "save" OR "saveAndClose"
|
||||
--->
|
||||
<cfargument name="sel">
|
||||
<cfargument name="key">
|
||||
<cfscript>
|
||||
if (isArray(sel)) {
|
||||
for(i=1; i <= ArrayLen(sel); i++){
|
||||
if (sel[i]==key) {return true;}
|
||||
}
|
||||
return false;
|
||||
} else { //считаем, что из сложных типов тут бывает только массив
|
||||
if (!isSimpleValue(sel)) {return false;}
|
||||
/*return (sel == key);*/
|
||||
return listFind(sel,key);
|
||||
}
|
||||
</cfscript>
|
||||
</cffunction>
|
||||
|
||||
<cffunction name="strSelected" returnType="string">
|
||||
<cfargument name="sel">
|
||||
<cfargument name="key">
|
||||
<!---unsupported in CF8: <cfreturn (isSelected(sel,key)? " selected" : "")>--->
|
||||
<cfif isSelected(sel,key)>
|
||||
<cfreturn " selected">
|
||||
<cfelse>
|
||||
<cfreturn "">
|
||||
</cfif>
|
||||
</cffunction>
|
||||
|
||||
<!--- функция условного обертывания --->
|
||||
<cffunction name="w" returnType="string">
|
||||
<cfargument name="prefix"/>
|
||||
<cfargument name="input"/>
|
||||
<cfargument name="suffix" default=""/>
|
||||
|
||||
<cfif len(input) GT 0>
|
||||
<cfreturn "#prefix##input##suffix#"/>
|
||||
<cfelse>
|
||||
<cfreturn ""/>
|
||||
</cfif>
|
||||
</cffunction>
|
||||
|
||||
<cffunction name="strAttribute" returnType="string">
|
||||
<!---returns formatted string ' attribute="value"',
|
||||
where attribute name is the first argument,
|
||||
and value is taken from passed structure(third argument) by key (second argument)--->
|
||||
<cfargument name="name"/>
|
||||
<cfargument name="selector"/>
|
||||
<cfargument name="spec" type="struct"/>
|
||||
|
||||
<cfif StructKeyExists(spec, selector)>
|
||||
<cfreturn ' #name#="#structFind(spec, selector)#"'/>
|
||||
<cfelse>
|
||||
<cfreturn "">
|
||||
</cfif>
|
||||
</cffunction>
|
||||
|
||||
<!--- ---------------------------------------------------------------------------------- --->
|
||||
|
||||
<cfif structKeyExists(ATTRIBUTES,"query")>
|
||||
<cfset qSel=ATTRIBUTES.query>
|
||||
<cfelseif structKeyExists(ATTRIBUTES,"queryString")>
|
||||
<cfquery name="qSel" datasource="#ATTRIBUTES.DS#">
|
||||
#preserveSingleQuotes(ATTRIBUTES.queryString)#
|
||||
</cfquery>
|
||||
<cfelseif structKeyExists(ATTRIBUTES,"list")>
|
||||
<cfset qSel=#queryNew("item")#/>
|
||||
<cfloop list=#ATTRIBUTES.list# item="item">
|
||||
<cfset queryAddRow(qSel,{"item":"#item#"})/>
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
|
||||
<!--- parse class specifications--->
|
||||
<cfscript>
|
||||
</cfscript>
|
||||
|
||||
<cfif ATTRIBUTES.readonly>
|
||||
<cfif isArray(ATTRIBUTES.selected)>
|
||||
<cfset selectedList=ArrayToList(ATTRIBUTES.selected)/>
|
||||
<cfelse>
|
||||
<cfset selectedList=ATTRIBUTES.selected/>
|
||||
</cfif>
|
||||
|
||||
<cfquery name="qSelFiltered" dbtype="query">
|
||||
select * from qSel where <cfif len(selectedList)>#ATTRIBUTES.key# in (#selectedList#)<cfelse>1=0</cfif>
|
||||
</cfquery>
|
||||
|
||||
<cfoutput>
|
||||
<div class="textbox-disabled" style="display:inline-block;"<cfloop collection=#ATTRIBUTES# item="attr"><!---
|
||||
---><cfif NOT listFindNoCase(attributeList,attr)> #attr#="#structFind(ATTRIBUTES,attr)#"</cfif><!---
|
||||
---></cfloop>>
|
||||
<cfif qSelFiltered.recordCount GT 0>
|
||||
<cfloop query="qSelFiltered"><!---
|
||||
---><cfset key=evaluate("#ATTRIBUTES.key#")/><!---
|
||||
---><cfset key=trim(escape64(key))/><!---
|
||||
---><div><input type="hidden" name="#ATTRIBUTES.combo#" value="#key#"/>#Evaluate(ATTRIBUTES.display)#<cfset Evaluate("WriteOutput('#ATTRIBUTES.displayf#')")/></div>
|
||||
</cfloop>
|
||||
<cfelseif isDefined("ATTRIBUTES.empty")>
|
||||
<input type="hidden" name="#ATTRIBUTES.combo#" value="#ATTRIBUTES.empty#"/><!-- #ATTRIBUTES.combo#: nothing selected -->
|
||||
|
||||
<cfelse>
|
||||
|
||||
</cfif>
|
||||
</div>
|
||||
</cfoutput>
|
||||
<cfelse><!--- ATTRIBUTES.readonly --->
|
||||
|
||||
<cfoutput>
|
||||
<select name="#ATTRIBUTES.combo#"<!---
|
||||
passthrough additional attributes
|
||||
---><cfloop collection=#ATTRIBUTES# item="attr"><!---
|
||||
---><cfif NOT listFindNoCase(attributeList,attr)> #attr#="#structFind(ATTRIBUTES,attr)#"</cfif><!---
|
||||
---></cfloop><cfif ATTRIBUTES.disabled> disabled="disabled"</cfif><cfif len(ATTRIBUTES.extra)>#ATTRIBUTES.extra#</cfif>>
|
||||
<cfif isDefined("ATTRIBUTES.empty")>
|
||||
<option value="#ATTRIBUTES.empty#"></option><!--- *** Надо было делать не пустое, а дефолтное значение, чтобы можно было ввести, например, {N/A, -1} --->
|
||||
</cfif>
|
||||
<cfloop query=qSel>
|
||||
<cfset key=evaluate("#ATTRIBUTES.key#")/><!--- в контексте запроса, поэтому находится в цикле! *** не самый лучший способ в смысле производительности --->
|
||||
<cfset key=trim(escape64(key))/>
|
||||
<cfset str_sel=strSelected(ATTRIBUTES.selected, key)/>
|
||||
<option value="#key#"#str_sel#<!---
|
||||
---><cfif len(ATTRIBUTES.style_selector) GT 0>#strAttribute("style",
|
||||
Evaluate(ATTRIBUTES.style_selector),ATTRIBUTES.style_spec)#</cfif><!---
|
||||
---><cfif len(ATTRIBUTES.class_selector) GT 0>#strAttribute("class", Evaluate(ATTRIBUTES.class_selector),ATTRIBUTES.class_spec)#</cfif><!---
|
||||
---><cfif len(ATTRIBUTES.flag_disabled) GT 0><cfif Evaluate(ATTRIBUTES.flag_disabled) GT 0> disabled="1"</cfif></cfif><!---
|
||||
--->>#Evaluate(ATTRIBUTES.display)#<cfset Evaluate("WriteOutput('#ATTRIBUTES.displayf#')")/></option>
|
||||
</cfloop>
|
||||
</select>
|
||||
</cfoutput>
|
||||
</cfif>
|
||||
|
||||
</cfprocessingdirective><cfexit method="EXITTAG"/>
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<cfsilent>
|
||||
<cfparam name="ATTRIBUTES.name"/>
|
||||
|
||||
<cfif structKeyExists(ATTRIBUTES,"value")>
|
||||
<cfset value=#ATTRIBUTES.value#/>
|
||||
<cfelse>
|
||||
<cfset value=#ATTRIBUTES.container[ATTRIBUTES.name]#/>
|
||||
</cfif>
|
||||
|
||||
<cfparam name="ATTRIBUTES.suffix" default=""/>
|
||||
<cfparam name="ATTRIBUTES.id" default="#ATTRIBUTES.name##ATTRIBUTES.suffix#"/>
|
||||
<cfparam name="ATTRIBUTES.format" default="YYYY-MM-DD"/>
|
||||
<cfparam name="ATTRIBUTES.size" default="#len(ATTRIBUTES.format)#"/>
|
||||
<cfparam name="ATTRIBUTES.disabled" type="boolean" default="No"/>
|
||||
<cfset attributeList="name,value,container,suffix,id,format,size,disabled"/>
|
||||
|
||||
</cfsilent><cfoutput><input type="text" name="#ATTRIBUTES.name#"<cfif len(ATTRIBUTES.id)> id=#ATTRIBUTES.id#</cfif> value="#dateFormat(value, ATTRIBUTES.format)#" size="#ATTRIBUTES.size#"<cfif ATTRIBUTES.disabled> disabled="disabled"</cfif><!---
|
||||
passthrough additional attributes
|
||||
---><cfloop collection=#ATTRIBUTES# item="attr"><!---
|
||||
---><cfif NOT listFindNoCase(attributeList,attr)> #attr#="#structFind(ATTRIBUTES,attr)#"</cfif><!---
|
||||
---></cfloop>/></cfoutput><cfexit method="exittag"/>
|
||||
@@ -0,0 +1,29 @@
|
||||
<cfsilent>
|
||||
<cfparam name="ATTRIBUTES.name"/>
|
||||
|
||||
<cfif structKeyExists(ATTRIBUTES,"value")>
|
||||
<cfset value=#ATTRIBUTES.value#/>
|
||||
<cfelse>
|
||||
<cfset value=#ATTRIBUTES.container[ATTRIBUTES.name]#/>
|
||||
</cfif>
|
||||
|
||||
<cfparam name="ATTRIBUTES.suffix" default=""/>
|
||||
<cfparam name="ATTRIBUTES.id" default="#ATTRIBUTES.name##ATTRIBUTES.suffix#"/>
|
||||
<cfparam name="ATTRIBUTES.dformat" default="YYYY-MM-DD"/>
|
||||
<cfparam name="ATTRIBUTES.tformat" default="HH:MM"/>
|
||||
<cfparam name="ATTRIBUTES.size" default="#len(ATTRIBUTES.dformat)+len(ATTRIBUTES.tformat)+1#"/>
|
||||
<cfparam name="ATTRIBUTES.disabled" type="boolean" default="No"/>
|
||||
<cfparam name="ATTRIBUTES.timeFirst" type="boolean" default="No"/>
|
||||
|
||||
<cfif ATTRIBUTES.timeFirst>
|
||||
<cfset value="#timeFormat(value, ATTRIBUTES.tformat)# #dateFormat(value, ATTRIBUTES.dformat)#"/>
|
||||
<cfelse>
|
||||
<cfset value="#dateFormat(value, ATTRIBUTES.dformat)# #timeFormat(value, ATTRIBUTES.tformat)#"/>
|
||||
</cfif>
|
||||
<cfset attributeList="name,value,container,suffix,id,dformat,tformat,size,disabled"/>
|
||||
|
||||
</cfsilent><cfoutput><input type="text" name="#ATTRIBUTES.name#"<cfif len(ATTRIBUTES.id)> id=#ATTRIBUTES.id#</cfif> value="#value#" size="#ATTRIBUTES.size#"<cfif ATTRIBUTES.disabled> disabled="disabled"</cfif><!---
|
||||
passthrough additional attributes
|
||||
---><cfloop collection=#ATTRIBUTES# item="attr"><!---
|
||||
---><cfif NOT listFindNoCase(attributeList,attr)> #attr#="#structFind(ATTRIBUTES,attr)#"</cfif><!---
|
||||
---></cfloop>/></cfoutput><cfexit method="exittag"/>
|
||||
@@ -0,0 +1,18 @@
|
||||
<!---moved to layout--->
|
||||
<!---<cfif thisTag.executionMode IS "end" OR NOT thisTag.hasEndTag>
|
||||
<cfparam name="ATTRIBUTES.backUrl" type="string" default="."/>
|
||||
<cfparam name="ATTRIBUTES.enable" type="boolean" default="No"/>
|
||||
<cfoutput>
|
||||
<div class="row" style="margin:0px;">
|
||||
<div class="col-sm-3" style="padding: 0px;">
|
||||
<button type="submit" name="save" class="btn btn-secondary" style="width: 100%; padding: 6px 0px;"<cfif NOT ATTRIBUTES.enable> disabled</cfif>>#request.i18("Сохранить","Save")#</button>
|
||||
</div>
|
||||
<div class="col-sm-6" style="padding: 0px 5px;">
|
||||
<button type="submit" name="saveAndClose" class="btn btn-secondary" style="width: 100%; padding: 6px 0px;"<cfif NOT ATTRIBUTES.enable> disabled</cfif>>#request.i18("Сохранить и закрыть","Save and Close")#</button>
|
||||
</div>
|
||||
<div class="col-sm-3" style="padding: 0px;">
|
||||
<button type="button" name="close" class="btn btn-secondary" style="width: 100%; padding: 6px 0px;" onClick="document.location.href='#ATTRIBUTES.backUrl#'">#request.i18("Закрыть","Close")#</button>
|
||||
</div>
|
||||
</div>
|
||||
</cfoutput>
|
||||
</cfif>--->
|
||||
@@ -0,0 +1,18 @@
|
||||
<cfsilent>
|
||||
<cfparam name="ATTRIBUTES.titleMap" default=#structNew()#/>
|
||||
<cfparam name="ATTRIBUTES.sortArray" default=#arrayNew(1)#/>
|
||||
|
||||
<cfset attributeList="titleMap,sortArray"/>
|
||||
|
||||
<cfset extraAttributes=structNew()/>
|
||||
<cfloop collection=#ATTRIBUTES# item="attr">
|
||||
<cfif NOT listFindNoCase(attributeList, attr)>
|
||||
<cfset val="#structFind(ATTRIBUTES, attr)#"/>
|
||||
<cfif IsSimpleValue(val)>
|
||||
<cfset structInsert(extraAttributes, attr, val)/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
|
||||
</cfsilent><!---
|
||||
---><cfif thisTag.executionMode is "start"><tr><cfelseif thisTag.executionMode is "end"></tr></cfif>
|
||||
@@ -0,0 +1,11 @@
|
||||
<cfsilent>
|
||||
<cfparam name="ATTRIBUTES.canWrite" type="boolean" default="Yes"/>
|
||||
<cfif NOT ATTRIBUTES.canWrite>
|
||||
<cfexit method="exitTag"/>
|
||||
</cfif>
|
||||
<cfparam name="ATTRIBUTES.entity"/>
|
||||
<cfparam name="ATTRIBUTES.key" default="#ATTRIBUTES.entity#_id"/>
|
||||
<cfparam name="ATTRIBUTES.extra" default=""/>
|
||||
<cfparam name="ATTRIBUTES.fwx"/>
|
||||
<cfparam name="ATTRIBUTES.title" default="создать"/>
|
||||
</cfsilent><cfoutput><a href="#ATTRIBUTES.entity#.cfm?#ATTRIBUTES.key#=-1<cfif len(ATTRIBUTES.extra)>&#ATTRIBUTES.extra#</cfif>&#ATTRIBUTES.fwx#" title="#ATTRIBUTES.title#" class="add"></a></cfoutput><cfexit method="exitTag"/>
|
||||
@@ -0,0 +1,10 @@
|
||||
<cfsilent>
|
||||
<cfparam name="ATTRIBUTES.canWrite" type="boolean" default="Yes"/>
|
||||
<cfif NOT ATTRIBUTES.canWrite>
|
||||
<cfexit method="exitTag"/>
|
||||
</cfif>
|
||||
<cfparam name="ATTRIBUTES.entity"/>
|
||||
<cfparam name="ATTRIBUTES.key" default="#ATTRIBUTES.entity#_id"/>
|
||||
<cfparam name="ATTRIBUTES.id"/>
|
||||
<cfparam name="ATTRIBUTES.fwx"/>
|
||||
</cfsilent><cfoutput><a href="#ATTRIBUTES.entity#_del.cfm?#ATTRIBUTES.key#=#ATTRIBUTES.id#&#ATTRIBUTES.fwx#" title="удалить" name="#ATTRIBUTES.id#" class="del"></a></cfoutput><cfexit method="exitTag"/>
|
||||
@@ -0,0 +1,9 @@
|
||||
<!---***deprecated. Use link_view_edit---><cfsilent>
|
||||
<cfparam name="ATTRIBUTES.canWrite" type="boolean" default="Yes"/>
|
||||
<cfparam name="ATTRIBUTES.entity"/>
|
||||
<cfparam name="ATTRIBUTES.key" default="#ATTRIBUTES.entity#_id"/>
|
||||
<cfparam name="ATTRIBUTES.id"/>
|
||||
<cfparam name="ATTRIBUTES.fwx"/>
|
||||
<cfparam name="ATTRIBUTES.title_edit" default="редактировать"/>
|
||||
<cfparam name="ATTRIBUTES.title_view" default="просмотреть"/>
|
||||
</cfsilent><cfoutput><a href="#ATTRIBUTES.entity#.cfm?#ATTRIBUTES.key#=#ATTRIBUTES.id#&#ATTRIBUTES.fwx#" name="#ATTRIBUTES.id#" <cfif ATTRIBUTES.canWrite>title="#ATTRIBUTES.title_edit#" class="edit"<cfelse>title="#ATTRIBUTES.title_view#" class="view"</cfif>></a></cfoutput><cfexit method="exitTag"/>
|
||||
@@ -0,0 +1,6 @@
|
||||
<cfsilent>
|
||||
<cfparam name="ATTRIBUTES.entity"/>
|
||||
<cfparam name="ATTRIBUTES.key" default="#ATTRIBUTES.entity#_id"/>
|
||||
<cfparam name="ATTRIBUTES.id"/>
|
||||
<cfparam name="ATTRIBUTES.fwx"/>
|
||||
</cfsilent><cfoutput><a href="#ATTRIBUTES.entity#.cfm?#ATTRIBUTES.key#=#ATTRIBUTES.id#&#ATTRIBUTES.fwx#" title="просмотреть" name="#ATTRIBUTES.id#" class="view"></a></cfoutput><cfexit method="exitTag"/>
|
||||
@@ -0,0 +1,9 @@
|
||||
<cfsilent>
|
||||
<cfparam name="ATTRIBUTES.canWrite" type="boolean" default="Yes"/>
|
||||
<cfparam name="ATTRIBUTES.entity"/>
|
||||
<cfparam name="ATTRIBUTES.key" default="#ATTRIBUTES.entity#_id"/>
|
||||
<cfparam name="ATTRIBUTES.id"/>
|
||||
<cfparam name="ATTRIBUTES.fwx"/>
|
||||
<cfparam name="ATTRIBUTES.title_edit" default="редактировать"/>
|
||||
<cfparam name="ATTRIBUTES.title_view" default="просмотреть"/>
|
||||
</cfsilent><cfoutput><a href="#ATTRIBUTES.entity#.cfm?#ATTRIBUTES.key#=#ATTRIBUTES.id#&#ATTRIBUTES.fwx#" name="#ATTRIBUTES.id#" <cfif ATTRIBUTES.canWrite>title="#ATTRIBUTES.title_edit#" class="edit"<cfelse>title="#ATTRIBUTES.title_view#" class="view"</cfif>></a></cfoutput><cfexit method="exitTag"/>
|
||||
@@ -0,0 +1,25 @@
|
||||
<cfprocessingdirective suppressWhitespace="YES"><cfsilent>
|
||||
|
||||
<cfparam name="ATTRIBUTES.page" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.queryString" type="string" default=""/>
|
||||
<cfparam name="ATTRIBUTES.acl" type="string" default=""/>
|
||||
<cfparam name="ATTRIBUTES.label" type="string" default=""/>
|
||||
|
||||
<cfif structKeyExists(#ATTRIBUTES#,"external")>
|
||||
<cfset class="menu-item-ext"/>
|
||||
<cfset target=' target="_blank"'/>
|
||||
<cfelse>
|
||||
<cfset class="menu-item"/>
|
||||
<cfset target=''/>
|
||||
</cfif>
|
||||
|
||||
</cfsilent><!---
|
||||
---><cfmodule template="../ac.cfm" obj="#ATTRIBUTES.acl#"><cfif NOT (request.thisPage EQ ATTRIBUTES.page)><cfsilent>
|
||||
<cfif len(ATTRIBUTES.queryString)>
|
||||
<cfset pageUrl="#ATTRIBUTES.page#?#ATTRIBUTES.queryString#"/>
|
||||
<cfelse>
|
||||
<cfset pageUrl="#ATTRIBUTES.page#"/>
|
||||
</cfif>
|
||||
</cfsilent><cfoutput><li class="#class#"><a href="#pageUrl#"#target#>#ATTRIBUTES.label#</a></li></cfoutput>
|
||||
<cfelse><cfoutput><li class="selected">#ATTRIBUTES.label#</li></cfoutput></cfif><!---
|
||||
---></cfmodule></cfprocessingdirective><cfexit method="EXITTAG"/>
|
||||
@@ -0,0 +1,6 @@
|
||||
<cfsilent>
|
||||
<cfparam name="ATTRIBUTES.targetid"/>
|
||||
<cfparam name="ATTRIBUTES.enabled" default="Yes"/>
|
||||
<cfparam name="ATTRIBUTES.suffix" default=""/>
|
||||
<cfparam name="ATTRIBUTES.title" default="Сейчас"/>
|
||||
</cfsilent><cfoutput><button onclick="document.getElementById(#ATTRIBUTES.targetid#).value=""></</cfoutput><cfexit method="exittag"/>
|
||||
@@ -0,0 +1,36 @@
|
||||
<cfsilent>
|
||||
<cfparam name="ATTRIBUTES.n" type="numeric"/>
|
||||
<cfset attributeList="n,sortArray"/>
|
||||
|
||||
<cfset img_up="arr_up.png"/>
|
||||
<cfset img_dn="arr_dn.png"/>
|
||||
<cfset HIGHLIGHTED_CNT=2/>
|
||||
|
||||
<cfif isDefined("ATTRIBUTES.sortArray")>
|
||||
<cfset i=1>
|
||||
<cfloop condition="i LE HIGHLIGHTED_CNT AND i LE arrayLen(ATTRIBUTES.sortArray)">
|
||||
<cftry>
|
||||
<cfif ATTRIBUTES.sortArray[i].fld EQ ATTRIBUTES.n>
|
||||
<cfif ATTRIBUTES.sortArray[i].asc>
|
||||
<cfset img_up="arr_up#i#.png">
|
||||
<cfelse>
|
||||
<cfset img_dn="arr_dn#i#.png">
|
||||
</cfif>
|
||||
</cfif>
|
||||
<cfcatch type="Any"></cfcatch>
|
||||
</cftry>
|
||||
<cfset i=i+1>
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<cfset extra_query_string=""/>
|
||||
<cfloop collection=#ATTRIBUTES# item="attr">
|
||||
<cfif NOT listFindNoCase(attributeList,attr)>
|
||||
<cfset val="#structFind(ATTRIBUTES,attr)#"/>
|
||||
<cfif IsSimpleValue(val)>
|
||||
<cfset extra_query_string="#extra_query_string#&#attr#=#val#"/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
|
||||
</cfsilent><cfoutput><a href="?sort=#ATTRIBUTES.n#a#extra_query_string#" class="noprint" style="padding:2px;" title="по возрастанию"><img src="img/#img_up#" alt="по возрастанию"></a><a href="?sort=#ATTRIBUTES.n#d#extra_query_string#" title="по убыванию"><img src="img/#img_dn#" alt="по убыванию"></a></cfoutput><cfexit method="exittag"/>
|
||||
@@ -0,0 +1,80 @@
|
||||
<cfparam name="nStart" type="integer" default="1"/>
|
||||
|
||||
<cfparam name="ATTRIBUTES.recordCount" type="integer"/>
|
||||
<cfparam name="ATTRIBUTES.recordsPerPage" type="integer"/>
|
||||
<cfparam name="ATTRIBUTES.thisPage" type="string" default=""/>
|
||||
<cfparam name="ATTRIBUTES.addtionalUrlParams" type="string" default=""/>
|
||||
<cfparam name="ATTRIBUTES.self" type="string" default=""/>
|
||||
<!---<cfparam name="ATTRIBUTES.fwx" type="string" default=""/>--->
|
||||
<cfparam name="ATTRIBUTES.output" type="string" default="paginator"/>
|
||||
|
||||
<!--- Исключение: рассчитанный индекс страницы превышает количество существующих страниц - надо возвращаться на первую --->
|
||||
|
||||
<cfset nPages = Int((ATTRIBUTES.recordCount-1)/ATTRIBUTES.recordsPerPage)+1/>
|
||||
<cfset nCurrentPage = Int((nStart-1)/ATTRIBUTES.recordsPerPage)+1/>
|
||||
<cfif nStart GT ATTRIBUTES.recordCount>
|
||||
<cfset nStart=1/>
|
||||
</cfif>
|
||||
|
||||
<cfset UrlSuffix=""/>
|
||||
<cfif len(ATTRIBUTES.addtionalUrlParams) GT 0>
|
||||
<cfset UrlSuffix="&#ATTRIBUTES.addtionalUrlParams#"/>
|
||||
</cfif>
|
||||
<cfif len(ATTRIBUTES.self) GT 0>
|
||||
<cfset UrlSuffix="&track=#ATTRIBUTES.self#"/>
|
||||
</cfif>
|
||||
|
||||
<cfset somePages=3/>
|
||||
|
||||
<cfsavecontent variable="pages">
|
||||
<cfif ATTRIBUTES.recordCount GT ATTRIBUTES.recordsPerPage>
|
||||
<cfset doMerge = false/>
|
||||
<cfloop index="i" from="1" to="#nPages#">
|
||||
<cfset nPageStartRecordNum=(i-1)*ATTRIBUTES.recordsPerPage+1>
|
||||
<!---
|
||||
схема, которая обеспечивает дихотомический поиск
|
||||
первые несколько страниц (не менее 2)
|
||||
если есть разрыв - многоточие
|
||||
посередине
|
||||
если есть разрыв - многоточие
|
||||
несколько страниц до текушей
|
||||
текущую без ссылки
|
||||
несколько страниц после текущей
|
||||
если есть разрыв - многоточие
|
||||
посередине
|
||||
если есть разрыв - многоточие
|
||||
последние несколько страниц
|
||||
--->
|
||||
<!---Можно сделать на многоточии ссылку на середину интервала!--->
|
||||
<!---Хочется добиться, чтобы при хождении вперед-назад значения повторялись--->
|
||||
<!---забавный эффект, когда остается разрыв в 1 страницу, а там все равно многоточие--->
|
||||
<cfoutput>
|
||||
<cfif i NEQ nCurrentPage>
|
||||
<cfif i GT somePages AND (nCurrentPage-i) GT somePages>
|
||||
<cfif NOT doMerge><!---*** неуклюже--->
|
||||
<cfset nMidPage = ceiling(nCurrentPage/2)/>
|
||||
<cfset nMidStartRecord = (nMidPage-1)*ATTRIBUTES.recordsPerPage+1/>
|
||||
<a href="#ATTRIBUTES.thisPage#?nStart=#nMidStartRecord##UrlSuffix#" title="#nMidPage#">...</a> <cfset doMerge=true/>
|
||||
</cfif>
|
||||
<cfelseif (i-nCurrentPage) GT somePages AND (nPages-i) GT somePages>
|
||||
<cfif NOT doMerge>
|
||||
<cfset nMidPage = ceiling((nCurrentPage+nPages)/2)/>
|
||||
<cfset nMidStartRecord = (nMidPage-1)*ATTRIBUTES.recordsPerPage+1/>
|
||||
<a href="#ATTRIBUTES.thisPage#?nStart=#nMidStartRecord##UrlSuffix#" title="#nMidPage#">...</a> <cfset doMerge=true/>
|
||||
</cfif>
|
||||
<cfelse>
|
||||
<a href="#ATTRIBUTES.thisPage#?nStart=#nPageStartRecordNum##UrlSuffix#">#i#</a>
|
||||
<cfset doMerge=false/>
|
||||
</cfif>
|
||||
<cfelse>
|
||||
<b>#i#</b>
|
||||
</cfif>
|
||||
</cfoutput>
|
||||
</cfloop>
|
||||
</cfif>
|
||||
</cfsavecontent>
|
||||
|
||||
<cfset "CALLER.#ATTRIBUTES.output#.links"=#pages#/>
|
||||
<cfset "CALLER.#ATTRIBUTES.output#.recordsPerPage"=#ATTRIBUTES.recordsPerPage#/>
|
||||
|
||||
<cfexit method="exittag"/>
|
||||
@@ -0,0 +1,154 @@
|
||||
<cfimport prefix="c" taglib="."/>
|
||||
<cfif thisTag.executionMode IS "end">
|
||||
<!--- <cfloop collection=#CALLER# item="item">
|
||||
<cfset structInsert(variables, item, CALLER[item], false)/>
|
||||
</cfloop> --->
|
||||
|
||||
<cfparam name="ATTRIBUTES.query" type="query"/>
|
||||
<cfparam name="ATTRIBUTES.recordsPerPage" type="integer" default="500"/>
|
||||
<cfparam name="ATTRIBUTES.nStart" type="integer" default="1"/>
|
||||
<cfparam name="ATTRIBUTES.titleMap" type="struct" default=srtuctNew()/><!---for definition see: field_set.cfm--->
|
||||
<cfparam name="ATTRIBUTES.sortArray" type="array" default=arrayNew(1)/>
|
||||
|
||||
<cfset tableAttributeList="query,recordsPerPage,nStart,titleMap,sortArray"/>
|
||||
<cfset colAttributeList="lang,th,td,content,field,formatter,sortable,visible,columnOrder"/>
|
||||
<cfset tdAttributeList="content,field"/>
|
||||
|
||||
|
||||
<cfparam name="thisTag.columns" type="array"/>
|
||||
|
||||
|
||||
<cffunction name=reorderColumns output="No">
|
||||
<!--- Вариант сортировки. Вынимаем все элементы с указанным порядком в отдельную коллекцию,
|
||||
после чего вставляем их в оставшуюся коллекцию на указанные позиции.
|
||||
нет смысла делать вид, что мы реализуем что-то универсальное
|
||||
(поле для сортировки в совершенно конкретном поле структуры в массиве),
|
||||
поэтому ничего не передаем в аргументах, спокойно ссылаемся на окружение--->
|
||||
<cfset var tmpOrderedIndexes=ArrayNew(1)/>
|
||||
<cfset var tmpUnorderedIndexes=ArrayNew(1)/>
|
||||
|
||||
<cfloop from=1 to=#arrayLen(thisTag.columns)# index="i">
|
||||
<cfif thisTag.columns[i].columnOrder GT 0>
|
||||
<cfset arrayAppend(tmpOrderedIndexes,i)/>
|
||||
<cfelse>
|
||||
<cfset arrayAppend(tmpUnorderedIndexes,i)/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
|
||||
<cfloop from=#arrayLen(tmpOrderedIndexes)# to=1 step=-1 index="i">
|
||||
<!--- counting up-down preserves entry order for equal columnOrders --->
|
||||
<cfset var pos=max(min(thisTag.columns[tmpOrderedIndexes[i]].columnOrder, len(tmpUnorderedIndexes)+1),1)/>
|
||||
<cfset arrayInsertAt(tmpUnorderedIndexes,pos,tmpOrderedIndexes[i])/>
|
||||
</cfloop>
|
||||
|
||||
<cfset var sortedColumns=ArrayNew(1)/>
|
||||
<cfloop from=1 to=#arrayLen(tmpUnorderedIndexes)# index="i">
|
||||
<cfset sortedColumns[i]=thisTag.columns[tmpUnorderedIndexes[i]]/>
|
||||
</cfloop>
|
||||
|
||||
<cfreturn sortedColumns/>
|
||||
</cffunction>
|
||||
|
||||
<cfset sortedColumns=reorderColumns()/>
|
||||
|
||||
<cfset thisTag.generatedContent=""/>
|
||||
|
||||
<table<!--- passthrough additional attributes
|
||||
---><cfoutput><cfloop collection=#ATTRIBUTES# item="attr"><!---
|
||||
---><cfif NOT listFindNoCase(tableAttributeList,attr)<!--- AND isSimpleValue(structFind(ATTRIBUTES,attr))--->> #attr#="#structFind(ATTRIBUTES,attr)#"</cfif><!---
|
||||
---></cfloop></cfoutput>>
|
||||
<thead>
|
||||
<tr>
|
||||
<cfloop array=#sortedColumns# index="column">
|
||||
<cfset th=column.th[1]/>
|
||||
<th<!--- атрибуты колонки передаются в TH, хотя это выглядит не очень нужным --->
|
||||
<cfloop collection=#column# item="colAttr">
|
||||
<cfif NOT listFindNoCase(colAttributeList,colAttr)><cfoutput>#colAttr#="#structFind(column,colAttr)#" </cfoutput></cfif>
|
||||
</cfloop>>
|
||||
<cfif len(column.field) AND column.sortable>
|
||||
<c:order_arrows sortArray=#ATTRIBUTES.sortArray# n=#ATTRIBUTES.titleMap[column.field].ordinal#<!--- attributeCollection=#extraAttributes#--->/>
|
||||
</cfif>
|
||||
<cfif len(th.content)>
|
||||
<cfset Evaluate("WriteOutput('#th.content#')")/>
|
||||
<cfelseif len(column.field)>
|
||||
<cfif structKeyExists(ATTRIBUTES.titleMap[column.field],"title")>
|
||||
<cfoutput>#ATTRIBUTES.titleMap[column.field].title#</cfoutput>
|
||||
</cfif>
|
||||
</cfif>
|
||||
</th>
|
||||
</cfloop>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<cfoutput query=#ATTRIBUTES.query# maxrows=#ATTRIBUTES.recordsPerPage# startrow=#ATTRIBUTES.nStart#>
|
||||
<tr>
|
||||
<cfloop array=#sortedColumns# index="column">
|
||||
<cfset td=column.td[1]/>
|
||||
<td<!--- Если нужно передать атрибут в TD, можно ввести тег <C:TD class="r"/> только как плейсхолдер для атрибутов, а поле будет получено от колонки --->
|
||||
<cfloop collection=#td# item="tdAttr">
|
||||
<cfif NOT listFindNoCase(tdAttributeList,tdAttr)>#tdAttr#="#structFind(td,tdAttr)#" </cfif>
|
||||
</cfloop>
|
||||
><cfif len(td.content)><cfset Evaluate("WriteOutput('#td.content#')")/><!---#td.content#--->
|
||||
<cfelseif len(td.field)>#ATTRIBUTES.query[td.field][currentRow]#
|
||||
<cfelseif len(column.field)>#column.formatter(ATTRIBUTES.query[column.field][currentRow])#
|
||||
</cfif></td>
|
||||
</cfloop>
|
||||
</tr>
|
||||
</cfoutput>
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
<!--- <cfdump var=#variables#/> --->
|
||||
</cfif>
|
||||
<!--- <cfexit method="exitTag"/> --->
|
||||
|
||||
<cfscript>
|
||||
/**
|
||||
* Sorts an array of structures based on a key in the structures.
|
||||
*
|
||||
* @param aofS Array of structures.
|
||||
* @param key Key to sort by.
|
||||
* @param sortOrder Order to sort by, asc or desc.
|
||||
* @param sortType Text, textnocase, or numeric.
|
||||
* @param delim Delimiter used for temporary data storage. Must not exist in data. Defaults to a period.
|
||||
* @return Returns a sorted array.
|
||||
* @author Nathan Dintenfass (nathan@changemedia.com)
|
||||
* @version 1, December 10, 2001
|
||||
*/
|
||||
function arrayOfStructsSort(aOfS,key){
|
||||
//by default we'll use an ascending sort
|
||||
var sortOrder = "asc";
|
||||
//by default, we'll use a textnocase sort
|
||||
var sortType = "textnocase";
|
||||
//by default, use ascii character 30 as the delim
|
||||
var delim = ".";
|
||||
//make an array to hold the sort stuff
|
||||
var sortArray = arraynew(1);
|
||||
//make an array to return
|
||||
var returnArray = arraynew(1);
|
||||
//grab the number of elements in the array (used in the loops)
|
||||
var count = arrayLen(aOfS);
|
||||
//make a variable to use in the loop
|
||||
var ii = 1;
|
||||
//if there is a 3rd argument, set the sortOrder
|
||||
if(arraylen(arguments) GT 2)
|
||||
sortOrder = arguments[3];
|
||||
//if there is a 4th argument, set the sortType
|
||||
if(arraylen(arguments) GT 3)
|
||||
sortType = arguments[4];
|
||||
//if there is a 5th argument, set the delim
|
||||
if(arraylen(arguments) GT 4)
|
||||
delim = arguments[5];
|
||||
//loop over the array of structs, building the sortArray
|
||||
for(ii = 1; ii lte count; ii = ii + 1)
|
||||
sortArray[ii] = aOfS[ii][key] & delim & ii;
|
||||
//now sort the array
|
||||
arraySort(sortArray,sortType,sortOrder);
|
||||
//now build the return array
|
||||
for(ii = 1; ii lte count; ii = ii + 1)
|
||||
returnArray[ii] = aOfS[listLast(sortArray[ii],delim)];
|
||||
//return the array
|
||||
return returnArray;
|
||||
}
|
||||
</cfscript>
|
||||
@@ -0,0 +1,15 @@
|
||||
<cfif thisTag.executionMode IS "end">
|
||||
<!--- <cfloop collection=#CALLER# item="item">
|
||||
<cfset structInsert(variables, item, CALLER[item], false)/>
|
||||
</cfloop> --->
|
||||
|
||||
<cfassociate basetag="cf_column" datacollection="td"/>
|
||||
<cfset attributeList="field"/>
|
||||
<cfparam name="ATTRIBUTES.field" default=""/>
|
||||
<cfset ATTRIBUTES.content=thisTag.generatedContent/>
|
||||
</cfif>
|
||||
<!---<cfparam name="ATTRIBUTES.lang" type="string" default=""/>
|
||||
<cfparam name="request.language" type="string" default=""/>
|
||||
<cfif len(ATTRIBUTES.lang) AND #ATTRIBUTES.lang# NEQ #request.language#>
|
||||
<cfexit method="exittag"/>
|
||||
</cfif>--->
|
||||
@@ -0,0 +1,20 @@
|
||||
<cfsilent>
|
||||
<cfparam name="ATTRIBUTES.name"/>
|
||||
|
||||
<cfif structKeyExists(ATTRIBUTES,"value")>
|
||||
<cfset value=#ATTRIBUTES.value#/>
|
||||
<cfelse>
|
||||
<cfset value=#ATTRIBUTES.container[ATTRIBUTES.name]#/>
|
||||
</cfif>
|
||||
|
||||
<cfparam name="ATTRIBUTES.suffix" default=""/>
|
||||
<cfparam name="ATTRIBUTES.id" default="#ATTRIBUTES.name##ATTRIBUTES.suffix#"/>
|
||||
<cfparam name="ATTRIBUTES.size" default=""/>
|
||||
<cfparam name="ATTRIBUTES.disabled" type="boolean" default="No"/>
|
||||
<cfset attributeList="name,value,container,suffix,id,size,disabled"/>
|
||||
|
||||
</cfsilent><cfoutput><input type="text" name="#ATTRIBUTES.name#"<cfif len(ATTRIBUTES.id)> id=#ATTRIBUTES.id#</cfif> value="#value#"<cfif len(ATTRIBUTES.size)> size="#ATTRIBUTES.size#"</cfif><cfif ATTRIBUTES.disabled> disabled="disabled"</cfif><!---
|
||||
passthrough additional attributes
|
||||
---><cfloop collection=#ATTRIBUTES# item="attr"><!---
|
||||
---><cfif NOT listFindNoCase(attributeList,attr)> #attr#="#structFind(ATTRIBUTES,attr)#"</cfif><!---
|
||||
---></cfloop>/></cfoutput><cfexit method="exittag"/>
|
||||
@@ -0,0 +1,6 @@
|
||||
<cfif thisTag.executionMode IS "end">
|
||||
<cfassociate basetag="cf_column" datacollection="th"/>
|
||||
<cfset attributeList="field"/>
|
||||
<cfparam name="ATTRIBUTES.field" default=""/>
|
||||
<cfset ATTRIBUTES.content=thisTag.generatedContent/>
|
||||
</cfif>
|
||||
@@ -0,0 +1,21 @@
|
||||
<cfsilent>
|
||||
<cfparam name="ATTRIBUTES.name"/>
|
||||
|
||||
<cfif structKeyExists(ATTRIBUTES,"value")>
|
||||
<cfset value=#ATTRIBUTES.value#/>
|
||||
<cfelse>
|
||||
<cfset value=#ATTRIBUTES.container[ATTRIBUTES.name]#/>
|
||||
</cfif>
|
||||
|
||||
<cfparam name="ATTRIBUTES.suffix" default=""/>
|
||||
<cfparam name="ATTRIBUTES.id" default="#ATTRIBUTES.name##ATTRIBUTES.suffix#"/>
|
||||
<cfparam name="ATTRIBUTES.format" default="HH:MM"/>
|
||||
<cfparam name="ATTRIBUTES.size" default="#len(ATTRIBUTES.format)#"/>
|
||||
<cfparam name="ATTRIBUTES.disabled" type="boolean" default="No"/>
|
||||
<cfset attributeList="name,value,container,suffix,id,format,size,disabled"/>
|
||||
|
||||
</cfsilent><cfoutput><input type="text" name="#ATTRIBUTES.name#"<cfif len(ATTRIBUTES.id)> id=#ATTRIBUTES.id#</cfif> value="#timeFormat(value, ATTRIBUTES.format)#" size="#ATTRIBUTES.size#"<cfif ATTRIBUTES.disabled> disabled="disabled"</cfif><!---
|
||||
passthrough additional attributes
|
||||
---><cfloop collection=#ATTRIBUTES# item="attr"><!---
|
||||
---><cfif NOT listFindNoCase(attributeList,attr)> #attr#="#structFind(ATTRIBUTES,attr)#"</cfif><!---
|
||||
---></cfloop>/></cfoutput><cfexit method="exittag"/>
|
||||
@@ -0,0 +1,401 @@
|
||||
<!---
|
||||
bean v0.96
|
||||
msyu@mail.ru
|
||||
2013-08-29 v0.1
|
||||
2013-09-04 v0.2 tested with CF8 and Railo
|
||||
2013-10-14 added meta attribute - can now export each parameter metadata
|
||||
2014-12-26 POST-GET read-pass-save
|
||||
2015-01-19 read-pass-save, добавлен formmarker, убрано определение режима по POST-GET
|
||||
2015-01-19 убран formmarker, упразднен режим init (используется pass)
|
||||
2015-07-16 добавлен passmarker для перерисовки формы с введенными значениями
|
||||
2015-10-02 поддержка составных ключей
|
||||
2015-10-09 v0.9 если задано value параметра, считается, что он hasInput (корректно работает в составе ключа)
|
||||
2015-11-25 добавлен readmarker, mode (принудительная установка режима)
|
||||
2015-11-26 добавлен mode=skip
|
||||
2016-09-01 изменена трактовка processingMode. Теперь понимается как исходная команда, фиксируется до начала действий. Можно использовать для управления
|
||||
2018-09-16 добавлена ограниченная поддержка нецелых первичных ключей (idstamp)
|
||||
child tag: param
|
||||
to save - should send parameter with name from list ATTRIBUTES.savemarker (value doesn't matter) in FORM, e.g. URL.save="trtrtr", while ATTRIBUTES.savemarker="save,saveAndClose"; for multiple forms on a page (and bean tags) different savemarkers should be used
|
||||
2022-01-06 PostgreSQL (MSSQL incompatibility because of scope_identity)
|
||||
2024-04-13 PostgreSQL GUID, autoincrement by RETURNING
|
||||
2024-09-05 added status.recordExists (*** при вставке принудительно устанавливаем в true, веря, что если insert прошел, то запись появилась)
|
||||
--->
|
||||
|
||||
<!---
|
||||
Автогенерируемое поле GUID можно заполнять несколькими способами
|
||||
- как default или init bean/param, но это не очень удобно, потому что может потеряться удобный признак новой записи - инвалидный ключ, и сейчас init-default взаимодействуют некорректно, по крайней мере, неочевидно
|
||||
- генерируемое в БД (например, как default). Для PostgreSQL значение возвращается через Returning, как это делать для других БД, непонятно.
|
||||
- можно генерировать при сохранении в bean, но для этого нужно расширение синтаксиса, зато не зависит от БД (*** TODO)
|
||||
--->
|
||||
|
||||
<cfif thisTag.ExecutionMode is 'end'>
|
||||
<cfparam name="ATTRIBUTES.readmarker" type="string" default="read"/><!--- наличие в FORM или URL поля с таким именем воспринимается как команда перечитывания. Имеет приоритет перед savemarker, passmarker. Можно передавать несколько вариантов списком через запятую. --->
|
||||
<cfparam name="ATTRIBUTES.savemarker" type="string" default="save,saveAndClose"/><!--- наличие в FORM или URL поля с таким именем воспринимается как команда сохранения. Обычно это имя кнопки. Можно передавать несколько вариантов списком через запятую. --->
|
||||
<cfparam name="ATTRIBUTES.passmarker" type="string" default="pass"/><!--- наличие в FORM или URL поля с таким именем воспринимается как команда заполнить форму отправленными данными без перечитывания. В форме такое поле обычно есть. Команда сохранения имеет приоритет перед пробросом. Можно передавать несколько вариантов списком через запятую. --->
|
||||
<cfparam name="ATTRIBUTES.datasource" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.table" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.output" type="string"/><!--- имя переменной (структуры) области CALLER, в которую возвращаются данные. Обычно "d" --->
|
||||
<cfparam name="ATTRIBUTES.info" type="string" default=""/>
|
||||
<cfparam name="ATTRIBUTES.meta" type="string" default=""/>
|
||||
<cfparam name="ATTRIBUTES.status" type="string"/><!--- имя переменной (структуры) области CALLER, в которую возвращается статуc. Обычно "status" --->
|
||||
<cfparam name="ATTRIBUTES.readonly" type="boolean" default="No"/>
|
||||
<cfparam name="ATTRIBUTES.mode" type="string" default=""/> <!--- Принудительный режим read|pass|save|skip. Имеет приоритет перед маркерами --->
|
||||
|
||||
<cfif ATTRIBUTES.mode EQ "skip">
|
||||
<!---<cfset SetVariable("CALLER.#ATTRIBUTES.status#.errorState", false) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#.errorMessage", "") />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#.processingMode", "skip") />--->
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#", CreateObject("component","status").init(false,"","skip",false))/><!--- *** можно было не создавать компонент, он все равно не имеет логики, это map из нескольких полей. С другой стороны, хоть поля декларированы. Не очень удобно, что в отдельном файле --->
|
||||
<cfexit method="exittag"/>
|
||||
</cfif>
|
||||
|
||||
<cfset validationOk="true" />
|
||||
<cfset errorState="false" />
|
||||
<cfset errorMessage="" />
|
||||
<cfset warningState="false" />
|
||||
<cfset warningMessage="" />
|
||||
<!---<cfset keyField=""/>
|
||||
<cfset keyValue=""/>--->
|
||||
<cfset hasAutoIncrement="false"/>
|
||||
<cfset autoIncrementKeyIndex=0/><!--- сгенерированное значение присваивается первому полю, отмеченному как autoincrement --->
|
||||
<cfset recordExists = "false"/>
|
||||
<cfset keyInvalid = "false"/>
|
||||
|
||||
<!--- разбор метаданных - поиск ключа --->
|
||||
<!--- поддерживаются только простые целочисленные ключи --->
|
||||
<cfset keys=arrayNew(1)/>
|
||||
<!--- *** почему где-то копируем поля param в key, а где-то прямо цикл по параметрам --->
|
||||
<!--- коллекция thistag.params формируется вложенными тегами param --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<!---<cfdump var=#param#/>--->
|
||||
<cfif structFind(param,"key")><!--- not just structKeyExists! Not exisis, OR exists, but FALSE! --->
|
||||
<cfset key = structNew()/>
|
||||
<cfset ArrayAppend(keys, key)/>
|
||||
|
||||
<cfset key.name = param.param />
|
||||
<cfset key.field = param.field />
|
||||
<cfset key.type = param.type />
|
||||
<cfset key.value = param.value /><!--- должно уже быть присвоено --->
|
||||
<cfset key.null = param.null />
|
||||
|
||||
<cfif param.errorState OR !param.hasInput>
|
||||
<cfset keyInvalid="true"/>
|
||||
<cfelse>
|
||||
<cfset keyInvalid=!checkDataFormat(param.type, param.value)/>
|
||||
</cfif>
|
||||
|
||||
<cfif !hasAutoIncrement><!--- take only first field with "autoincrement" attribute--->
|
||||
<cfif structFind(param, "autoincrement")>
|
||||
<cfset hasAutoIncrement = true/>
|
||||
<cfset autoIncrementKeyIndex = arrayLen(keys)/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
</cfif>
|
||||
</cfloop>
|
||||
<!---<cfdump var=#keys#/>--->
|
||||
|
||||
<cfif !keyInvalid>
|
||||
<!--- *** дублируется похожий cfqueryparam, перепутал один раз --->
|
||||
<cfquery name="qCheckExistence" datasource="#ATTRIBUTES.datasource#">
|
||||
select count(*) as cnt
|
||||
from #ATTRIBUTES.table#
|
||||
where 1=1
|
||||
<cfloop array=#keys# index="key">
|
||||
AND #key.field#=<cfqueryparam cfsqltype="#sqlType(key.type)#" value="#key.value#" null="#key.null#"/>
|
||||
</cfloop>
|
||||
</cfquery>
|
||||
<cfset recordExists = (qCheckExistence.cnt GT 0)/>
|
||||
<!--- <cfdump var=#qCheckExistence#/> --->
|
||||
<cfelse>
|
||||
<cfset recordExists = "false"/>
|
||||
</cfif>
|
||||
|
||||
<cfif listFindNoCase("read,pass,save", ATTRIBUTES.mode)>
|
||||
<cfset processingMode=ATTRIBUTES.mode/>
|
||||
|
||||
<cfelse>
|
||||
|
||||
<!--- ищем команду принудительного перечитывания --->
|
||||
<cfset doRead = false/>
|
||||
<cfloop list=#ATTRIBUTES.readmarker# index="marker">
|
||||
<cfif structKeyExists(FORM,"#marker#") OR structKeyExists(URL,"#marker#")>
|
||||
<cfset doRead = true/>
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
|
||||
<!--- ищем команду сохранения --->
|
||||
<cfset doSave = false/>
|
||||
<cfif !doRead AND !ATTRIBUTES.readonly>
|
||||
<cfloop list=#ATTRIBUTES.savemarker# index="marker">
|
||||
<cfif structKeyExists(FORM,"#marker#") OR structKeyExists(URL,"#marker#")>
|
||||
<cfset doSave = true/>
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<!--- ищем команду проброса --->
|
||||
<cfset doPass = false/>
|
||||
<cfif !doRead AND !doSave>
|
||||
<cfloop list=#ATTRIBUTES.passmarker# index="marker">
|
||||
<cfif structKeyExists(FORM,"#marker#") OR structKeyExists(URL,"#marker#")>
|
||||
<cfset doPass = true/>
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<!--- определяем режим --->
|
||||
<cfif doRead>
|
||||
<cfset processingMode="read"/>
|
||||
<cfelseif doSave>
|
||||
<cfset processingMode="save"/>
|
||||
<cfelse>
|
||||
<cfif doPass OR !recordExists>
|
||||
<cfset processingMode="pass"/>
|
||||
<cfelse>
|
||||
<cfset processingMode="read"/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
</cfif>
|
||||
|
||||
<cfset initialProcessingMode = processingMode/>
|
||||
|
||||
|
||||
<!---debug <cfoutput>processingMode:#processingMode#</cfoutput>--->
|
||||
<!--- ---------------------------------------------------------- --->
|
||||
|
||||
<!---*** Необходимость вставки (против апдейта) определяется по существованию записи. Это небезопасно, поскольку наличие записи с ключом -1 может прекратить создание новых записей. Конечно, можно добавить констрейнт на ключевое поле, но это лишняя зависимость.
|
||||
Можно явно передавать команду вставки, а не заморачиваться с анализом ключа. Просто традиционно мы сигнализировали необходимость вставки, передавая невалидное значение ключа, обычно -1. Для целочисленных ключей можно было бы просто проверять положительность (что всю жизнь отлично работало), но хочется более общего.
|
||||
--->
|
||||
|
||||
<cfif processingMode IS "save"> <!--- validation lookup --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
|
||||
<cfif !param.key>
|
||||
<cfif param.warningState>
|
||||
<cfif NOT warningState><!--- catch the first fault --->
|
||||
<cfset warningMessage=param.warningMessage />
|
||||
</cfif>
|
||||
<cfset warningState="true" />
|
||||
</cfif>
|
||||
|
||||
<cfif param.errorState>
|
||||
<cfif NOT errorState><!--- catch the first fault --->
|
||||
<cfset errorMessage=param.errorMessage />
|
||||
</cfif>
|
||||
<cfset errorState="true" />
|
||||
<cfset validationOk="false"/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
<cfif errorState>
|
||||
<!--- clear warning state --->
|
||||
<cfset warningMessage="" />
|
||||
<cfset warningState=false />
|
||||
<!--- finish lookup --->
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
|
||||
</cfloop>
|
||||
|
||||
<cfif validationOk>
|
||||
<!---<cfdump var=#param#/> --->
|
||||
<cftry>
|
||||
<cfif recordExists><!--- update. Наличие keyValue гарантировано (уверен) --->
|
||||
<cfquery name="qSave" datasource="#ATTRIBUTES.datasource#" result="qSaveResult">
|
||||
update #ATTRIBUTES.table# set
|
||||
<cfset i=0 />
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<!--- не обновляем ключевые поля --->
|
||||
<cfif NOT (StructFind(param, "key")
|
||||
OR StructFind(param, "autoincrement")
|
||||
OR StructFind(param, "readonly")
|
||||
OR StructFind(param, "skipUpdate")
|
||||
)><cfif i++ GT 0>,</cfif>
|
||||
#param.field#=<cfqueryparam cfsqltype="#sqlType(param.type)#" value="#param.value#" null="#param.null#"/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
where 1=1
|
||||
<cfloop array=#keys# index="key">
|
||||
AND #key.field#=<cfqueryparam cfsqltype="#sqlType(key.type)#" value="#key.value#"/>
|
||||
</cfloop>
|
||||
</cfquery>
|
||||
<!---<cfdump var=#qSaveResult#/>--->
|
||||
<cfelse><!--- insert --->
|
||||
<cfquery name="qSave" datasource="#ATTRIBUTES.datasource#">
|
||||
insert into #ATTRIBUTES.table#
|
||||
(
|
||||
<cfset i=0 />
|
||||
<!--- ключевые поля без автоинкремента попадают в insert! --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfif NOT (StructFind(param, "autoincrement")
|
||||
OR StructFind(param, "readonly")
|
||||
OR StructFind(param, "skipInsert")
|
||||
)><cfif i++ GT 0>,</cfif>
|
||||
#param.field#
|
||||
</cfif>
|
||||
</cfloop>
|
||||
)
|
||||
values
|
||||
(
|
||||
<cfset i=0 />
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfif NOT (StructFind(param, "autoincrement")
|
||||
OR StructFind(param, "readonly")
|
||||
OR StructFind(param, "skipInsert")
|
||||
)><cfif i++ GT 0>,</cfif>
|
||||
<cfqueryparam cfsqltype="#sqlType(param.type)#" value="#param.value#" null="#param.null#"/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
)
|
||||
<!--- /*MSSQL syntax*/
|
||||
<cfif hasAutoIncrement>
|
||||
select scope_identity() as id;
|
||||
</cfif>
|
||||
--->
|
||||
<!---*** PostgreSQL incompatible hack follows--->
|
||||
<cfif hasAutoIncrement>
|
||||
returning #thistag.params[autoIncrementKeyIndex].field# as id;
|
||||
</cfif>;
|
||||
</cfquery>
|
||||
<!--- <cfdump var=#qSave#/> --->
|
||||
<cfif hasAutoIncrement>
|
||||
<cfset keys[autoIncrementKeyIndex].value=qSave.id/>
|
||||
</cfif>
|
||||
<!--- здесь можно установить recordExists=true, если твердо верить, что вставка прошла, если нет исключения --->
|
||||
<cfset recordExists=true/>
|
||||
</cfif>
|
||||
<!--- recordExists --->
|
||||
|
||||
|
||||
<cfset processingMode="read"/>
|
||||
|
||||
<cfcatch type="database">
|
||||
<cfset errorState="true" />
|
||||
<cfset errorMessage="Ошибка при записи в базу данных. #cfcatch.message# #cfcatch.detail#" />
|
||||
<cfset processingMode="pass" />
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
<cfelse><!--- (not) validationOk --->
|
||||
<cfset processingMode="pass"/>
|
||||
</cfif><!--- validationOk --->
|
||||
|
||||
</cfif><!--- processingMode EQ "save" --->
|
||||
|
||||
<!--- экспортируем данные --->
|
||||
<cfswitch expression=#processingMode#>
|
||||
<cfcase value="read">
|
||||
<cfquery name="qRead" datasource="#ATTRIBUTES.datasource#">
|
||||
select
|
||||
<cfset i=0 />
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfset i=i+1/>
|
||||
#param.field#<cfif i LT ArrayLen(thistag.params)>,</cfif>
|
||||
</cfloop>
|
||||
from #ATTRIBUTES.table#
|
||||
where 1=1
|
||||
<cfloop array=#keys# index="key">
|
||||
/*#sqlType(key.type)#*/
|
||||
AND #key.field#=<cfqueryparam cfsqltype="#sqlType(key.type)#" value="#key.value#" null="#key.null#"/>
|
||||
</cfloop>
|
||||
</cfquery>
|
||||
|
||||
<cfloop array=#thistag.params# index="param"><!--- *** --->
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.output#.#param.param#", structFind(qRead, #param.field#)) />
|
||||
</cfloop>
|
||||
</cfcase>
|
||||
|
||||
|
||||
<cfcase value="pass"><!--- заполнить все поля. Если значения переданы в форме или урле, тег параметра обязан их разобрать и подставить, в противном случае подставить инит-значения. Инит-значение по умолчанию пустая строка, дефолт по умолчанию тоже пустая строка --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<!--- <cfdump var=#param#/>--->
|
||||
<cfif param.hasInput>
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.output#.#param.param#", param.submittedValue) /><!---*** дефект: 03.12.2015, передаваемая строкой, при обработке dateFormat неправильно парсится --->
|
||||
<cfelse>
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.output#.#param.param#", param.init) />
|
||||
</cfif>
|
||||
</cfloop>
|
||||
</cfcase>
|
||||
|
||||
<cfdefaultcase>
|
||||
</cfdefaultcase>
|
||||
|
||||
</cfswitch>
|
||||
|
||||
<cfif len(ATTRIBUTES.info)><!--- экспортируем дополнительные сведения--->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.submittedValue", #param.submittedValue#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.errorState", #param.errorState#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.errorMessage", #param.errorMessage#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.warningState", #param.warningState#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.warningMessage", #param.warningMessage#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.null", #param.null#) />
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<cfif len(ATTRIBUTES.meta)><!--- экспортируем метаданные параметра - для инвариантности вызовов --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.param", #param.param#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.field", #param.field#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.type", #param.type#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.displayName", #param.displayName#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.default", #param.default#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.size", #param.size#) />
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#", CreateObject("component","status").init(errorState,errorMessage,initialProcessingMode,recordExists))/>
|
||||
|
||||
</cfif><!--- thisTag.ExecutionMode is 'end'--->
|
||||
|
||||
<!--- quick and dirty --->
|
||||
<cffunction name="sqlType">
|
||||
<cfargument name="type"/>
|
||||
|
||||
<cfswitch expression=#type#>
|
||||
<cfcase value="guid,uuid,idstamp"><cfreturn "CF_SQL_OTHER"/></cfcase><!--- hack for PostgreSQL uuid --->
|
||||
<cfdefaultcase><cfreturn uCase("CF_SQL_#type#")/></cfdefaultcase>
|
||||
</cfswitch>
|
||||
</cffunction>
|
||||
|
||||
<cffunction name="checkDataFormat">
|
||||
<cfargument name="type"/>
|
||||
<cfargument name="value"/>
|
||||
|
||||
<cfswitch expression=#type#>
|
||||
<cfcase value="integer"><cfreturn isValid("integer",value)/></cfcase>
|
||||
<cfcase value="guid,uuid,idstamp"><cfreturn isValid("guid",value)/></cfcase>
|
||||
<cfdefaultcase><cfreturn true/></cfdefaultcase>
|
||||
</cfswitch>
|
||||
</cffunction>
|
||||
|
||||
|
||||
<!--- //quick and dirty
|
||||
function sqlType(type) {
|
||||
switch (type) {
|
||||
case "guid,idstamp": return "CF_SQL_OTHER"; /*hack for PostgreSQL uuid*/ /*break not needed!*/
|
||||
default: return uCase("CF_SQL_#type#");
|
||||
}
|
||||
}
|
||||
|
||||
function checkDataFormat(type,value) {
|
||||
switch (type) {
|
||||
case "integer": return isValid("integer",value); /*break not needed!*/
|
||||
case "guid,uuid,idstamp": return isValid("guid",value); /*break not needed!*/ /*INCORRECT cfscript switch-case does not support lists*/
|
||||
default: return true;
|
||||
}
|
||||
} --->
|
||||
<cfscript>
|
||||
//readonly может транслироваться в pass!
|
||||
function translateMode(readonly) {
|
||||
if (readonly) {
|
||||
return "read";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
</cfscript>
|
||||
@@ -0,0 +1,400 @@
|
||||
<!---
|
||||
bean v0.95
|
||||
msyu@mail.ru
|
||||
2013-08-29 v0.1
|
||||
2013-09-04 v0.2 tested with CF8 and Railo
|
||||
2013-10-14 added meta attribute - can now export each parameter metadata
|
||||
2014-12-26 POST-GET read-pass-save
|
||||
2015-01-19 read-pass-save, добавлен formmarker, убрано определение режима по POST-GET
|
||||
2015-01-19 убран formmarker, упразднен режим init (используется pass)
|
||||
2015-07-16 добавлен passmarker для перерисовки формы с введенными значениями
|
||||
2015-10-02 поддержка составных ключей
|
||||
2015-10-09 v0.9 если задано value параметра, считается, что он hasInput (корректно работает в составе ключа)
|
||||
2015-11-25 добавлен readmarker, mode (принудительная установка режима)
|
||||
2015-11-26 добавлен mode=skip
|
||||
2016-09-01 изменена трактовка processingMode. Теперь понимается как исходная команда, фиксируется до начала действий. Можно использовать для управления
|
||||
2018-09-16 добавлена ограниченная поддержка нецелых первичных ключей (idstamp)
|
||||
child tag: param
|
||||
to save - should send parameter with name from list ATTRIBUTES.savemarker (value doesn't matter) in FORM, e.g. URL.save="trtrtr", while ATTRIBUTES.savemarker="save,saveAndClose"; for multiple forms on a page (and bean tags) different savemarkers should be used
|
||||
2022-01-06 PostgreSQL (MSSQL incompatibility because of scope_identity)
|
||||
2024-04-13 PostgreSQL GUID, autoincrement by RETURNING
|
||||
--->
|
||||
|
||||
<!---
|
||||
Автогенерируемое поле GUID можно заполнять несколькими способами
|
||||
- как default или init bean/param, но это не очень удобно, потому что может потеряться удобный признак новой записи - инвалидный ключ, и сейчас init-default взаимодействуют некорректно, по крайней мере, неочевидно
|
||||
- генерируемое в БД (например, как default). Для PostgreSQL значение возвращается через Returning, как это делать для других БД, непонятно.
|
||||
- можно генерировать при сохранении в bean, но для этого нужно расширение синтаксиса, зато не зависит от БД (*** TODO)
|
||||
--->
|
||||
|
||||
<cfif thisTag.ExecutionMode is 'end'>
|
||||
<cfparam name="ATTRIBUTES.readmarker" type="string" default="read"/><!--- наличие в FORM или URL поля с таким именем воспринимается как команда перечитывания. Имеет приоритет перед savemarker, passmarker. Можно передавать несколько вариантов списком через запятую. --->
|
||||
<cfparam name="ATTRIBUTES.savemarker" type="string" default="save,saveAndClose"/><!--- наличие в FORM или URL поля с таким именем воспринимается как команда сохранения. Обычно это имя кнопки. Можно передавать несколько вариантов списком через запятую. --->
|
||||
<cfparam name="ATTRIBUTES.passmarker" type="string" default="pass"/><!--- наличие в FORM или URL поля с таким именем воспринимается как команда заполнить форму отправленными данными без перечитывания. В форме такое поле обычно есть. Команда сохранения имеет приоритет перед пробросом. Можно передавать несколько вариантов списком через запятую. --->
|
||||
<cfparam name="ATTRIBUTES.datasource" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.table" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.output" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.info" type="string" default=""/>
|
||||
<cfparam name="ATTRIBUTES.meta" type="string" default=""/>
|
||||
<cfparam name="ATTRIBUTES.status" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.readonly" type="boolean" default="No"/>
|
||||
<cfparam name="ATTRIBUTES.mode" type="string" default=""/> <!--- Принудительный режим read|pass|save|skip. Имеет приоритет перед маркерами --->
|
||||
|
||||
<cfif ATTRIBUTES.mode EQ "skip">
|
||||
<!---<cfset SetVariable("CALLER.#ATTRIBUTES.status#.errorState", false) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#.errorMessage", "") />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#.processingMode", "skip") />--->
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#", CreateObject("component","status").init(false,"","skip"))/>
|
||||
<cfexit method="exittag"/>
|
||||
</cfif>
|
||||
|
||||
<cfset validationOk="true" />
|
||||
<cfset errorState="false" />
|
||||
<cfset errorMessage="" />
|
||||
<cfset warningState="false" />
|
||||
<cfset warningMessage="" />
|
||||
<!---<cfset keyField=""/>
|
||||
<cfset keyValue=""/>--->
|
||||
<cfset hasAutoIncrement="false"/>
|
||||
<cfset autoIncrementKeyIndex=0/><!--- сгенерированное значение присваивается первому полю, отмеченному как autoincrement --->
|
||||
<cfset recordExists = "false"/>
|
||||
<cfset keyInvalid = "false"/>
|
||||
|
||||
<!--- разбор метаданных - поиск ключа --->
|
||||
<!--- поддерживаются только простые целочисленные ключи --->
|
||||
<cfset keys=arrayNew(1)/>
|
||||
<!--- *** почему где-то копируем поля param в key, а где-то прямо цикл по параметрам --->
|
||||
<!--- коллекция thistag.params формируется вложенными тегами param --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<!---<cfdump var=#param#/>--->
|
||||
<cfif structFind(param,"key")><!--- not just structKeyExists! Not exisis, OR exists, but FALSE! --->
|
||||
<cfset key = structNew()/>
|
||||
<cfset ArrayAppend(keys, key)/>
|
||||
|
||||
<cfset key.name = param.param />
|
||||
<cfset key.field = param.field />
|
||||
<cfset key.type = param.type />
|
||||
<cfset key.value = param.value /><!--- должно уже быть присвоено --->
|
||||
<cfset key.null = param.null />
|
||||
|
||||
<cfif param.errorState OR !param.hasInput>
|
||||
<cfset keyInvalid="true"/>
|
||||
<cfelse>
|
||||
<cfset keyInvalid=!checkDataFormat(param.type, param.value)/>
|
||||
</cfif>
|
||||
|
||||
<cfif !hasAutoIncrement><!--- take only first field with "autoincrement" attribute--->
|
||||
<cfif structFind(param, "autoincrement")>
|
||||
<cfset hasAutoIncrement = true/>
|
||||
<cfset autoIncrementKeyIndex = arrayLen(keys)/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
</cfif>
|
||||
</cfloop>
|
||||
<!---<cfdump var=#keys#/>--->
|
||||
|
||||
<cfif !keyInvalid>
|
||||
<!--- *** дублируется похожий cfqueryparam, перепутал один раз --->
|
||||
<cfquery name="qCheckExistence" datasource="#ATTRIBUTES.datasource#">
|
||||
select count(*) as cnt
|
||||
from #ATTRIBUTES.table#
|
||||
where 1=1
|
||||
<cfloop array=#keys# index="key">
|
||||
AND #key.field#=<cfqueryparam cfsqltype="#sqlType(key.type)#" value="#key.value#" null="#key.null#"/>
|
||||
</cfloop>
|
||||
</cfquery>
|
||||
<cfset recordExists = (qCheckExistence.cnt GT 0)/>
|
||||
<!--- <cfdump var=#qCheckExistence#/> --->
|
||||
<cfelse>
|
||||
<cfset recordExists = "false"/>
|
||||
</cfif>
|
||||
|
||||
<cfif listFindNoCase("read,pass,save", ATTRIBUTES.mode)>
|
||||
<cfset processingMode=ATTRIBUTES.mode/>
|
||||
|
||||
<cfelse>
|
||||
|
||||
<!--- ищем команду принудительного перечитывания --->
|
||||
<cfset doRead = false/>
|
||||
<cfloop list=#ATTRIBUTES.readmarker# index="marker">
|
||||
<cfif structKeyExists(FORM,"#marker#") OR structKeyExists(URL,"#marker#")>
|
||||
<cfset doRead = true/>
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
|
||||
<!--- ищем команду сохранения --->
|
||||
<cfset doSave = false/>
|
||||
<cfif !doRead AND !ATTRIBUTES.readonly>
|
||||
<cfloop list=#ATTRIBUTES.savemarker# index="marker">
|
||||
<cfif structKeyExists(FORM,"#marker#") OR structKeyExists(URL,"#marker#")>
|
||||
<cfset doSave = true/>
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<!--- ищем команду проброса --->
|
||||
<cfset doPass = false/>
|
||||
<cfif !doRead AND !doSave>
|
||||
<cfloop list=#ATTRIBUTES.passmarker# index="marker">
|
||||
<cfif structKeyExists(FORM,"#marker#") OR structKeyExists(URL,"#marker#")>
|
||||
<cfset doPass = true/>
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<!--- определяем режим --->
|
||||
<cfif doRead>
|
||||
<cfset processingMode="read"/>
|
||||
<cfelseif doSave>
|
||||
<cfset processingMode="save"/>
|
||||
<cfelse>
|
||||
<cfif doPass OR !recordExists>
|
||||
<cfset processingMode="pass"/>
|
||||
<cfelse>
|
||||
<cfset processingMode="read"/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
</cfif>
|
||||
|
||||
<cfset initialProcessingMode = processingMode/>
|
||||
|
||||
|
||||
<!---debug <cfoutput>processingMode:#processingMode#</cfoutput>--->
|
||||
<!--- ---------------------------------------------------------- --->
|
||||
|
||||
<!---*** Необходимость вставки (против апдейта) определяется по существованию записи. Это небезопасно, поскольку наличие записи с ключом -1 может прекратить создание новых записей. Конечно, можно добавить констрейнт на ключевое поле, но это лишняя зависимость.
|
||||
Можно явно передавать команду вставки, а не заморачиваться с анализом ключа. Просто традиционно мы сигнализировали необходимость вставки, передавая невалидное значение ключа, обычно -1. Для целочисленных ключей можно было бы просто проверять положительность (что всю жизнь отлично работало), но хочется более общего.
|
||||
--->
|
||||
|
||||
<cfif processingMode IS "save"> <!--- validation lookup --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
|
||||
<cfif !param.key>
|
||||
<cfif param.warningState>
|
||||
<cfif NOT warningState><!--- catch the first fault --->
|
||||
<cfset warningMessage=param.warningMessage />
|
||||
</cfif>
|
||||
<cfset warningState="true" />
|
||||
</cfif>
|
||||
|
||||
<cfif param.errorState>
|
||||
<cfif NOT errorState><!--- catch the first fault --->
|
||||
<cfset errorMessage=param.errorMessage />
|
||||
</cfif>
|
||||
<cfset errorState="true" />
|
||||
<cfset validationOk="false"/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
<cfif errorState>
|
||||
<!--- clear warning state --->
|
||||
<cfset warningMessage="" />
|
||||
<cfset warningState=false />
|
||||
<!--- finish lookup --->
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
|
||||
</cfloop>
|
||||
|
||||
<cfif validationOk>
|
||||
<!---<cfdump var=#param#/> --->
|
||||
<cftry>
|
||||
<cfif recordExists><!--- update. Наличие keyValue гарантировано (уверен) --->
|
||||
<cfquery name="qSave" datasource="#ATTRIBUTES.datasource#" result="qSaveResult">
|
||||
update #ATTRIBUTES.table# set
|
||||
<cfset i=0 />
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<!--- не обновляем ключевые поля --->
|
||||
<cfif NOT (StructFind(param, "key")
|
||||
OR StructFind(param, "autoincrement")
|
||||
OR StructFind(param, "readonly")
|
||||
OR StructFind(param, "skipUpdate")
|
||||
)><cfif i++ GT 0>,</cfif>
|
||||
#param.field#=<cfqueryparam cfsqltype="#sqlType(param.type)#" value="#param.value#" null="#param.null#"/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
where 1=1
|
||||
<cfloop array=#keys# index="key">
|
||||
AND #key.field#=<cfqueryparam cfsqltype="#sqlType(key.type)#" value="#key.value#"/>
|
||||
</cfloop>
|
||||
</cfquery>
|
||||
<!---<cfdump var=#qSaveResult#/>--->
|
||||
<cfelse><!--- insert --->
|
||||
<cfquery name="qSave" datasource="#ATTRIBUTES.datasource#">
|
||||
insert into #ATTRIBUTES.table#
|
||||
(
|
||||
<cfset i=0 />
|
||||
<!--- ключевые поля без автоинкремента попадают в insert! --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfif NOT (StructFind(param, "autoincrement")
|
||||
OR StructFind(param, "readonly")
|
||||
OR StructFind(param, "skipInsert")
|
||||
)><cfif i++ GT 0>,</cfif>
|
||||
#param.field#
|
||||
</cfif>
|
||||
</cfloop>
|
||||
)
|
||||
values
|
||||
(
|
||||
<cfset i=0 />
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfif NOT (StructFind(param, "autoincrement")
|
||||
OR StructFind(param, "readonly")
|
||||
OR StructFind(param, "skipInsert")
|
||||
)><cfif i++ GT 0>,</cfif>
|
||||
<cfqueryparam cfsqltype="#sqlType(param.type)#" value="#param.value#" null="#param.null#"/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
);
|
||||
<!---
|
||||
<cfif hasAutoIncrement>
|
||||
select scope_identity() as id;
|
||||
</cfif>
|
||||
--->
|
||||
<!---
|
||||
*** PostgreSQL incompatible hack
|
||||
--->
|
||||
<cfif hasAutoIncrement>
|
||||
select LASTVAL() as id;
|
||||
</cfif>
|
||||
</cfquery>
|
||||
|
||||
<cfif hasAutoIncrement>
|
||||
<cfset keys[autoIncrementKeyIndex].value=qSave.id/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
<!--- recordExists --->
|
||||
|
||||
|
||||
<cfset processingMode="read"/>
|
||||
|
||||
<cfcatch type="database">
|
||||
<cfset errorState="true" />
|
||||
<cfset errorMessage="Ошибка при записи в базу данных. #cfcatch.message# #cfcatch.detail#" />
|
||||
<cfset processingMode="pass" />
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
<cfelse><!--- (not) validationOk --->
|
||||
<cfset processingMode="pass"/>
|
||||
</cfif><!--- validationOk --->
|
||||
|
||||
</cfif><!--- processingMode EQ "save" --->
|
||||
|
||||
<!--- экспортируем данные --->
|
||||
<cfswitch expression=#processingMode#>
|
||||
<cfcase value="read">
|
||||
<cfquery name="qRead" datasource="#ATTRIBUTES.datasource#">
|
||||
select
|
||||
<cfset i=0 />
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfset i=i+1/>
|
||||
#param.field#<cfif i LT ArrayLen(thistag.params)>,</cfif>
|
||||
</cfloop>
|
||||
from #ATTRIBUTES.table#
|
||||
where 1=1
|
||||
<cfloop array=#keys# index="key">
|
||||
/*#sqlType(key.type)#*/
|
||||
AND #key.field#=<cfqueryparam cfsqltype="#sqlType(key.type)#" value="#key.value#" null="#key.null#"/>
|
||||
</cfloop>
|
||||
</cfquery>
|
||||
|
||||
<cfloop array=#thistag.params# index="param"><!--- *** --->
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.output#.#param.param#", structFind(qRead, #param.field#)) />
|
||||
</cfloop>
|
||||
</cfcase>
|
||||
|
||||
|
||||
<cfcase value="pass"><!--- заполнить все поля. Если значения переданы в форме или урле, тег параметра обязан их разобрать и подставить, в противном случае подставить инит-значения. Инит-значение по умолчанию пустая строка, дефолт по умолчанию тоже пустая строка --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<!--- <cfdump var=#param#/>--->
|
||||
<cfif param.hasInput>
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.output#.#param.param#", param.submittedValue) /><!---*** дефект: 03.12.2015, передаваемая строкой, при обработке dateFormat неправильно парсится --->
|
||||
<cfelse>
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.output#.#param.param#", param.init) />
|
||||
</cfif>
|
||||
</cfloop>
|
||||
</cfcase>
|
||||
|
||||
<cfdefaultcase>
|
||||
</cfdefaultcase>
|
||||
|
||||
</cfswitch>
|
||||
|
||||
<cfif len(ATTRIBUTES.info)><!--- экспортируем дополнительные сведения--->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.submittedValue", #param.submittedValue#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.errorState", #param.errorState#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.errorMessage", #param.errorMessage#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.warningState", #param.warningState#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.warningMessage", #param.warningMessage#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.null", #param.null#) />
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<cfif len(ATTRIBUTES.meta)><!--- экспортируем метаданные параметра - для инвариантности вызовов --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.param", #param.param#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.field", #param.field#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.type", #param.type#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.displayName", #param.displayName#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.default", #param.default#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.size", #param.size#) />
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#", CreateObject("component","status").init(errorState,errorMessage,initialProcessingMode))/>
|
||||
|
||||
</cfif><!--- thisTag.ExecutionMode is 'end'--->
|
||||
|
||||
<!--- quick and dirty --->
|
||||
<cffunction name="sqlType">
|
||||
<cfargument name="type"/>
|
||||
|
||||
<cfswitch expression=#type#>
|
||||
<cfcase value="guid,uuid,idstamp"><cfreturn "CF_SQL_OTHER"/></cfcase><!--- hack for PostgreSQL uuid --->
|
||||
<cfdefaultcase><cfreturn uCase("CF_SQL_#type#")/></cfdefaultcase>
|
||||
</cfswitch>
|
||||
</cffunction>
|
||||
|
||||
<cffunction name="checkDataFormat">
|
||||
<cfargument name="type"/>
|
||||
<cfargument name="value"/>
|
||||
|
||||
<cfswitch expression=#type#>
|
||||
<cfcase value="integer"><cfreturn isValid("integer",value)/></cfcase>
|
||||
<cfcase value="guid,uuid,idstamp"><cfreturn isValid("guid",value)/></cfcase>
|
||||
<cfdefaultcase><cfreturn true/></cfdefaultcase>
|
||||
</cfswitch>
|
||||
</cffunction>
|
||||
|
||||
|
||||
<!--- //quick and dirty
|
||||
function sqlType(type) {
|
||||
switch (type) {
|
||||
case "guid,idstamp": return "CF_SQL_OTHER"; /*hack for PostgreSQL uuid*/ /*break not needed!*/
|
||||
default: return uCase("CF_SQL_#type#");
|
||||
}
|
||||
}
|
||||
|
||||
function checkDataFormat(type,value) {
|
||||
switch (type) {
|
||||
case "integer": return isValid("integer",value); /*break not needed!*/
|
||||
case "guid,uuid,idstamp": return isValid("guid",value); /*break not needed!*/ /*INCORRECT cfscript switch-case does not support lists*/
|
||||
default: return true;
|
||||
}
|
||||
} --->
|
||||
<cfscript>
|
||||
//readonly может транслироваться в pass!
|
||||
function translateMode(readonly) {
|
||||
if (readonly) {
|
||||
return "read";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
</cfscript>
|
||||
@@ -0,0 +1,398 @@
|
||||
<!---
|
||||
bean v0.95
|
||||
msyu@mail.ru
|
||||
2013-08-29 v0.1
|
||||
2013-09-04 v0.2 tested with CF8 and Railo
|
||||
2013-10-14 added meta attribute - can now export each parameter metadata
|
||||
2014-12-26 POST-GET read-pass-save
|
||||
2015-01-19 read-pass-save, добавлен formmarker, убрано определение режима по POST-GET
|
||||
2015-01-19 убран formmarker, упразднен режим init (используется pass)
|
||||
2015-07-16 добавлен passmarker для перерисовки формы с введенными значениями
|
||||
2015-10-02 поддержка составных ключей
|
||||
2015-10-09 v0.9 если задано value параметра, считается, что он hasInput (корректно работает в составе ключа)
|
||||
2015-11-25 добавлен readmarker, mode (принудительная установка режима)
|
||||
2015-11-26 добавлен mode=skip
|
||||
2016-09-01 изменена трактовка processingMode. Теперь понимается как исходная команда, фиксируется до начала действий. Можно использовать для управления
|
||||
2018-09-16 добавлена ограниченная поддержка нецелых первичных ключей (idstamp)
|
||||
child tag: param
|
||||
to save - should send parameter with name from list ATTRIBUTES.savemarker (value doesn't matter) in FORM, e.g. URL.save="trtrtr", while ATTRIBUTES.savemarker="save,saveAndClose"; for multiple forms on a page (and bean tags) different savemarkers should be used
|
||||
2022-01-06 PostgreSQL (MSSQL incompatibility because of scope_identity)
|
||||
2024-04-13 PostgreSQL GUID, autoincrement by RETURNING
|
||||
--->
|
||||
|
||||
<!---
|
||||
Автогенерируемое поле GUID можно заполнять несколькими способами
|
||||
- как default или init bean/param, но это не очень удобно, потому что может потеряться удобный признак новой записи - инвалидный ключ, и сейчас init-default взаимодействуют некорректно, по крайней мере, неочевидно
|
||||
- генерируемое в БД (например, как default). Для PostgreSQL значение возвращается через Returning, как это делать для других БД, непонятно.
|
||||
- можно генерировать при сохранении в bean, но для этого нужно расширение синтаксиса, зато не зависит от БД (*** TODO)
|
||||
--->
|
||||
|
||||
<cfif thisTag.ExecutionMode is 'end'>
|
||||
<cfparam name="ATTRIBUTES.readmarker" type="string" default="read"/><!--- наличие в FORM или URL поля с таким именем воспринимается как команда перечитывания. Имеет приоритет перед savemarker, passmarker. Можно передавать несколько вариантов списком через запятую. --->
|
||||
<cfparam name="ATTRIBUTES.savemarker" type="string" default="save,saveAndClose"/><!--- наличие в FORM или URL поля с таким именем воспринимается как команда сохранения. Обычно это имя кнопки. Можно передавать несколько вариантов списком через запятую. --->
|
||||
<cfparam name="ATTRIBUTES.passmarker" type="string" default="pass"/><!--- наличие в FORM или URL поля с таким именем воспринимается как команда заполнить форму отправленными данными без перечитывания. В форме такое поле обычно есть. Команда сохранения имеет приоритет перед пробросом. Можно передавать несколько вариантов списком через запятую. --->
|
||||
<cfparam name="ATTRIBUTES.datasource" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.table" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.output" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.info" type="string" default=""/>
|
||||
<cfparam name="ATTRIBUTES.meta" type="string" default=""/>
|
||||
<cfparam name="ATTRIBUTES.status" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.readonly" type="boolean" default="No"/>
|
||||
<cfparam name="ATTRIBUTES.mode" type="string" default=""/> <!--- Принудительный режим read|pass|save|skip. Имеет приоритет перед маркерами --->
|
||||
|
||||
<cfif ATTRIBUTES.mode EQ "skip">
|
||||
<!---<cfset SetVariable("CALLER.#ATTRIBUTES.status#.errorState", false) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#.errorMessage", "") />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#.processingMode", "skip") />--->
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#", CreateObject("component","status").init(false,"","skip"))/>
|
||||
<cfexit method="exittag"/>
|
||||
</cfif>
|
||||
|
||||
<cfset validationOk="true" />
|
||||
<cfset errorState="false" />
|
||||
<cfset errorMessage="" />
|
||||
<cfset warningState="false" />
|
||||
<cfset warningMessage="" />
|
||||
<!---<cfset keyField=""/>
|
||||
<cfset keyValue=""/>--->
|
||||
<cfset hasAutoIncrement="false"/>
|
||||
<cfset autoIncrementKeyIndex=0/><!--- сгенерированное значение присваивается первому полю, отмеченному как autoincrement --->
|
||||
<cfset recordExists = "false"/>
|
||||
<cfset keyInvalid = "false"/>
|
||||
|
||||
<!--- разбор метаданных - поиск ключа --->
|
||||
<!--- поддерживаются только простые целочисленные ключи --->
|
||||
<cfset keys=arrayNew(1)/>
|
||||
<!--- *** почему где-то копируем поля param в key, а где-то прямо цикл по параметрам --->
|
||||
<!--- коллекция thistag.params формируется вложенными тегами param --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<!---<cfdump var=#param#/>--->
|
||||
<cfif structFind(param,"key")><!--- not just structKeyExists! Not exisis, OR exists, but FALSE! --->
|
||||
<cfset key = structNew()/>
|
||||
<cfset ArrayAppend(keys, key)/>
|
||||
|
||||
<cfset key.name = param.param />
|
||||
<cfset key.field = param.field />
|
||||
<cfset key.type = param.type />
|
||||
<cfset key.value = param.value /><!--- должно уже быть присвоено --->
|
||||
<cfset key.null = param.null />
|
||||
|
||||
<cfif param.errorState OR !param.hasInput>
|
||||
<cfset keyInvalid="true"/>
|
||||
<cfelse>
|
||||
<cfset keyInvalid=!checkDataFormat(param.type, param.value)/>
|
||||
</cfif>
|
||||
|
||||
<cfif !hasAutoIncrement><!--- take only first field with "autoincrement" attribute--->
|
||||
<cfif structFind(param, "autoincrement")>
|
||||
<cfset hasAutoIncrement = true/>
|
||||
<cfset autoIncrementKeyIndex = arrayLen(keys)/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
</cfif>
|
||||
</cfloop>
|
||||
<!---<cfdump var=#keys#/>--->
|
||||
|
||||
<cfif !keyInvalid>
|
||||
<!--- *** дублируется похожий cfqueryparam, перепутал один раз --->
|
||||
<cfquery name="qCheckExistence" datasource="#ATTRIBUTES.datasource#">
|
||||
select count(*) as cnt
|
||||
from #ATTRIBUTES.table#
|
||||
where 1=1
|
||||
<cfloop array=#keys# index="key">
|
||||
AND #key.field#=<cfqueryparam cfsqltype="#sqlType(key.type)#" value="#key.value#" null="#key.null#"/>
|
||||
</cfloop>
|
||||
</cfquery>
|
||||
<cfset recordExists = (qCheckExistence.cnt GT 0)/>
|
||||
<!--- <cfdump var=#qCheckExistence#/> --->
|
||||
<cfelse>
|
||||
<cfset recordExists = "false"/>
|
||||
</cfif>
|
||||
|
||||
<cfif listFindNoCase("read,pass,save", ATTRIBUTES.mode)>
|
||||
<cfset processingMode=ATTRIBUTES.mode/>
|
||||
|
||||
<cfelse>
|
||||
|
||||
<!--- ищем команду принудительного перечитывания --->
|
||||
<cfset doRead = false/>
|
||||
<cfloop list=#ATTRIBUTES.readmarker# index="marker">
|
||||
<cfif structKeyExists(FORM,"#marker#") OR structKeyExists(URL,"#marker#")>
|
||||
<cfset doRead = true/>
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
|
||||
<!--- ищем команду сохранения --->
|
||||
<cfset doSave = false/>
|
||||
<cfif !doRead AND !ATTRIBUTES.readonly>
|
||||
<cfloop list=#ATTRIBUTES.savemarker# index="marker">
|
||||
<cfif structKeyExists(FORM,"#marker#") OR structKeyExists(URL,"#marker#")>
|
||||
<cfset doSave = true/>
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<!--- ищем команду проброса --->
|
||||
<cfset doPass = false/>
|
||||
<cfif !doRead AND !doSave>
|
||||
<cfloop list=#ATTRIBUTES.passmarker# index="marker">
|
||||
<cfif structKeyExists(FORM,"#marker#") OR structKeyExists(URL,"#marker#")>
|
||||
<cfset doPass = true/>
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<!--- определяем режим --->
|
||||
<cfif doRead>
|
||||
<cfset processingMode="read"/>
|
||||
<cfelseif doSave>
|
||||
<cfset processingMode="save"/>
|
||||
<cfelse>
|
||||
<cfif doPass OR !recordExists>
|
||||
<cfset processingMode="pass"/>
|
||||
<cfelse>
|
||||
<cfset processingMode="read"/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
</cfif>
|
||||
|
||||
<cfset initialProcessingMode = processingMode/>
|
||||
|
||||
|
||||
<!---debug <cfoutput>processingMode:#processingMode#</cfoutput>--->
|
||||
<!--- ---------------------------------------------------------- --->
|
||||
|
||||
<!---*** Необходимость вставки (против апдейта) определяется по существованию записи. Это небезопасно, поскольку наличие записи с ключом -1 может прекратить создание новых записей. Конечно, можно добавить констрейнт на ключевое поле, но это лишняя зависимость.
|
||||
Можно явно передавать команду вставки, а не заморачиваться с анализом ключа. Просто традиционно мы сигнализировали необходимость вставки, передавая невалидное значение ключа, обычно -1. Для целочисленных ключей можно было бы просто проверять положительность (что всю жизнь отлично работало), но хочется более общего.
|
||||
--->
|
||||
|
||||
<cfif processingMode IS "save"> <!--- validation lookup --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
|
||||
<cfif !param.key>
|
||||
<cfif param.warningState>
|
||||
<cfif NOT warningState><!--- catch the first fault --->
|
||||
<cfset warningMessage=param.warningMessage />
|
||||
</cfif>
|
||||
<cfset warningState="true" />
|
||||
</cfif>
|
||||
|
||||
<cfif param.errorState>
|
||||
<cfif NOT errorState><!--- catch the first fault --->
|
||||
<cfset errorMessage=param.errorMessage />
|
||||
</cfif>
|
||||
<cfset errorState="true" />
|
||||
<cfset validationOk="false"/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
<cfif errorState>
|
||||
<!--- clear warning state --->
|
||||
<cfset warningMessage="" />
|
||||
<cfset warningState=false />
|
||||
<!--- finish lookup --->
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
|
||||
</cfloop>
|
||||
|
||||
<cfif validationOk>
|
||||
<!---<cfdump var=#param#/> --->
|
||||
<cftry>
|
||||
<cfif recordExists><!--- update. Наличие keyValue гарантировано (уверен) --->
|
||||
<cfquery name="qSave" datasource="#ATTRIBUTES.datasource#" result="qSaveResult">
|
||||
update #ATTRIBUTES.table# set
|
||||
<cfset i=0 />
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<!--- не обновляем ключевые поля --->
|
||||
<cfif NOT (StructFind(param, "key")
|
||||
OR StructFind(param, "autoincrement")
|
||||
OR StructFind(param, "readonly")
|
||||
OR StructFind(param, "skipUpdate")
|
||||
)><cfif i++ GT 0>,</cfif>
|
||||
#param.field#=<cfqueryparam cfsqltype="#sqlType(param.type)#" value="#param.value#" null="#param.null#"/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
where 1=1
|
||||
<cfloop array=#keys# index="key">
|
||||
AND #key.field#=<cfqueryparam cfsqltype="#sqlType(key.type)#" value="#key.value#"/>
|
||||
</cfloop>
|
||||
</cfquery>
|
||||
<!---<cfdump var=#qSaveResult#/>--->
|
||||
<cfelse><!--- insert --->
|
||||
<cfquery name="qSave" datasource="#ATTRIBUTES.datasource#">
|
||||
insert into #ATTRIBUTES.table#
|
||||
(
|
||||
<cfset i=0 />
|
||||
<!--- ключевые поля без автоинкремента попадают в insert! --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfif NOT (StructFind(param, "autoincrement")
|
||||
OR StructFind(param, "readonly")
|
||||
OR StructFind(param, "skipInsert")
|
||||
)><cfif i++ GT 0>,</cfif>
|
||||
#param.field#
|
||||
</cfif>
|
||||
</cfloop>
|
||||
)
|
||||
values
|
||||
(
|
||||
<cfset i=0 />
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfif NOT (StructFind(param, "autoincrement")
|
||||
OR StructFind(param, "readonly")
|
||||
OR StructFind(param, "skipInsert")
|
||||
)><cfif i++ GT 0>,</cfif>
|
||||
<cfqueryparam cfsqltype="#sqlType(param.type)#" value="#param.value#" null="#param.null#"/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
)
|
||||
<!---
|
||||
<cfif hasAutoIncrement>
|
||||
select scope_identity() as id;
|
||||
</cfif>
|
||||
--->
|
||||
<!---*** PostgreSQL incompatible hack follows--->
|
||||
<cfif hasAutoIncrement>
|
||||
returning #thistag.params[autoIncrementKeyIndex].field# as id;
|
||||
</cfif>;
|
||||
</cfquery>
|
||||
<!--- <cfdump var=#qSave#/> --->
|
||||
<cfif hasAutoIncrement>
|
||||
<cfset keys[autoIncrementKeyIndex].value=qSave.id/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
<!--- recordExists --->
|
||||
|
||||
|
||||
<cfset processingMode="read"/>
|
||||
|
||||
<cfcatch type="database">
|
||||
<cfset errorState="true" />
|
||||
<cfset errorMessage="Ошибка при записи в базу данных. #cfcatch.message# #cfcatch.detail#" />
|
||||
<cfset processingMode="pass" />
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
<cfelse><!--- (not) validationOk --->
|
||||
<cfset processingMode="pass"/>
|
||||
</cfif><!--- validationOk --->
|
||||
|
||||
</cfif><!--- processingMode EQ "save" --->
|
||||
|
||||
<!--- экспортируем данные --->
|
||||
<cfswitch expression=#processingMode#>
|
||||
<cfcase value="read">
|
||||
<cfquery name="qRead" datasource="#ATTRIBUTES.datasource#">
|
||||
select
|
||||
<cfset i=0 />
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfset i=i+1/>
|
||||
#param.field#<cfif i LT ArrayLen(thistag.params)>,</cfif>
|
||||
</cfloop>
|
||||
from #ATTRIBUTES.table#
|
||||
where 1=1
|
||||
<cfloop array=#keys# index="key">
|
||||
/*#sqlType(key.type)#*/
|
||||
AND #key.field#=<cfqueryparam cfsqltype="#sqlType(key.type)#" value="#key.value#" null="#key.null#"/>
|
||||
</cfloop>
|
||||
</cfquery>
|
||||
|
||||
<cfloop array=#thistag.params# index="param"><!--- *** --->
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.output#.#param.param#", structFind(qRead, #param.field#)) />
|
||||
</cfloop>
|
||||
</cfcase>
|
||||
|
||||
|
||||
<cfcase value="pass"><!--- заполнить все поля. Если значения переданы в форме или урле, тег параметра обязан их разобрать и подставить, в противном случае подставить инит-значения. Инит-значение по умолчанию пустая строка, дефолт по умолчанию тоже пустая строка --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<!--- <cfdump var=#param#/>--->
|
||||
<cfif param.hasInput>
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.output#.#param.param#", param.submittedValue) /><!---*** дефект: 03.12.2015, передаваемая строкой, при обработке dateFormat неправильно парсится --->
|
||||
<cfelse>
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.output#.#param.param#", param.init) />
|
||||
</cfif>
|
||||
</cfloop>
|
||||
</cfcase>
|
||||
|
||||
<cfdefaultcase>
|
||||
</cfdefaultcase>
|
||||
|
||||
</cfswitch>
|
||||
|
||||
<cfif len(ATTRIBUTES.info)><!--- экспортируем дополнительные сведения--->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.submittedValue", #param.submittedValue#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.errorState", #param.errorState#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.errorMessage", #param.errorMessage#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.warningState", #param.warningState#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.warningMessage", #param.warningMessage#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.null", #param.null#) />
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<cfif len(ATTRIBUTES.meta)><!--- экспортируем метаданные параметра - для инвариантности вызовов --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.param", #param.param#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.field", #param.field#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.type", #param.type#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.displayName", #param.displayName#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.default", #param.default#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.size", #param.size#) />
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#", CreateObject("component","status").init(errorState,errorMessage,initialProcessingMode))/>
|
||||
|
||||
</cfif><!--- thisTag.ExecutionMode is 'end'--->
|
||||
|
||||
<!--- quick and dirty --->
|
||||
<cffunction name="sqlType">
|
||||
<cfargument name="type"/>
|
||||
|
||||
<cfswitch expression=#type#>
|
||||
<cfcase value="guid,uuid,idstamp"><cfreturn "CF_SQL_OTHER"/></cfcase><!--- hack for PostgreSQL uuid --->
|
||||
<cfdefaultcase><cfreturn uCase("CF_SQL_#type#")/></cfdefaultcase>
|
||||
</cfswitch>
|
||||
</cffunction>
|
||||
|
||||
<cffunction name="checkDataFormat">
|
||||
<cfargument name="type"/>
|
||||
<cfargument name="value"/>
|
||||
|
||||
<cfswitch expression=#type#>
|
||||
<cfcase value="integer"><cfreturn isValid("integer",value)/></cfcase>
|
||||
<cfcase value="guid,uuid,idstamp"><cfreturn isValid("guid",value)/></cfcase>
|
||||
<cfdefaultcase><cfreturn true/></cfdefaultcase>
|
||||
</cfswitch>
|
||||
</cffunction>
|
||||
|
||||
|
||||
<!--- //quick and dirty
|
||||
function sqlType(type) {
|
||||
switch (type) {
|
||||
case "guid,idstamp": return "CF_SQL_OTHER"; /*hack for PostgreSQL uuid*/ /*break not needed!*/
|
||||
default: return uCase("CF_SQL_#type#");
|
||||
}
|
||||
}
|
||||
|
||||
function checkDataFormat(type,value) {
|
||||
switch (type) {
|
||||
case "integer": return isValid("integer",value); /*break not needed!*/
|
||||
case "guid,uuid,idstamp": return isValid("guid",value); /*break not needed!*/ /*INCORRECT cfscript switch-case does not support lists*/
|
||||
default: return true;
|
||||
}
|
||||
} --->
|
||||
<cfscript>
|
||||
//readonly может транслироваться в pass!
|
||||
function translateMode(readonly) {
|
||||
if (readonly) {
|
||||
return "read";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
</cfscript>
|
||||
@@ -0,0 +1,398 @@
|
||||
<!---
|
||||
bean v0.95
|
||||
msyu@mail.ru
|
||||
2013-08-29 v0.1
|
||||
2013-09-04 v0.2 tested with CF8 and Railo
|
||||
2013-10-14 added meta attribute - can now export each parameter metadata
|
||||
2014-12-26 POST-GET read-pass-save
|
||||
2015-01-19 read-pass-save, добавлен formmarker, убрано определение режима по POST-GET
|
||||
2015-01-19 убран formmarker, упразднен режим init (используется pass)
|
||||
2015-07-16 добавлен passmarker для перерисовки формы с введенными значениями
|
||||
2015-10-02 поддержка составных ключей
|
||||
2015-10-09 v0.9 если задано value параметра, считается, что он hasInput (корректно работает в составе ключа)
|
||||
2015-11-25 добавлен readmarker, mode (принудительная установка режима)
|
||||
2015-11-26 добавлен mode=skip
|
||||
2016-09-01 изменена трактовка processingMode. Теперь понимается как исходная команда, фиксируется до начала действий. Можно использовать для управления
|
||||
2018-09-16 добавлена ограниченная поддержка нецелых первичных ключей (idstamp)
|
||||
child tag: param
|
||||
to save - should send parameter with name from list ATTRIBUTES.savemarker (value doesn't matter) in FORM, e.g. URL.save="trtrtr", while ATTRIBUTES.savemarker="save,saveAndClose"; for multiple forms on a page (and bean tags) different savemarkers should be used
|
||||
2022-01-06 PostgreSQL (MSSQL incompatibility because of scope_identity)
|
||||
2024-04-13 PostgreSQL GUID, autoincrement by RETURNING
|
||||
--->
|
||||
|
||||
<!---
|
||||
Автогенерируемое поле GUID можно заполнять несколькими способами
|
||||
- как default или init bean/param, но это не очень удобно, потому что может потеряться удобный признак новой записи - инвалидный ключ, и сейчас init-default взаимодействуют некорректно, по крайней мере, неочевидно
|
||||
- генерируемое в БД (например, как default). Для PostgreSQL значение возвращается через Returning, как это делать для других БД, непонятно.
|
||||
- можно генерировать при сохранении в bean, но для этого нужно расширение синтаксиса, зато не зависит от БД (*** TODO)
|
||||
--->
|
||||
|
||||
<cfif thisTag.ExecutionMode is 'end'>
|
||||
<cfparam name="ATTRIBUTES.readmarker" type="string" default="read"/><!--- наличие в FORM или URL поля с таким именем воспринимается как команда перечитывания. Имеет приоритет перед savemarker, passmarker. Можно передавать несколько вариантов списком через запятую. --->
|
||||
<cfparam name="ATTRIBUTES.savemarker" type="string" default="save,saveAndClose"/><!--- наличие в FORM или URL поля с таким именем воспринимается как команда сохранения. Обычно это имя кнопки. Можно передавать несколько вариантов списком через запятую. --->
|
||||
<cfparam name="ATTRIBUTES.passmarker" type="string" default="pass"/><!--- наличие в FORM или URL поля с таким именем воспринимается как команда заполнить форму отправленными данными без перечитывания. В форме такое поле обычно есть. Команда сохранения имеет приоритет перед пробросом. Можно передавать несколько вариантов списком через запятую. --->
|
||||
<cfparam name="ATTRIBUTES.datasource" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.table" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.output" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.info" type="string" default=""/>
|
||||
<cfparam name="ATTRIBUTES.meta" type="string" default=""/>
|
||||
<cfparam name="ATTRIBUTES.status" type="string"/>
|
||||
<cfparam name="ATTRIBUTES.readonly" type="boolean" default="No"/>
|
||||
<cfparam name="ATTRIBUTES.mode" type="string" default=""/> <!--- Принудительный режим read|pass|save|skip. Имеет приоритет перед маркерами --->
|
||||
|
||||
<cfif ATTRIBUTES.mode EQ "skip">
|
||||
<!---<cfset SetVariable("CALLER.#ATTRIBUTES.status#.errorState", false) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#.errorMessage", "") />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#.processingMode", "skip") />--->
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#", CreateObject("component","status").init(false,"","skip"))/>
|
||||
<cfexit method="exittag"/>
|
||||
</cfif>
|
||||
|
||||
<cfset validationOk="true" />
|
||||
<cfset errorState="false" />
|
||||
<cfset errorMessage="" />
|
||||
<cfset warningState="false" />
|
||||
<cfset warningMessage="" />
|
||||
<!---<cfset keyField=""/>
|
||||
<cfset keyValue=""/>--->
|
||||
<cfset hasAutoIncrement="false"/>
|
||||
<cfset autoIncrementKeyIndex=0/><!--- сгенерированное значение присваивается первому полю, отмеченному как autoincrement --->
|
||||
<cfset recordExists = "false"/>
|
||||
<cfset keyInvalid = "false"/>
|
||||
|
||||
<!--- разбор метаданных - поиск ключа --->
|
||||
<!--- поддерживаются только простые целочисленные ключи --->
|
||||
<cfset keys=arrayNew(1)/>
|
||||
<!--- *** почему где-то копируем поля param в key, а где-то прямо цикл по параметрам --->
|
||||
<!--- коллекция thistag.params формируется вложенными тегами param --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<!---<cfdump var=#param#/>--->
|
||||
<cfif structFind(param,"key")><!--- not just structKeyExists! Not exisis, OR exists, but FALSE! --->
|
||||
<cfset key = structNew()/>
|
||||
<cfset ArrayAppend(keys, key)/>
|
||||
|
||||
<cfset key.name = param.param />
|
||||
<cfset key.field = param.field />
|
||||
<cfset key.type = param.type />
|
||||
<cfset key.value = param.value /><!--- должно уже быть присвоено --->
|
||||
<cfset key.null = param.null />
|
||||
|
||||
<cfif param.errorState OR !param.hasInput>
|
||||
<cfset keyInvalid="true"/>
|
||||
<cfelse>
|
||||
<cfset keyInvalid=!checkDataFormat(param.type, param.value)/>
|
||||
</cfif>
|
||||
|
||||
<cfif !hasAutoIncrement><!--- take only first field with "autoincrement" attribute--->
|
||||
<cfif structFind(param, "autoincrement")>
|
||||
<cfset hasAutoIncrement = true/>
|
||||
<cfset autoIncrementKeyIndex = arrayLen(keys)/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
</cfif>
|
||||
</cfloop>
|
||||
<!---<cfdump var=#keys#/>--->
|
||||
|
||||
<cfif !keyInvalid>
|
||||
<!--- *** дублируется похожий cfqueryparam, перепутал один раз --->
|
||||
<cfquery name="qCheckExistence" datasource="#ATTRIBUTES.datasource#">
|
||||
select count(*) as cnt
|
||||
from #ATTRIBUTES.table#
|
||||
where 1=1
|
||||
<!--- <cfloop array=#keys# index="key">
|
||||
AND #key.field#=<cfqueryparam cfsqltype="#sqlType(key.type)#" value="#key.value#" null="#key.null#"/>
|
||||
</cfloop> --->
|
||||
</cfquery>
|
||||
<cfset recordExists = (qCheckExistence.cnt GT 0)/>
|
||||
<!--- <cfdump var=#qCheckExistence#/> --->
|
||||
<cfelse>
|
||||
<cfset recordExists = "false"/>
|
||||
</cfif>
|
||||
|
||||
<cfif listFindNoCase("read,pass,save", ATTRIBUTES.mode)>
|
||||
<cfset processingMode=ATTRIBUTES.mode/>
|
||||
|
||||
<cfelse>
|
||||
|
||||
<!--- ищем команду принудительного перечитывания --->
|
||||
<cfset doRead = false/>
|
||||
<cfloop list=#ATTRIBUTES.readmarker# index="marker">
|
||||
<cfif structKeyExists(FORM,"#marker#") OR structKeyExists(URL,"#marker#")>
|
||||
<cfset doRead = true/>
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
|
||||
<!--- ищем команду сохранения --->
|
||||
<cfset doSave = false/>
|
||||
<cfif !doRead AND !ATTRIBUTES.readonly>
|
||||
<cfloop list=#ATTRIBUTES.savemarker# index="marker">
|
||||
<cfif structKeyExists(FORM,"#marker#") OR structKeyExists(URL,"#marker#")>
|
||||
<cfset doSave = true/>
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<!--- ищем команду проброса --->
|
||||
<cfset doPass = false/>
|
||||
<cfif !doRead AND !doSave>
|
||||
<cfloop list=#ATTRIBUTES.passmarker# index="marker">
|
||||
<cfif structKeyExists(FORM,"#marker#") OR structKeyExists(URL,"#marker#")>
|
||||
<cfset doPass = true/>
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<!--- определяем режим --->
|
||||
<cfif doRead>
|
||||
<cfset processingMode="read"/>
|
||||
<cfelseif doSave>
|
||||
<cfset processingMode="save"/>
|
||||
<cfelse>
|
||||
<cfif doPass OR !recordExists>
|
||||
<cfset processingMode="pass"/>
|
||||
<cfelse>
|
||||
<cfset processingMode="read"/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
</cfif>
|
||||
|
||||
<cfset initialProcessingMode = processingMode/>
|
||||
|
||||
|
||||
<!---debug <cfoutput>processingMode:#processingMode#</cfoutput>--->
|
||||
<!--- ---------------------------------------------------------- --->
|
||||
|
||||
<!---*** Необходимость вставки (против апдейта) определяется по существованию записи. Это небезопасно, поскольку наличие записи с ключом -1 может прекратить создание новых записей. Конечно, можно добавить констрейнт на ключевое поле, но это лишняя зависимость.
|
||||
Можно явно передавать команду вставки, а не заморачиваться с анализом ключа. Просто традиционно мы сигнализировали необходимость вставки, передавая невалидное значение ключа, обычно -1. Для целочисленных ключей можно было бы просто проверять положительность (что всю жизнь отлично работало), но хочется более общего.
|
||||
--->
|
||||
|
||||
<cfif processingMode IS "save"> <!--- validation lookup --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
|
||||
<cfif !param.key>
|
||||
<cfif param.warningState>
|
||||
<cfif NOT warningState><!--- catch the first fault --->
|
||||
<cfset warningMessage=param.warningMessage />
|
||||
</cfif>
|
||||
<cfset warningState="true" />
|
||||
</cfif>
|
||||
|
||||
<cfif param.errorState>
|
||||
<cfif NOT errorState><!--- catch the first fault --->
|
||||
<cfset errorMessage=param.errorMessage />
|
||||
</cfif>
|
||||
<cfset errorState="true" />
|
||||
<cfset validationOk="false"/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
<cfif errorState>
|
||||
<!--- clear warning state --->
|
||||
<cfset warningMessage="" />
|
||||
<cfset warningState=false />
|
||||
<!--- finish lookup --->
|
||||
<cfbreak/>
|
||||
</cfif>
|
||||
|
||||
</cfloop>
|
||||
|
||||
<cfif validationOk>
|
||||
<!---<cfdump var=#param#/> --->
|
||||
<cftry>
|
||||
<cfif recordExists><!--- update. Наличие keyValue гарантировано (уверен) --->
|
||||
<cfquery name="qSave" datasource="#ATTRIBUTES.datasource#" result="qSaveResult">
|
||||
update #ATTRIBUTES.table# set
|
||||
<cfset i=0 />
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<!--- не обновляем ключевые поля --->
|
||||
<cfif NOT (StructFind(param, "key")
|
||||
OR StructFind(param, "autoincrement")
|
||||
OR StructFind(param, "readonly")
|
||||
OR StructFind(param, "skipUpdate")
|
||||
)><cfif i++ GT 0>,</cfif>
|
||||
#param.field#=<cfqueryparam cfsqltype="#sqlType(param.type)#" value="#param.value#" null="#param.null#"/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
where 1=1
|
||||
<cfloop array=#keys# index="key">
|
||||
AND #key.field#=<cfqueryparam cfsqltype="#sqlType(key.type)#" value="#key.value#"/>
|
||||
</cfloop>
|
||||
</cfquery>
|
||||
<!---<cfdump var=#qSaveResult#/>--->
|
||||
<cfelse><!--- insert --->
|
||||
<cfquery name="qSave" datasource="#ATTRIBUTES.datasource#">
|
||||
insert into #ATTRIBUTES.table#
|
||||
(
|
||||
<cfset i=0 />
|
||||
<!--- ключевые поля без автоинкремента попадают в insert! --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfif NOT (StructFind(param, "autoincrement")
|
||||
OR StructFind(param, "readonly")
|
||||
OR StructFind(param, "skipInsert")
|
||||
)><cfif i++ GT 0>,</cfif>
|
||||
#param.field#
|
||||
</cfif>
|
||||
</cfloop>
|
||||
)
|
||||
values
|
||||
(
|
||||
<cfset i=0 />
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfif NOT (StructFind(param, "autoincrement")
|
||||
OR StructFind(param, "readonly")
|
||||
OR StructFind(param, "skipInsert")
|
||||
)><cfif i++ GT 0>,</cfif>
|
||||
<cfqueryparam cfsqltype="#sqlType(param.type)#" value="#param.value#" null="#param.null#"/>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
)
|
||||
<!---
|
||||
<cfif hasAutoIncrement>
|
||||
select scope_identity() as id;
|
||||
</cfif>
|
||||
--->
|
||||
<!---*** PostgreSQL incompatible hack follows--->
|
||||
<cfif hasAutoIncrement>
|
||||
returning #thistag.params[autoIncrementKeyIndex].field# as id;
|
||||
</cfif>;
|
||||
</cfquery>
|
||||
<!--- <cfdump var=#qSave#/> --->
|
||||
<cfif hasAutoIncrement>
|
||||
<cfset keys[autoIncrementKeyIndex].value=qSave.id/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
<!--- recordExists --->
|
||||
|
||||
|
||||
<cfset processingMode="read"/>
|
||||
|
||||
<cfcatch type="database">
|
||||
<cfset errorState="true" />
|
||||
<cfset errorMessage="Ошибка при записи в базу данных. #cfcatch.message# #cfcatch.detail#" />
|
||||
<cfset processingMode="pass" />
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
<cfelse><!--- (not) validationOk --->
|
||||
<cfset processingMode="pass"/>
|
||||
</cfif><!--- validationOk --->
|
||||
|
||||
</cfif><!--- processingMode EQ "save" --->
|
||||
|
||||
<!--- экспортируем данные --->
|
||||
<cfswitch expression=#processingMode#>
|
||||
<cfcase value="read">
|
||||
<cfquery name="qRead" datasource="#ATTRIBUTES.datasource#">
|
||||
select
|
||||
<cfset i=0 />
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfset i=i+1/>
|
||||
#param.field#<cfif i LT ArrayLen(thistag.params)>,</cfif>
|
||||
</cfloop>
|
||||
from #ATTRIBUTES.table#
|
||||
where 1=1
|
||||
<cfloop array=#keys# index="key">
|
||||
/*#sqlType(key.type)#*/
|
||||
AND #key.field#=<cfqueryparam cfsqltype="#sqlType(key.type)#" value="#key.value#" null="#key.null#"/>
|
||||
</cfloop>
|
||||
</cfquery>
|
||||
|
||||
<cfloop array=#thistag.params# index="param"><!--- *** --->
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.output#.#param.param#", structFind(qRead, #param.field#)) />
|
||||
</cfloop>
|
||||
</cfcase>
|
||||
|
||||
|
||||
<cfcase value="pass"><!--- заполнить все поля. Если значения переданы в форме или урле, тег параметра обязан их разобрать и подставить, в противном случае подставить инит-значения. Инит-значение по умолчанию пустая строка, дефолт по умолчанию тоже пустая строка --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<!--- <cfdump var=#param#/>--->
|
||||
<cfif param.hasInput>
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.output#.#param.param#", param.submittedValue) /><!---*** дефект: 03.12.2015, передаваемая строкой, при обработке dateFormat неправильно парсится --->
|
||||
<cfelse>
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.output#.#param.param#", param.init) />
|
||||
</cfif>
|
||||
</cfloop>
|
||||
</cfcase>
|
||||
|
||||
<cfdefaultcase>
|
||||
</cfdefaultcase>
|
||||
|
||||
</cfswitch>
|
||||
|
||||
<cfif len(ATTRIBUTES.info)><!--- экспортируем дополнительные сведения--->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.submittedValue", #param.submittedValue#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.errorState", #param.errorState#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.errorMessage", #param.errorMessage#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.warningState", #param.warningState#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.warningMessage", #param.warningMessage#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.info#.#param.param#.null", #param.null#) />
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<cfif len(ATTRIBUTES.meta)><!--- экспортируем метаданные параметра - для инвариантности вызовов --->
|
||||
<cfloop array=#thistag.params# index="param">
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.param", #param.param#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.field", #param.field#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.type", #param.type#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.displayName", #param.displayName#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.default", #param.default#) />
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.meta#.#param.param#.size", #param.size#) />
|
||||
</cfloop>
|
||||
</cfif>
|
||||
|
||||
<cfset SetVariable("CALLER.#ATTRIBUTES.status#", CreateObject("component","status").init(errorState,errorMessage,initialProcessingMode))/>
|
||||
|
||||
</cfif><!--- thisTag.ExecutionMode is 'end'--->
|
||||
|
||||
<!--- quick and dirty --->
|
||||
<cffunction name="sqlType">
|
||||
<cfargument name="type"/>
|
||||
|
||||
<cfswitch expression=#type#>
|
||||
<cfcase value="guid,uuid,idstamp"><cfreturn "CF_SQL_OTHER"/></cfcase><!--- hack for PostgreSQL uuid --->
|
||||
<cfdefaultcase><cfreturn uCase("CF_SQL_#type#")/></cfdefaultcase>
|
||||
</cfswitch>
|
||||
</cffunction>
|
||||
|
||||
<cffunction name="checkDataFormat">
|
||||
<cfargument name="type"/>
|
||||
<cfargument name="value"/>
|
||||
|
||||
<cfswitch expression=#type#>
|
||||
<cfcase value="integer"><cfreturn isValid("integer",value)/></cfcase>
|
||||
<cfcase value="guid,uuid,idstamp"><cfreturn isValid("guid",value)/></cfcase>
|
||||
<cfdefaultcase><cfreturn true/></cfdefaultcase>
|
||||
</cfswitch>
|
||||
</cffunction>
|
||||
|
||||
|
||||
<!--- //quick and dirty
|
||||
function sqlType(type) {
|
||||
switch (type) {
|
||||
case "guid,idstamp": return "CF_SQL_OTHER"; /*hack for PostgreSQL uuid*/ /*break not needed!*/
|
||||
default: return uCase("CF_SQL_#type#");
|
||||
}
|
||||
}
|
||||
|
||||
function checkDataFormat(type,value) {
|
||||
switch (type) {
|
||||
case "integer": return isValid("integer",value); /*break not needed!*/
|
||||
case "guid,uuid,idstamp": return isValid("guid",value); /*break not needed!*/ /*INCORRECT cfscript switch-case does not support lists*/
|
||||
default: return true;
|
||||
}
|
||||
} --->
|
||||
<cfscript>
|
||||
//readonly может транслироваться в pass!
|
||||
function translateMode(readonly) {
|
||||
if (readonly) {
|
||||
return "read";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
</cfscript>
|
||||
@@ -0,0 +1,24 @@
|
||||
<cfsilent>
|
||||
<!--- 20181209 v0.3 --->
|
||||
<!---v0.3 добавлен атрибут cfSqlType--->
|
||||
<cfif thisTag.executionMode IS "end" OR !thisTag.hasEndTag>
|
||||
<cfassociate basetag="cf_field_set" datacollection="fieldsArray"/>
|
||||
|
||||
<cfparam name="ATTRIBUTES.expression" default=""/>
|
||||
<cfparam name="ATTRIBUTES.title" default=""/>
|
||||
<cfparam name="ATTRIBUTES.name" default=""/>
|
||||
<cfparam name="ATTRIBUTES.cfSqlType" default="CF_SQL_VARCHAR"/>
|
||||
|
||||
<cfif ATTRIBUTES.expression IS "">
|
||||
<cfset ATTRIBUTES.expression=thisTag.generatedContent/>
|
||||
</cfif>
|
||||
|
||||
<cfif ATTRIBUTES.name IS "">
|
||||
<cfset regex="([[:word:]]+)[[:space:]]*$"/>
|
||||
<cfset matches=REFindNoCase(regex, ATTRIBUTES.expression, 1, true)/>
|
||||
<cfif arrayLen(matches.pos) GT 1>
|
||||
<cfset ATTRIBUTES.name=mid(ATTRIBUTES.expression, matches.pos[2], matches.len[2])/>
|
||||
</cfif>
|
||||
</cfif>
|
||||
</cfif>
|
||||
</cfsilent>
|
||||