diff options
Diffstat (limited to 'subsonic-main/src/main/webapp')
686 files changed, 22654 insertions, 0 deletions
diff --git a/subsonic-main/src/main/webapp/WEB-INF/applicationContext-cache.xml b/subsonic-main/src/main/webapp/WEB-INF/applicationContext-cache.xml new file mode 100644 index 00000000..a8692d08 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/applicationContext-cache.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> + + + <bean id="cacheFactory" class="net.sourceforge.subsonic.cache.CacheFactory"/> + + <bean id="userCache" factory-bean="cacheFactory" factory-method="getCache"> + <constructor-arg value="userCache"/> + </bean> + + <bean id="mediaFileMemoryCache" factory-bean="cacheFactory" factory-method="getCache"> + <constructor-arg value="mediaFileMemoryCache"/> + </bean> + + <bean id="musicFileMemoryCache" factory-bean="cacheFactory" factory-method="getCache"> + <constructor-arg value="musicFileMemoryCache"/> + </bean> + +</beans> diff --git a/subsonic-main/src/main/webapp/WEB-INF/applicationContext-security.xml b/subsonic-main/src/main/webapp/WEB-INF/applicationContext-security.xml new file mode 100644 index 00000000..8cf5e9c2 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/applicationContext-security.xml @@ -0,0 +1,234 @@ +<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+ <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
+ <property name="filterInvocationDefinitionSource">
+ <value>
+ PATTERN_TYPE_APACHE_ANT
+ /wap**=httpSessionContextIntegrationFilter,logoutFilter,basicProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,basicExceptionTranslationFilter,filterInvocationInterceptor
+ /podcastReceiver**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,basicProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
+ /podcast**=httpSessionContextIntegrationFilter,logoutFilter,basicProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,basicExceptionTranslationFilter,filterInvocationInterceptor
+ /rest/**=httpSessionContextIntegrationFilter,logoutFilter,basicProcessingFilter,restRequestParameterProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,basicExceptionTranslationFilter,filterInvocationInterceptor
+ /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,basicProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
+ </value>
+ </property>
+ </bean>
+
+ <bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>
+
+ <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
+ <constructor-arg value="/login.view?logout"/>
+ <!-- URL redirected to after logout -->
+ <constructor-arg>
+ <list>
+ <ref bean="rememberMeServices"/>
+ <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
+ </list>
+ </constructor-arg>
+ </bean>
+
+ <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
+ <property name="authenticationManager" ref="authenticationManager"/>
+ <property name="authenticationFailureUrl" value="/login.view?error"/>
+ <property name="defaultTargetUrl" value="/"/>
+ <property name="alwaysUseDefaultTargetUrl" value="true"/>
+ <property name="filterProcessesUrl" value="/j_acegi_security_check"/>
+ <property name="rememberMeServices" ref="rememberMeServices"/>
+ </bean>
+
+ <bean id="basicProcessingFilter" class="org.acegisecurity.ui.basicauth.BasicProcessingFilter">
+ <property name="authenticationManager" ref="authenticationManager"/>
+ <property name="authenticationEntryPoint" ref="basicProcessingFilterEntryPoint"/>
+ </bean>
+
+ <bean id="restRequestParameterProcessingFilter" class="net.sourceforge.subsonic.security.RESTRequestParameterProcessingFilter">
+ <property name="authenticationManager" ref="authenticationManager"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+
+ <bean id="basicProcessingFilterEntryPoint" class="org.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">
+ <property name="realmName" value="Subsonic"/>
+ </bean>
+
+ <bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter"/>
+
+ <bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
+ <property name="authenticationManager" ref="authenticationManager"/>
+ <property name="rememberMeServices" ref="rememberMeServices"/>
+ </bean>
+
+ <bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
+ <property name="key" value="subsonic"/>
+ <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
+ </bean>
+
+ <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
+ <property name="authenticationEntryPoint">
+ <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
+ <property name="loginFormUrl" value="/login.view?"/>
+ <property name="forceHttps" value="false"/>
+ </bean>
+ </property>
+ <property name="accessDeniedHandler">
+ <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
+ <property name="errorPage" value="/accessDenied.view"/>
+ </bean>
+ </property>
+ </bean>
+
+ <bean id="basicExceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
+ <property name="authenticationEntryPoint">
+ <bean class="org.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">
+ <property name="realmName" value="Subsonic"/>
+ </bean>
+ </property>
+ </bean>
+
+ <bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
+ <property name="authenticationManager" ref="authenticationManager"/>
+ <property name="alwaysReauthenticate" value="true"/>
+ <property name="accessDecisionManager" ref="accessDecisionManager"/>
+ <property name="objectDefinitionSource">
+ <value>
+ PATTERN_TYPE_APACHE_ANT
+
+ /login.view=IS_AUTHENTICATED_ANONYMOUSLY
+ /recover.view=IS_AUTHENTICATED_ANONYMOUSLY
+ /accessDenied.view=IS_AUTHENTICATED_ANONYMOUSLY
+ /videoPlayer.view=IS_AUTHENTICATED_ANONYMOUSLY
+ /coverArt.view=IS_AUTHENTICATED_ANONYMOUSLY
+ /stream/**=IS_AUTHENTICATED_ANONYMOUSLY
+ /share/**=IS_AUTHENTICATED_ANONYMOUSLY
+ /style/**=IS_AUTHENTICATED_ANONYMOUSLY
+ /icons/**=IS_AUTHENTICATED_ANONYMOUSLY
+ /flash/**=IS_AUTHENTICATED_ANONYMOUSLY
+ /script/**=IS_AUTHENTICATED_ANONYMOUSLY
+ /crossdomain.xml=IS_AUTHENTICATED_ANONYMOUSLY
+
+ /personalSettings.view=ROLE_SETTINGS
+ /passwordSettings.view=ROLE_SETTINGS
+ /playerSettings.view=ROLE_SETTINGS
+ /shareSettings.view=ROLE_SETTINGS
+
+ /generalSettings.view=ROLE_ADMIN
+ /advancedSettings.view=ROLE_ADMIN
+ /userSettings.view=ROLE_ADMIN
+ /musicFolderSettings.view=ROLE_ADMIN
+ /networkSettings.view=ROLE_ADMIN
+ /transcodingSettings.view=ROLE_ADMIN
+ /internetRadioSettings.view=ROLE_ADMIN
+ /podcastSettings.view=ROLE_ADMIN
+ /db.view=ROLE_ADMIN
+
+ /deletePlaylist.view=ROLE_PLAYLIST
+ /savePlaylist.view=ROLE_PLAYLIST
+
+ /download.view=ROLE_DOWNLOAD
+
+ /upload.view=ROLE_UPLOAD
+
+ /createShare.view=ROLE_SHARE
+
+ /changeCoverArt.view=ROLE_COVERART
+ /editTags.view=ROLE_COVERART
+
+ /setMusicFileInfo.view=ROLE_COMMENT
+
+ /podcastReceiverAdmin.view=ROLE_PODCAST
+
+ /**=IS_AUTHENTICATED_REMEMBERED
+ </value>
+ </property>
+ </bean>
+
+ <bean id="accessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
+ <property name="allowIfAllAbstainDecisions" value="false"/>
+ <property name="decisionVoters">
+ <list>
+ <bean class="org.acegisecurity.vote.RoleVoter"/>
+ <bean class="org.acegisecurity.vote.AuthenticatedVoter"/>
+ </list>
+ </property>
+ </bean>
+
+ <bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
+ <property name="userDetailsService" ref="securityService"/>
+ <property name="tokenValiditySeconds" value="31536000"/>
+ <!-- One year -->
+ <property name="key" value="subsonic"/>
+ </bean>
+
+ <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
+ <property name="providers">
+ <list>
+ <ref local="daoAuthenticationProvider"/>
+ <ref local="ldapAuthenticationProvider"/>
+ <bean class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
+ <property name="key" value="subsonic"/>
+ </bean>
+ <bean class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
+ <property name="key" value="subsonic"/>
+ </bean>
+ </list>
+ </property>
+ </bean>
+
+ <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
+ <property name="userDetailsService" ref="securityService"/>
+ <property name="userCache" ref="userCacheWrapper"/>
+ </bean>
+
+ <bean id="userCacheWrapper" class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
+ <property name="cache" ref="userCache"/>
+ </bean>
+
+ <bean id="ldapAuthenticationProvider" class="org.acegisecurity.providers.ldap.LdapAuthenticationProvider">
+ <constructor-arg ref="bindAuthenticator"/>
+ <constructor-arg ref="userDetailsServiceBasedAuthoritiesPopulator"/>
+ <property name="userCache" ref="userCacheWrapper"/>
+ </bean>
+
+ <bean id="bindAuthenticator" class="net.sourceforge.subsonic.ldap.SubsonicLdapBindAuthenticator">
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+
+ <bean id="userDetailsServiceBasedAuthoritiesPopulator"
+ class="net.sourceforge.subsonic.ldap.UserDetailsServiceBasedAuthoritiesPopulator">
+ <property name="userDetailsService" ref="securityService"/>
+ </bean>
+
+ <!-- Authorization of AJAX services. -->
+ <bean id="ajaxServiceInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
+ <property name="authenticationManager" ref="authenticationManager"/>
+ <property name="accessDecisionManager" ref="accessDecisionManager"/>
+ <property name="objectDefinitionSource">
+ <value>
+ net.sourceforge.subsonic.ajax.TagService.setTags=ROLE_COVERART
+ net.sourceforge.subsonic.ajax.TransferService.getUploadInfo=ROLE_UPLOAD
+ </value>
+ </property>
+ </bean>
+
+ <bean id="ajaxTagServiceSecure" class="org.springframework.aop.framework.ProxyFactoryBean">
+ <property name="target" ref="ajaxTagService"/>
+ <property name="interceptorNames">
+ <list>
+ <idref local="ajaxServiceInterceptor"/>
+ </list>
+ </property>
+ </bean>
+
+ <bean id="ajaxTransferServiceSecure" class="org.springframework.aop.framework.ProxyFactoryBean">
+ <property name="target" ref="ajaxTransferService"/>
+ <property name="interceptorNames">
+ <list>
+ <idref local="ajaxServiceInterceptor"/>
+ </list>
+ </property>
+ </bean>
+
+</beans>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/applicationContext-service.xml b/subsonic-main/src/main/webapp/WEB-INF/applicationContext-service.xml new file mode 100644 index 00000000..95f76359 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/applicationContext-service.xml @@ -0,0 +1,245 @@ +<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+ <!-- DAO's -->
+
+ <bean id="playerDao" class="net.sourceforge.subsonic.dao.PlayerDao">
+ <property name="daoHelper" ref="daoHelper"/>
+ </bean>
+
+ <bean id="mediaFileDao" class="net.sourceforge.subsonic.dao.MediaFileDao">
+ <property name="daoHelper" ref="daoHelper"/>
+ </bean>
+
+ <bean id="artistDao" class="net.sourceforge.subsonic.dao.ArtistDao">
+ <property name="daoHelper" ref="daoHelper"/>
+ </bean>
+
+ <bean id="albumDao" class="net.sourceforge.subsonic.dao.AlbumDao">
+ <property name="daoHelper" ref="daoHelper"/>
+ </bean>
+
+ <bean id="playlistDao" class="net.sourceforge.subsonic.dao.PlaylistDao">
+ <property name="daoHelper" ref="daoHelper"/>
+ </bean>
+
+ <bean id="internetRadioDao" class="net.sourceforge.subsonic.dao.InternetRadioDao">
+ <property name="daoHelper" ref="daoHelper"/>
+ </bean>
+
+ <bean id="musicFileInfoDao" class="net.sourceforge.subsonic.dao.RatingDao">
+ <property name="daoHelper" ref="daoHelper"/>
+ </bean>
+
+ <bean id="musicFolderDao" class="net.sourceforge.subsonic.dao.MusicFolderDao">
+ <property name="daoHelper" ref="daoHelper"/>
+ </bean>
+
+ <bean id="userDao" class="net.sourceforge.subsonic.dao.UserDao">
+ <property name="daoHelper" ref="daoHelper"/>
+ </bean>
+
+ <bean id="transcodingDao" class="net.sourceforge.subsonic.dao.TranscodingDao">
+ <property name="daoHelper" ref="daoHelper"/>
+ </bean>
+
+ <bean id="podcastDao" class="net.sourceforge.subsonic.dao.PodcastDao">
+ <property name="daoHelper" ref="daoHelper"/>
+ </bean>
+
+ <bean id="avatarDao" class="net.sourceforge.subsonic.dao.AvatarDao">
+ <property name="daoHelper" ref="daoHelper"/>
+ </bean>
+
+ <bean id="shareDao" class="net.sourceforge.subsonic.dao.ShareDao">
+ <property name="daoHelper" ref="daoHelper"/>
+ </bean>
+
+ <bean id="daoHelper" class="net.sourceforge.subsonic.dao.DaoHelper"/>
+
+
+ <!-- Services -->
+
+ <bean id="mediaFileService" class="net.sourceforge.subsonic.service.MediaFileService">
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="mediaFileMemoryCache" ref="mediaFileMemoryCache"/>
+ <property name="mediaFileDao" ref="mediaFileDao"/>
+ <property name="albumDao" ref="albumDao"/>
+ <property name="metaDataParserFactory" ref="metaDataParserFactory"/>
+ </bean>
+
+ <bean id="securityService" class="net.sourceforge.subsonic.service.SecurityService">
+ <property name="settingsService" ref="settingsService"/>
+ <property name="userDao" ref="userDao"/>
+ <property name="userCache" ref="userCache"/>
+ </bean>
+
+ <bean id="settingsService" class="net.sourceforge.subsonic.service.SettingsService" init-method="init">
+ <property name="internetRadioDao" ref="internetRadioDao"/>
+ <property name="musicFolderDao" ref="musicFolderDao"/>
+ <property name="userDao" ref="userDao"/>
+ <property name="avatarDao" ref="avatarDao"/>
+ <property name="versionService" ref="versionService"/>
+ </bean>
+
+ <bean id="mediaScannerService" class="net.sourceforge.subsonic.service.MediaScannerService" init-method="init" depends-on="metaDataParserFactory">
+ <property name="settingsService" ref="settingsService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="mediaFileDao" ref="mediaFileDao"/>
+ <property name="artistDao" ref="artistDao"/>
+ <property name="albumDao" ref="albumDao"/>
+ <property name="searchService" ref="searchService"/>
+ </bean>
+
+ <bean id="searchService" class="net.sourceforge.subsonic.service.SearchService">
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="artistDao" ref="artistDao"/>
+ <property name="albumDao" ref="albumDao"/>
+ </bean>
+
+ <bean id="networkService" class="net.sourceforge.subsonic.service.NetworkService" init-method="init">
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+
+ <bean id="playerService" class="net.sourceforge.subsonic.service.PlayerService" init-method="init">
+ <property name="playerDao" ref="playerDao"/>
+ <property name="statusService" ref="statusService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="transcodingService" ref="transcodingService"/>
+ </bean>
+
+ <bean id="playlistService" class="net.sourceforge.subsonic.service.PlaylistService" init-method="init">
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="mediaFileDao" ref="mediaFileDao"/>
+ <property name="playlistDao" ref="playlistDao"/>
+ </bean>
+
+ <bean id="versionService" class="net.sourceforge.subsonic.service.VersionService"/>
+
+ <bean id="statusService" class="net.sourceforge.subsonic.service.StatusService"/>
+
+ <bean id="musicInfoService" class="net.sourceforge.subsonic.service.RatingService">
+ <property name="ratingDao" ref="musicFileInfoDao"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="securityService" ref="securityService"/>
+ </bean>
+
+ <bean id="musicIndexService" class="net.sourceforge.subsonic.service.MusicIndexService">
+ <property name="settingsService" ref="settingsService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="mediaFileDao" ref="mediaFileDao"/>
+ </bean>
+
+ <bean id="audioScrobblerService" class="net.sourceforge.subsonic.service.AudioScrobblerService">
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+
+ <bean id="transcodingService" class="net.sourceforge.subsonic.service.TranscodingService">
+ <property name="transcodingDao" ref="transcodingDao"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="playerService" ref="playerService"/>
+ </bean>
+
+ <bean id="shareService" class="net.sourceforge.subsonic.service.ShareService">
+ <property name="shareDao" ref="shareDao"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ </bean>
+
+ <bean id="podcastService" class="net.sourceforge.subsonic.service.PodcastService" init-method="init">
+ <property name="podcastDao" ref="podcastDao"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ </bean>
+
+ <bean id="adService" class="net.sourceforge.subsonic.service.AdService">
+ <property name="adInterval" value="4"/>
+ </bean>
+
+ <bean id="jukeboxService" class="net.sourceforge.subsonic.service.JukeboxService">
+ <property name="statusService" ref="statusService"/>
+ <property name="transcodingService" ref="transcodingService"/>
+ <property name="audioScrobblerService" ref="audioScrobblerService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="securityService" ref="securityService"/>
+ </bean>
+
+ <bean id="metaDataParserFactory" class="net.sourceforge.subsonic.service.metadata.MetaDataParserFactory">
+ <property name="parsers">
+ <list>
+ <bean class="net.sourceforge.subsonic.service.metadata.JaudiotaggerParser"/>
+ <bean class="net.sourceforge.subsonic.service.metadata.FFmpegParser">
+ <property name="transcodingService" ref="transcodingService"/>
+ </bean>
+ <bean class="net.sourceforge.subsonic.service.metadata.DefaultMetaDataParser"/>
+ </list>
+ </property>
+ </bean>
+
+ <!-- AJAX services -->
+
+ <bean id="ajaxMultiService" class="net.sourceforge.subsonic.ajax.MultiService">
+ <property name="networkService" ref="networkService"/>
+ </bean>
+
+ <bean id="ajaxNowPlayingService" class="net.sourceforge.subsonic.ajax.NowPlayingService">
+ <property name="playerService" ref="playerService"/>
+ <property name="statusService" ref="statusService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="mediaScannerService" ref="mediaScannerService"/>
+ </bean>
+
+ <bean id="ajaxPlayQueueService" class="net.sourceforge.subsonic.ajax.PlayQueueService">
+ <property name="playerService" ref="playerService"/>
+ <property name="playlistService" ref="playlistService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="mediaFileDao" ref="mediaFileDao"/>
+ <property name="jukeboxService" ref="jukeboxService"/>
+ <property name="transcodingService" ref="transcodingService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="securityService" ref="securityService"/>
+ </bean>
+
+ <bean id="ajaxPlaylistService" class="net.sourceforge.subsonic.ajax.PlaylistService">
+ <property name="playlistService" ref="playlistService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="mediaFileDao" ref="mediaFileDao"/>
+ </bean>
+
+ <bean id="ajaxLyricsService" class="net.sourceforge.subsonic.ajax.LyricsService"/>
+
+ <bean id="ajaxCoverArtService" class="net.sourceforge.subsonic.ajax.CoverArtService">
+ <property name="securityService" ref="securityService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ </bean>
+
+ <bean id="ajaxStarService" class="net.sourceforge.subsonic.ajax.StarService">
+ <property name="securityService" ref="securityService"/>
+ <property name="mediaFileDao" ref="mediaFileDao"/>
+ </bean>
+
+ <bean id="ajaxTagService" class="net.sourceforge.subsonic.ajax.TagService">
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="metaDataParserFactory" ref="metaDataParserFactory"/>
+ </bean>
+
+ <bean id="ajaxTransferService" class="net.sourceforge.subsonic.ajax.TransferService"/>
+
+ <bean id="ajaxChatService" class="net.sourceforge.subsonic.ajax.ChatService" init-method="init">
+ <property name="securityService" ref="securityService"/>
+ </bean>
+
+</beans>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/dwr.xml b/subsonic-main/src/main/webapp/WEB-INF/dwr.xml new file mode 100644 index 00000000..e7ea3187 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/dwr.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr/dwr30.dtd">
+
+<dwr>
+ <allow>
+
+ <create creator="spring" javascript="multiService">
+ <param name="beanName" value="ajaxMultiService"/>
+ </create>
+
+ <create creator="spring" javascript="nowPlayingService">
+ <param name="beanName" value="ajaxNowPlayingService"/>
+ </create>
+
+ <create creator="spring" javascript="playQueueService">
+ <param name="beanName" value="ajaxPlayQueueService"/>
+ </create>
+
+ <create creator="spring" javascript="playlistService">
+ <param name="beanName" value="ajaxPlaylistService"/>
+ </create>
+
+ <create creator="spring" javascript="lyricsService">
+ <param name="beanName" value="ajaxLyricsService"/>
+ </create>
+
+ <create creator="spring" javascript="coverArtService">
+ <param name="beanName" value="ajaxCoverArtService"/>
+ </create>
+
+ <create creator="spring" javascript="starService">
+ <param name="beanName" value="ajaxStarService"/>
+ </create>
+
+ <create creator="spring" javascript="tagService">
+ <param name="beanName" value="ajaxTagService"/>
+ </create>
+
+ <create creator="spring" javascript="transferService">
+ <param name="beanName" value="ajaxTransferService"/>
+ </create>
+
+ <create creator="spring" javascript="chatService">
+ <param name="beanName" value="ajaxChatService"/>
+ </create>
+
+ <convert converter="bean" match="net.sourceforge.subsonic.ajax.NetworkStatus"/>
+ <convert converter="bean" match="net.sourceforge.subsonic.ajax.NowPlayingInfo"/>
+ <convert converter="bean" match="net.sourceforge.subsonic.ajax.ScanInfo"/>
+ <convert converter="bean" match="net.sourceforge.subsonic.ajax.PlayQueueInfo"/>
+ <convert converter="bean" match="net.sourceforge.subsonic.ajax.PlayQueueInfo$Entry"/>
+ <convert converter="bean" match="net.sourceforge.subsonic.ajax.PlaylistInfo"/>
+ <convert converter="bean" match="net.sourceforge.subsonic.ajax.PlaylistInfo$Entry"/>
+ <convert converter="bean" match="net.sourceforge.subsonic.domain.Playlist"/>
+ <convert converter="bean" match="net.sourceforge.subsonic.ajax.UploadInfo"/>
+ <convert converter="bean" match="net.sourceforge.subsonic.ajax.LyricsInfo"/>
+ <convert converter="bean" match="net.sourceforge.subsonic.ajax.CoverArtInfo"/>
+ <convert converter="bean" match="net.sourceforge.subsonic.ajax.ChatService$Message"/>
+ <convert converter="bean" match="net.sourceforge.subsonic.ajax.ChatService$Messages"/>
+
+ </allow>
+</dwr>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/accessDenied.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/accessDenied.jsp new file mode 100644 index 00000000..78d2b910 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/accessDenied.jsp @@ -0,0 +1,22 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<html>
+<head>
+ <%@ include file="head.jsp" %>
+</head>
+
+<body class="mainframe bgcolor1">
+
+<h1>
+ <img src="<spring:theme code="errorImage"/>" alt=""/>
+ <fmt:message key="accessDenied.title"/>
+</h1>
+
+<p>
+ <fmt:message key="accessDenied.text"/>
+</p>
+
+<div class="back"><a href="javascript:history.go(-1)"><fmt:message key="common.back"/></a></div>
+
+</body>
+</html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/advancedSettings.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/advancedSettings.jsp new file mode 100644 index 00000000..9b3a95b1 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/advancedSettings.jsp @@ -0,0 +1,142 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="<c:url value="/script/scripts.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/prototype.js"/>"></script>
+ <script type="text/javascript" language="javascript">
+ function enableLdapFields() {
+ var checkbox = $("ldap");
+ var table = $("ldapTable");
+
+ if (checkbox && checkbox.checked) {
+ table.show();
+ } else {
+ table.hide();
+ }
+ }
+ </script>
+</head>
+
+<body class="mainframe bgcolor1" onload="enableLdapFields()">
+<script type="text/javascript" src="<c:url value="/script/wz_tooltip.js"/>"></script>
+<script type="text/javascript" src="<c:url value="/script/tip_balloon.js"/>"></script>
+
+<c:import url="settingsHeader.jsp">
+ <c:param name="cat" value="advanced"/>
+</c:import>
+
+<form:form method="post" action="advancedSettings.view" commandName="command">
+
+ <table style="white-space:nowrap" class="indent">
+
+ <tr>
+ <td><fmt:message key="advancedsettings.downsamplecommand"/></td>
+ <td>
+ <form:input path="downsampleCommand" size="70"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="downsamplecommand"/></c:import>
+ </td>
+ </tr>
+
+ <tr><td colspan="2"> </td></tr>
+
+ <tr>
+ <td><fmt:message key="advancedsettings.coverartlimit"/></td>
+ <td>
+ <form:input path="coverArtLimit" size="8"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="coverartlimit"/></c:import>
+ </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="advancedsettings.downloadlimit"/></td>
+ <td>
+ <form:input path="downloadLimit" size="8"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="downloadlimit"/></c:import>
+ </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="advancedsettings.uploadlimit"/></td>
+ <td>
+ <form:input path="uploadLimit" size="8"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="uploadlimit"/></c:import>
+ </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="advancedsettings.streamport"/></td>
+ <td>
+ <form:input path="streamPort" size="8"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="streamport"/></c:import>
+ </td>
+ </tr>
+
+ <tr><td colspan="2"> </td></tr>
+
+ <tr>
+ <td colspan="2">
+ <form:checkbox path="ldapEnabled" id="ldap" cssClass="checkbox" onclick="javascript:enableLdapFields()"/>
+ <label for="ldap"><fmt:message key="advancedsettings.ldapenabled"/></label>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="ldap"/></c:import>
+ </td>
+ </tr>
+
+ <tr><td colspan="2">
+ <table class="indent" id="ldapTable" style="padding-left:2em">
+ <tr>
+ <td><fmt:message key="advancedsettings.ldapurl"/></td>
+ <td colspan="3">
+ <form:input path="ldapUrl" size="70"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="ldapurl"/></c:import>
+ </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="advancedsettings.ldapsearchfilter"/></td>
+ <td colspan="3">
+ <form:input path="ldapSearchFilter" size="70"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="ldapsearchfilter"/></c:import>
+ </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="advancedsettings.ldapmanagerdn"/></td>
+ <td>
+ <form:input path="ldapManagerDn" size="20"/>
+ </td>
+ <td><fmt:message key="advancedsettings.ldapmanagerpassword"/></td>
+ <td>
+ <form:password path="ldapManagerPassword" size="20"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="ldapmanagerdn"/></c:import>
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="5">
+ <form:checkbox path="ldapAutoShadowing" id="ldapAutoShadowing" cssClass="checkbox"/>
+ <label for="ldapAutoShadowing"><fmt:message key="advancedsettings.ldapautoshadowing"><fmt:param value="${command.brand}"/></fmt:message></label>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="ldapautoshadowing"/></c:import>
+ </td>
+ </tr>
+ </table>
+ </td></tr>
+
+ <tr>
+ <td colspan="2" style="padding-top:1.5em">
+ <input type="submit" value="<fmt:message key="common.save"/>" style="margin-right:0.3em">
+ <input type="button" value="<fmt:message key="common.cancel"/>" onclick="location.href='nowPlaying.view'">
+ </td>
+ </tr>
+
+ </table>
+</form:form>
+
+<c:if test="${command.reloadNeeded}">
+ <script language="javascript" type="text/javascript">
+ parent.frames.left.location.href="left.view?";
+ parent.frames.playQueue.location.href="playQueue.view?";
+ </script>
+</c:if>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/allmusic.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/allmusic.jsp new file mode 100644 index 00000000..1af611fb --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/allmusic.jsp @@ -0,0 +1,16 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+</head>
+
+<body onload="document.allmusic.submit();" class="mainframe bgcolor1">
+<h2><fmt:message key="allmusic.text"><fmt:param value="${album}"/></fmt:message></h2>
+
+<form name="allmusic" action="http://www.allmusic.com/search" method="POST" accept-charset="iso-8859-1">
+ <input type="hidden" name="search_term" value="${album}"/>
+ <input type="hidden" name="search_type" value="album"/>
+</form>
+
+</body>
+</html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/avatarUploadResult.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/avatarUploadResult.jsp new file mode 100644 index 00000000..6c3b1010 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/avatarUploadResult.jsp @@ -0,0 +1,35 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<html>
+<head>
+ <%@ include file="head.jsp" %>
+</head>
+<body class="mainframe bgcolor1">
+
+<h1>
+ <img src="<spring:theme code="settingsImage"/>" alt=""/>
+ <fmt:message key="avataruploadresult.title"/>
+</h1>
+
+<c:choose>
+ <c:when test="${empty model.error}">
+ <p>
+ <fmt:message key="avataruploadresult.success"><fmt:param value="${model.avatar.name}"/></fmt:message>
+ <sub:url value="avatar.view" var="avatarUrl">
+ <sub:param name="username" value="${model.username}"/>
+ </sub:url>
+ <img src="${avatarUrl}" alt="${model.avatar.name}" width="${model.avatar.width}"
+ height="${model.avatar.height}" style="padding-left:2em"/>
+ </p>
+ </c:when>
+ <c:otherwise>
+ <p class="warning">
+ <fmt:message key="avataruploadresult.failure"/>
+ </p>
+ </c:otherwise>
+</c:choose>
+
+<div class="back"><a href="personalSettings.view?"><fmt:message key="common.back"/></a></div>
+
+</body>
+</html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/changeCoverArt.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/changeCoverArt.jsp new file mode 100644 index 00000000..598f12ca --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/changeCoverArt.jsp @@ -0,0 +1,206 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/coverArtService.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/engine.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/util.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/prototype.js"/>"></script>
+ <script type="text/javascript" src="https://www.google.com/jsapi"></script>
+
+ <script type="text/javascript" language="javascript">
+
+ dwr.engine.setErrorHandler(null);
+ google.load('search', '1');
+ var imageSearch;
+
+ function setImage(imageUrl) {
+ $("wait").show();
+ $("result").hide();
+ $("success").hide();
+ $("error").hide();
+ $("errorDetails").hide();
+ $("noImagesFound").hide();
+ var id = dwr.util.getValue("id");
+ coverArtService.setCoverArtImage(id, imageUrl, setImageComplete);
+ }
+
+ function setImageComplete(errorDetails) {
+ $("wait").hide();
+ if (errorDetails != null) {
+ dwr.util.setValue("errorDetails", "<br/>" + errorDetails, { escapeHtml:false });
+ $("error").show();
+ $("errorDetails").show();
+ } else {
+ $("success").show();
+ }
+ }
+
+ function searchComplete() {
+
+ $("wait").hide();
+
+ if (imageSearch.results && imageSearch.results.length > 0) {
+
+ var images = $("images");
+ images.innerHTML = "";
+
+ var results = imageSearch.results;
+ for (var i = 0; i < results.length; i++) {
+ var result = results[i];
+ var node = $("template").cloneNode(true);
+
+ var link = node.getElementsByClassName("search-result-link")[0];
+ link.href = "javascript:setImage('" + result.url + "');";
+
+ var thumbnail = node.getElementsByClassName("search-result-thumbnail")[0];
+ thumbnail.src = result.tbUrl;
+
+ var title = node.getElementsByClassName("search-result-title")[0];
+ title.innerHTML = result.contentNoFormatting.truncate(30);
+
+ var dimension = node.getElementsByClassName("search-result-dimension")[0];
+ dimension.innerHTML = result.width + " × " + result.height;
+
+ var url = node.getElementsByClassName("search-result-url")[0];
+ url.innerHTML = result.visibleUrl;
+
+ node.show();
+ images.appendChild(node);
+ }
+
+ $("result").show();
+
+ addPaginationLinks(imageSearch);
+
+ } else {
+ $("noImagesFound").show();
+ }
+ }
+
+ function addPaginationLinks() {
+
+ // To paginate search results, use the cursor function.
+ var cursor = imageSearch.cursor;
+ var curPage = cursor.currentPageIndex; // check what page the app is on
+ var pagesDiv = document.createElement("div");
+ for (var i = 0; i < cursor.pages.length; i++) {
+ var page = cursor.pages[i];
+ var label;
+ if (curPage == i) {
+ // If we are on the current page, then don"t make a link.
+ label = document.createElement("b");
+ } else {
+
+ // Create links to other pages using gotoPage() on the searcher.
+ label = document.createElement("a");
+ label.href = "javascript:imageSearch.gotoPage(" + i + ");";
+ }
+ label.innerHTML = page.label;
+ label.style.marginRight = "1em";
+ pagesDiv.appendChild(label);
+ }
+
+ // Create link to next page.
+ if (curPage < cursor.pages.length - 1) {
+ var next = document.createElement("a");
+ next.href = "javascript:imageSearch.gotoPage(" + (curPage + 1) + ");";
+ next.innerHTML = "<fmt:message key="common.next"/>";
+ next.style.marginLeft = "1em";
+ pagesDiv.appendChild(next);
+ }
+
+ var pages = $("pages");
+ pages.innerHTML = "";
+ pages.appendChild(pagesDiv);
+ }
+
+ function search() {
+
+ $("wait").show();
+ $("result").hide();
+ $("success").hide();
+ $("error").hide();
+ $("errorDetails").hide();
+ $("noImagesFound").hide();
+
+ var query = dwr.util.getValue("query");
+ imageSearch.execute(query);
+ }
+
+ function onLoad() {
+
+ imageSearch = new google.search.ImageSearch();
+ imageSearch.setSearchCompleteCallback(this, searchComplete, null);
+ imageSearch.setNoHtmlGeneration();
+ imageSearch.setResultSetSize(8);
+
+ google.search.Search.getBranding("branding");
+
+ $("template").hide();
+
+ search();
+ }
+ google.setOnLoadCallback(onLoad);
+
+
+ </script>
+</head>
+<body class="mainframe bgcolor1">
+<h1><fmt:message key="changecoverart.title"/></h1>
+<form action="javascript:search()">
+ <table class="indent"><tr>
+ <td><input id="query" name="query" size="70" type="text" value="${model.artist} ${model.album}" onclick="select()"/></td>
+ <td style="padding-left:0.5em"><input type="submit" value="<fmt:message key="changecoverart.search"/>"/></td>
+ </tr></table>
+</form>
+
+<form action="javascript:setImage(dwr.util.getValue('url'))">
+ <table><tr>
+ <input id="id" type="hidden" name="id" value="${model.id}"/>
+ <td><label for="url"><fmt:message key="changecoverart.address"/></label></td>
+ <td style="padding-left:0.5em"><input type="text" name="url" size="50" id="url" value="http://" onclick="select()"/></td>
+ <td style="padding-left:0.5em"><input type="submit" value="<fmt:message key="common.ok"/>"></td>
+ </tr></table>
+</form>
+<sub:url value="main.view" var="backUrl"><sub:param name="id" value="${model.id}"/></sub:url>
+<div style="padding-top:0.5em;padding-bottom:0.5em">
+ <div class="back"><a href="${backUrl}"><fmt:message key="common.back"/></a></div>
+</div>
+
+<h2 id="wait" style="display:none"><fmt:message key="changecoverart.wait"/></h2>
+<h2 id="noImagesFound" style="display:none"><fmt:message key="changecoverart.noimagesfound"/></h2>
+<h2 id="success" style="display:none"><fmt:message key="changecoverart.success"/></h2>
+<h2 id="error" style="display:none"><fmt:message key="changecoverart.error"/></h2>
+<div id="errorDetails" class="warning" style="display:none">
+</div>
+
+<div id="result">
+
+ <div id="pages" style="float:left;padding-left:0.5em;padding-top:0.5em">
+ </div>
+
+ <div id="branding" style="float:right;padding-right:1em;padding-top:0.5em">
+ </div>
+
+ <div style="clear:both;">
+ </div>
+
+ <div id="images" style="width:100%;padding-bottom:2em">
+ </div>
+
+ <div style="clear:both;">
+ </div>
+
+</div>
+
+<div id="template" style="float:left; height:190px; width:220px;padding:0.5em;position:relative">
+ <div style="position:absolute;bottom:0">
+ <a class="search-result-link"><img class="search-result-thumbnail" style="padding:1px; border:1px solid #021a40; background-color:white;"></a>
+ <div class="search-result-title"></div>
+ <div class="search-result-dimension detail"></div>
+ <div class="search-result-url detail"></div>
+ </div>
+</div>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/coverArt.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/coverArt.jsp new file mode 100644 index 00000000..a5030499 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/coverArt.jsp @@ -0,0 +1,86 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+<%@ include file="include.jsp" %>
+
+<%--
+PARAMETERS
+ albumId: ID of album.
+ coverArtSize: Height and width of cover art.
+ albumName: Album name to display as caption and img alt.
+ showLink: Whether to make the cover art image link to the album page.
+ showZoom: Whether to display a link for zooming the cover art.
+ showChange: Whether to display a link for changing the cover art.
+ showCaption: Whether to display the album name as a caption below the image.
+ appearAfter: Fade in after this many milliseconds, or nil if no fading in should happen.
+--%>
+<c:choose>
+ <c:when test="${empty param.coverArtSize}">
+ <c:set var="size" value="auto"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="size" value="${param.coverArtSize + 8}px"/>
+ </c:otherwise>
+</c:choose>
+
+<c:set var="opacity" value="${empty param.appearAfter ? 1 : 0}"/>
+
+<div style="width:${size}; max-width:${size}; height:${size}; max-height:${size}" title="${param.albumName}">
+ <sub:url value="main.view" var="mainUrl">
+ <sub:param name="id" value="${param.albumId}"/>
+ </sub:url>
+
+ <sub:url value="/coverArt.view" var="coverArtUrl">
+ <c:if test="${not empty param.coverArtSize}">
+ <sub:param name="size" value="${param.coverArtSize}"/>
+ </c:if>
+ <sub:param name="id" value="${param.albumId}"/>
+ </sub:url>
+ <sub:url value="/coverArt.view" var="zoomCoverArtUrl">
+ <sub:param name="id" value="${param.albumId}"/>
+ </sub:url>
+
+ <str:randomString count="5" type="alphabet" var="divId"/>
+ <div class="outerpair1" id="${divId}" style="display:none">
+ <div class="outerpair2">
+ <div class="shadowbox">
+ <div class="innerbox">
+ <c:choose>
+ <c:when test="${param.showLink}"><a href="${mainUrl}" title="${param.albumName}"></c:when>
+ <c:when test="${param.showZoom}"><a href="${zoomCoverArtUrl}" rel="zoom" title="${param.albumName}"></c:when>
+ </c:choose>
+ <img src="${coverArtUrl}" alt="${param.albumName}">
+ <c:if test="${param.showLink or param.showZoom}"></a></c:if>
+ </div>
+ </div>
+ </div>
+ </div>
+ <c:if test="${not empty param.appearAfter}">
+ <script type="text/javascript">
+ if (window.addEventListener) {
+ window.addEventListener('load', function() {
+ setTimeout("$('#${divId}').fadeIn(500)", ${param.appearAfter});
+ }, false);
+ }
+ </script>
+ </c:if>
+</div>
+
+<div style="text-align:right; padding-right: 8px;">
+ <c:if test="${param.showChange}">
+ <sub:url value="/changeCoverArt.view" var="changeCoverArtUrl">
+ <sub:param name="id" value="${param.albumId}"/>
+ </sub:url>
+ <a class="detail" href="${changeCoverArtUrl}"><fmt:message key="coverart.change"/></a>
+ </c:if>
+
+ <c:if test="${param.showZoom and param.showChange}">
+ |
+ </c:if>
+
+ <c:if test="${param.showZoom}">
+ <a class="detail" rel="zoom" title="${param.albumName}" href="${zoomCoverArtUrl}"><fmt:message key="coverart.zoom"/></a>
+ </c:if>
+
+ <c:if test="${not param.showZoom and not param.showChange and param.showCaption}">
+ <span class="detail"><str:truncateNicely upper="17">${param.albumName}</str:truncateNicely></span>
+ </c:if>
+</div>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/createShare.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/createShare.jsp new file mode 100644 index 00000000..3f739077 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/createShare.jsp @@ -0,0 +1,51 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<html>
+<head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
+</head>
+<body class="mainframe bgcolor1">
+
+<h1><fmt:message key="share.title"/></h1>
+
+<c:choose>
+ <c:when test="${model.urlRedirectionEnabled}">
+ <fmt:message key="share.warning"/>
+ <p>
+ <a href="http://www.facebook.com/sharer.php?u=${model.playUrl}" target="_blank"><img src="<spring:theme code="shareFacebookImage"/>" alt=""></a>
+ <a href="http://www.facebook.com/sharer.php?u=${model.playUrl}" target="_blank"><fmt:message key="share.facebook"/></a>
+ </p>
+
+ <p>
+ <a href="http://twitter.com/?status=Listening to ${model.playUrl}" target="_blank"><img src="<spring:theme code="shareTwitterImage"/>" alt=""></a>
+ <a href="http://twitter.com/?status=Listening to ${model.playUrl}" target="_blank"><fmt:message key="share.twitter"/></a>
+ </p>
+ <p>
+ <g:plusone size="small" annotation="none" href="${model.playUrl}"></g:plusone> <fmt:message key="share.googleplus"/>
+ </p>
+ <p>
+ <fmt:message key="share.link">
+ <fmt:param>${model.playUrl}</fmt:param>
+ </fmt:message>
+ </p>
+ </c:when>
+ <c:otherwise>
+ <p>
+ <fmt:message key="share.disabled"/>
+ </p>
+ </c:otherwise>
+</c:choose>
+
+
+<div style="padding-top:1em">
+ <c:if test="${not empty model.dir}">
+ <sub:url value="main.view" var="backUrl"><sub:param name="path" value="${model.dir.path}"/></sub:url>
+ <div class="back" style="float:left;padding-right:10pt"><a href="${backUrl}"><fmt:message key="common.back"/></a></div>
+ </c:if>
+ <c:if test="${model.user.settingsRole}">
+ <div class="forward" style="float:left"><a href="shareSettings.view"><fmt:message key="share.manage"/></a></div>
+ </c:if>
+</div>
+</body>
+</html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/db.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/db.jsp new file mode 100644 index 00000000..52918ab1 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/db.jsp @@ -0,0 +1,45 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+</head><body class="mainframe bgcolor1">
+
+<h1>Database query</h1>
+
+<form method="post" action="db.view">
+ <textarea rows="10" cols="80" name="query" style="margin-top:1em">${model.query}</textarea>
+ <input type="submit" value="<fmt:message key="common.ok"/>">
+</form>
+
+<c:if test="${not empty model.result}">
+ <h1 style="margin-top:2em">Result</h1>
+
+ <table class="indent ruleTable">
+ <c:forEach items="${model.result}" var="row" varStatus="loopStatus">
+
+ <c:if test="${loopStatus.count == 1}">
+ <tr>
+ <c:forEach items="${row}" var="entry">
+ <td class="ruleTableHeader">${entry.key}</td>
+ </c:forEach>
+ </tr>
+ </c:if>
+ <tr>
+ <c:forEach items="${row}" var="entry">
+ <td class="ruleTableCell">${entry.value}</td>
+ </c:forEach>
+ </tr>
+ </c:forEach>
+
+ </table>
+</c:if>
+
+<c:if test="${not empty model.error}">
+ <h1 style="margin-top:2em">Error</h1>
+
+ <p class="warning">
+ ${model.error}
+ </p>
+</c:if>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/donate.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/donate.jsp new file mode 100644 index 00000000..77906cb1 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/donate.jsp @@ -0,0 +1,147 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+<%--@elvariable id="command" type="net.sourceforge.subsonic.command.DonateCommand"--%>
+<html>
+<head>
+ <%@ include file="head.jsp" %>
+</head>
+<body class="mainframe bgcolor1">
+
+<h1>
+ <img src="<spring:theme code="donateImage"/>" alt=""/>
+ <fmt:message key="donate.title"/>
+</h1>
+<c:if test="${not empty command.path}">
+ <sub:url value="main.view" var="backUrl">
+ <sub:param name="path" value="${command.path}"/>
+ </sub:url>
+ <div class="back"><a href="${backUrl}">
+ <fmt:message key="common.back"/>
+ </a></div>
+ <br/>
+</c:if>
+
+<c:url value="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=E5RNJMDJ7C862" var="donate10Url"/>
+<c:url value="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CKRS9A4J99TFN" var="donate15Url"/>
+<c:url value="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H79PAZLVHFT6E" var="donate20Url"/>
+<c:url value="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2TGXFN7AVREEN" var="donate25Url"/>
+<c:url value="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=BXJVAQALLFREC" var="donate30Url"/>
+<c:url value="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=M5PX55AC4ER9Y" var="donate50Url"/>
+
+<div style="width:50em; max-width:50em">
+
+<fmt:message key="donate.textbefore"><fmt:param value="${command.brand}"/></fmt:message>
+
+<table cellpadding="10">
+ <tr>
+ <td>
+ <table>
+ <tr>
+ <td><a href="${donate10Url}" target="_blank"><img src="<spring:theme code="paypalImage"/>" alt=""/></a> </td>
+ </tr>
+ <tr>
+ <td class="detail" style="text-align:center;"><fmt:message key="donate.amount"><fmt:param value="€10"/></fmt:message></td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tr>
+ <td><a href="${donate15Url}" target="_blank"><img src="<spring:theme code="paypalImage"/>" alt=""/></a> </td>
+ </tr>
+ <tr>
+ <td class="detail" style="text-align:center;"><fmt:message key="donate.amount"><fmt:param value="€15"/></fmt:message></td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tr>
+ <td><a href="${donate20Url}" target="_blank"><img src="<spring:theme code="paypalImage"/>" alt=""/></a> </td>
+ </tr>
+ <tr>
+ <td class="detail" style="text-align:center;"><fmt:message key="donate.amount"><fmt:param value="€20"/></fmt:message></td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tr>
+ <td><a href="${donate25Url}" target="_blank"><img src="<spring:theme code="paypalImage"/>" alt=""/></a> </td>
+ </tr>
+ <tr>
+ <td class="detail" style="text-align:center;"><fmt:message key="donate.amount"><fmt:param value="€25"/></fmt:message></td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tr>
+ <td><a href="${donate30Url}" target="_blank"><img src="<spring:theme code="paypalImage"/>" alt=""/></a> </td>
+ </tr>
+ <tr>
+ <td class="detail" style="text-align:center;"><fmt:message key="donate.amount"><fmt:param value="€30"/></fmt:message></td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tr>
+ <td><a href="${donate50Url}" target="_blank"><img src="<spring:theme code="paypalImage"/>" alt=""/></a> </td>
+ </tr>
+ <tr>
+ <td class="detail" style="text-align:center;"><fmt:message key="donate.amount"><fmt:param value="€50"/></fmt:message></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+
+<fmt:message key="donate.textafter"/>
+
+<c:choose>
+ <c:when test="${command.licenseValid}">
+ <p>
+ <b>
+ <fmt:formatDate value="${command.licenseDate}" dateStyle="long" var="licenseDate"/>
+ <fmt:message key="donate.licensed">
+ <fmt:param value="${command.emailAddress}"/>
+ <fmt:param value="${licenseDate}"/>
+ <fmt:param value="${command.brand}"/>
+ </fmt:message>
+ </p>
+ </c:when>
+ <c:otherwise>
+
+ <p><fmt:message key="donate.register"/></p>
+
+ <form:form commandName="command" method="post" action="donate.view">
+ <form:hidden path="path"/>
+ <table>
+ <tr>
+ <td><fmt:message key="donate.register.email"/></td>
+ <td>
+ <form:input path="emailAddress" size="40"/>
+ </td>
+ </tr>
+ <tr>
+ <td><fmt:message key="donate.register.license"/></td>
+ <td>
+ <form:input path="license" size="40"/>
+ </td>
+ <td><input type="submit" value="<fmt:message key="common.ok"/>"/></td>
+ </tr>
+ <tr>
+ <td/>
+ <td class="warning"><form:errors path="license"/></td>
+ </tr>
+ </table>
+ </form:form>
+
+ <p><fmt:message key="donate.resend"/></p>
+
+ </c:otherwise>
+</c:choose>
+
+</div>
+</body>
+</html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/editTags.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/editTags.jsp new file mode 100644 index 00000000..7d95edd9 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/editTags.jsp @@ -0,0 +1,164 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/tagService.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/engine.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/util.js"/>"></script>
+</head>
+<body class="mainframe bgcolor1">
+
+<script type="text/javascript" language="javascript">
+ var index = 0;
+ var fileCount = ${fn:length(model.songs)};
+ function setArtist() {
+ var artist = dwr.util.getValue("artistAll");
+ for (i = 0; i < fileCount; i++) {
+ dwr.util.setValue("artist" + i, artist);
+ }
+ }
+ function setAlbum() {
+ var album = dwr.util.getValue("albumAll");
+ for (i = 0; i < fileCount; i++) {
+ dwr.util.setValue("album" + i, album);
+ }
+ }
+ function setYear() {
+ var year = dwr.util.getValue("yearAll");
+ for (i = 0; i < fileCount; i++) {
+ dwr.util.setValue("year" + i, year);
+ }
+ }
+ function setGenre() {
+ var genre = dwr.util.getValue("genreAll");
+ for (i = 0; i < fileCount; i++) {
+ dwr.util.setValue("genre" + i, genre);
+ }
+ }
+ function suggestTitle() {
+ for (i = 0; i < fileCount; i++) {
+ var title = dwr.util.getValue("suggestedTitle" + i);
+ dwr.util.setValue("title" + i, title);
+ }
+ }
+ function resetTitle() {
+ for (i = 0; i < fileCount; i++) {
+ var title = dwr.util.getValue("originalTitle" + i);
+ dwr.util.setValue("title" + i, title);
+ }
+ }
+ function suggestTrack() {
+ for (i = 0; i < fileCount; i++) {
+ var track = dwr.util.getValue("suggestedTrack" + i);
+ dwr.util.setValue("track" + i, track);
+ }
+ }
+ function resetTrack() {
+ for (i = 0; i < fileCount; i++) {
+ var track = dwr.util.getValue("originalTrack" + i);
+ dwr.util.setValue("track" + i, track);
+ }
+ }
+ function updateTags() {
+ document.getElementById("save").disabled = true;
+ index = 0;
+ dwr.util.setValue("errors", "");
+ for (i = 0; i < fileCount; i++) {
+ dwr.util.setValue("status" + i, "");
+ }
+ updateNextTag();
+ }
+ function updateNextTag() {
+ var id = dwr.util.getValue("id" + index);
+ var artist = dwr.util.getValue("artist" + index);
+ var track = dwr.util.getValue("track" + index);
+ var album = dwr.util.getValue("album" + index);
+ var title = dwr.util.getValue("title" + index);
+ var year = dwr.util.getValue("year" + index);
+ var genre = dwr.util.getValue("genre" + index);
+ dwr.util.setValue("status" + index, "<fmt:message key="edittags.working"/>");
+ tagService.setTags(id, track, artist, album, title, year, genre, setTagsCallback);
+ }
+ function setTagsCallback(result) {
+ var message;
+ if (result == "SKIPPED") {
+ message = "<fmt:message key="edittags.skipped"/>";
+ } else if (result == "UPDATED") {
+ message = "<b><fmt:message key="edittags.updated"/></b>";
+ } else {
+ message = "<div class='warning'><fmt:message key="edittags.error"/></div>"
+ var errors = dwr.util.getValue("errors");
+ errors += result + "<br/>";
+ dwr.util.setValue("errors", errors, { escapeHtml:false });
+ }
+ dwr.util.setValue("status" + index, message, { escapeHtml:false });
+ index++;
+ if (index < fileCount) {
+ updateNextTag();
+ } else {
+ document.getElementById("save").disabled = false;
+ }
+ }
+</script>
+
+<h1><fmt:message key="edittags.title"/></h1>
+<sub:url value="main.view" var="backUrl"><sub:param name="id" value="${model.id}"/></sub:url>
+<div class="back"><a href="${backUrl}"><fmt:message key="common.back"/></a></div>
+
+<table class="ruleTable indent">
+ <tr>
+ <th class="ruleTableHeader"><fmt:message key="edittags.file"/></th>
+ <th class="ruleTableHeader"><fmt:message key="edittags.track"/></th>
+ <th class="ruleTableHeader"><fmt:message key="edittags.songtitle"/></th>
+ <th class="ruleTableHeader"><fmt:message key="edittags.artist"/></th>
+ <th class="ruleTableHeader"><fmt:message key="edittags.album"/></th>
+ <th class="ruleTableHeader"><fmt:message key="edittags.year"/></th>
+ <th class="ruleTableHeader"><fmt:message key="edittags.genre"/></th>
+ <th class="ruleTableHeader" width="60pt"><fmt:message key="edittags.status"/></th>
+ </tr>
+ <tr>
+ <th class="ruleTableHeader"/>
+ <th class="ruleTableHeader"><a href="javascript:suggestTrack()"><fmt:message key="edittags.suggest.short"/></a> |
+ <a href="javascript:resetTrack()"><fmt:message key="edittags.reset.short"/></a></th>
+ <th class="ruleTableHeader"><a href="javascript:suggestTitle()"><fmt:message key="edittags.suggest"/></a> |
+ <a href="javascript:resetTitle()"><fmt:message key="edittags.reset"/></a></th>
+ <th class="ruleTableHeader" style="white-space: nowrap"><input type="text" name="artistAll" size="15" onkeypress="dwr.util.onReturn(event, setArtist)" value="${model.defaultArtist}"/> <a href="javascript:setArtist()"><fmt:message key="edittags.set"/></a></th>
+ <th class="ruleTableHeader" style="white-space: nowrap"><input type="text" name="albumAll" size="15" onkeypress="dwr.util.onReturn(event, setAlbum)" value="${model.defaultAlbum}"/> <a href="javascript:setAlbum()"><fmt:message key="edittags.set"/></a></th>
+ <th class="ruleTableHeader" style="white-space: nowrap"><input type="text" name="yearAll" size="5" onkeypress="dwr.util.onReturn(event, setYear)" value="${model.defaultYear}"/> <a href="javascript:setYear()"><fmt:message key="edittags.set"/></a></th>
+ <th class="ruleTableHeader" style="white-space: nowrap">
+ <select name="genreAll" style="width:7em">
+ <option value=""/>
+ <c:forEach items="${model.allGenres}" var="genre">
+ <option ${genre eq model.defaultGenre ? "selected" : ""} value="${genre}">${genre}</option>
+ </c:forEach>
+ </select>
+
+ <a href="javascript:setGenre()"><fmt:message key="edittags.set"/></a>
+ </th>
+ <th class="ruleTableHeader"/>
+ </tr>
+
+ <c:forEach items="${model.songs}" var="song" varStatus="loopStatus">
+ <tr>
+ <str:truncateNicely lower="25" upper="25" var="fileName">${song.fileName}</str:truncateNicely>
+ <input type="hidden" name="id${loopStatus.count - 1}" value="${song.id}"/>
+ <input type="hidden" name="suggestedTitle${loopStatus.count - 1}" value="${song.suggestedTitle}"/>
+ <input type="hidden" name="originalTitle${loopStatus.count - 1}" value="${song.title}"/>
+ <input type="hidden" name="suggestedTrack${loopStatus.count - 1}" value="${song.suggestedTrack}"/>
+ <input type="hidden" name="originalTrack${loopStatus.count - 1}" value="${song.track}"/>
+ <td class="ruleTableCell" title="${song.fileName}">${fileName}</td>
+ <td class="ruleTableCell"><input type="text" size="5" name="track${loopStatus.count - 1}" value="${song.track}"/></td>
+ <td class="ruleTableCell"><input type="text" size="30" name="title${loopStatus.count - 1}" value="${song.title}"/></td>
+ <td class="ruleTableCell"><input type="text" size="15" name="artist${loopStatus.count - 1}" value="${song.artist}"/></td>
+ <td class="ruleTableCell"><input type="text" size="15" name="album${loopStatus.count - 1}" value="${song.album}"/></td>
+ <td class="ruleTableCell"><input type="text" size="5" name="year${loopStatus.count - 1}" value="${song.year}"/></td>
+ <td class="ruleTableCell"><input type="text" name="genre${loopStatus.count - 1}" value="${song.genre}" style="width:7em"/></td>
+ <td class="ruleTableCell"><div id="status${loopStatus.count - 1}"/></td>
+ </tr>
+ </c:forEach>
+
+</table>
+
+<p><input type="submit" id="save" value="<fmt:message key="common.save"/>" onclick="javascript:updateTags()"/></p>
+<div class="warning" id="errors"/>
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/externalPlayer.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/externalPlayer.jsp new file mode 100644 index 00000000..31077d85 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/externalPlayer.jsp @@ -0,0 +1,99 @@ +<%--@elvariable id="model" type="java.util.Map"--%>
+<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<html>
+<head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="<c:url value="/script/swfobject.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/prototype.js"/>"></script>
+
+ <sub:url value="/coverArt.view" var="coverArtUrl">
+ <c:if test="${not empty model.coverArt}">
+ <sub:param name="path" value="${model.coverArt.path}"/>
+ </c:if>
+ <sub:param name="size" value="200"/>
+ </sub:url>
+
+ <meta name="og:title" content="${fn:escapeXml(model.songs[0].artist)} — ${fn:escapeXml(model.songs[0].albumName)}"/>
+ <meta name="og:type" content="album"/>
+ <meta name="og:image" content="http://${model.redirectFrom}.subsonic.org${coverArtUrl}"/>
+
+ <script type="text/javascript">
+ function init() {
+ var flashvars = {
+ id:"player1",
+ screencolor:"000000",
+ frontcolor:"<spring:theme code="textColor"/>",
+ backcolor:"<spring:theme code="backgroundColor"/>",
+ stretching: "fill",
+ "playlist.position": "bottom",
+ "playlist.size": 200
+ };
+ var params = {
+ allowfullscreen:"true",
+ allowscriptaccess:"always"
+ };
+ var attributes = {
+ id:"player1",
+ name:"player1"
+ };
+ swfobject.embedSWF("<c:url value="/flash/jw-player-5.6.swf"/>", "placeholder", "500", "500", "9.0.0", false, flashvars, params, attributes);
+ }
+
+ function playerReady(thePlayer) {
+ var player = $("player1");
+ var list = new Array();
+
+ <c:forEach items="${model.songs}" var="song" varStatus="loopStatus">
+ <%--@elvariable id="song" type="net.sourceforge.subsonic.domain.MediaFile"--%>
+ <sub:url value="/stream" var="streamUrl">
+ <sub:param name="path" value="${song.path}"/>
+ <sub:param name="player" value="${model.player}"/>
+ </sub:url>
+ <sub:url value="/coverArt.view" var="coverUrl">
+ <sub:param name="size" value="500"/>
+ <c:if test="${not empty model.coverArts[loopStatus.count - 1]}">
+ <sub:param name="path" value="${model.coverArts[loopStatus.count - 1].path}"/>
+ </c:if>
+ </sub:url>
+
+ <!-- TODO: Use video provider for aac, m4a -->
+ list[${loopStatus.count - 1}] = {
+ file: "${streamUrl}",
+ image: "${coverUrl}",
+ title: "${fn:escapeXml(song.title)}",
+ provider: "${song.video ? "video" : "sound"}",
+ description: "${fn:escapeXml(song.artist)}"
+ };
+
+ <c:if test="${not empty song.durationSeconds}">
+ list[${loopStatus.count-1}].duration = ${song.durationSeconds};
+ </c:if>
+
+ </c:forEach>
+
+ player.sendEvent("LOAD", list);
+ player.sendEvent("PLAY");
+ }
+
+ </script>
+</head>
+
+<body class="mainframe bgcolor1" style="padding-top:2em" onload="init();">
+
+<div style="margin:auto;width:500px">
+ <h1 >${model.songs[0].artist}</h1>
+ <div style="float:left;padding-right:1.5em">
+ <h2 style="margin:0;">${model.songs[0].albumName}</h2>
+ </div>
+ <div class="detail" style="float:right">Streaming by <a href="http://subsonic.org/" target="_blank"><b>Subsonic</b></a></div>
+
+ <div style="clear:both;padding-top:1em">
+ <div id="placeholder">
+ <a href="http://www.adobe.com/go/getflashplayer" target="_blank"><fmt:message key="playlist.getflash"/></a>
+ </div>
+ </div>
+ <div style="padding-top: 2em">${fn:escapeXml(model.share.description)}</div>
+</div>
+</body>
+</html>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/generalSettings.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/generalSettings.jsp new file mode 100644 index 00000000..f5cffe35 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/generalSettings.jsp @@ -0,0 +1,165 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+<%--@elvariable id="command" type="net.sourceforge.subsonic.command.GeneralSettingsCommand"--%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="<c:url value="/script/scripts.js"/>"></script>
+</head>
+
+<body class="mainframe bgcolor1">
+<script type="text/javascript" src="<c:url value="/script/wz_tooltip.js"/>"></script>
+<script type="text/javascript" src="<c:url value="/script/tip_balloon.js"/>"></script>
+
+<c:import url="settingsHeader.jsp">
+ <c:param name="cat" value="general"/>
+</c:import>
+
+<form:form method="post" action="generalSettings.view" commandName="command">
+
+ <table style="white-space:nowrap" class="indent">
+
+ <tr>
+ <td><fmt:message key="generalsettings.musicmask"/></td>
+ <td>
+ <form:input path="musicFileTypes" size="70"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="musicmask"/></c:import>
+ </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="generalsettings.videomask"/></td>
+ <td>
+ <form:input path="videoFileTypes" size="70"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="videomask"/></c:import>
+ </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="generalsettings.coverartmask"/></td>
+ <td>
+ <form:input path="coverArtFileTypes" size="70"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="coverartmask"/></c:import>
+ </td>
+ </tr>
+
+ <tr><td colspan="2"> </td></tr>
+
+ <tr>
+ <td><fmt:message key="generalsettings.index"/></td>
+ <td>
+ <form:input path="index" size="70"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="index"/></c:import>
+ </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="generalsettings.ignoredarticles"/></td>
+ <td>
+ <form:input path="ignoredArticles" size="70"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="ignoredarticles"/></c:import>
+ </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="generalsettings.shortcuts"/></td>
+ <td>
+ <form:input path="shortcuts" size="70"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="shortcuts"/></c:import>
+ </td>
+ </tr>
+
+ <tr><td colspan="2"> </td></tr>
+
+ <tr>
+ <td><fmt:message key="generalsettings.language"/></td>
+ <td>
+ <form:select path="localeIndex" cssStyle="width:15em">
+ <c:forEach items="${command.locales}" var="locale" varStatus="loopStatus">
+ <form:option value="${loopStatus.count - 1}" label="${locale}"/>
+ </c:forEach>
+ </form:select>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="language"/></c:import>
+ </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="generalsettings.theme"/></td>
+ <td>
+ <form:select path="themeIndex" cssStyle="width:15em">
+ <c:forEach items="${command.themes}" var="theme" varStatus="loopStatus">
+ <form:option value="${loopStatus.count - 1}" label="${theme.name}"/>
+ </c:forEach>
+ </form:select>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="theme"/></c:import>
+ </td>
+ </tr>
+
+ <tr><td colspan="2"> </td></tr>
+
+ <tr>
+ <td>
+ </td>
+ <td>
+ <form:checkbox path="sortAlbumsByYear" id="sortAlbumsByYear"/>
+ <label for="sortAlbumsByYear"><fmt:message key="generalsettings.sortalbumsbyyear"/></label>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ </td>
+ <td>
+ <form:checkbox path="gettingStartedEnabled" id="gettingStartedEnabled"/>
+ <label for="gettingStartedEnabled"><fmt:message key="generalsettings.showgettingstarted"/></label>
+ </td>
+ </tr>
+
+ <tr><td colspan="2"> </td></tr>
+
+ <tr>
+ <td><fmt:message key="generalsettings.welcometitle"/></td>
+ <td>
+ <form:input path="welcomeTitle" size="70"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="welcomemessage"/></c:import>
+ </td>
+ </tr>
+ <tr>
+ <td><fmt:message key="generalsettings.welcomesubtitle"/></td>
+ <td>
+ <form:input path="welcomeSubtitle" size="70"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="welcomemessage"/></c:import>
+ </td>
+ </tr>
+ <tr>
+ <td style="vertical-align:top;"><fmt:message key="generalsettings.welcomemessage"/></td>
+ <td>
+ <form:textarea path="welcomeMessage" rows="5" cols="70"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="welcomemessage"/></c:import>
+ </td>
+ </tr>
+ <tr>
+ <td style="vertical-align:top;"><fmt:message key="generalsettings.loginmessage"/></td>
+ <td>
+ <form:textarea path="loginMessage" rows="5" cols="70"/>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="loginmessage"/></c:import>
+ <fmt:message key="main.wiki"/>
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="2" style="padding-top:1.5em">
+ <input type="submit" value="<fmt:message key="common.save"/>" style="margin-right:0.3em">
+ <input type="button" value="<fmt:message key="common.cancel"/>" onclick="location.href='nowPlaying.view'">
+ </td>
+ </tr>
+
+ </table>
+</form:form>
+
+<c:if test="${command.reloadNeeded}">
+ <script language="javascript" type="text/javascript">
+ parent.frames.left.location.href="left.view?";
+ parent.frames.playQueue.location.href="playQueue.view?";
+ </script>
+</c:if>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/gettingStarted.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/gettingStarted.jsp new file mode 100644 index 00000000..ad7b2a77 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/gettingStarted.jsp @@ -0,0 +1,53 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" language="javascript">
+ function hideGettingStarted() {
+ alert("<fmt:message key="gettingStarted.hidealert"/>");
+ location.href = "gettingStarted.view?hide";
+ }
+ </script>
+</head>
+<body class="mainframe bgcolor1">
+
+<h1 style="padding-bottom:0.5em">
+ <img src="<spring:theme code="homeImage"/>" alt="">
+ <fmt:message key="gettingStarted.title"/>
+</h1>
+
+<fmt:message key="gettingStarted.text"/>
+
+<c:if test="${model.runningAsRoot}">
+ <h2 class="warning"><fmt:message key="gettingStarted.root"/></h2>
+</c:if>
+
+<table style="padding-top:1em;padding-bottom:2em;width:60%">
+ <tr>
+ <td style="font-size:26pt;padding:20pt">1</td>
+ <td>
+ <div style="font-size:14pt"><a href="userSettings.view?userIndex=0"><fmt:message key="gettingStarted.step1.title"/></a></div>
+ <div style="padding-top:5pt"><fmt:message key="gettingStarted.step1.text"/></div>
+ </td>
+ </tr>
+ <tr>
+ <td style="font-size:26pt;padding:20pt">2</td>
+ <td>
+ <div style="font-size:14pt"><a href="musicFolderSettings.view"><fmt:message key="gettingStarted.step2.title"/></a></div>
+ <div style="padding-top:5pt"><fmt:message key="gettingStarted.step2.text"/></div>
+ </td>
+ </tr>
+ <tr>
+ <td style="font-size:26pt;padding:20pt">3</td>
+ <td>
+ <div style="font-size:14pt"><a href="networkSettings.view"><fmt:message key="gettingStarted.step3.title"/></a></div>
+ <div style="padding-top:5pt"><fmt:message key="gettingStarted.step3.text"/></div>
+ </td>
+ </tr>
+
+</table>
+
+<div class="forward"><a href="javascript:hideGettingStarted()"><fmt:message key="gettingStarted.hide"/></a></div>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/head.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/head.jsp new file mode 100644 index 00000000..cedadd8d --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/head.jsp @@ -0,0 +1,11 @@ +<%@ include file="include.jsp" %>
+
+<!--[if lt IE 7.]>
+<script defer type="text/javascript" src="<c:url value="/script/pngfix.js"/>"></script>
+<![endif]-->
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<c:set var="styleSheet"><spring:theme code="styleSheet"/></c:set>
+<c:set var="faviconImage"><spring:theme code="faviconImage"/></c:set>
+<link rel="stylesheet" href="<c:url value="/${styleSheet}"/>" type="text/css">
+<link rel="shortcut icon" href="<c:url value="/${faviconImage}"/>" type="text/css">
+<title>Subsonic</title>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/help.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/help.jsp new file mode 100644 index 00000000..58421828 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/help.jsp @@ -0,0 +1,70 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="<c:url value="/script/scripts.js"/>"></script>
+</head>
+<body class="mainframe bgcolor1">
+
+<c:choose>
+ <c:when test="${empty model.buildDate}">
+ <fmt:message key="common.unknown" var="buildDateString"/>
+ </c:when>
+ <c:otherwise>
+ <fmt:formatDate value="${model.buildDate}" dateStyle="long" var="buildDateString"/>
+ </c:otherwise>
+</c:choose>
+
+<c:choose>
+ <c:when test="${empty model.localVersion}">
+ <fmt:message key="common.unknown" var="versionString"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="versionString" value="${model.localVersion} (build ${model.buildNumber})"/>
+ </c:otherwise>
+</c:choose>
+
+<h1>
+ <img src="<spring:theme code="helpImage"/>" alt="">
+ <fmt:message key="help.title"><fmt:param value="${model.brand}"/></fmt:message>
+</h1>
+
+<c:if test="${model.newVersionAvailable}">
+ <p class="warning"><fmt:message key="help.upgrade"><fmt:param value="${model.brand}"/><fmt:param value="${model.latestVersion}"/></fmt:message></p>
+</c:if>
+
+<table width="75%" class="ruleTable indent">
+ <tr><td class="ruleTableHeader"><fmt:message key="help.version.title"/></td><td class="ruleTableCell">${versionString} – ${buildDateString}</td></tr>
+ <tr><td class="ruleTableHeader"><fmt:message key="help.server.title"/></td><td class="ruleTableCell">${model.serverInfo} (<sub:formatBytes bytes="${model.usedMemory}"/> / <sub:formatBytes bytes="${model.totalMemory}"/>)</td></tr>
+ <tr><td class="ruleTableHeader"><fmt:message key="help.license.title"/></td><td class="ruleTableCell">
+ <a href="http://www.gnu.org/copyleft/gpl.html" target="_blank"><img style="float:right;margin-left: 10px" alt="GPL 3.0" src="<c:url value="/icons/gpl.png"/>"></a>
+ <fmt:message key="help.license.text"><fmt:param value="${model.brand}"/></fmt:message></td></tr>
+ <tr><td class="ruleTableHeader"><fmt:message key="help.homepage.title"/></td><td class="ruleTableCell"><a target="_blank" href="http://www.subsonic.org/">subsonic.org</a></td></tr>
+ <tr><td class="ruleTableHeader"><fmt:message key="help.forum.title"/></td><td class="ruleTableCell"><a target="_blank" href="http://forum.subsonic.org/">forum.subsonic.org</a></td></tr>
+ <tr><td class="ruleTableHeader"><fmt:message key="help.contact.title"/></td><td class="ruleTableCell"><fmt:message key="help.contact.text"><fmt:param value="${model.brand}"/></fmt:message></td></tr>
+</table>
+
+<p></p>
+
+<table width="75%"><tr>
+ <td><a href="<c:url value="/donate.view"/>"><img src="<spring:theme code="paypalImage"/>" alt=""></a></td>
+ <td><fmt:message key="help.donate"><fmt:param value="${model.brand}"/></fmt:message></td>
+</tr></table>
+
+<h2><img src="<spring:theme code="logImage"/>" alt=""> <fmt:message key="help.log"/></h2>
+
+<table cellpadding="2" class="log indent">
+ <c:forEach items="${model.logEntries}" var="entry">
+ <tr>
+ <td>[<fmt:formatDate value="${entry.date}" dateStyle="short" timeStyle="long" type="both"/>]</td>
+ <td>${entry.level}</td><td>${entry.category}</td><td>${entry.message}</td>
+ </tr>
+ </c:forEach>
+</table>
+
+<p><fmt:message key="help.logfile"><fmt:param value="${model.logFile}"/></fmt:message> </p>
+
+<div class="forward"><a href="help.view?"><fmt:message key="common.refresh"/></a></div>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/helpToolTip.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/helpToolTip.jsp new file mode 100644 index 00000000..04de8ad0 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/helpToolTip.jsp @@ -0,0 +1,18 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<%@ include file="include.jsp" %>
+
+<%--
+ Shows online help as a balloon tool tip.
+
+PARAMETERS
+ topic: Refers to a key in the resource bundle containing the text to display in the tool tip.
+--%>
+
+<spring:theme code="helpPopupImage" var="imageUrl"/>
+<fmt:message key="common.help" var="help"/>
+
+<div id="placeholder-${param.topic}" style="display:none">
+ <div style="font-weight:bold;"><fmt:message key="helppopup.${param.topic}.title"><fmt:param value="Subsonic"/></fmt:message></div>
+ <div><fmt:message key="helppopup.${param.topic}.text"><fmt:param value="Subsonic"/></fmt:message></div>
+</div>
+<img src="${imageUrl}" alt="${help}" title="${help}" onmouseover="TagToTip('placeholder-${param.topic}', BALLOON, true, ABOVE, true, OFFSETX, -17, PADDING, 8, WIDTH, -240, CLICKSTICKY, true, CLICKCLOSE, true)" onmouseout="UnTip()"/>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/home.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/home.jsp new file mode 100644 index 00000000..8792d60d --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/home.jsp @@ -0,0 +1,189 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <%@ include file="jquery.jsp" %>
+ <link href="<c:url value="/style/shadow.css"/>" rel="stylesheet">
+
+ <script type="text/javascript" language="javascript">
+ function init() {
+ <c:if test="${model.listType eq 'random'}">
+ setTimeout("refresh()", 20000);
+ </c:if>
+ }
+
+ function refresh() {
+ top.main.location.href = top.main.location.href;
+ }
+ </script>
+</head>
+<body class="mainframe bgcolor1" onload="init();">
+<h1>
+ <img src="<spring:theme code="homeImage"/>" alt="">
+ ${model.welcomeTitle}
+</h1>
+
+<c:if test="${not empty model.welcomeSubtitle}">
+ <h2>${model.welcomeSubtitle}</h2>
+</c:if>
+
+<h2>
+ <c:forTokens items="random newest starred highest frequent recent alphabetical users" delims=" " var="cat" varStatus="loopStatus">
+ <c:if test="${loopStatus.count > 1}"> | </c:if>
+ <sub:url var="url" value="home.view">
+ <sub:param name="listSize" value="${model.listSize}"/>
+ <sub:param name="listType" value="${cat}"/>
+ </sub:url>
+
+ <c:choose>
+ <c:when test="${model.listType eq cat}">
+ <span class="headerSelected"><fmt:message key="home.${cat}.title"/></span>
+ </c:when>
+ <c:otherwise>
+ <a href="${url}"><fmt:message key="home.${cat}.title"/></a>
+ </c:otherwise>
+ </c:choose>
+
+ </c:forTokens>
+</h2>
+
+<c:if test="${model.isIndexBeingCreated}">
+ <p class="warning"><fmt:message key="home.scan"/></p>
+</c:if>
+
+<h2><fmt:message key="home.${model.listType}.text"/></h2>
+
+<table width="100%">
+ <tr>
+ <td style="vertical-align:top;">
+<c:choose>
+<c:when test="${model.listType eq 'users'}">
+ <table>
+ <tr>
+ <th><fmt:message key="home.chart.total"/></th>
+ <th><fmt:message key="home.chart.stream"/></th>
+ </tr>
+ <tr>
+ <td><img src="<c:url value="/userChart.view"><c:param name="type" value="total"/></c:url>" alt=""></td>
+ <td><img src="<c:url value="/userChart.view"><c:param name="type" value="stream"/></c:url>" alt=""></td>
+ </tr>
+ <tr>
+ <th><fmt:message key="home.chart.download"/></th>
+ <th><fmt:message key="home.chart.upload"/></th>
+ </tr>
+ <tr>
+ <td><img src="<c:url value="/userChart.view"><c:param name="type" value="download"/></c:url>" alt=""></td>
+ <td><img src="<c:url value="/userChart.view"><c:param name="type" value="upload"/></c:url>" alt=""></td>
+ </tr>
+</table>
+
+</c:when>
+<c:otherwise>
+
+ <table>
+ <c:forEach items="${model.albums}" var="album" varStatus="loopStatus">
+ <c:if test="${loopStatus.count % 5 == 1}">
+ <tr>
+ </c:if>
+
+ <td style="vertical-align:top">
+ <table>
+ <tr><td>
+ <c:import url="coverArt.jsp">
+ <c:param name="albumId" value="${album.id}"/>
+ <c:param name="albumName" value="${album.albumTitle}"/>
+ <c:param name="coverArtSize" value="110"/>
+ <c:param name="showLink" value="true"/>
+ <c:param name="showZoom" value="false"/>
+ <c:param name="showChange" value="false"/>
+ <c:param name="appearAfter" value="${loopStatus.count * 30}"/>
+ </c:import>
+
+ <div class="detail">
+ <c:if test="${not empty album.playCount}">
+ <fmt:message key="home.playcount"><fmt:param value="${album.playCount}"/></fmt:message>
+ </c:if>
+ <c:if test="${not empty album.lastPlayed}">
+ <fmt:formatDate value="${album.lastPlayed}" dateStyle="short" var="lastPlayedDate"/>
+ <fmt:message key="home.lastplayed"><fmt:param value="${lastPlayedDate}"/></fmt:message>
+ </c:if>
+ <c:if test="${not empty album.created}">
+ <fmt:formatDate value="${album.created}" dateStyle="short" var="creationDate"/>
+ <fmt:message key="home.created"><fmt:param value="${creationDate}"/></fmt:message>
+ </c:if>
+ <c:if test="${not empty album.rating}">
+ <c:import url="rating.jsp">
+ <c:param name="readonly" value="true"/>
+ <c:param name="rating" value="${album.rating}"/>
+ </c:import>
+ </c:if>
+ </div>
+
+ <c:choose>
+ <c:when test="${empty album.artist and empty album.albumTitle}">
+ <div class="detail"><fmt:message key="common.unknown"/></div>
+ </c:when>
+ <c:otherwise>
+ <div class="detail"><em><str:truncateNicely lower="15" upper="15">${album.artist}</str:truncateNicely></em></div>
+ <div class="detail"><str:truncateNicely lower="15" upper="15">${album.albumTitle}</str:truncateNicely></div>
+ </c:otherwise>
+ </c:choose>
+
+ </td></tr>
+ </table>
+ </td>
+ <c:if test="${loopStatus.count % 5 == 0}">
+ </tr>
+ </c:if>
+ </c:forEach>
+ </table>
+
+<table>
+ <tr>
+ <td style="padding-right:1.5em">
+ <select name="listSize" onchange="location='home.view?listType=${model.listType}&listOffset=${model.listOffset}&listSize=' + options[selectedIndex].value;">
+ <c:forTokens items="5 10 15 20 30 40 50" delims=" " var="size">
+ <option ${size eq model.listSize ? "selected" : ""} value="${size}"><fmt:message key="home.listsize"><fmt:param value="${size}"/></fmt:message></option>
+ </c:forTokens>
+ </select>
+ </td>
+
+ <c:choose>
+ <c:when test="${model.listType eq 'random'}">
+ <td><div class="forward"><a href="home.view?listType=random&listSize=${model.listSize}"><fmt:message key="common.more"/></a></div></td>
+ </c:when>
+
+ <c:otherwise>
+ <sub:url value="home.view" var="previousUrl">
+ <sub:param name="listType" value="${model.listType}"/>
+ <sub:param name="listOffset" value="${model.listOffset - model.listSize}"/>
+ <sub:param name="listSize" value="${model.listSize}"/>
+ </sub:url>
+ <sub:url value="home.view" var="nextUrl">
+ <sub:param name="listType" value="${model.listType}"/>
+ <sub:param name="listOffset" value="${model.listOffset + model.listSize}"/>
+ <sub:param name="listSize" value="${model.listSize}"/>
+ </sub:url>
+
+ <td style="padding-right:1.5em"><fmt:message key="home.albums"><fmt:param value="${model.listOffset + 1}"/><fmt:param value="${model.listOffset + model.listSize}"/></fmt:message></td>
+ <td style="padding-right:1.5em"><div class="back"><a href="${previousUrl}"><fmt:message key="common.previous"/></a></div></td>
+ <td><div class="forward"><a href="${nextUrl}"><fmt:message key="common.next"/></a></div></td>
+ </c:otherwise>
+ </c:choose>
+ </tr>
+ </table>
+</c:otherwise>
+</c:choose>
+ </td>
+ <c:if test="${not empty model.welcomeMessage}">
+ <td style="vertical-align:top;width:20em">
+ <div style="padding:0 1em 0 1em;border-left:1px solid #<spring:theme code="detailColor"/>">
+ <sub:wiki text="${model.welcomeMessage}"/>
+ </div>
+ </td>
+ </c:if>
+ </tr>
+ </table>
+
+</body></html>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/importPlaylist.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/importPlaylist.jsp new file mode 100644 index 00000000..4bc09b88 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/importPlaylist.jsp @@ -0,0 +1,37 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<html><head>
+ <%@ include file="head.jsp" %>
+</head>
+<body class="mainframe bgcolor1">
+
+<h1 style="padding-bottom:0.5em">
+ <fmt:message key="importPlaylist.title"/>
+</h1>
+
+<c:if test="${not empty model.playlist}">
+ <p>
+ <fmt:message key="importPlaylist.success"><fmt:param value="${model.playlist.name}"/></fmt:message>
+ <script type="text/javascript" language="javascript">
+ top.left.updatePlaylists();
+ </script>
+ </p>
+</c:if>
+
+<c:if test="${not empty model.error}">
+ <p class="warning">
+ <fmt:message key="importPlaylist.error"><fmt:param value="${model.error}"/></fmt:message>
+ </p>
+</c:if>
+
+<div style="padding-bottom: 0.25em">
+ <fmt:message key="importPlaylist.text"/>
+</div>
+<form method="post" enctype="multipart/form-data" action="importPlaylist.view">
+ <input type="file" id="file" name="file" size="40"/>
+ <input type="submit" value="<fmt:message key="common.ok"/>"/>
+</form>
+
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/include.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/include.jsp new file mode 100644 index 00000000..41c0aa2d --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/include.jsp @@ -0,0 +1,8 @@ +<%@ page session="false"%>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
+<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
+<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
+<%@ taglib prefix="sub" uri="http://subsonic.org/taglib/sub" %>
+<%@ taglib prefix="str" uri="http://jakarta.apache.org/taglibs/string-1.1" %>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/index.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/index.jsp new file mode 100644 index 00000000..4ec7e2b0 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/index.jsp @@ -0,0 +1,26 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <link rel="alternate" type="application/rss+xml" title="Subsonic Podcast" href="podcast.view?suffix=.rss">
+</head>
+
+<frameset rows="70,*,0" border="0" framespacing="0" frameborder="0">
+ <frame name="upper" src="top.view?">
+ <frameset cols="15%,85%" border="0" framespacing="0" frameborder="0">
+ <frame name="left" src="left.view?" marginwidth="0" marginheight="0">
+
+ <frameset rows="70%,30%" border="0" framespacing="0" frameborder="0">
+ <frameset cols="*,${model.showRight ? 230 : 0}" border="0" framespacing="0" frameborder="0">
+ <frame name="main" src="nowPlaying.view?" marginwidth="0" marginheight="0">
+ <frame name="right" src="right.view?">
+ </frameset>
+ <frame name="playQueue" src="playQueue.view?">
+ </frameset>
+ </frameset>
+ <frame name="hidden" frameborder="0" noresize="noresize">
+
+</frameset>
+
+</html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/internetRadioSettings.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/internetRadioSettings.jsp new file mode 100644 index 00000000..ba3fbe1b --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/internetRadioSettings.jsp @@ -0,0 +1,62 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+</head>
+<body class="mainframe bgcolor1">
+
+<c:import url="settingsHeader.jsp">
+ <c:param name="cat" value="internetRadio"/>
+</c:import>
+
+<form method="post" action="internetRadioSettings.view">
+<table class="indent">
+ <tr>
+ <th><fmt:message key="internetradiosettings.name"/></th>
+ <th><fmt:message key="internetradiosettings.streamurl"/></th>
+ <th><fmt:message key="internetradiosettings.homepageurl"/></th>
+ <th style="padding-left:1em"><fmt:message key="internetradiosettings.enabled"/></th>
+ <th style="padding-left:1em"><fmt:message key="common.delete"/></th>
+ </tr>
+
+ <c:forEach items="${model.internetRadios}" var="radio">
+ <tr>
+ <td><input type="text" name="name[${radio.id}]" size="20" value="${radio.name}"/></td>
+ <td><input type="text" name="streamUrl[${radio.id}]" size="40" value="${radio.streamUrl}"/></td>
+ <td><input type="text" name="homepageUrl[${radio.id}]" size="40" value="${radio.homepageUrl}"/></td>
+ <td align="center" style="padding-left:1em"><input type="checkbox" ${radio.enabled ? "checked" : ""} name="enabled[${radio.id}]" class="checkbox"/></td>
+ <td align="center" style="padding-left:1em"><input type="checkbox" name="delete[${radio.id}]" class="checkbox"/></td>
+ </tr>
+ </c:forEach>
+
+ <tr>
+ <th colspan="5" align="left" style="padding-top:1em"><fmt:message key="internetradiosettings.add"/></th>
+ </tr>
+
+ <tr>
+ <td><input type="text" name="name" size="20"/></td>
+ <td><input type="text" name="streamUrl" size="40"/></td>
+ <td><input type="text" name="homepageUrl" size="40"/></td>
+ <td align="center" style="padding-left:1em"><input name="enabled" checked type="checkbox" class="checkbox"/></td>
+ <td/>
+ </tr>
+
+ <tr>
+ <td style="padding-top:1.5em" colspan="5">
+ <input type="submit" value="<fmt:message key="common.save"/>" style="margin-right:0.3em">
+ <input type="button" value="<fmt:message key="common.cancel"/>" onclick="location.href='nowPlaying.view'">
+ </td>
+ </tr>
+</table>
+</form>
+
+
+<c:if test="${not empty model.error}">
+ <p class="warning"><fmt:message key="${model.error}"/></p>
+</c:if>
+
+<c:if test="${model.reload}">
+ <script language="javascript" type="text/javascript">parent.frames.left.location.href="left.view?"</script>
+</c:if>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/jquery.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/jquery.jsp new file mode 100644 index 00000000..094b9bcc --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/jquery.jsp @@ -0,0 +1,3 @@ +<link rel="stylesheet" href="<c:url value="/style/smoothness/jquery-ui-1.8.18.custom.css"/>" type="text/css"> +<script type="text/javascript" src="<c:url value='/script/jquery-1.7.1.min.js'/>"></script> +<script type="text/javascript" src="<c:url value='/script/jquery-ui-1.8.18.custom.min.js'/>"></script> diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/left.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/left.jsp new file mode 100644 index 00000000..d47c25f6 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/left.jsp @@ -0,0 +1,168 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html><head>
+ <%@ include file="head.jsp" %>
+ <%@ include file="jquery.jsp" %>
+ <script type="text/javascript" src="<c:url value="/script/scripts.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/smooth-scroll.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/engine.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/playlistService.js"/>"></script>
+ <script type="text/javascript" language="javascript">
+
+ var playlists;
+
+ function init() {
+ dwr.engine.setErrorHandler(null);
+ updatePlaylists();
+ }
+
+ function updatePlaylists() {
+ playlistService.getReadablePlaylists(playlistCallback);
+ }
+
+ function createEmptyPlaylist() {
+ playlistService.createEmptyPlaylist(playlistCallback);
+ }
+
+ function playlistCallback(playlists) {
+ this.playlists = playlists;
+
+ $("#playlists").empty();
+ for (var i = 0; i < playlists.length; i++) {
+ var playlist = playlists[i];
+ $("<p class='dense'><a target='main' href='playlist.view?id=" +
+ playlist.id + "'>" + playlist.name + " (" + playlist.fileCount + ")</a></p>").appendTo("#playlists");
+ }
+ }
+ </script>
+</head>
+
+<body class="bgcolor2 leftframe" onload="init()">
+<a name="top"></a>
+
+<c:if test="${model.scanning}">
+ <div style="padding-bottom:1.0em">
+ <div class="warning"><fmt:message key="left.scanning"/></div>
+ <div class="forward"><a href="left.view"><fmt:message key="common.refresh"/></a></div>
+ </div>
+</c:if>
+
+<div style="padding-bottom:0.5em">
+ <c:forEach items="${model.indexes}" var="index">
+ <a href="#${index.index}" accesskey="${index.index}">${index.index}</a>
+ </c:forEach>
+</div>
+
+<c:if test="${model.statistics.songCount gt 0}">
+ <div class="detail">
+ <fmt:message key="left.statistics">
+ <fmt:param value="${model.statistics.artistCount}"/>
+ <fmt:param value="${model.statistics.albumCount}"/>
+ <fmt:param value="${model.statistics.songCount}"/>
+ <fmt:param value="${model.bytes}"/>
+ <fmt:param value="${model.hours}"/>
+ </fmt:message>
+ </div>
+</c:if>
+
+<c:if test="${fn:length(model.musicFolders) > 1}">
+ <div style="padding-top:1em">
+ <select name="musicFolderId" style="width:100%" onchange="location='left.view?musicFolderId=' + options[selectedIndex].value;" >
+ <option value="-1"><fmt:message key="left.allfolders"/></option>
+ <c:forEach items="${model.musicFolders}" var="musicFolder">
+ <option ${model.selectedMusicFolder.id == musicFolder.id ? "selected" : ""} value="${musicFolder.id}">${musicFolder.name}</option>
+ </c:forEach>
+ </select>
+ </div>
+</c:if>
+
+<c:if test="${not empty model.shortcuts}">
+ <h2 class="bgcolor1"><fmt:message key="left.shortcut"/></h2>
+ <c:forEach items="${model.shortcuts}" var="shortcut">
+ <p class="dense" style="padding-left:0.5em">
+ <sub:url value="main.view" var="mainUrl">
+ <sub:param name="id" value="${shortcut.id}"/>
+ </sub:url>
+ <a target="main" href="${mainUrl}">${shortcut.name}</a>
+ </p>
+ </c:forEach>
+</c:if>
+
+<h2 class="bgcolor1"><fmt:message key="left.playlists"/></h2>
+<div style='padding-left:0.5em'>
+ <div id="playlists"></div>
+ <div style="margin-top: 0.3em"><a href="javascript:noop()" onclick="createEmptyPlaylist()"><fmt:message key="left.createplaylist"/></a></div>
+ <div><a href="importPlaylist.view" target="main"><fmt:message key="left.importplaylist"/></a></div>
+</div>
+
+<c:if test="${not empty model.radios}">
+ <h2 class="bgcolor1"><fmt:message key="left.radio"/></h2>
+ <c:forEach items="${model.radios}" var="radio">
+ <p class="dense">
+ <a target="hidden" href="${radio.streamUrl}">
+ <img src="<spring:theme code="playImage"/>" alt="<fmt:message key="common.play"/>" title="<fmt:message key="common.play"/>"></a>
+ <c:choose>
+ <c:when test="${empty radio.homepageUrl}">
+ ${radio.name}
+ </c:when>
+ <c:otherwise>
+ <a target="main" href="${radio.homepageUrl}">${radio.name}</a>
+ </c:otherwise>
+ </c:choose>
+ </p>
+ </c:forEach>
+</c:if>
+
+<c:forEach items="${model.indexedArtists}" var="entry">
+ <table class="bgcolor1" style="width:100%;padding:0;margin:1em 0 0 0;border:0">
+ <tr style="padding:0;margin:0;border:0">
+ <th style="text-align:left;padding:0;margin:0;border:0"><a name="${entry.key.index}"></a>
+ <h2 style="padding:0;margin:0;border:0">${entry.key.index}</h2>
+ </th>
+ <th style="text-align:right;">
+ <a href="#top"><img src="<spring:theme code="upImage"/>" alt=""></a>
+ </th>
+ </tr>
+ </table>
+
+ <c:forEach items="${entry.value}" var="artist">
+ <p class="dense" style="padding-left:0.5em">
+ <span title="${artist.name}">
+ <sub:url value="main.view" var="mainUrl">
+ <c:forEach items="${artist.mediaFiles}" var="mediaFile">
+ <sub:param name="id" value="${mediaFile.id}"/>
+ </c:forEach>
+ </sub:url>
+ <a target="main" href="${mainUrl}"><str:truncateNicely upper="${model.captionCutoff}">${artist.name}</str:truncateNicely></a>
+ </span>
+ </p>
+ </c:forEach>
+</c:forEach>
+
+<div style="padding-top:1em"></div>
+
+<c:forEach items="${model.singleSongs}" var="song">
+ <p class="dense" style="padding-left:0.5em">
+ <span title="${song.title}">
+ <c:import url="playAddDownload.jsp">
+ <c:param name="id" value="${song.id}"/>
+ <c:param name="playEnabled" value="${model.user.streamRole and not model.partyMode}"/>
+ <c:param name="addEnabled" value="${model.user.streamRole}"/>
+ <c:param name="downloadEnabled" value="${model.user.downloadRole and not model.partyMode}"/>
+ <c:param name="video" value="${song.video and model.player.web}"/>
+ </c:import>
+ <str:truncateNicely upper="${model.captionCutoff}">${song.title}</str:truncateNicely>
+ </span>
+ </p>
+</c:forEach>
+
+<div style="height:5em"></div>
+
+<div class="bgcolor2" style="opacity: 1.0; clear: both; position: fixed; bottom: 0; right: 0; left: 0;
+ padding: 0.25em 0.75em 0.25em 0.75em; border-top:1px solid black; max-width: 850px;">
+ <c:forEach items="${model.indexes}" var="index">
+ <a href="#${index.index}">${index.index}</a>
+ </c:forEach>
+</div>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/login.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/login.jsp new file mode 100644 index 00000000..0173ca8c --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/login.jsp @@ -0,0 +1,64 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript">
+ if (window != window.top) {
+ top.location.href = location.href;
+ }
+ </script>
+
+</head>
+<body class="mainframe bgcolor1" onload="document.getElementById('j_username').focus()">
+
+<form action="<c:url value="/j_acegi_security_check"/>" method="POST">
+ <div class="bgcolor2" align="center" style="border:1px solid black; padding:20px 50px 20px 50px; margin-top:100px">
+
+ <div style="margin-bottom:1em;max-width:50em;text-align:left;"><sub:wiki text="${model.loginMessage}"/></div>
+
+ <table>
+ <tr>
+ <td colspan="2" align="left" style="padding-bottom:10px">
+ <img src="<spring:theme code="logoImage"/>" alt="">
+ </td>
+ </tr>
+ <tr>
+ <td align="left" style="padding-right:10px"><fmt:message key="login.username"/></td>
+ <td align="left"><input type="text" id="j_username" name="j_username" style="width:12em" tabindex="1"></td>
+ </tr>
+
+ <tr>
+ <td align="left" style="padding-bottom:10px"><fmt:message key="login.password"/></td>
+ <td align="left" style="padding-bottom:10px"><input type="password" name="j_password" style="width:12em" tabindex="2"></td>
+ </tr>
+
+ <tr>
+ <td align="left"><input name="submit" type="submit" value="<fmt:message key="login.login"/>" tabindex="4"></td>
+ <td align="left" class="detail">
+ <input type="checkbox" name="_acegi_security_remember_me" id="remember" class="checkbox" tabindex="3">
+ <label for="remember"><fmt:message key="login.remember"/></label>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td align="left" class="detail"><a href="recover.view"><fmt:message key="login.recover"/></a></td>
+ </tr>
+
+ <c:if test="${model.logout}">
+ <tr><td colspan="2" style="padding-top:10px"><b><fmt:message key="login.logout"/></b></td></tr>
+ </c:if>
+ <c:if test="${model.error}">
+ <tr><td colspan="2" style="padding-top:10px"><b class="warning"><fmt:message key="login.error"/></b></td></tr>
+ </c:if>
+
+ </table>
+
+ <c:if test="${model.insecure}">
+ <p><b class="warning"><fmt:message key="login.insecure"><fmt:param value="${model.brand}"/></fmt:message></b></p>
+ </c:if>
+
+ </div>
+</form>
+</body>
+</html>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/lyrics.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/lyrics.jsp new file mode 100644 index 00000000..82d5ce37 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/lyrics.jsp @@ -0,0 +1,79 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <title><fmt:message key="lyrics.title"/></title>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/lyricsService.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/engine.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/util.js"/>"></script>
+
+ <script type="text/javascript" language="javascript">
+
+ dwr.engine.setErrorHandler(null);
+
+ function init() {
+ getLyrics('${model.artist}', '${model.song}');
+ }
+
+ function getLyrics(artist, song) {
+ $("wait").style.display = "inline";
+ $("lyrics").style.display = "none";
+ $("noLyricsFound").style.display = "none";
+ lyricsService.getLyrics(artist, song, getLyricsCallback);
+ }
+
+ function getLyricsCallback(lyricsInfo) {
+ dwr.util.setValue("lyricsHeader", lyricsInfo.artist + " - " + lyricsInfo.title);
+ var lyrics;
+ if (lyricsInfo.lyrics != null) {
+ lyrics = lyricsInfo.lyrics.replace(/\n/g, "<br>");
+ }
+ dwr.util.setValue("lyricsText", lyrics, { escapeHtml:false });
+ $("wait").style.display = "none";
+ if (lyrics != null) {
+ $("lyrics").style.display = "inline";
+ } else {
+ $("noLyricsFound").style.display = "inline";
+ }
+ }
+ </script>
+
+</head>
+<body class="mainframe bgcolor1" onload="init();">
+
+<table>
+ <tr>
+ <td><fmt:message key="lyrics.artist"/></td>
+ <td style="padding-left:0.50em"><input id="artist" type="text" size="40" value="${model.artist}" tabindex="1"/></td>
+ <td style="padding-left:0.75em"><input type="submit" value="<fmt:message key="lyrics.search"/>" style="width:6em"
+ onclick="getLyrics(dwr.util.getValue('artist'), dwr.util.getValue('song'))" tabindex="3"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="lyrics.song"/></td>
+ <td style="padding-left:0.50em"><input id="song" type="text" size="40" value="${model.song}" tabindex="2"/></td>
+ <td style="padding-left:0.75em"><input type="submit" value="<fmt:message key="common.close"/>" style="width:6em"
+ onclick="self.close()" tabindex="4"/></td>
+ </tr>
+</table>
+
+<hr/>
+<h2 id="wait"><fmt:message key="lyrics.wait"/></h2>
+<h2 id="noLyricsFound" style="display:none"><fmt:message key="lyrics.nolyricsfound"/></h2>
+
+<div id="lyrics" style="display:none;">
+ <h2 id="lyricsHeader" style="text-align:center;margin-bottom:1em"></h2>
+
+ <div id="lyricsText"></div>
+
+ <p class="detail" style="text-align:right">
+ <fmt:message key="lyrics.courtesy"/>
+ </p>
+</div>
+
+<hr/>
+<p style="text-align:center">
+ <a href="javascript:self.close()">[<fmt:message key="common.close"/>]</a>
+</p>
+
+</body>
+</html>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/main.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/main.jsp new file mode 100644 index 00000000..fbbd553d --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/main.jsp @@ -0,0 +1,479 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<%--@elvariable id="model" type="java.util.Map"--%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <%@ include file="jquery.jsp" %>
+ <link href="<c:url value="/style/shadow.css"/>" rel="stylesheet">
+ <c:if test="${not model.updateNowPlaying}">
+ <meta http-equiv="refresh" content="180;URL=nowPlaying.view?">
+ </c:if>
+ <script type="text/javascript" src="<c:url value="/dwr/engine.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/starService.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/playlistService.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/fancyzoom/FancyZoom.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/fancyzoom/FancyZoomHTML.js"/>"></script>
+</head><body class="mainframe bgcolor1" onload="init();">
+
+<sub:url value="createShare.view" var="shareUrl">
+ <sub:param name="dir" value="${model.dir.path}"/>
+</sub:url>
+<sub:url value="download.view" var="downloadUrl">
+ <sub:param name="dir" value="${model.dir.path}"/>
+</sub:url>
+<sub:url value="appendPlaylist.view" var="appendPlaylistUrl">
+ <sub:param name="dir" value="${model.dir.path}"/>
+</sub:url>
+
+<script type="text/javascript" language="javascript">
+ function init() {
+ setupZoom('<c:url value="/"/>');
+
+ $("#dialog-select-playlist").dialog({resizable: true, height: 220, position: 'top', modal: true, autoOpen: false,
+ buttons: {
+ "<fmt:message key="common.cancel"/>": function() {
+ $(this).dialog("close");
+ }
+ }});
+ }
+
+ <!-- actionSelected() is invoked when the users selects from the "More actions..." combo box. -->
+ function actionSelected(id) {
+
+ if (id == "top") {
+ return;
+ } else if (id == "selectAll") {
+ selectAll(true);
+ } else if (id == "selectNone") {
+ selectAll(false);
+ } else if (id == "share") {
+ parent.frames.main.location.href = "${shareUrl}&" + getSelectedIndexes();
+ } else if (id == "download") {
+ location.href = "${downloadUrl}&" + getSelectedIndexes();
+ } else if (id == "appendPlaylist") {
+ onAppendPlaylist();
+ }
+ $("#moreActions").prop("selectedIndex", 0);
+ }
+
+ function getSelectedIndexes() {
+ var result = "";
+ for (var i = 0; i < ${fn:length(model.children)}; i++) {
+ var checkbox = $("#songIndex" + i);
+ if (checkbox != null && checkbox.is(":checked")) {
+ result += "i=" + i + "&";
+ }
+ }
+ return result;
+ }
+
+ function selectAll(b) {
+ for (var i = 0; i < ${fn:length(model.children)}; i++) {
+ var checkbox = $("#songIndex" + i);
+ if (checkbox != null) {
+ if (b) {
+ checkbox.attr("checked", "checked");
+ } else {
+ checkbox.removeAttr("checked");
+ }
+ }
+ }
+ }
+
+ function toggleStar(mediaFileId, imageId) {
+ if ($(imageId).attr("src").indexOf("<spring:theme code="ratingOnImage"/>") != -1) {
+ $(imageId).attr("src", "<spring:theme code="ratingOffImage"/>");
+ starService.unstar(mediaFileId);
+ }
+ else if ($(imageId).attr("src").indexOf("<spring:theme code="ratingOffImage"/>") != -1) {
+ $(imageId).attr("src", "<spring:theme code="ratingOnImage"/>");
+ starService.star(mediaFileId);
+ }
+ }
+
+ function onAppendPlaylist() {
+ playlistService.getWritablePlaylists(playlistCallback);
+ }
+ function playlistCallback(playlists) {
+ $("#dialog-select-playlist-list").empty();
+ for (var i = 0; i < playlists.length; i++) {
+ var playlist = playlists[i];
+ $("<p class='dense'><b><a href='#' onclick='appendPlaylist(" + playlist.id + ")'>" + playlist.name + "</a></b></p>").appendTo("#dialog-select-playlist-list");
+ }
+ $("#dialog-select-playlist").dialog("open");
+ }
+ function appendPlaylist(playlistId) {
+ $("#dialog-select-playlist").dialog("close");
+
+ var mediaFileIds = new Array();
+ for (var i = 0; i < ${fn:length(model.children)}; i++) {
+ var checkbox = $("#songIndex" + i);
+ if (checkbox && checkbox.is(":checked")) {
+ mediaFileIds.push($("#songId" + i).html());
+ }
+ }
+ playlistService.appendToPlaylist(playlistId, mediaFileIds, function (){top.left.updatePlaylists();});
+ }
+
+</script>
+
+<c:if test="${model.updateNowPlaying}">
+
+ <script type="text/javascript" language="javascript">
+ // Variable used by javascript in playlist.jsp
+ var updateNowPlaying = true;
+ </script>
+</c:if>
+
+<h1>
+ <a href="#" onclick="toggleStar(${model.dir.id}, '#starImage'); return false;">
+ <c:choose>
+ <c:when test="${not empty model.dir.starredDate}">
+ <img id="starImage" src="<spring:theme code="ratingOnImage"/>" alt="">
+ </c:when>
+ <c:otherwise>
+ <img id="starImage" src="<spring:theme code="ratingOffImage"/>" alt="">
+ </c:otherwise>
+ </c:choose>
+ </a>
+
+ <c:forEach items="${model.ancestors}" var="ancestor">
+ <sub:url value="main.view" var="ancestorUrl">
+ <sub:param name="id" value="${ancestor.id}"/>
+ </sub:url>
+ <a href="${ancestorUrl}">${ancestor.name}</a> »
+ </c:forEach>
+ ${model.dir.name}
+
+ <c:if test="${model.dir.album and model.averageRating gt 0}">
+
+ <c:import url="rating.jsp">
+ <c:param name="path" value="${model.dir.path}"/>
+ <c:param name="readonly" value="true"/>
+ <c:param name="rating" value="${model.averageRating}"/>
+ </c:import>
+ </c:if>
+</h1>
+
+<c:if test="${not model.partyMode}">
+<h2>
+ <c:if test="${model.navigateUpAllowed}">
+ <sub:url value="main.view" var="upUrl">
+ <sub:param name="id" value="${model.parent.id}"/>
+ </sub:url>
+ <a href="${upUrl}"><fmt:message key="main.up"/></a>
+ <c:set var="needSep" value="true"/>
+ </c:if>
+
+ <c:if test="${model.user.streamRole}">
+ <c:if test="${needSep}">|</c:if>
+ <a href="#" onclick="top.playQueue.onPlay(${model.dir.id});"><fmt:message key="main.playall"/></a> |
+ <a href="#" onclick="top.playQueue.onPlayRandom(${model.dir.id}, 10);"><fmt:message key="main.playrandom"/></a> |
+ <a href="#" onclick="top.playQueue.onAdd(${model.dir.id});"><fmt:message key="main.addall"/></a>
+ <c:set var="needSep" value="true"/>
+ </c:if>
+
+ <c:if test="${model.dir.album}">
+
+ <c:if test="${model.user.downloadRole}">
+ <sub:url value="download.view" var="downloadUrl">
+ <sub:param name="id" value="${model.dir.id}"/>
+ </sub:url>
+ <c:if test="${needSep}">|</c:if>
+ <a href="${downloadUrl}"><fmt:message key="common.download"/></a>
+ <c:set var="needSep" value="true"/>
+ </c:if>
+
+ <c:if test="${model.user.coverArtRole}">
+ <sub:url value="editTags.view" var="editTagsUrl">
+ <sub:param name="id" value="${model.dir.id}"/>
+ </sub:url>
+ <c:if test="${needSep}">|</c:if>
+ <a href="${editTagsUrl}"><fmt:message key="main.tags"/></a>
+ <c:set var="needSep" value="true"/>
+ </c:if>
+
+ </c:if>
+
+ <c:if test="${model.user.commentRole}">
+ <c:if test="${needSep}">|</c:if>
+ <a href="javascript:toggleComment()"><fmt:message key="main.comment"/></a>
+ </c:if>
+</h2>
+</c:if>
+
+<c:if test="${model.dir.album}">
+
+ <div class="detail">
+ <c:if test="${model.user.commentRole}">
+ <c:import url="rating.jsp">
+ <c:param name="path" value="${model.dir.path}"/>
+ <c:param name="readonly" value="false"/>
+ <c:param name="rating" value="${model.userRating}"/>
+ </c:import>
+ </c:if>
+
+ <c:if test="${model.user.shareRole}">
+ <a href="${shareUrl}"><img src="<spring:theme code="shareFacebookImage"/>" alt=""></a>
+ <a href="${shareUrl}"><img src="<spring:theme code="shareTwitterImage"/>" alt=""></a>
+ <a href="${shareUrl}"><img src="<spring:theme code="shareGooglePlusImage"/>" alt=""></a>
+ <a href="${shareUrl}"><span class="detail"><fmt:message key="main.sharealbum"/></span></a> |
+ </c:if>
+
+ <c:if test="${not empty model.artist and not empty model.album}">
+ <sub:url value="http://www.google.com/search" var="googleUrl" encoding="UTF-8">
+ <sub:param name="q" value="\"${model.artist}\" \"${model.album}\""/>
+ </sub:url>
+ <sub:url value="http://en.wikipedia.org/wiki/Special:Search" var="wikipediaUrl" encoding="UTF-8">
+ <sub:param name="search" value="\"${model.album}\""/>
+ <sub:param name="go" value="Go"/>
+ </sub:url>
+ <sub:url value="allmusic.view" var="allmusicUrl">
+ <sub:param name="album" value="${model.album}"/>
+ </sub:url>
+ <sub:url value="http://www.last.fm/search" var="lastFmUrl" encoding="UTF-8">
+ <sub:param name="q" value="\"${model.artist}\" \"${model.album}\""/>
+ <sub:param name="type" value="album"/>
+ </sub:url>
+ <fmt:message key="top.search"/> <a target="_blank" href="${googleUrl}">Google</a> |
+ <a target="_blank" href="${wikipediaUrl}">Wikipedia</a> |
+ <a target="_blank" href="${allmusicUrl}">allmusic</a> |
+ <a target="_blank" href="${lastFmUrl}">Last.fm</a>
+ </c:if>
+ </div>
+ <div class="detail" style="padding-top:0.2em">
+ <fmt:message key="main.playcount"><fmt:param value="${model.dir.playCount}"/></fmt:message>
+ <c:if test="${not empty model.dir.lastPlayed}">
+ <fmt:message key="main.lastplayed">
+ <fmt:param><fmt:formatDate type="date" dateStyle="long" value="${model.dir.lastPlayed}"/></fmt:param>
+ </fmt:message>
+ </c:if>
+ </div>
+
+</c:if>
+
+<div id="comment" class="albumComment"><sub:wiki text="${model.dir.comment}"/></div>
+
+<div id="commentForm" style="display:none">
+ <form method="post" action="setMusicFileInfo.view">
+ <input type="hidden" name="action" value="comment">
+ <input type="hidden" name="path" value="${model.dir.path}">
+ <textarea name="comment" rows="6" cols="70">${model.dir.comment}</textarea>
+ <input type="submit" value="<fmt:message key="common.save"/>">
+ </form>
+ <fmt:message key="main.wiki"/>
+</div>
+
+<script type='text/javascript'>
+ function toggleComment() {
+ $("#commentForm").toggle();
+ $("#comment").toggle();
+ }
+</script>
+
+
+<table cellpadding="10" style="width:100%">
+<tr style="vertical-align:top;">
+ <td style="vertical-align:top;">
+ <table style="border-collapse:collapse;white-space:nowrap">
+ <c:set var="cutoff" value="${model.visibility.captionCutoff}"/>
+ <c:forEach items="${model.children}" var="child" varStatus="loopStatus">
+ <%--@elvariable id="child" type="net.sourceforge.subsonic.domain.MediaFile"--%>
+ <c:choose>
+ <c:when test="${loopStatus.count % 2 == 1}">
+ <c:set var="class" value="class='bgcolor2'"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="class" value=""/>
+ </c:otherwise>
+ </c:choose>
+
+ <tr style="margin:0;padding:0;border:0">
+ <c:import url="playAddDownload.jsp">
+ <c:param name="id" value="${child.id}"/>
+ <c:param name="video" value="${child.video and model.player.web}"/>
+ <c:param name="playEnabled" value="${model.user.streamRole and not model.partyMode}"/>
+ <c:param name="addEnabled" value="${model.user.streamRole and (not model.partyMode or not child.directory)}"/>
+ <c:param name="downloadEnabled" value="${model.user.downloadRole and not model.partyMode}"/>
+ <c:param name="starEnabled" value="true"/>
+ <c:param name="starred" value="${not empty child.starredDate}"/>
+ <c:param name="asTable" value="true"/>
+ </c:import>
+
+ <c:choose>
+ <c:when test="${child.directory}">
+ <sub:url value="main.view" var="childUrl">
+ <sub:param name="id" value="${child.id}"/>
+ </sub:url>
+ <td style="padding-left:0.25em" colspan="3">
+ <a href="${childUrl}" title="${child.name}"><span style="white-space:nowrap;"><str:truncateNicely upper="${cutoff}">${child.name}</str:truncateNicely></span></a>
+ </td>
+ <td style="padding-left:1.25em"><c:if test="${model.showAlbumYear and not empty child.year}"><span class="detail">${child.year}</span></c:if></td>
+ </c:when>
+
+ <c:otherwise>
+ <td ${class} style="padding-left:0.25em"><input type="checkbox" class="checkbox" id="songIndex${loopStatus.count - 1}">
+ <span id="songId${loopStatus.count - 1}" style="display: none">${child.id}</span></td>
+
+ <c:if test="${model.visibility.trackNumberVisible}">
+ <td ${class} style="padding-right:0.5em;text-align:right">
+ <span class="detail">${child.trackNumber}</span>
+ </td>
+ </c:if>
+
+ <td ${class} style="padding-right:1.25em;white-space:nowrap">
+ <span title="${child.title}"><str:truncateNicely upper="${cutoff}">${fn:escapeXml(child.title)}</str:truncateNicely></span>
+ </td>
+
+ <c:if test="${model.visibility.albumVisible}">
+ <td ${class} style="padding-right:1.25em;white-space:nowrap">
+ <span class="detail" title="${child.albumName}"><str:truncateNicely upper="${cutoff}">${fn:escapeXml(child.albumName)}</str:truncateNicely></span>
+ </td>
+ </c:if>
+
+ <c:if test="${model.visibility.artistVisible and model.multipleArtists}">
+ <td ${class} style="padding-right:1.25em;white-space:nowrap">
+ <span class="detail" title="${child.artist}"><str:truncateNicely upper="${cutoff}">${fn:escapeXml(child.artist)}</str:truncateNicely></span>
+ </td>
+ </c:if>
+
+ <c:if test="${model.visibility.genreVisible}">
+ <td ${class} style="padding-right:1.25em;white-space:nowrap">
+ <span class="detail">${child.genre}</span>
+ </td>
+ </c:if>
+
+ <c:if test="${model.visibility.yearVisible}">
+ <td ${class} style="padding-right:1.25em">
+ <span class="detail">${child.year}</span>
+ </td>
+ </c:if>
+
+ <c:if test="${model.visibility.formatVisible}">
+ <td ${class} style="padding-right:1.25em">
+ <span class="detail">${fn:toLowerCase(child.format)}</span>
+ </td>
+ </c:if>
+
+ <c:if test="${model.visibility.fileSizeVisible}">
+ <td ${class} style="padding-right:1.25em;text-align:right">
+ <span class="detail"><sub:formatBytes bytes="${child.fileSize}"/></span>
+ </td>
+ </c:if>
+
+ <c:if test="${model.visibility.durationVisible}">
+ <td ${class} style="padding-right:1.25em;text-align:right">
+ <span class="detail">${child.durationString}</span>
+ </td>
+ </c:if>
+
+ <c:if test="${model.visibility.bitRateVisible}">
+ <td ${class} style="padding-right:0.25em">
+ <span class="detail">
+ <c:if test="${not empty child.bitRate}">
+ ${child.bitRate} Kbps ${child.variableBitRate ? "vbr" : ""}
+ </c:if>
+ <c:if test="${child.video and not empty child.width and not empty child.height}">
+ (${child.width}x${child.height})
+ </c:if>
+ </span>
+ </td>
+ </c:if>
+
+
+ </c:otherwise>
+ </c:choose>
+ </tr>
+ </c:forEach>
+ </table>
+ </td>
+
+ <td style="vertical-align:top;width:100%">
+ <c:forEach items="${model.coverArts}" var="coverArt" varStatus="loopStatus">
+ <div style="float:left; padding:5px">
+ <c:import url="coverArt.jsp">
+ <c:param name="albumId" value="${coverArt.id}"/>
+ <c:param name="albumName" value="${coverArt.name}"/>
+ <c:param name="coverArtSize" value="${model.coverArtSize}"/>
+ <c:param name="showLink" value="${coverArt ne model.dir}"/>
+ <c:param name="showZoom" value="${coverArt eq model.dir}"/>
+ <c:param name="showChange" value="${(coverArt eq model.dir) and model.user.coverArtRole}"/>
+ <c:param name="showCaption" value="true"/>
+ <c:param name="appearAfter" value="${loopStatus.count * 30}"/>
+ </c:import>
+ </div>
+ </c:forEach>
+
+ <c:if test="${model.showGenericCoverArt}">
+ <div style="float:left; padding:5px">
+ <c:import url="coverArt.jsp">
+ <c:param name="albumId" value="${model.dir.id}"/>
+ <c:param name="coverArtSize" value="${model.coverArtSize}"/>
+ <c:param name="showLink" value="false"/>
+ <c:param name="showZoom" value="false"/>
+ <c:param name="showChange" value="${model.user.coverArtRole}"/>
+ <c:param name="appearAfter" value="0"/>
+ </c:import>
+ </div>
+ </c:if>
+ </td>
+
+ <td style="vertical-align:top;">
+ <div style="padding:0 1em 0 1em;">
+ <c:if test="${not empty model.ad}">
+ <div class="detail" style="text-align:center">
+ ${model.ad}
+ <br/>
+ <br/>
+ <sub:url value="donate.view" var="donateUrl">
+ <sub:param name="path" value="${model.dir.path}"/>
+ </sub:url>
+ <fmt:message key="main.donate"><fmt:param value="${donateUrl}"/><fmt:param value="${model.brand}"/></fmt:message>
+ </div>
+ </c:if>
+ </div>
+ </td>
+</tr>
+</table>
+
+<select id="moreActions" onchange="actionSelected(this.options[selectedIndex].id);" style="margin-bottom:1.0em">
+ <option id="top" selected="selected"><fmt:message key="main.more"/></option>
+ <option style="color:blue;"><fmt:message key="main.more.selection"/></option>
+ <option id="selectAll"> <fmt:message key="playlist.more.selectall"/></option>
+ <option id="selectNone"> <fmt:message key="playlist.more.selectnone"/></option>
+ <c:if test="${model.user.shareRole}">
+ <option id="share"> <fmt:message key="main.more.share"/></option>
+ </c:if>
+ <c:if test="${model.user.downloadRole}">
+ <option id="download"> <fmt:message key="common.download"/></option>
+ </c:if>
+ <option id="appendPlaylist"> <fmt:message key="playlist.append"/></option>
+</select>
+
+<div style="padding-bottom: 1em">
+ <c:if test="${not empty model.previousAlbum}">
+ <sub:url value="main.view" var="previousUrl">
+ <sub:param name="id" value="${model.previousAlbum.id}"/>
+ </sub:url>
+ <div class="back" style="float:left;padding-right:10pt"><a href="${previousUrl}" title="${model.previousAlbum.name}">
+ <str:truncateNicely upper="30">${fn:escapeXml(model.previousAlbum.name)}</str:truncateNicely>
+ </a></div>
+ </c:if>
+ <c:if test="${not empty model.nextAlbum}">
+ <sub:url value="main.view" var="nextUrl">
+ <sub:param name="id" value="${model.nextAlbum.id}"/>
+ </sub:url>
+ <div class="forward" style="float:left"><a href="${nextUrl}" title="${model.nextAlbum.name}">
+ <str:truncateNicely upper="30">${fn:escapeXml(model.nextAlbum.name)}</str:truncateNicely>
+ </a></div>
+ </c:if>
+</div>
+
+<div id="dialog-select-playlist" title="<fmt:message key="main.addtoplaylist.title"/>" style="display: none;">
+ <p><fmt:message key="main.addtoplaylist.text"/></p>
+ <div id="dialog-select-playlist-list"></div>
+</div>
+
+</body>
+</html>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/more.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/more.jsp new file mode 100644 index 00000000..18be91fe --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/more.jsp @@ -0,0 +1,159 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <style type="text/css">
+ #progressBar {width: 350px; height: 10px; border: 1px solid black; display:none;}
+ #progressBarContent {width: 0; height: 10px; background: url("<c:url value="/icons/progress.png"/>") repeat;}
+ </style>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/transferService.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/engine.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/util.js"/>"></script>
+
+ <script type="text/javascript">
+ function refreshProgress() {
+ transferService.getUploadInfo(updateProgress);
+ }
+
+ function updateProgress(uploadInfo) {
+
+ var progressBar = document.getElementById("progressBar");
+ var progressBarContent = document.getElementById("progressBarContent");
+ var progressText = document.getElementById("progressText");
+
+
+ if (uploadInfo.bytesTotal > 0) {
+ var percent = Math.ceil((uploadInfo.bytesUploaded / uploadInfo.bytesTotal) * 100);
+ var width = parseInt(percent * 3.5) + 'px';
+ progressBarContent.style.width = width;
+ progressText.innerHTML = percent + "<fmt:message key="more.upload.progress"/>";
+ progressBar.style.display = "block";
+ progressText.style.display = "block";
+ window.setTimeout("refreshProgress()", 1000);
+ } else {
+ progressBar.style.display = "none";
+ progressText.style.display = "none";
+ window.setTimeout("refreshProgress()", 5000);
+ }
+ }
+ </script>
+
+</head>
+<body class="mainframe bgcolor1" onload="${model.user.uploadRole ? "refreshProgress()" : ""}">
+
+<h1>
+ <img src="<spring:theme code="moreImage"/>" alt=""/>
+ <fmt:message key="more.title"/>
+</h1>
+
+<c:if test="${model.user.streamRole}">
+ <h2><img src="<spring:theme code="randomImage"/>" alt=""/> <fmt:message key="more.random.title"/></h2>
+
+ <form method="post" action="randomPlayQueue.view?">
+ <table>
+ <tr>
+ <td><fmt:message key="more.random.text"/></td>
+ <td>
+ <select name="size">
+ <option value="5"><fmt:message key="more.random.songs"><fmt:param value="5"/></fmt:message></option>
+ <option value="10" selected="true"><fmt:message key="more.random.songs"><fmt:param value="10"/></fmt:message></option>
+ <option value="20"><fmt:message key="more.random.songs"><fmt:param value="20"/></fmt:message></option>
+ <option value="50"><fmt:message key="more.random.songs"><fmt:param value="50"/></fmt:message></option>
+ </select>
+ </td>
+ <td><fmt:message key="more.random.genre"/></td>
+ <td>
+ <select name="genre">
+ <option value="any"><fmt:message key="more.random.anygenre"/></option>
+ <c:forEach items="${model.genres}" var="genre">
+ <option value="${genre}"><str:truncateNicely upper="20">${genre}</str:truncateNicely></option>
+ </c:forEach>
+ </select>
+ </td>
+ <td><fmt:message key="more.random.year"/></td>
+ <td>
+ <select name="year">
+ <option value="any"><fmt:message key="more.random.anyyear"/></option>
+
+ <c:forEach begin="0" end="${model.currentYear - 2006}" var="yearOffset">
+ <c:set var="year" value="${model.currentYear - yearOffset}"/>
+ <option value="${year} ${year}">${year}</option>
+ </c:forEach>
+
+ <option value="2005 2010">2005 – 2010</option>
+ <option value="2000 2005">2000 – 2005</option>
+ <option value="1990 2000">1990 – 2000</option>
+ <option value="1980 1990">1980 – 1990</option>
+ <option value="1970 1980">1970 – 1980</option>
+ <option value="1960 1970">1960 – 1970</option>
+ <option value="1950 1960">1950 – 1960</option>
+ <option value="0 1949">< 1950</option>
+ </select>
+ </td>
+ <td><fmt:message key="more.random.folder"/></td>
+ <td>
+ <select name="musicFolderId">
+ <option value="-1"><fmt:message key="more.random.anyfolder"/></option>
+ <c:forEach items="${model.musicFolders}" var="musicFolder">
+ <option value="${musicFolder.id}">${musicFolder.name}</option>
+ </c:forEach>
+ </select>
+ </td>
+ <td>
+ <input type="submit" value="<fmt:message key="more.random.ok"/>">
+ </td>
+ </tr>
+ <c:if test="${not model.clientSidePlaylist}">
+ <tr>
+ <td colspan="9">
+ <input type="checkbox" name="autoRandom" id="autoRandom" class="checkbox"/>
+ <label for="autoRandom"><fmt:message key="more.random.auto"/></label>
+ </td>
+ </tr>
+ </c:if>
+ </table>
+ </form>
+</c:if>
+<h2><img src="<spring:theme code="androidImage"/>" alt=""/> <fmt:message key="more.apps.title"/></h2>
+<fmt:message key="more.apps.text"/>
+
+<h2><img src="<spring:theme code="wapImage"/>" alt=""/> <fmt:message key="more.mobile.title"/></h2>
+<fmt:message key="more.mobile.text"><fmt:param value="${model.brand}"/></fmt:message>
+
+<h2><img src="<spring:theme code="podcastImage"/>" alt=""/> <fmt:message key="more.podcast.title"/></h2>
+<fmt:message key="more.podcast.text"/>
+
+<c:if test="${model.user.uploadRole}">
+
+ <h2><img src="<spring:theme code="uploadImage"/>" alt=""/> <fmt:message key="more.upload.title"/></h2>
+
+ <form method="post" enctype="multipart/form-data" action="upload.view">
+ <table>
+ <tr>
+ <td><fmt:message key="more.upload.source"/></td>
+ <td colspan="2"><input type="file" id="file" name="file" size="40"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="more.upload.target"/></td>
+ <td><input type="text" id="dir" name="dir" size="37" value="${model.uploadDirectory}"/></td>
+ <td><input type="submit" value="<fmt:message key="more.upload.ok"/>"/></td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <input type="checkbox" checked name="unzip" id="unzip" class="checkbox"/>
+ <label for="unzip"><fmt:message key="more.upload.unzip"/></label>
+ </td>
+ </tr>
+ </table>
+ </form>
+
+
+ <p class="detail" id="progressText"/>
+
+ <div id="progressBar">
+ <div id="progressBarContent"/>
+ </div>
+
+</c:if>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/musicFolderSettings.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/musicFolderSettings.jsp new file mode 100644 index 00000000..283e6878 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/musicFolderSettings.jsp @@ -0,0 +1,114 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+<%--@elvariable id="command" type="net.sourceforge.subsonic.command.MusicFolderSettingsCommand"--%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+</head>
+<body class="mainframe bgcolor1">
+
+<c:import url="settingsHeader.jsp">
+ <c:param name="cat" value="musicFolder"/>
+</c:import>
+
+<form:form commandName="command" action="musicFolderSettings.view" method="post">
+
+<table class="indent">
+ <tr>
+ <th><fmt:message key="musicfoldersettings.name"/></th>
+ <th><fmt:message key="musicfoldersettings.path"/></th>
+ <th style="padding-left:1em"><fmt:message key="musicfoldersettings.enabled"/></th>
+ <th style="padding-left:1em"><fmt:message key="common.delete"/></th>
+ <th></th>
+ </tr>
+
+ <c:forEach items="${command.musicFolders}" var="folder" varStatus="loopStatus">
+ <tr>
+ <td><form:input path="musicFolders[${loopStatus.count-1}].name" size="20"/></td>
+ <td><form:input path="musicFolders[${loopStatus.count-1}].path" size="40"/></td>
+ <td align="center" style="padding-left:1em"><form:checkbox path="musicFolders[${loopStatus.count-1}].enabled" cssClass="checkbox"/></td>
+ <td align="center" style="padding-left:1em"><form:checkbox path="musicFolders[${loopStatus.count-1}].delete" cssClass="checkbox"/></td>
+ <td><c:if test="${not folder.existing}"><span class="warning"><fmt:message key="musicfoldersettings.notfound"/></span></c:if></td>
+ </tr>
+ </c:forEach>
+
+ <tr>
+ <th colspan="4" align="left" style="padding-top:1em"><fmt:message key="musicfoldersettings.add"/></th>
+ </tr>
+
+ <tr>
+ <td><form:input path="newMusicFolder.name" size="20"/></td>
+ <td><form:input path="newMusicFolder.path" size="40"/></td>
+ <td align="center" style="padding-left:1em"><form:checkbox path="newMusicFolder.enabled" cssClass="checkbox"/></td>
+ <td></td>
+ </tr>
+
+</table>
+
+ <div style="padding-top: 1.2em;padding-bottom: 0.3em">
+ <span style="white-space: nowrap">
+ <fmt:message key="musicfoldersettings.scan"/>
+ <form:select path="interval">
+ <fmt:message key="musicfoldersettings.interval.never" var="never"/>
+ <fmt:message key="musicfoldersettings.interval.one" var="one"/>
+ <form:option value="-1" label="${never}"/>
+ <form:option value="1" label="${one}"/>
+
+ <c:forTokens items="2 3 7 14 30 60" delims=" " var="interval">
+ <fmt:message key="musicfoldersettings.interval.many" var="many"><fmt:param value="${interval}"/></fmt:message>
+ <form:option value="${interval}" label="${many}"/>
+ </c:forTokens>
+ </form:select>
+ <form:select path="hour">
+ <c:forEach begin="0" end="23" var="hour">
+ <fmt:message key="musicfoldersettings.hour" var="hourLabel"><fmt:param value="${hour}"/></fmt:message>
+ <form:option value="${hour}" label="${hourLabel}"/>
+ </c:forEach>
+ </form:select>
+ </span>
+ </div>
+
+ <p class="forward"><a href="musicFolderSettings.view?scanNow"><fmt:message key="musicfoldersettings.scannow"/></a></p>
+
+ <c:if test="${command.scanning}">
+ <p style="width:60%"><b><fmt:message key="musicfoldersettings.nowscanning"/></b></p>
+ </c:if>
+
+ <div>
+ <form:checkbox path="fastCache" cssClass="checkbox" id="fastCache"/>
+ <form:label path="fastCache"><fmt:message key="musicfoldersettings.fastcache"/></form:label>
+ </div>
+
+ <p class="detail" style="width:60%;white-space:normal;">
+ <fmt:message key="musicfoldersettings.fastcache.description"/>
+ </p>
+
+ <p class="forward"><a href="musicFolderSettings.view?expunge"><fmt:message key="musicfoldersettings.expunge"/></a></p>
+ <p class="detail" style="width:60%;white-space:normal;margin-top:-10px;">
+ <fmt:message key="musicfoldersettings.expunge.description"/>
+ </p>
+
+ <%--<div>--%>
+ <%--<form:checkbox path="organizeByFolderStructure" cssClass="checkbox" id="organizeByFolderStructure"/>--%>
+ <%--<form:label path="organizeByFolderStructure"><fmt:message key="musicfoldersettings.organizebyfolderstructure"/></form:label>--%>
+ <%--</div>--%>
+
+ <%--<p class="detail" style="width:60%;white-space:normal;">--%>
+ <%--<fmt:message key="musicfoldersettings.organizebyfolderstructure.description"/>--%>
+ <%--</p>--%>
+
+ <p >
+ <input type="submit" value="<fmt:message key="common.save"/>" style="margin-right:0.3em">
+ <input type="button" value="<fmt:message key="common.cancel"/>" onclick="location.href='nowPlaying.view'">
+ </p>
+
+</form:form>
+
+<c:if test="${command.reload}">
+ <script type="text/javascript">
+ parent.frames.upper.location.href="top.view?";
+ parent.frames.left.location.href="left.view?";
+ parent.frames.right.location.href="right.view?";
+ </script>
+</c:if>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/networkSettings.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/networkSettings.jsp new file mode 100644 index 00000000..c59c16c9 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/networkSettings.jsp @@ -0,0 +1,107 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+<%--@elvariable id="command" type="net.sourceforge.subsonic.command.NetworkSettingsCommand"--%>
+
+<html>
+<head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="<c:url value="/script/prototype.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/multiService.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/engine.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/util.js"/>"></script>
+ <script type="text/javascript" language="javascript">
+
+ function init() {
+ enableUrlRedirectionFields();
+ refreshStatus();
+ }
+
+ function refreshStatus() {
+ multiService.getNetworkStatus(updateStatus);
+ }
+
+ function updateStatus(networkStatus) {
+ dwr.util.setValue("portForwardingStatus", networkStatus.portForwardingStatusText);
+ dwr.util.setValue("urlRedirectionStatus", networkStatus.urlRedirectionStatusText);
+ window.setTimeout("refreshStatus()", 1000);
+ }
+
+ function enableUrlRedirectionFields() {
+ var checkbox = $("urlRedirectionEnabled");
+ var field = $("urlRedirectFrom");
+
+ if (checkbox && checkbox.checked) {
+ field.enable();
+ } else {
+ field.disable();
+ }
+ }
+
+ </script>
+</head>
+<body class="mainframe bgcolor1" onload="init()">
+<script type="text/javascript" src="<c:url value="/script/wz_tooltip.js"/>"></script>
+<script type="text/javascript" src="<c:url value="/script/tip_balloon.js"/>"></script>
+
+<c:import url="settingsHeader.jsp">
+ <c:param name="cat" value="network"/>
+</c:import>
+
+<p style="padding-top:1em"><fmt:message key="networksettings.text"/></p>
+
+<form:form commandName="command" action="networkSettings.view" method="post">
+ <p style="padding-top:1em">
+ <form:checkbox id="portForwardingEnabled" path="portForwardingEnabled"/>
+ <label for="portForwardingEnabled"><fmt:message key="networksettings.portforwardingenabled"/></label>
+ </p>
+
+ <div style="padding-left:2em;max-width:60em">
+ <p>
+ <fmt:message key="networksettings.portforwardinghelp"><fmt:param>${command.port}</fmt:param></fmt:message>
+ </p>
+
+ <p class="detail">
+ <fmt:message key="networksettings.status"/>
+ <span id="portForwardingStatus" style="margin-left:0.25em"></span>
+ </p>
+ </div>
+
+ <p style="padding-top:1em"><form:checkbox id="urlRedirectionEnabled" path="urlRedirectionEnabled"
+ onclick="enableUrlRedirectionFields()"/>
+ <label for="urlRedirectionEnabled"><fmt:message key="networksettings.urlredirectionenabled"/></label>
+ </p>
+
+ <div style="padding-left:2em">
+
+ <p>http://<form:input id="urlRedirectFrom" path="urlRedirectFrom" size="16" cssStyle="margin-left:0.25em"/>.subsonic.org</p>
+
+ <p class="detail">
+ <fmt:message key="networksettings.status"/>
+ <span id="urlRedirectionStatus" style="margin-left:0.25em"></span>
+ <span id="urlRedirectionTestStatus" style="margin-left:0.25em"></span>
+ </p>
+ </div>
+
+ <c:if test="${command.trial}">
+ <fmt:formatDate value="${command.trialExpires}" dateStyle="long" var="expiryDate"/>
+
+ <p class="warning" style="padding-top:1em">
+ <c:choose>
+ <c:when test="${command.trialExpired}">
+ <fmt:message key="networksettings.trialexpired"><fmt:param>${expiryDate}</fmt:param></fmt:message>
+ </c:when>
+ <c:otherwise>
+ <fmt:message
+ key="networksettings.trialnotexpired"><fmt:param>${expiryDate}</fmt:param></fmt:message>
+ </c:otherwise>
+ </c:choose>
+ </p>
+ </c:if>
+
+ <p style="padding-top:1em">
+ <input type="submit" value="<fmt:message key="common.save"/>" style="margin-right:0.3em">
+ <input type="button" value="<fmt:message key="common.cancel"/>" onclick="location.href='nowPlaying.view'">
+ </p>
+
+</form:form>
+</body>
+</html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/notFound.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/notFound.jsp new file mode 100644 index 00000000..84e666af --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/notFound.jsp @@ -0,0 +1,21 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<html>
+<head>
+ <%@ include file="head.jsp" %>
+</head>
+
+<body class="mainframe bgcolor1">
+
+<h1>
+ <img src="<spring:theme code="errorImage"/>" alt=""/>
+ <fmt:message key="notFound.title"/>
+</h1>
+
+<fmt:message key="notFound.text"/>
+
+<div class="forward" style="float:left;padding-right:10pt"><a href="javascript:top.location.reload(true)"><fmt:message key="notFound.reload"/></a></div>
+<div class="forward" style="float:left"><a href="musicFolderSettings.view"><fmt:message key="notFound.scan"/></a></div>
+
+</body>
+</html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/passwordSettings.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/passwordSettings.jsp new file mode 100644 index 00000000..75fd3e01 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/passwordSettings.jsp @@ -0,0 +1,45 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+</head>
+<body class="mainframe bgcolor1">
+
+<c:import url="settingsHeader.jsp">
+ <c:param name="cat" value="password"/>
+ <c:param name="restricted" value="true"/>
+</c:import>
+
+<c:choose>
+
+ <c:when test="${command.ldapAuthenticated}">
+ <p><fmt:message key="usersettings.passwordnotsupportedforldap"/></p>
+ </c:when>
+
+ <c:otherwise>
+ <h2><fmt:message key="passwordsettings.title"><fmt:param>${command.username}</fmt:param></fmt:message></h2>
+ <form:form method="post" action="passwordSettings.view" commandName="command">
+ <table class="indent">
+ <tr>
+ <td><fmt:message key="usersettings.newpassword"/></td>
+ <td><form:password path="password"/></td>
+ <td class="warning"><form:errors path="password"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="usersettings.confirmpassword"/></td>
+ <td><form:password path="confirmPassword"/></td>
+ <td/>
+ </tr>
+ <tr>
+ <td colspan="3" style="padding-top:1.5em">
+ <input type="submit" value="<fmt:message key="common.save"/>" style="margin-right:0.3em">
+ <input type="button" value="<fmt:message key="common.cancel"/>" onclick="location.href='nowPlaying.view'">
+ </td>
+ </tr>
+
+ </table>
+ </form:form>
+ </c:otherwise>
+</c:choose>
+
+</body></html>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/personalSettings.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/personalSettings.jsp new file mode 100644 index 00000000..2942d195 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/personalSettings.jsp @@ -0,0 +1,228 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+<%--@elvariable id="command" type="net.sourceforge.subsonic.command.PersonalSettingsCommand"--%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="<c:url value="/script/scripts.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/prototype.js"/>"></script>
+
+ <script type="text/javascript" language="javascript">
+ function enableLastFmFields() {
+ var checkbox = $("lastFm");
+ var table = $("lastFmTable");
+
+ if (checkbox && checkbox.checked) {
+ table.show();
+ } else {
+ table.hide();
+ }
+ }
+ </script>
+</head>
+
+<body class="mainframe bgcolor1" onload="enableLastFmFields()">
+<script type="text/javascript" src="<c:url value="/script/wz_tooltip.js"/>"></script>
+<script type="text/javascript" src="<c:url value="/script/tip_balloon.js"/>"></script>
+
+<c:import url="settingsHeader.jsp">
+ <c:param name="cat" value="personal"/>
+ <c:param name="restricted" value="${not command.user.adminRole}"/>
+</c:import>
+
+<h2><fmt:message key="personalsettings.title"><fmt:param>${command.user.username}</fmt:param></fmt:message></h2>
+
+<fmt:message key="common.default" var="default"/>
+<form:form method="post" action="personalSettings.view" commandName="command">
+
+ <table style="white-space:nowrap" class="indent">
+
+ <tr>
+ <td><fmt:message key="personalsettings.language"/></td>
+ <td>
+ <form:select path="localeIndex" cssStyle="width:15em">
+ <form:option value="-1" label="${default}"/>
+ <c:forEach items="${command.locales}" var="locale" varStatus="loopStatus">
+ <form:option value="${loopStatus.count - 1}" label="${locale}"/>
+ </c:forEach>
+ </form:select>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="language"/></c:import>
+ </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="personalsettings.theme"/></td>
+ <td>
+ <form:select path="themeIndex" cssStyle="width:15em">
+ <form:option value="-1" label="${default}"/>
+ <c:forEach items="${command.themes}" var="theme" varStatus="loopStatus">
+ <form:option value="${loopStatus.count - 1}" label="${theme.name}"/>
+ </c:forEach>
+ </form:select>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="theme"/></c:import>
+ </td>
+ </tr>
+ </table>
+
+ <table class="indent">
+ <tr>
+ <th style="padding:0 0.5em 0.5em 0;text-align:left;"><fmt:message key="personalsettings.display"/></th>
+ <th style="padding:0 0.5em 0.5em 0.5em;text-align:center;"><fmt:message key="personalsettings.browse"/></th>
+ <th style="padding:0 0 0.5em 0.5em;text-align:center;"><fmt:message key="personalsettings.playlist"/></th>
+ <th style="padding:0 0 0.5em 0.5em">
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="visibility"/></c:import>
+ </th>
+ </tr>
+ <tr>
+ <td><fmt:message key="personalsettings.tracknumber"/></td>
+ <td style="text-align:center"><form:checkbox path="mainVisibility.trackNumberVisible" cssClass="checkbox"/></td>
+ <td style="text-align:center"><form:checkbox path="playlistVisibility.trackNumberVisible" cssClass="checkbox"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="personalsettings.artist"/></td>
+ <td style="text-align:center"><form:checkbox path="mainVisibility.artistVisible" cssClass="checkbox"/></td>
+ <td style="text-align:center"><form:checkbox path="playlistVisibility.artistVisible" cssClass="checkbox"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="personalsettings.album"/></td>
+ <td style="text-align:center"><form:checkbox path="mainVisibility.albumVisible" cssClass="checkbox"/></td>
+ <td style="text-align:center"><form:checkbox path="playlistVisibility.albumVisible" cssClass="checkbox"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="personalsettings.genre"/></td>
+ <td style="text-align:center"><form:checkbox path="mainVisibility.genreVisible" cssClass="checkbox"/></td>
+ <td style="text-align:center"><form:checkbox path="playlistVisibility.genreVisible" cssClass="checkbox"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="personalsettings.year"/></td>
+ <td style="text-align:center"><form:checkbox path="mainVisibility.yearVisible" cssClass="checkbox"/></td>
+ <td style="text-align:center"><form:checkbox path="playlistVisibility.yearVisible" cssClass="checkbox"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="personalsettings.bitrate"/></td>
+ <td style="text-align:center"><form:checkbox path="mainVisibility.bitRateVisible" cssClass="checkbox"/></td>
+ <td style="text-align:center"><form:checkbox path="playlistVisibility.bitRateVisible" cssClass="checkbox"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="personalsettings.duration"/></td>
+ <td style="text-align:center"><form:checkbox path="mainVisibility.durationVisible" cssClass="checkbox"/></td>
+ <td style="text-align:center"><form:checkbox path="playlistVisibility.durationVisible" cssClass="checkbox"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="personalsettings.format"/></td>
+ <td style="text-align:center"><form:checkbox path="mainVisibility.formatVisible" cssClass="checkbox"/></td>
+ <td style="text-align:center"><form:checkbox path="playlistVisibility.formatVisible" cssClass="checkbox"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="personalsettings.filesize"/></td>
+ <td style="text-align:center"><form:checkbox path="mainVisibility.fileSizeVisible" cssClass="checkbox"/></td>
+ <td style="text-align:center"><form:checkbox path="playlistVisibility.fileSizeVisible" cssClass="checkbox"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="personalsettings.captioncutoff"/></td>
+ <td style="text-align:center"><form:input path="mainVisibility.captionCutoff" size="3"/></td>
+ <td style="text-align:center"><form:input path="playlistVisibility.captionCutoff" size="3"/></td>
+ </tr>
+ </table>
+
+ <table class="indent">
+ <tr>
+ <td><form:checkbox path="showNowPlayingEnabled" id="nowPlaying" cssClass="checkbox"/></td>
+ <td><label for="nowPlaying"><fmt:message key="personalsettings.shownowplaying"/></label></td>
+ <td style="padding-left:2em"><form:checkbox path="showChatEnabled" id="chat" cssClass="checkbox"/></td>
+ <td><label for="chat"><fmt:message key="personalsettings.showchat"/></label></td>
+ </tr>
+ <tr>
+ <td><form:checkbox path="nowPlayingAllowed" id="nowPlayingAllowed" cssClass="checkbox"/></td>
+ <td><label for="nowPlayingAllowed"><fmt:message key="personalsettings.nowplayingallowed"/></label></td>
+ <td style="padding-left:2em"><form:checkbox path="partyModeEnabled" id="partyModeEnabled" cssClass="checkbox"/></td>
+ <td><label for="partyModeEnabled"><fmt:message key="personalsettings.partymode"/></label>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="partymode"/></c:import>
+ </td>
+ </tr>
+ </table>
+
+ <table class="indent">
+ <tr>
+ <td><form:checkbox path="finalVersionNotificationEnabled" id="final" cssClass="checkbox"/></td>
+ <td><label for="final"><fmt:message key="personalsettings.finalversionnotification"/></label></td>
+ </tr>
+ <tr>
+ <td><form:checkbox path="betaVersionNotificationEnabled" id="beta" cssClass="checkbox"/></td>
+ <td><label for="beta"><fmt:message key="personalsettings.betaversionnotification"/></label></td>
+ </tr>
+ </table>
+
+ <table class="indent">
+ <tr>
+ <td><form:checkbox path="lastFmEnabled" id="lastFm" cssClass="checkbox" onclick="javascript:enableLastFmFields()"/></td>
+ <td><label for="lastFm"><fmt:message key="personalsettings.lastfmenabled"/></label></td>
+ </tr>
+ </table>
+
+ <table id="lastFmTable" style="padding-left:2em">
+ <tr>
+ <td><fmt:message key="personalsettings.lastfmusername"/></td>
+ <td><form:input path="lastFmUsername" size="24"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="personalsettings.lastfmpassword"/></td>
+ <td><form:password path="lastFmPassword" size="24"/></td>
+ </tr>
+ </table>
+
+ <p style="padding-top:1em;padding-bottom:1em">
+ <input type="submit" value="<fmt:message key="common.save"/>" style="margin-right:0.3em"/>
+ <input type="button" value="<fmt:message key="common.cancel"/>" onclick="location.href='nowPlaying.view'">
+ </p>
+
+ <h2><fmt:message key="personalsettings.avatar.title"/></h2>
+
+ <p style="padding-top:1em">
+ <c:forEach items="${command.avatars}" var="avatar">
+ <c:url value="avatar.view" var="avatarUrl">
+ <c:param name="id" value="${avatar.id}"/>
+ </c:url>
+ <span style="white-space:nowrap;">
+ <form:radiobutton id="avatar-${avatar.id}" path="avatarId" value="${avatar.id}"/>
+ <label for="avatar-${avatar.id}"><img src="${avatarUrl}" alt="${avatar.name}" width="${avatar.width}" height="${avatar.height}" style="padding-right:2em;padding-bottom:1em"/></label>
+ </span>
+ </c:forEach>
+ </p>
+ <p>
+ <form:radiobutton id="noAvatar" path="avatarId" value="-1"/>
+ <label for="noAvatar"><fmt:message key="personalsettings.avatar.none"/></label>
+ </p>
+ <p>
+ <form:radiobutton id="customAvatar" path="avatarId" value="-2"/>
+ <label for="customAvatar"><fmt:message key="personalsettings.avatar.custom"/>
+ <c:if test="${not empty command.customAvatar}">
+ <sub:url value="avatar.view" var="avatarUrl">
+ <sub:param name="username" value="${command.user.username}"/>
+ </sub:url>
+ <img src="${avatarUrl}" alt="${command.customAvatar.name}" width="${command.customAvatar.width}" height="${command.customAvatar.height}" style="padding-right:2em"/>
+ </c:if>
+ </label>
+ </p>
+</form:form>
+
+<form method="post" enctype="multipart/form-data" action="avatarUpload.view">
+ <table>
+ <tr>
+ <td style="padding-right:1em"><fmt:message key="personalsettings.avatar.changecustom"/></td>
+ <td style="padding-right:1em"><input type="file" id="file" name="file" size="40"/></td>
+ <td style="padding-right:1em"><input type="submit" value="<fmt:message key="personalsettings.avatar.upload"/>"/></td>
+ </tr>
+ </table>
+</form>
+
+<p class="detail" style="text-align:right">
+ <fmt:message key="personalsettings.avatar.courtesy"/>
+</p>
+
+<c:if test="${command.reloadNeeded}">
+ <script language="javascript" type="text/javascript">
+ parent.location.href="index.view?";
+ </script>
+</c:if>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/playAddDownload.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/playAddDownload.jsp new file mode 100644 index 00000000..e0852182 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/playAddDownload.jsp @@ -0,0 +1,64 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<%@ include file="include.jsp" %>
+
+<%--
+PARAMETERS
+ id: ID of file.
+ video: Whether the file is a video (default false).
+ playEnabled: Whether the current user is allowed to play songs (default true).
+ addEnabled: Whether the current user is allowed to add songs to the playlist (default true).
+ downloadEnabled: Whether the current user is allowed to download songs (default false).
+ starEnabled: Whether to show star/unstar controls (default false).
+ starred: Whether the file is currently starred.
+ asTable: Whether to put the images in td tags.
+--%>
+
+<sub:url value="/download.view" var="downloadUrl">
+ <sub:param name="id" value="${param.id}"/>
+</sub:url>
+<c:if test="${param.starEnabled}">
+ <c:if test="${param.asTable}"><td></c:if>
+ <a href="#" onclick="toggleStar(${param.id}, '#starImage${param.id}'); return false;">
+ <c:choose>
+ <c:when test="${param.starred}">
+ <img id="starImage${param.id}" src="<spring:theme code="ratingOnImage"/>" alt="">
+ </c:when>
+ <c:otherwise>
+ <img id="starImage${param.id}" src="<spring:theme code="ratingOffImage"/>" alt="">
+ </c:otherwise>
+ </c:choose>
+ </a>
+ <c:if test="${param.asTable}"></td></c:if>
+</c:if>
+
+<c:if test="${param.asTable}"><td></c:if>
+<c:if test="${empty param.playEnabled or param.playEnabled}">
+ <c:choose>
+ <c:when test="${param.video}">
+ <sub:url value="/videoPlayer.view" var="videoUrl">
+ <sub:param name="id" value="${param.id}"/>
+ </sub:url>
+ <a href="${videoUrl}" target="main">
+ <img src="<spring:theme code="playImage"/>" alt="<fmt:message key="common.play"/>" title="<fmt:message key="common.play"/>"></a>
+ </c:when>
+ <c:otherwise>
+ <a href="javascript:noop()" onclick="top.playQueue.onPlay(${param.id});">
+ <img src="<spring:theme code="playImage"/>" alt="<fmt:message key="common.play"/>" title="<fmt:message key="common.play"/>"></a>
+ </c:otherwise>
+ </c:choose>
+</c:if>
+<c:if test="${param.asTable}"></td></c:if>
+
+<c:if test="${param.asTable}"><td></c:if>
+<c:if test="${(empty param.addEnabled or param.addEnabled) and not param.video}">
+ <a href="javascript:noop()" onclick="top.playQueue.onAdd(${param.id});">
+ <img src="<spring:theme code="addImage"/>" alt="<fmt:message key="common.add"/>" title="<fmt:message key="common.add"/>"></a>
+</c:if>
+<c:if test="${param.asTable}"></td></c:if>
+
+<c:if test="${param.asTable}"><td></c:if>
+<c:if test="${param.downloadEnabled}">
+ <a href="${downloadUrl}">
+ <img src="<spring:theme code="downloadImage"/>" alt="<fmt:message key="common.download"/>" title="<fmt:message key="common.download"/>"></a>
+</c:if>
+<c:if test="${param.asTable}"></td></c:if>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/playQueue.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/playQueue.jsp new file mode 100644 index 00000000..5ac4ac46 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/playQueue.jsp @@ -0,0 +1,617 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html><head>
+ <%@ include file="head.jsp" %>
+ <%@ include file="jquery.jsp" %>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/nowPlayingService.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/playQueueService.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/playlistService.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/engine.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/util.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/swfobject.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/webfx/range.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/webfx/timer.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/webfx/slider.js"/>"></script>
+ <link type="text/css" rel="stylesheet" href="<c:url value="/script/webfx/luna.css"/>">
+</head>
+
+<body class="bgcolor2 playlistframe" onload="init()">
+
+<script type="text/javascript" language="javascript">
+ var player = null;
+ var songs = null;
+ var currentAlbumUrl = null;
+ var currentStreamUrl = null;
+ var startPlayer = false;
+ var repeatEnabled = false;
+ var slider = null;
+
+ function init() {
+ dwr.engine.setErrorHandler(null);
+ startTimer();
+
+ $("#dialog-select-playlist").dialog({resizable: true, height: 220, position: 'top', modal: true, autoOpen: false,
+ buttons: {
+ "<fmt:message key="common.cancel"/>": function() {
+ $(this).dialog("close");
+ }
+ }});
+
+ <c:choose>
+ <c:when test="${model.player.web}">
+ createPlayer();
+ </c:when>
+ <c:otherwise>
+ getPlayQueue();
+ </c:otherwise>
+ </c:choose>
+ }
+
+ function startTimer() {
+ <!-- Periodically check if the current song has changed. -->
+ nowPlayingService.getNowPlayingForCurrentPlayer(nowPlayingCallback);
+ setTimeout("startTimer()", 10000);
+ }
+
+ function nowPlayingCallback(nowPlayingInfo) {
+ if (nowPlayingInfo != null && nowPlayingInfo.streamUrl != currentStreamUrl) {
+ getPlayQueue();
+ if (currentAlbumUrl != nowPlayingInfo.albumUrl && top.main.updateNowPlaying) {
+ top.main.location.replace("nowPlaying.view?");
+ currentAlbumUrl = nowPlayingInfo.albumUrl;
+ }
+ <c:if test="${not model.player.web}">
+ currentStreamUrl = nowPlayingInfo.streamUrl;
+ updateCurrentImage();
+ </c:if>
+ }
+ }
+
+ function createPlayer() {
+ var flashvars = {
+ backcolor:"<spring:theme code="backgroundColor"/>",
+ frontcolor:"<spring:theme code="textColor"/>",
+ id:"player1"
+ };
+ var params = {
+ allowfullscreen:"true",
+ allowscriptaccess:"always"
+ };
+ var attributes = {
+ id:"player1",
+ name:"player1"
+ };
+ swfobject.embedSWF("<c:url value="/flash/jw-player-5.6.swf"/>", "placeholder", "340", "24", "9.0.0", false, flashvars, params, attributes);
+ }
+
+ function playerReady(thePlayer) {
+ player = document.getElementById("player1");
+ player.addModelListener("STATE", "stateListener");
+ getPlayQueue();
+ }
+
+ function stateListener(obj) { // IDLE, BUFFERING, PLAYING, PAUSED, COMPLETED
+ if (obj.newstate == "COMPLETED") {
+ onNext(repeatEnabled);
+ }
+ }
+
+ function getPlayQueue() {
+ playQueueService.getPlayQueue(playQueueCallback);
+ }
+
+ function onClear() {
+ var ok = true;
+ <c:if test="${model.partyMode}">
+ ok = confirm("<fmt:message key="playlist.confirmclear"/>");
+ </c:if>
+ if (ok) {
+ playQueueService.clear(playQueueCallback);
+ }
+ }
+ function onStart() {
+ playQueueService.start(playQueueCallback);
+ }
+ function onStop() {
+ playQueueService.stop(playQueueCallback);
+ }
+ function onGain(gain) {
+ playQueueService.setGain(gain);
+ }
+ function onSkip(index) {
+ <c:choose>
+ <c:when test="${model.player.web}">
+ skip(index);
+ </c:when>
+ <c:otherwise>
+ currentStreamUrl = songs[index].streamUrl;
+ playQueueService.skip(index, playQueueCallback);
+ </c:otherwise>
+ </c:choose>
+ }
+ function onNext(wrap) {
+ var index = parseInt(getCurrentSongIndex()) + 1;
+ if (wrap) {
+ index = index % songs.length;
+ }
+ skip(index);
+ }
+ function onPrevious() {
+ skip(parseInt(getCurrentSongIndex()) - 1);
+ }
+ function onPlay(id) {
+ startPlayer = true;
+ playQueueService.play(id, playQueueCallback);
+ }
+ function onPlayPlaylist(id) {
+ startPlayer = true;
+ playQueueService.playPlaylist(id, playQueueCallback);
+ }
+ function onPlayRandom(id, count) {
+ startPlayer = true;
+ playQueueService.playRandom(id, count, playQueueCallback);
+ }
+ function onAdd(id) {
+ startPlayer = false;
+ playQueueService.add(id, playQueueCallback);
+ }
+ function onShuffle() {
+ playQueueService.shuffle(playQueueCallback);
+ }
+ function onStar(index) {
+ playQueueService.toggleStar(index, playQueueCallback);
+ }
+ function onRemove(index) {
+ playQueueService.remove(index, playQueueCallback);
+ }
+ function onRemoveSelected() {
+ var indexes = new Array();
+ var counter = 0;
+ for (var i = 0; i < songs.length; i++) {
+ var index = i + 1;
+ if ($("#songIndex" + index).is(":checked")) {
+ indexes[counter++] = i;
+ }
+ }
+ playQueueService.removeMany(indexes, playQueueCallback);
+ }
+
+ function onUp(index) {
+ playQueueService.up(index, playQueueCallback);
+ }
+ function onDown(index) {
+ playQueueService.down(index, playQueueCallback);
+ }
+ function onToggleRepeat() {
+ playQueueService.toggleRepeat(playQueueCallback);
+ }
+ function onUndo() {
+ playQueueService.undo(playQueueCallback);
+ }
+ function onSortByTrack() {
+ playQueueService.sortByTrack(playQueueCallback);
+ }
+ function onSortByArtist() {
+ playQueueService.sortByArtist(playQueueCallback);
+ }
+ function onSortByAlbum() {
+ playQueueService.sortByAlbum(playQueueCallback);
+ }
+ function onSavePlaylist() {
+ playQueueService.savePlaylist(function () {top.left.updatePlaylists();});
+ }
+ function onAppendPlaylist() {
+ playlistService.getWritablePlaylists(playlistCallback);
+ }
+ function playlistCallback(playlists) {
+ $("#dialog-select-playlist-list").empty();
+ for (var i = 0; i < playlists.length; i++) {
+ var playlist = playlists[i];
+ $("<p class='dense'><b><a href='#' onclick='appendPlaylist(" + playlist.id + ")'>" + playlist.name + "</a></b></p>").appendTo("#dialog-select-playlist-list");
+ }
+ $("#dialog-select-playlist").dialog("open");
+ }
+ function appendPlaylist(playlistId) {
+ $("#dialog-select-playlist").dialog("close");
+
+ var mediaFileIds = new Array();
+ for (var i = 0; i < songs.length; i++) {
+ if ($("#songIndex" + (i + 1)).is(":checked")) {
+ mediaFileIds.push(songs[i].id);
+ }
+ }
+ playlistService.appendToPlaylist(playlistId, mediaFileIds, function (){top.left.updatePlaylists();});
+ }
+
+ function playQueueCallback(playQueue) {
+ songs = playQueue.entries;
+ repeatEnabled = playQueue.repeatEnabled;
+ if ($("#start")) {
+ if (playQueue.stopEnabled) {
+ $("#start").hide();
+ $("#stop").show();
+ } else {
+ $("#start").show();
+ $("#stop").hide();
+ }
+ }
+
+ if ($("#toggleRepeat")) {
+ var text = repeatEnabled ? "<fmt:message key="playlist.repeat_on"/>" : "<fmt:message key="playlist.repeat_off"/>";
+ $("#toggleRepeat").html(text);
+ }
+
+ if (songs.length == 0) {
+ $("#empty").show();
+ } else {
+ $("#empty").hide();
+ }
+
+ // Delete all the rows except for the "pattern" row
+ dwr.util.removeAllRows("playlistBody", { filter:function(tr) {
+ return (tr.id != "pattern");
+ }});
+
+ // Create a new set cloned from the pattern row
+ for (var i = 0; i < songs.length; i++) {
+ var song = songs[i];
+ var id = i + 1;
+ dwr.util.cloneNode("pattern", { idSuffix:id });
+ if ($("#trackNumber" + id)) {
+ $("#trackNumber" + id).html(song.trackNumber);
+ }
+ if (song.starred) {
+ $("#starSong" + id).attr("src", "<spring:theme code='ratingOnImage'/>");
+ } else {
+ $("#starSong" + id).attr("src", "<spring:theme code='ratingOffImage'/>");
+ }
+ if ($("#currentImage" + id) && song.streamUrl == currentStreamUrl) {
+ $("#currentImage" + id).show();
+ }
+ if ($("#title" + id)) {
+ $("#title" + id).html(truncate(song.title));
+ $("#title" + id).attr("title", song.title);
+ }
+ if ($("#titleUrl" + id)) {
+ $("#titleUrl" + id).html(truncate(song.title));
+ $("#titleUrl" + id).attr("title", song.title);
+ $("#titleUrl" + id).click(function () {onSkip(this.id.substring(8) - 1)});
+ }
+ if ($("#album" + id)) {
+ $("#album" + id).html(truncate(song.album));
+ $("#album" + id).attr("title", song.album);
+ $("#albumUrl" + id).attr("href", song.albumUrl);
+ }
+ if ($("#artist" + id)) {
+ $("#artist" + id).html(truncate(song.artist));
+ $("#artist" + id).attr("title", song.artist);
+ }
+ if ($("#genre" + id)) {
+ $("#genre" + id).html(song.genre);
+ }
+ if ($("#year" + id)) {
+ $("#year" + id).html(song.year);
+ }
+ if ($("#bitRate" + id)) {
+ $("#bitRate" + id).html(song.bitRate);
+ }
+ if ($("#duration" + id)) {
+ $("#duration" + id).html(song.durationAsString);
+ }
+ if ($("#format" + id)) {
+ $("#format" + id).html(song.format);
+ }
+ if ($("#fileSize" + id)) {
+ $("#fileSize" + id).html(song.fileSize);
+ }
+
+ $("#pattern" + id).show();
+ $("#pattern" + id).addClass((i % 2 == 0) ? "bgcolor1" : "bgcolor2");
+ }
+
+ if (playQueue.sendM3U) {
+ parent.frames.main.location.href="play.m3u?";
+ }
+
+ if (slider) {
+ slider.setValue(playQueue.gain * 100);
+ }
+
+ <c:if test="${model.player.web}">
+ triggerPlayer();
+ </c:if>
+ }
+
+ function triggerPlayer() {
+ if (startPlayer) {
+ startPlayer = false;
+ if (songs.length > 0) {
+ skip(0);
+ }
+ }
+ updateCurrentImage();
+ if (songs.length == 0) {
+ player.sendEvent("LOAD", new Array());
+ player.sendEvent("STOP");
+ }
+ }
+
+ function skip(index) {
+ if (index < 0 || index >= songs.length) {
+ return;
+ }
+
+ var song = songs[index];
+ currentStreamUrl = song.streamUrl;
+ updateCurrentImage();
+ var list = new Array();
+ list[0] = {
+ file:song.streamUrl,
+ title:song.title,
+ provider:"sound"
+ };
+
+ if (song.duration != null) {
+ list[0].duration = song.duration;
+ }
+ if (song.format == "aac" || song.format == "m4a") {
+ list[0].provider = "video";
+ }
+
+ player.sendEvent("LOAD", list);
+ player.sendEvent("PLAY");
+ }
+
+ function updateCurrentImage() {
+ for (var i = 0; i < songs.length; i++) {
+ var song = songs[i];
+ var id = i + 1;
+ var image = $("#currentImage" + id);
+
+ if (image) {
+ if (song.streamUrl == currentStreamUrl) {
+ image.show();
+ } else {
+ image.hide();
+ }
+ }
+ }
+ }
+
+ function getCurrentSongIndex() {
+ for (var i = 0; i < songs.length; i++) {
+ if (songs[i].streamUrl == currentStreamUrl) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ function truncate(s) {
+ if (s == null) {
+ return s;
+ }
+ var cutoff = ${model.visibility.captionCutoff};
+
+ if (s.length > cutoff) {
+ return s.substring(0, cutoff) + "...";
+ }
+ return s;
+ }
+
+ <!-- actionSelected() is invoked when the users selects from the "More actions..." combo box. -->
+ function actionSelected(id) {
+ if (id == "top") {
+ return;
+ } else if (id == "savePlaylist") {
+ onSavePlaylist();
+ } else if (id == "downloadPlaylist") {
+ location.href = "download.view?player=${model.player.id}";
+ } else if (id == "sharePlaylist") {
+ parent.frames.main.location.href = "createShare.view?player=${model.player.id}&" + getSelectedIndexes();
+ } else if (id == "sortByTrack") {
+ onSortByTrack();
+ } else if (id == "sortByArtist") {
+ onSortByArtist();
+ } else if (id == "sortByAlbum") {
+ onSortByAlbum();
+ } else if (id == "selectAll") {
+ selectAll(true);
+ } else if (id == "selectNone") {
+ selectAll(false);
+ } else if (id == "removeSelected") {
+ onRemoveSelected();
+ } else if (id == "download") {
+ location.href = "download.view?player=${model.player.id}&" + getSelectedIndexes();
+ } else if (id == "appendPlaylist") {
+ onAppendPlaylist();
+ }
+ $("#moreActions").prop("selectedIndex", 0);
+ }
+
+ function getSelectedIndexes() {
+ var result = "";
+ for (var i = 0; i < songs.length; i++) {
+ if ($("#songIndex" + (i + 1)).is(":checked")) {
+ result += "i=" + i + "&";
+ }
+ }
+ return result;
+ }
+
+ function selectAll(b) {
+ for (var i = 0; i < songs.length; i++) {
+ if (b) {
+ $("#songIndex" + (i + 1)).attr("checked", "checked");
+ } else {
+ $("#songIndex" + (i + 1)).removeAttr("checked");
+ }
+ }
+ }
+
+</script>
+
+<div class="bgcolor2" style="position:fixed; top:0; width:100%;padding-top:0.5em">
+ <table style="white-space:nowrap;">
+ <tr style="white-space:nowrap;">
+ <c:if test="${model.user.settingsRole}">
+ <td><select name="player" onchange="location='playQueue.view?player=' + options[selectedIndex].value;">
+ <c:forEach items="${model.players}" var="player">
+ <option ${player.id eq model.player.id ? "selected" : ""} value="${player.id}">${player.shortDescription}</option>
+ </c:forEach>
+ </select></td>
+ </c:if>
+ <c:if test="${model.player.web}">
+ <td style="width:340px; height:24px;padding-left:10px;padding-right:10px"><div id="placeholder">
+ <a href="http://www.adobe.com/go/getflashplayer" target="_blank"><fmt:message key="playlist.getflash"/></a>
+ </div></td>
+ </c:if>
+
+ <c:if test="${model.user.streamRole and not model.player.web}">
+ <td style="white-space:nowrap;" id="stop"><b><a href="#" onclick="onStop()"><fmt:message key="playlist.stop"/></a></b> | </td>
+ <td style="white-space:nowrap;" id="start"><b><a href="#" onclick="onStart()"><fmt:message key="playlist.start"/></a></b> | </td>
+ </c:if>
+
+ <c:if test="${model.player.jukebox}">
+ <td style="white-space:nowrap;">
+ <img src="<spring:theme code="volumeImage"/>" alt="">
+ </td>
+ <td style="white-space:nowrap;">
+ <div class="slider bgcolor2" id="slider-1" style="width:90px">
+ <input class="slider-input" id="slider-input-1" name="slider-input-1">
+ </div>
+ <script type="text/javascript">
+
+ var updateGainTimeoutId = 0;
+ slider = new Slider(document.getElementById("slider-1"), document.getElementById("slider-input-1"));
+ slider.onchange = function () {
+ clearTimeout(updateGainTimeoutId);
+ updateGainTimeoutId = setTimeout("updateGain()", 250);
+ };
+
+ function updateGain() {
+ var gain = slider.getValue() / 100.0;
+ onGain(gain);
+ }
+ </script>
+ </td>
+ </c:if>
+
+ <c:if test="${model.player.web}">
+ <td style="white-space:nowrap;"><a href="#" onclick="onPrevious()"><b>«</b></a></td>
+ <td style="white-space:nowrap;"><a href="#" onclick="onNext(false)"><b>»</b></a> |</td>
+ </c:if>
+
+ <td style="white-space:nowrap;"><a href="#" onclick="onClear()"><fmt:message key="playlist.clear"/></a> |</td>
+ <td style="white-space:nowrap;"><a href="#" onclick="onShuffle()"><fmt:message key="playlist.shuffle"/></a> |</td>
+
+ <c:if test="${model.player.web or model.player.jukebox or model.player.external}">
+ <td style="white-space:nowrap;"><a href="#" onclick="onToggleRepeat()"><span id="toggleRepeat"><fmt:message key="playlist.repeat_on"/></span></a> |</td>
+ </c:if>
+
+ <td style="white-space:nowrap;"><a href="#" onclick="onUndo()"><fmt:message key="playlist.undo"/></a> |</td>
+
+ <c:if test="${model.user.settingsRole}">
+ <td style="white-space:nowrap;"><a href="playerSettings.view?id=${model.player.id}" target="main"><fmt:message key="playlist.settings"/></a> |</td>
+ </c:if>
+
+ <td style="white-space:nowrap;"><select id="moreActions" onchange="actionSelected(this.options[selectedIndex].id)">
+ <option id="top" selected="selected"><fmt:message key="playlist.more"/></option>
+ <option style="color:blue;"><fmt:message key="playlist.more.playlist"/></option>
+ <option id="savePlaylist"> <fmt:message key="playlist.save"/></option>
+ <c:if test="${model.user.downloadRole}">
+ <option id="downloadPlaylist"> <fmt:message key="common.download"/></option>
+ </c:if>
+ <c:if test="${model.user.shareRole}">
+ <option id="sharePlaylist"> <fmt:message key="main.more.share"/></option>
+ </c:if>
+ <option id="sortByTrack"> <fmt:message key="playlist.more.sortbytrack"/></option>
+ <option id="sortByAlbum"> <fmt:message key="playlist.more.sortbyalbum"/></option>
+ <option id="sortByArtist"> <fmt:message key="playlist.more.sortbyartist"/></option>
+ <option style="color:blue;"><fmt:message key="playlist.more.selection"/></option>
+ <option id="selectAll"> <fmt:message key="playlist.more.selectall"/></option>
+ <option id="selectNone"> <fmt:message key="playlist.more.selectnone"/></option>
+ <option id="removeSelected"> <fmt:message key="playlist.remove"/></option>
+ <c:if test="${model.user.downloadRole}">
+ <option id="download"> <fmt:message key="common.download"/></option>
+ </c:if>
+ <option id="appendPlaylist"> <fmt:message key="playlist.append"/></option>
+ </select>
+ </td>
+
+ </tr></table>
+</div>
+
+<div style="height:3.2em"></div>
+
+<p id="empty"><em><fmt:message key="playlist.empty"/></em></p>
+
+<table style="border-collapse:collapse;white-space:nowrap;">
+ <tbody id="playlistBody">
+ <tr id="pattern" style="display:none;margin:0;padding:0;border:0">
+ <td class="bgcolor2"><a href="#">
+ <img id="starSong" onclick="onStar(this.id.substring(8) - 1)" src="<spring:theme code="ratingOffImage"/>"
+ alt="" title=""></a></td>
+ <td class="bgcolor2"><a href="#">
+ <img id="removeSong" onclick="onRemove(this.id.substring(10) - 1)" src="<spring:theme code="removeImage"/>"
+ alt="<fmt:message key="playlist.remove"/>" title="<fmt:message key="playlist.remove"/>"></a></td>
+ <td class="bgcolor2"><a href="#">
+ <img id="up" onclick="onUp(this.id.substring(2) - 1)" src="<spring:theme code="upImage"/>"
+ alt="<fmt:message key="playlist.up"/>" title="<fmt:message key="playlist.up"/>"></a></td>
+ <td class="bgcolor2"><a href="#">
+ <img id="down" onclick="onDown(this.id.substring(4) - 1)" src="<spring:theme code="downImage"/>"
+ alt="<fmt:message key="playlist.down"/>" title="<fmt:message key="playlist.down"/>"></a></td>
+
+ <td class="bgcolor2" style="padding-left: 0.1em"><input type="checkbox" class="checkbox" id="songIndex"></td>
+ <td style="padding-right:0.25em"></td>
+
+ <c:if test="${model.visibility.trackNumberVisible}">
+ <td style="padding-right:0.5em;text-align:right"><span class="detail" id="trackNumber">1</span></td>
+ </c:if>
+
+ <td style="padding-right:1.25em">
+ <img id="currentImage" src="<spring:theme code="currentImage"/>" alt="" style="display:none">
+ <c:choose>
+ <c:when test="${model.player.externalWithPlaylist}">
+ <span id="title">Title</span>
+ </c:when>
+ <c:otherwise>
+ <a id="titleUrl" href="#">Title</a>
+ </c:otherwise>
+ </c:choose>
+ </td>
+
+ <c:if test="${model.visibility.albumVisible}">
+ <td style="padding-right:1.25em"><a id="albumUrl" target="main"><span id="album" class="detail">Album</span></a></td>
+ </c:if>
+ <c:if test="${model.visibility.artistVisible}">
+ <td style="padding-right:1.25em"><span id="artist" class="detail">Artist</span></td>
+ </c:if>
+ <c:if test="${model.visibility.genreVisible}">
+ <td style="padding-right:1.25em"><span id="genre" class="detail">Genre</span></td>
+ </c:if>
+ <c:if test="${model.visibility.yearVisible}">
+ <td style="padding-right:1.25em"><span id="year" class="detail">Year</span></td>
+ </c:if>
+ <c:if test="${model.visibility.formatVisible}">
+ <td style="padding-right:1.25em"><span id="format" class="detail">Format</span></td>
+ </c:if>
+ <c:if test="${model.visibility.fileSizeVisible}">
+ <td style="padding-right:1.25em;text-align:right;"><span id="fileSize" class="detail">Format</span></td>
+ </c:if>
+ <c:if test="${model.visibility.durationVisible}">
+ <td style="padding-right:1.25em;text-align:right;"><span id="duration" class="detail">Duration</span></td>
+ </c:if>
+ <c:if test="${model.visibility.bitRateVisible}">
+ <td style="padding-right:0.25em"><span id="bitRate" class="detail">Bit Rate</span></td>
+ </c:if>
+ </tr>
+ </tbody>
+</table>
+
+<div id="dialog-select-playlist" title="<fmt:message key="main.addtoplaylist.title"/>" style="display: none;">
+ <p><fmt:message key="main.addtoplaylist.text"/></p>
+ <div id="dialog-select-playlist-list"></div>
+</div>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/playerSettings.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/playerSettings.jsp new file mode 100644 index 00000000..3381c3a8 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/playerSettings.jsp @@ -0,0 +1,177 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+<%--@elvariable id="command" type="net.sourceforge.subsonic.command.PlayerSettingsCommand"--%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="<c:url value="/script/scripts.js"/>"></script>
+</head>
+<body class="mainframe bgcolor1">
+<script type="text/javascript" src="<c:url value="/script/wz_tooltip.js"/>"></script>
+<script type="text/javascript" src="<c:url value="/script/tip_balloon.js"/>"></script>
+
+<c:import url="settingsHeader.jsp">
+ <c:param name="cat" value="player"/>
+ <c:param name="restricted" value="${not command.admin}"/>
+</c:import>
+
+<fmt:message key="common.unknown" var="unknown"/>
+
+<c:choose>
+<c:when test="${empty command.players}">
+ <p><fmt:message key="playersettings.noplayers"/></p>
+</c:when>
+<c:otherwise>
+
+<c:url value="playerSettings.view" var="deleteUrl">
+ <c:param name="delete" value="${command.playerId}"/>
+</c:url>
+<c:url value="playerSettings.view" var="cloneUrl">
+ <c:param name="clone" value="${command.playerId}"/>
+</c:url>
+
+<table class="indent">
+ <tr>
+ <td><b><fmt:message key="playersettings.title"/></b></td>
+ <td>
+ <select name="player" onchange="location='playerSettings.view?id=' + options[selectedIndex].value;">
+ <c:forEach items="${command.players}" var="player">
+ <option ${player.id eq command.playerId ? "selected" : ""}
+ value="${player.id}">${player.description}</option>
+ </c:forEach>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td style="padding-right:1em"><div class="forward"><a href="${deleteUrl}"><fmt:message key="playersettings.forget"/></a></div></td>
+ <td><div class="forward"><a href="${cloneUrl}"><fmt:message key="playersettings.clone"/></a></div></td>
+ </tr>
+</table>
+
+<form:form commandName="command" method="post" action="playerSettings.view">
+<form:hidden path="playerId"/>
+
+<table class="ruleTable indent">
+ <c:forEach items="${command.technologyHolders}" var="technologyHolder">
+ <c:set var="technologyName">
+ <fmt:message key="playersettings.technology.${fn:toLowerCase(technologyHolder.name)}.title"/>
+ </c:set>
+
+ <tr>
+ <td class="ruleTableHeader">
+ <form:radiobutton id="radio-${technologyName}" path="technologyName" value="${technologyHolder.name}"/>
+ <b><label for="radio-${technologyName}">${technologyName}</label></b>
+ </td>
+ <td class="ruleTableCell" style="width:40em">
+ <fmt:message key="playersettings.technology.${fn:toLowerCase(technologyHolder.name)}.text"/>
+ </td>
+ </tr>
+ </c:forEach>
+</table>
+
+
+<table class="indent" style="border-spacing:3pt">
+ <tr>
+ <td><fmt:message key="playersettings.type"/></td>
+ <td colspan="3">
+ <c:choose>
+ <c:when test="${empty command.type}">${unknown}</c:when>
+ <c:otherwise>${command.type}</c:otherwise>
+ </c:choose>
+ </td>
+ </tr>
+ <tr>
+ <td><fmt:message key="playersettings.lastseen"/></td>
+ <td colspan="3"><fmt:formatDate value="${command.lastSeen}" type="both" dateStyle="long" timeStyle="medium"/></td>
+ </tr>
+
+ <tr>
+ <td colspan="4"> </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="playersettings.name"/></td>
+ <td><form:input path="name" size="16"/></td>
+ <td colspan="2"><c:import url="helpToolTip.jsp"><c:param name="topic" value="playername"/></c:import></td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="playersettings.coverartsize"/></td>
+ <td>
+ <form:select path="coverArtSchemeName" cssStyle="width:8em">
+ <c:forEach items="${command.coverArtSchemeHolders}" var="coverArtSchemeHolder">
+ <c:set var="coverArtSchemeName">
+ <fmt:message key="playersettings.coverart.${fn:toLowerCase(coverArtSchemeHolder.name)}"/>
+ </c:set>
+ <form:option value="${coverArtSchemeHolder.name}" label="${coverArtSchemeName}"/>
+ </c:forEach>
+ </form:select>
+ </td>
+ <td colspan="2"><c:import url="helpToolTip.jsp"><c:param name="topic" value="cover"/></c:import></td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="playersettings.maxbitrate"/></td>
+ <td>
+ <form:select path="transcodeSchemeName" cssStyle="width:8em">
+ <c:forEach items="${command.transcodeSchemeHolders}" var="transcodeSchemeHolder">
+ <form:option value="${transcodeSchemeHolder.name}" label="${transcodeSchemeHolder.description}"/>
+ </c:forEach>
+ </form:select>
+ </td>
+ <td>
+ <c:import url="helpToolTip.jsp"><c:param name="topic" value="transcode"/></c:import>
+ </td>
+ <td class="warning">
+ <c:if test="${not command.transcodingSupported}">
+ <fmt:message key="playersettings.nolame"/>
+ </c:if>
+ </td>
+ </tr>
+
+</table>
+
+<table class="indent" style="border-spacing:3pt">
+
+ <tr>
+ <td>
+ <form:checkbox path="dynamicIp" id="dynamicIp" cssClass="checkbox"/>
+ <label for="dynamicIp"><fmt:message key="playersettings.dynamicip"/></label>
+ </td>
+ <td><c:import url="helpToolTip.jsp"><c:param name="topic" value="dynamicip"/></c:import></td>
+ </tr>
+
+ <tr>
+ <td>
+ <form:checkbox path="autoControlEnabled" id="autoControlEnabled" cssClass="checkbox"/>
+ <label for="autoControlEnabled"><fmt:message key="playersettings.autocontrol"/></label>
+ </td>
+ <td><c:import url="helpToolTip.jsp"><c:param name="topic" value="autocontrol"/></c:import></td>
+ </tr>
+</table>
+
+ <c:if test="${not empty command.allTranscodings}">
+ <table class="indent">
+ <tr><td><b><fmt:message key="playersettings.transcodings"/></b></td></tr>
+ <c:forEach items="${command.allTranscodings}" var="transcoding" varStatus="loopStatus">
+ <c:if test="${loopStatus.count % 3 == 1}"><tr></c:if>
+ <td style="padding-right:2em">
+ <form:checkbox path="activeTranscodingIds" id="transcoding${transcoding.id}" value="${transcoding.id}" cssClass="checkbox"/>
+ <label for="transcoding${transcoding.id}">${transcoding.name}</label>
+ </td>
+ <c:if test="${loopStatus.count % 3 == 0 or loopStatus.count eq fn:length(command.allTranscodings)}"></tr></c:if>
+ </c:forEach>
+ </table>
+ </c:if>
+
+ <input type="submit" value="<fmt:message key="common.save"/>" style="margin-top:1em;margin-right:0.3em">
+ <input type="button" value="<fmt:message key="common.cancel"/>" style="margin-top:1em" onclick="location.href='nowPlaying.view'">
+</form:form>
+
+</c:otherwise>
+</c:choose>
+
+<c:if test="${command.reloadNeeded}">
+ <script language="javascript" type="text/javascript">parent.frames.playQueue.location.href="playQueue.view?"</script>
+</c:if>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/playlist.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/playlist.jsp new file mode 100644 index 00000000..b0cb1f74 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/playlist.jsp @@ -0,0 +1,235 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <%@ include file="jquery.jsp" %>
+ <script type="text/javascript" src="<c:url value='/dwr/util.js'/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/engine.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/playlistService.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/starService.js"/>"></script>
+ <script type="text/javascript" language="javascript">
+
+ var playlist;
+ var songs;
+
+ function init() {
+ dwr.engine.setErrorHandler(null);
+ $("#dialog-edit").dialog({resizable: true, width:400, position: 'top', modal: true, autoOpen: false,
+ buttons: {
+ "<fmt:message key="common.save"/>": function() {
+ $(this).dialog("close");
+ var name = $("#newName").val();
+ var comment = $("#newComment").val();
+ var isPublic = $("#newPublic").is(":checked");
+ $("#name").html(name);
+ $("#comment").html(comment);
+ playlistService.updatePlaylist(playlist.id, name, comment, isPublic, function (playlistInfo){playlistCallback(playlistInfo); top.left.updatePlaylists()});
+ },
+ "<fmt:message key="common.cancel"/>": function() {
+ $(this).dialog("close");
+ }
+ }});
+
+ $("#dialog-delete").dialog({resizable: false, height: 170, position: 'top', modal: true, autoOpen: false,
+ buttons: {
+ "<fmt:message key="common.delete"/>": function() {
+ $(this).dialog("close");
+ playlistService.deletePlaylist(playlist.id, function (){top.left.updatePlaylists(); location = "home.view";});
+ },
+ "<fmt:message key="common.cancel"/>": function() {
+ $(this).dialog("close");
+ }
+ }});
+ getPlaylist();
+ }
+
+ function getPlaylist() {
+ playlistService.getPlaylist(${model.playlist.id}, playlistCallback);
+ }
+
+ function playlistCallback(playlistInfo) {
+ this.playlist = playlistInfo.playlist;
+ this.songs = playlistInfo.entries;
+
+ if (songs.length == 0) {
+ $("#empty").show();
+ } else {
+ $("#empty").hide();
+ }
+
+
+ $("#songCount").html(playlist.fileCount);
+ $("#duration").html(playlist.durationAsString);
+
+ if (playlist.public) {
+ $("#shared").html("<fmt:message key="playlist2.shared"/>");
+ } else {
+ $("#shared").html("<fmt:message key="playlist2.notshared"/>");
+ }
+
+ // Delete all the rows except for the "pattern" row
+ dwr.util.removeAllRows("playlistBody", { filter:function(tr) {
+ return (tr.id != "pattern");
+ }});
+
+ // Create a new set cloned from the pattern row
+ for (var i = 0; i < songs.length; i++) {
+ var song = songs[i];
+ var id = i + 1;
+ dwr.util.cloneNode("pattern", { idSuffix:id });
+ if (song.starred) {
+ $("#starSong" + id).attr("src", "<spring:theme code='ratingOnImage'/>");
+ } else {
+ $("#starSong" + id).attr("src", "<spring:theme code='ratingOffImage'/>");
+ }
+ if ($("#title" + id)) {
+ $("#title" + id).html(truncate(song.title));
+ $("#title" + id).attr("title", song.title);
+ }
+ if ($("#album" + id)) {
+ $("#album" + id).html(truncate(song.album));
+ $("#album" + id).attr("title", song.album);
+ $("#albumUrl" + id).attr("href", "main.view?id=" + song.id);
+ }
+ if ($("#artist" + id)) {
+ $("#artist" + id).html(truncate(song.artist));
+ $("#artist" + id).attr("title", song.artist);
+ }
+ if ($("#duration" + id)) {
+ $("#duration" + id).html(song.durationAsString);
+ }
+
+ $("#pattern" + id).addClass((i % 2 == 0) ? "bgcolor2" : "bgcolor1");
+ $("#pattern" + id).show();
+ }
+ }
+
+ function truncate(s) {
+ if (s == null) {
+ return s;
+ }
+ var cutoff = 30;
+
+ if (s.length > cutoff) {
+ return s.substring(0, cutoff) + "...";
+ }
+ return s;
+ }
+
+ function onPlay(index) {
+ top.playQueue.onPlay(songs[index].id);
+ }
+ function onPlayAll() {
+ top.playQueue.onPlayPlaylist(playlist.id);
+ }
+ function onAdd(index) {
+ top.playQueue.onAdd(songs[index].id);
+ }
+ function onStar(index) {
+ playlistService.toggleStar(playlist.id, index, playlistCallback);
+ }
+ function onRemove(index) {
+ playlistService.remove(playlist.id, index, function (playlistInfo){playlistCallback(playlistInfo); top.left.updatePlaylists()});
+ }
+ function onUp(index) {
+ playlistService.up(playlist.id, index, playlistCallback);
+ }
+ function onDown(index) {
+ playlistService.down(playlist.id, index, playlistCallback);
+ }
+ function onEditPlaylist() {
+ $("#dialog-edit").dialog("open");
+ }
+ function onDeletePlaylist() {
+ $("#dialog-delete").dialog("open");
+ }
+
+ </script>
+</head>
+<body class="mainframe bgcolor1" onload="init()">
+
+<h1 id="name">${model.playlist.name}</h1>
+<h2>
+ <a href="#" onclick="onPlayAll();"><fmt:message key="common.play"/></a>
+
+ <c:if test="${model.user.downloadRole}">
+ <c:url value="download.view" var="downloadUrl"><c:param name="playlist" value="${model.playlist.id}"/></c:url>
+ | <a href="${downloadUrl}"><fmt:message key="common.download"/></a>
+ </c:if>
+ <c:if test="${model.editAllowed}">
+ | <a href="#" onclick="onEditPlaylist();"><fmt:message key="common.edit"/></a>
+ | <a href="#" onclick="onDeletePlaylist();"><fmt:message key="common.delete"/></a>
+ </c:if>
+ <c:url value="exportPlaylist.view" var="exportUrl"><c:param name="id" value="${model.playlist.id}"/></c:url>
+ | <a href="${exportUrl}"><fmt:message key="playlist2.export"/></a>
+
+</h2>
+
+<div id="comment" class="detail" style="padding-top:0.2em">${model.playlist.comment}</div>
+
+<div class="detail" style="padding-top:0.2em">
+ <fmt:message key="playlist2.created">
+ <fmt:param>${model.playlist.username}</fmt:param>
+ <fmt:param><fmt:formatDate type="date" dateStyle="long" value="${model.playlist.created}"/></fmt:param>
+ </fmt:message>.
+ <span id="shared"></span>.
+ <span id="songCount"></span> <fmt:message key="playlist2.songs"/> (<span id="duration"></span>)
+</div>
+
+<div style="height:0.7em"></div>
+
+<p id="empty" style="display: none;"><em><fmt:message key="playlist2.empty"/></em></p>
+
+<table style="border-collapse:collapse;white-space:nowrap">
+ <tbody id="playlistBody">
+ <tr id="pattern" style="display:none;margin:0;padding:0;border:0">
+ <td class="bgcolor1"><a href="#">
+ <img id="starSong" onclick="onStar(this.id.substring(8) - 1)" src="<spring:theme code="ratingOffImage"/>" alt="" title=""></a></td>
+ <td class="bgcolor1"><a href="#">
+ <img id="play" src="<spring:theme code="playImage"/>" alt="<fmt:message key="common.play"/>" title="<fmt:message key="common.play"/>"
+ onclick="onPlay(this.id.substring(4) - 1)"></a></td>
+ <td class="bgcolor1"><a href="#">
+ <img id="add" src="<spring:theme code="addImage"/>" alt="<fmt:message key="common.add"/>" title="<fmt:message key="common.add"/>"
+ onclick="onAdd(this.id.substring(3) - 1)"></a></td>
+
+ <td style="padding-right:0.25em"></td>
+ <td style="padding-right:1.25em"><span id="title">Title</span></td>
+ <td style="padding-right:1.25em"><a id="albumUrl" target="main"><span id="album" class="detail">Album</span></a></td>
+ <td style="padding-right:1.25em"><span id="artist" class="detail">Artist</span></td>
+ <td style="padding-right:1.25em;text-align:right;"><span id="duration" class="detail">Duration</span></td>
+
+ <c:if test="${model.editAllowed}">
+ <td class="bgcolor1"><a href="#">
+ <img id="removeSong" onclick="onRemove(this.id.substring(10) - 1)" src="<spring:theme code="removeImage"/>"
+ alt="<fmt:message key="playlist.remove"/>" title="<fmt:message key="playlist.remove"/>"></a></td>
+ <td class="bgcolor1"><a href="#">
+ <img id="up" onclick="onUp(this.id.substring(2) - 1)" src="<spring:theme code="upImage"/>"
+ alt="<fmt:message key="playlist.up"/>" title="<fmt:message key="playlist.up"/>"></a></td>
+ <td class="bgcolor1"><a href="#">
+ <img id="down" onclick="onDown(this.id.substring(4) - 1)" src="<spring:theme code="downImage"/>"
+ alt="<fmt:message key="playlist.down"/>" title="<fmt:message key="playlist.down"/>"></a></td>
+ </c:if>
+
+ </tr>
+ </tbody>
+</table>
+
+<div id="dialog-delete" title="<fmt:message key="common.confirm"/>" style="display: none;">
+ <p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>
+ <fmt:message key="playlist2.confirmdelete"/></p>
+</div>
+
+<div id="dialog-edit" title="<fmt:message key="common.edit"/>" style="display: none;">
+ <form>
+ <label for="newName" style="display:block;"><fmt:message key="playlist2.name"/></label>
+ <input type="text" name="newName" id="newName" value="${model.playlist.name}" class="ui-widget-content"
+ style="display:block;width:95%;"/>
+ <label for="newComment" style="display:block;margin-top:1em"><fmt:message key="playlist2.comment"/></label>
+ <input type="text" name="newComment" id="newComment" value="${model.playlist.comment}" class="ui-widget-content"
+ style="display:block;width:95%;"/>
+ <input type="checkbox" name="newPublic" id="newPublic" ${model.playlist.public ? "checked='checked'" : ""} style="margin-top:1.5em" class="ui-widget-content"/>
+ <label for="newPublic"><fmt:message key="playlist2.public"/></label>
+ </form>
+</div>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/podcast.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/podcast.jsp new file mode 100644 index 00000000..6f2b88d8 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/podcast.jsp @@ -0,0 +1,26 @@ +<%@ include file="include.jsp" %>
+<%@ page language="java" contentType="text/xml; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<rss version="2.0">
+ <channel>
+ <title>Subsonic Podcast</title>
+ <link>${model.url}</link>
+ <description>Subsonic Podcast</description>
+ <language>en-us</language>
+ <image>
+ <url>http://subsonic.org/pages/inc/img/subsonic.png</url>
+ <title>Subsonic Podcast</title>
+ </image>
+
+ <c:forEach var="podcast" items="${model.podcasts}">
+ <item>
+ <title>${fn:escapeXml(podcast.name)}</title>
+ <link>${model.url}</link>
+ <description>Subsonic playlist "${fn:escapeXml(podcast.name)}"</description>
+ <pubDate>${podcast.publishDate}</pubDate>
+ <enclosure url="${podcast.enclosureUrl}" length="${podcast.length}" type="${podcast.type}"/>
+ </item>
+ </c:forEach>
+
+ </channel>
+</rss>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/podcastReceiver.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/podcastReceiver.jsp new file mode 100644 index 00000000..35a0ffdb --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/podcastReceiver.jsp @@ -0,0 +1,269 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="<c:url value="/script/scripts.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/prototype.js"/>"></script>
+</head>
+<body class="mainframe bgcolor1">
+
+<script type="text/javascript" language="javascript">
+ var channelCount = ${fn:length(model.channels)};
+
+ function downloadSelected() {
+ location.href = "podcastReceiverAdmin.view?downloadChannel=" + getSelectedChannels() +
+ "&downloadEpisode=" + getSelectedEpisodes() +
+ "&expandedChannels=" + getExpandedChannels();
+ }
+
+ function deleteSelected() {
+ if (confirm("<fmt:message key="podcastreceiver.confirmdelete"/>")) {
+ location.href = "podcastReceiverAdmin.view?deleteChannel=" + getSelectedChannels() +
+ "&deleteEpisode=" + getSelectedEpisodes() +
+ "&expandedChannels=" + getExpandedChannels();
+ }
+ }
+
+ function refreshChannels() {
+ location.href = "podcastReceiverAdmin.view?refresh=" +
+ "&expandedChannels=" + getExpandedChannels();
+ }
+
+ function refreshPage() {
+ location.href = "podcastReceiver.view?expandedChannels=" + getExpandedChannels();
+ }
+
+ function toggleEpisodes(channelIndex) {
+ for (var i = 0; i < episodeCount; i++) {
+ var row = $("episodeRow" + i);
+ if (row.title == "channel" + channelIndex) {
+ row.toggle();
+ $("channelExpanded" + channelIndex).checked = row.visible() ? "checked" : "";
+ }
+ }
+ }
+
+ function toggleAllEpisodes(visible) {
+ for (var i = 0; i < episodeCount; i++) {
+ var row = $("episodeRow" + i);
+ if (visible) {
+ row.show();
+ } else {
+ row.hide();
+ }
+ }
+ for (i = 0; i < channelCount; i++) {
+ $("channelExpanded" + i).checked = visible ? "checked" : "";
+ }
+ }
+
+ function getExpandedChannels() {
+ var result = "";
+ for (var i = 0; i < channelCount; i++) {
+ var checkbox = $("channelExpanded" + i);
+ if (checkbox.checked) {
+ result += (checkbox.value + " ");
+ }
+ }
+ return result;
+ }
+
+ function getSelectedChannels() {
+ var result = "";
+ for (var i = 0; i < channelCount; i++) {
+ var checkbox = $("channel" + i);
+ if (checkbox.checked) {
+ result += (checkbox.value + " ");
+ }
+ }
+ return result;
+ }
+
+ function getSelectedEpisodes() {
+ var result = "";
+ for (var i = 0; i < episodeCount; i++) {
+ var checkbox = $("episode" + i);
+ if (checkbox.checked) {
+ result += (checkbox.value + " ");
+ }
+ }
+ return result;
+ }
+</script>
+
+<h1>
+ <img src="<spring:theme code="podcastLargeImage"/>" alt=""/>
+ <fmt:message key="podcastreceiver.title"/>
+</h1>
+
+<table><tr>
+ <td style="padding-right:2em"><div class="forward"><a href="javascript:toggleAllEpisodes(true)"><fmt:message key="podcastreceiver.expandall"/></a></div></td>
+ <td style="padding-right:2em"><div class="forward"><a href="javascript:toggleAllEpisodes(false)"><fmt:message key="podcastreceiver.collapseall"/></a></div></td>
+</tr></table>
+
+<table style="border-collapse:collapse;white-space:nowrap">
+
+ <c:set var="episodeCount" value="0"/>
+
+ <c:forEach items="${model.channels}" var="channel" varStatus="i">
+
+ <c:set var="title" value="${channel.key.title}"/>
+ <c:if test="${empty title}">
+ <c:set var="title" value="${channel.key.url}"/>
+ </c:if>
+
+ <c:set var="channelExpanded" value="false"/>
+ <c:forEach items="${model.expandedChannels}" var="expandedChannelId">
+ <c:if test="${expandedChannelId eq channel.key.id}">
+ <c:set var="channelExpanded" value="true"/>
+ </c:if>
+ </c:forEach>
+
+ <tr style="margin:0;padding:0;border:0">
+ <td style="padding-top:1em">
+ <input type="checkbox" class="checkbox" id="channel${i.index}" value="${channel.key.id}"/>
+ <input type="checkbox" class="checkbox" id="channelExpanded${i.index}" value="${channel.key.id}" style="display:none"
+ <c:if test="${channelExpanded}">checked="checked"</c:if>/>
+ </td>
+ <td colspan="6" style="padding-left:0.25em;padding-top:1em">
+ <a href="javascript:toggleEpisodes(${i.index})">
+ <span title="${title}"><b><str:truncateNicely upper="40">${title}</str:truncateNicely></b></span>
+ (${fn:length(channel.value)})
+ </a>
+ </td>
+ <td style="padding-left:1.5em;padding-top:1em;text-align:center;">
+ <span class="detail"><fmt:message key="podcastreceiver.status.${fn:toLowerCase(channel.key.status)}"/></span>
+ </td>
+ <td style="padding-left:1.5em;padding-top:1em">
+ <c:choose>
+ <c:when test="${channel.key.status eq 'ERROR'}">
+ <span class="detail warning" title="${channel.key.errorMessage}"><str:truncateNicely upper="100">${channel.key.errorMessage}</str:truncateNicely></span>
+ </c:when>
+ <c:otherwise>
+ <span class="detail" title="${channel.key.description}"><str:truncateNicely upper="100">${channel.key.description}</str:truncateNicely></span>
+ </c:otherwise>
+ </c:choose>
+ </td>
+ </tr>
+
+ <c:set var="class" value=""/>
+
+ <c:forEach items="${channel.value}" var="episode" varStatus="j">
+
+ <c:choose>
+ <c:when test="${empty class}">
+ <c:set var="class" value="class='bgcolor2'"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="class" value=""/>
+ </c:otherwise>
+ </c:choose>
+ <tr title="channel${i.index}" id="episodeRow${episodeCount}" style="margin:0;padding:0;border:0;display:${channelExpanded ? "table-row" : "none"}">
+
+ <td><input type="checkbox" class="checkbox" id="episode${episodeCount}" value="${episode.id}"/></td>
+
+ <c:choose>
+ <c:when test="${empty episode.path}">
+ <td ${class} colspan="3"/>
+ </c:when>
+ <c:otherwise>
+ <c:import url="playAddDownload.jsp">
+ <c:param name="id" value="${episode.mediaFileId}"/>
+ <c:param name="playEnabled" value="${model.user.streamRole and not model.partyMode}"/>
+ <c:param name="addEnabled" value="${model.user.streamRole and not model.partyMode}"/>
+ <c:param name="downloadEnabled" value="false"/>
+ <c:param name="asTable" value="true"/>
+ </c:import>
+ </c:otherwise>
+ </c:choose>
+
+ <c:set var="episodeCount" value="${episodeCount + 1}"/>
+
+
+ <sub:url value="main.view" var="mainUrl">
+ <sub:param name="path" value="${episode.path}"/>
+ </sub:url>
+
+
+ <td ${class} style="padding-left:0.6em">
+ <span title="${episode.title}">
+ <c:choose>
+ <c:when test="${empty episode.path}">
+ <str:truncateNicely upper="40">${episode.title}</str:truncateNicely>
+ </c:when>
+ <c:otherwise>
+ <a target="main" href="${mainUrl}"><str:truncateNicely upper="40">${episode.title}</str:truncateNicely></a>
+ </c:otherwise>
+ </c:choose>
+ </span>
+ </td>
+
+ <td ${class} style="padding-left:1.5em">
+ <span class="detail">${episode.duration}</span>
+ </td>
+
+ <td ${class} style="padding-left:1.5em">
+ <span class="detail"><fmt:formatDate value="${episode.publishDate}" dateStyle="medium"/></span>
+ </td>
+
+ <td ${class} style="padding-left:1.5em;text-align:center">
+ <span class="detail">
+ <c:choose>
+ <c:when test="${episode.status eq 'DOWNLOADING'}">
+ <fmt:formatNumber type="percent" value="${episode.completionRate}"/>
+ </c:when>
+ <c:otherwise>
+ <fmt:message key="podcastreceiver.status.${fn:toLowerCase(episode.status)}"/>
+ </c:otherwise>
+ </c:choose>
+ </span>
+ </td>
+
+ <td ${class} style="padding-left:1.5em">
+ <c:choose>
+ <c:when test="${episode.status eq 'ERROR'}">
+ <span class="detail warning" title="${episode.errorMessage}"><str:truncateNicely upper="100">${episode.errorMessage}</str:truncateNicely></span>
+ </c:when>
+ <c:otherwise>
+ <span class="detail" title="${episode.description}"><str:truncateNicely upper="100">${episode.description}</str:truncateNicely></span>
+ </c:otherwise>
+ </c:choose>
+ </td>
+
+ </tr>
+ </c:forEach>
+ </c:forEach>
+</table>
+
+<script type="text/javascript" language="javascript">
+ var episodeCount = ${episodeCount};
+</script>
+
+<table style="padding-top:1em"><tr>
+ <c:if test="${model.user.podcastRole}">
+ <td style="padding-right:2em"><div class="forward"><a href="javascript:downloadSelected()"><fmt:message key="podcastreceiver.downloadselected"/></a></div></td>
+ <td style="padding-right:2em"><div class="forward"><a href="javascript:deleteSelected()"><fmt:message key="podcastreceiver.deleteselected"/></a></div></td>
+ <td style="padding-right:2em"><div class="forward"><a href="javascript:refreshChannels()"><fmt:message key="podcastreceiver.check"/></a></div></td>
+ </c:if>
+ <td style="padding-right:2em"><div class="forward"><a href="javascript:refreshPage()"><fmt:message key="podcastreceiver.refresh"/></a></div></td>
+ <c:if test="${model.user.adminRole}">
+ <td style="padding-right:2em"><div class="forward"><a href="podcastSettings.view?"><fmt:message key="podcastreceiver.settings"/></a></div></td>
+ </c:if>
+</tr></table>
+
+<c:if test="${model.user.podcastRole}">
+ <form method="post" action="podcastReceiverAdmin.view?">
+ <input type="hidden" name="expandedChannels" value=""/>
+ <table>
+ <tr>
+ <td><fmt:message key="podcastreceiver.subscribe"/></td>
+ <td><input type="text" name="add" value="http://" style="width:30em" onclick="select()"/></td>
+ <td><input type="submit" value="<fmt:message key="common.ok"/>"/></td>
+ </tr>
+ </table>
+ </form>
+</c:if>
+
+
+</body>
+</html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/podcastSettings.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/podcastSettings.jsp new file mode 100644 index 00000000..07d99e28 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/podcastSettings.jsp @@ -0,0 +1,88 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+</head>
+<body class="mainframe bgcolor1">
+
+<c:import url="settingsHeader.jsp">
+ <c:param name="cat" value="podcast"/>
+</c:import>
+
+<form:form commandName="command" action="podcastSettings.view" method="post">
+
+<table class="indent">
+ <tr>
+ <td><fmt:message key="podcastsettings.update"/></td>
+ <td>
+ <form:select path="interval" cssStyle="width:20em">
+ <fmt:message key="podcastsettings.interval.manually" var="never"/>
+ <fmt:message key="podcastsettings.interval.hourly" var="hourly"/>
+ <fmt:message key="podcastsettings.interval.daily" var="daily"/>
+ <fmt:message key="podcastsettings.interval.weekly" var="weekly"/>
+
+ <form:option value="-1" label="${never}"/>
+ <form:option value="1" label="${hourly}"/>
+ <form:option value="24" label="${daily}"/>
+ <form:option value="168" label="${weekly}"/>
+ </form:select>
+ </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="podcastsettings.keep"/></td>
+ <td>
+ <form:select path="episodeRetentionCount" cssStyle="width:20em">
+ <fmt:message key="podcastsettings.keep.all" var="all"/>
+ <fmt:message key="podcastsettings.keep.one" var="one"/>
+
+ <form:option value="-1" label="${all}"/>
+ <form:option value="1" label="${one}"/>
+
+ <c:forTokens items="2 3 4 5 10 20 30 50" delims=" " var="count">
+ <fmt:message key="podcastsettings.keep.many" var="many"><fmt:param value="${count}"/></fmt:message>
+ <form:option value="${count}" label="${many}"/>
+ </c:forTokens>
+
+ </form:select>
+ </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="podcastsettings.download"/></td>
+ <td>
+ <form:select path="episodeDownloadCount" cssStyle="width:20em">
+ <fmt:message key="podcastsettings.download.all" var="all"/>
+ <fmt:message key="podcastsettings.download.one" var="one"/>
+ <fmt:message key="podcastsettings.download.none" var="none"/>
+
+ <form:option value="-1" label="${all}"/>
+ <form:option value="1" label="${one}"/>
+
+ <c:forTokens items="2 3 4 5 10" delims=" " var="count">
+ <fmt:message key="podcastsettings.download.many" var="many"><fmt:param value="${count}"/></fmt:message>
+ <form:option value="${count}" label="${many}"/>
+ </c:forTokens>
+ <form:option value="0" label="${none}"/>
+
+ </form:select>
+ </td>
+ </tr>
+
+ <tr>
+ <td><fmt:message key="podcastsettings.folder"/></td>
+ <td><form:input path="folder" cssStyle="width:20em"/></td>
+ </tr>
+
+ <tr>
+ <td style="padding-top:1.5em" colspan="2">
+ <input type="submit" value="<fmt:message key="common.save"/>" style="margin-right:0.3em">
+ <input type="button" value="<fmt:message key="common.cancel"/>" onclick="location.href='nowPlaying.view'">
+ </td>
+ </tr>
+
+</table>
+
+</form:form>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/rating.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/rating.jsp new file mode 100644 index 00000000..9e956de3 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/rating.jsp @@ -0,0 +1,51 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<%@ include file="include.jsp" %>
+
+<%--
+Creates HTML for displaying the rating stars.
+PARAMETERS
+ path: Album path. May be null if readonly.
+ readonly: Whether rating can be changed.
+ rating: The rating, an integer from 0 (no rating), through 10 (lowest rating), to 50 (highest rating).
+--%>
+
+<c:forEach var="i" begin="1" end="5">
+
+ <sub:url value="setRating.view" var="ratingUrl">
+ <sub:param name="path" value="${param.path}"/>
+ <sub:param name="action" value="rating"/>
+ <sub:param name="rating" value="${i}"/>
+ </sub:url>
+
+ <c:choose>
+ <c:when test="${param.rating ge i * 10}">
+ <spring:theme code="ratingOnImage" var="imageUrl"/>
+ </c:when>
+ <c:when test="${param.rating ge i*10 - 7 and param.rating le i*10 - 3}">
+ <spring:theme code="ratingHalfImage" var="imageUrl"/>
+ </c:when>
+ <c:otherwise>
+ <spring:theme code="ratingOffImage" var="imageUrl"/>
+ </c:otherwise>
+ </c:choose>
+
+ <c:choose>
+ <c:when test="${param.readonly}">
+ <img src="${imageUrl}" style="margin-right:-3px" alt="" title="<fmt:message key="rating.rating"/> ${param.rating/10}">
+ </c:when>
+ <c:otherwise>
+ <a href="${ratingUrl}"><img src="${imageUrl}" style="margin-right:-3px" alt="" title="<fmt:message key="rating.rating"/> ${i}"></a>
+ </c:otherwise>
+ </c:choose>
+
+</c:forEach>
+
+<sub:url value="setRating.view" var="clearRatingUrl">
+ <sub:param name="path" value="${param.path}"/>
+ <sub:param name="action" value="rating"/>
+ <sub:param name="rating" value="0"/>
+</sub:url>
+
+<c:if test="${not param.readonly}">
+ | <a href="${clearRatingUrl}"><img src="<spring:theme code="clearRatingImage"/>" alt="" title="<fmt:message key="rating.clearrating"/>" style="margin-left:-3px; margin-right:5px"></a>
+</c:if>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/recover.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/recover.jsp new file mode 100644 index 00000000..ff206d14 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/recover.jsp @@ -0,0 +1,34 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+<head>
+ <%@ include file="head.jsp" %>
+</head>
+<body class="mainframe bgcolor1" onload="document.getElementById('usernameOrEmail').focus()">
+
+<form action="recover.view" method="POST">
+ <div class="bgcolor2" style="border:1px solid black; padding:20px 50px 20px 50px; margin-top:100px">
+
+ <div style="margin-left: auto; margin-right: auto; width: 45em">
+
+ <h1><fmt:message key="recover.title"/></h1>
+ <p style="padding-top: 1em; padding-bottom: 0.5em"><fmt:message key="recover.text"/></p>
+ <input type="text" id="usernameOrEmail" name="usernameOrEmail" style="width:18em;margin-right: 1em">
+ <input name="submit" type="submit" value="<fmt:message key="recover.send"/>">
+
+ <c:if test="${not empty model.sentTo}">
+ <p style="padding-top: 1em"><fmt:message key="recover.success"><fmt:param value="${model.sentTo}"/></fmt:message></p>
+ </c:if>
+
+ <c:if test="${not empty model.error}">
+ <p style="padding-top: 1em" class="warning"><fmt:message key="${model.error}"/></p>
+ </c:if>
+
+ <div class="back" style="margin-top: 1.5em"><a href="login.view"><fmt:message key="common.back"/></a></div>
+
+ </div>
+ </div>
+</form>
+</body>
+</html>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/reload.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/reload.jsp new file mode 100644 index 00000000..1b8384a7 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/reload.jsp @@ -0,0 +1,11 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+</head><body>
+
+<c:forEach items="${model.reloadFrames}" var="reloadFrame">
+ <script language="javascript" type="text/javascript">parent.frames.${reloadFrame.frame}.location.href="${reloadFrame.view}"</script>
+</c:forEach>
+
+</body></html>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/rest/videoPlayer.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/rest/videoPlayer.jsp new file mode 100644 index 00000000..ccd18a93 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/rest/videoPlayer.jsp @@ -0,0 +1,142 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<html>
+<head>
+ <%@ include file="../include.jsp" %>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <link rel="stylesheet" href="../<spring:theme code="styleSheet"/>" type="text/css">
+ <link rel="shortcut icon" href="../<spring:theme code="faviconImage"/>">
+
+ <c:url value="/rest/stream.view" var="streamUrl">
+ <c:param name="c" value="${model.c}"/>
+ <c:param name="v" value="${model.v}"/>
+ <c:param name="id" value="${model.id}"/>
+ </c:url>
+
+ <script type="text/javascript" src="<c:url value="/script/swfobject.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/prototype.js"/>"></script>
+ <script type="text/javascript" language="javascript">
+
+ var player;
+ var position;
+ var maxBitRate = ${model.maxBitRate};
+ var timeOffset = ${model.timeOffset};
+
+ function init() {
+ var flashvars = {
+ id:"player1",
+ skin:"<c:url value="/flash/whotube.zip"/>",
+ screencolor:"000000",
+ autostart:false,
+ bufferlength:4,
+ backcolor:"<spring:theme code="backgroundColor"/>",
+ frontcolor:"<spring:theme code="textColor"/>",
+ provider:"video"
+ };
+ var params = {
+ allowfullscreen:"true",
+ allowscriptaccess:"always"
+ };
+ var attributes = {
+ id:"player1",
+ name:"player1"
+ };
+
+ swfobject.embedSWF("<c:url value="/flash/jw-player-5.6.swf"/>", "placeholder1", "360", "240", "9.0.0", false, flashvars, params, attributes);
+ }
+
+ function playerReady(thePlayer) {
+ player = $("player1");
+ player.addModelListener("TIME", "timeListener");
+
+ <c:if test="${model.autoplay}">
+ play();
+ </c:if>
+ }
+
+ function play() {
+ var list = new Array();
+ list[0] = {
+ file:"${streamUrl}&maxBitRate=" + maxBitRate + "&timeOffset=" + timeOffset + "&p=${model.p}" + "&u=${model.u}",
+ duration:${model.duration} - timeOffset,
+ provider:"video"
+ };
+ player.sendEvent("LOAD", list);
+ player.sendEvent("PLAY");
+ }
+
+ function timeListener(obj) {
+ var newPosition = Math.round(obj.position);
+ if (newPosition != position) {
+ position = newPosition;
+ updatePosition();
+ }
+ }
+
+ function updatePosition() {
+ var pos = parseInt(timeOffset) + parseInt(position);
+
+ var minutes = Math.round(pos / 60);
+ var seconds = pos % 60;
+
+ var result = minutes + ":";
+ if (seconds < 10) {
+ result += "0";
+ }
+ result += seconds;
+ $("position").innerHTML = result;
+ }
+
+ function changeTimeOffset() {
+ timeOffset = $("timeOffset").getValue();
+ play();
+ }
+
+ function changeBitRate() {
+ maxBitRate = $("maxBitRate").getValue();
+ timeOffset = parseInt(timeOffset) + parseInt(position);
+ play();
+ }
+
+ </script>
+</head>
+
+<body class="mainframe bgcolor1" onload="init();">
+<h1>${model.video.title}</h1>
+
+<div id="wrapper" style="padding-top:1em">
+ <div id="placeholder1"><span class="warning"><a href="http://www.adobe.com/go/getflashplayer"><fmt:message key="playlist.getflash"/></a></span></div>
+</div>
+
+<div style="padding-top:1.3em;padding-bottom:0.7em;font-size:16px">
+
+ <span id="position" style="padding-right:0.5em">0:00</span>
+ <select id="timeOffset" onchange="changeTimeOffset();" style="padding-left:0.25em;padding-right:0.25em;margin-right:0.5em;font-size:16px">
+ <c:forEach items="${model.skipOffsets}" var="skipOffset">
+ <c:choose>
+ <c:when test="${skipOffset.value eq model.timeOffset}">
+ <option selected="selected" value="${skipOffset.value}">${skipOffset.key}</option>
+ </c:when>
+ <c:otherwise>
+ <option value="${skipOffset.value}">${skipOffset.key}</option>
+ </c:otherwise>
+ </c:choose>
+ </c:forEach>
+ </select>
+
+ <select id="maxBitRate" onchange="changeBitRate();" style="padding-left:0.25em;padding-right:0.25em;margin-right:0.5em;font-size:16px">
+ <c:forEach items="${model.bitRates}" var="bitRate">
+ <c:choose>
+ <c:when test="${bitRate eq model.maxBitRate}">
+ <option selected="selected" value="${bitRate}">${bitRate} Kbps</option>
+ </c:when>
+ <c:otherwise>
+ <option value="${bitRate}">${bitRate} Kbps</option>
+ </c:otherwise>
+ </c:choose>
+ </c:forEach>
+ </select>
+</div>
+
+</body>
+</html>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/right.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/right.jsp new file mode 100644 index 00000000..ada7385f --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/right.jsp @@ -0,0 +1,191 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<html>
+<head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="<c:url value="/dwr/engine.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/util.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/chatService.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/nowPlayingService.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/prototype.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/scripts.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/fancyzoom/FancyZoom.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/fancyzoom/FancyZoomHTML.js"/>"></script>
+</head>
+<body class="bgcolor1 rightframe" style="padding-top:2em" onload="init()">
+
+<script type="text/javascript">
+ function init() {
+ setupZoom('<c:url value="/"/>');
+ dwr.engine.setErrorHandler(null);
+ <c:if test="${model.showChat}">
+ chatService.addMessage(null);
+ </c:if>
+ }
+</script>
+
+<div id="scanningStatus" style="display: none;" class="warning">
+ <img src="<spring:theme code="scanningImage"/>" title="" alt=""> <fmt:message key="main.scanning"/> <span id="scanCount"></span>
+</div>
+
+<c:if test="${model.showNowPlaying}">
+
+ <!-- This script uses AJAX to periodically retrieve what all users are playing. -->
+ <script type="text/javascript" language="javascript">
+
+ startGetNowPlayingTimer();
+
+ function startGetNowPlayingTimer() {
+ nowPlayingService.getNowPlaying(getNowPlayingCallback);
+ setTimeout("startGetNowPlayingTimer()", 10000);
+ }
+
+ function getNowPlayingCallback(nowPlaying) {
+ var html = nowPlaying.length == 0 ? "" : "<h2><fmt:message key="main.nowplaying"/></h2><table>";
+ for (var i = 0; i < nowPlaying.length; i++) {
+ html += "<tr><td colspan='2' class='detail' style='padding-top:1em;white-space:nowrap'>";
+
+ if (nowPlaying[i].avatarUrl != null) {
+ html += "<img src='" + nowPlaying[i].avatarUrl + "' style='padding-right:5pt'>";
+ }
+ html += "<b>" + nowPlaying[i].username + "</b></td></tr>"
+
+ html += "<tr><td class='detail' style='padding-right:1em'>" +
+ "<a title='" + nowPlaying[i].tooltip + "' target='main' href='" + nowPlaying[i].albumUrl + "'>";
+
+ if (nowPlaying[i].artist != null) {
+ html += "<em>" + nowPlaying[i].artist + "</em><br/>";
+ }
+
+ html += nowPlaying[i].title + "</a><br/>" +
+ "<span class='forward'><a href='" + nowPlaying[i].lyricsUrl + "' onclick=\"return popupSize(this, 'lyrics', 430, 550)\">" +
+ "<fmt:message key="main.lyrics"/>" + "</a></span></td><td style='padding-top:1em'>";
+
+ if (nowPlaying[i].coverArtUrl != null) {
+ html += "<a title='" + nowPlaying[i].tooltip + "' rel='zoom' href='" + nowPlaying[i].coverArtZoomUrl + "'>" +
+ "<img src='" + nowPlaying[i].coverArtUrl + "' width='48' height='48'></a>";
+ }
+ html += "</td></tr>";
+
+ var minutesAgo = nowPlaying[i].minutesAgo;
+ if (minutesAgo > 4) {
+ html += "<tr><td class='detail' colspan='2'>" + minutesAgo + " <fmt:message key="main.minutesago"/></td></tr>";
+ }
+ }
+ html += "</table>";
+ $('nowPlaying').innerHTML = html;
+ prepZooms();
+ }
+ </script>
+
+ <div id="nowPlaying">
+ </div>
+
+</c:if>
+
+<c:if test="${model.showChat}">
+ <script type="text/javascript">
+
+ var revision = 0;
+ startGetMessagesTimer();
+
+ function startGetMessagesTimer() {
+ chatService.getMessages(revision, getMessagesCallback);
+ setTimeout("startGetMessagesTimer()", 10000);
+ }
+
+ function addMessage() {
+ chatService.addMessage($("message").value);
+ dwr.util.setValue("message", null);
+ setTimeout("startGetMessagesTimer()", 500);
+ }
+ function clearMessages() {
+ chatService.clearMessages();
+ setTimeout("startGetMessagesTimer()", 500);
+ }
+ function getMessagesCallback(messages) {
+
+ if (messages == null) {
+ return;
+ }
+ revision = messages.revision;
+
+ // Delete all the rows except for the "pattern" row
+ dwr.util.removeAllRows("chatlog", { filter:function(div) {
+ return (div.id != "pattern");
+ }});
+
+ // Create a new set cloned from the pattern row
+ for (var i = 0; i < messages.messages.length; i++) {
+ var message = messages.messages[i];
+ var id = i + 1;
+ dwr.util.cloneNode("pattern", { idSuffix:id });
+ dwr.util.setValue("user" + id, message.username);
+ dwr.util.setValue("date" + id, " [" + formatDate(message.date) + "]");
+ dwr.util.setValue("content" + id, message.content);
+ $("pattern" + id).show();
+ }
+
+ var clearDiv = $("clearDiv");
+ if (clearDiv) {
+ if (messages.messages.length == 0) {
+ clearDiv.hide();
+ } else {
+ clearDiv.show();
+ }
+ }
+ }
+ function formatDate(date) {
+ var hours = date.getHours();
+ var minutes = date.getMinutes();
+ var result = hours < 10 ? "0" : "";
+ result += hours;
+ result += ":";
+ if (minutes < 10) {
+ result += "0";
+ }
+ result += minutes;
+ return result;
+ }
+ </script>
+
+ <script type="text/javascript">
+
+ startGetScanningStatusTimer();
+
+ function startGetScanningStatusTimer() {
+ nowPlayingService.getScanningStatus(getScanningStatusCallback);
+ }
+
+ function getScanningStatusCallback(scanInfo) {
+ dwr.util.setValue("scanCount", scanInfo.count);
+ if (scanInfo.scanning) {
+ $("scanningStatus").show();
+ setTimeout("startGetScanningStatusTimer()", 1000);
+ } else {
+ $("scanningStatus").hide();
+ setTimeout("startGetScanningStatusTimer()", 15000);
+ }
+ }
+ </script>
+
+ <h2><fmt:message key="main.chat"/></h2>
+ <div style="padding-top:0.3em;padding-bottom:0.3em">
+ <input id="message" value=" <fmt:message key="main.message"/>" style="width:90%" onclick="dwr.util.setValue('message', null);" onkeypress="dwr.util.onReturn(event, addMessage)"/>
+ </div>
+
+ <table>
+ <tbody id="chatlog">
+ <tr id="pattern" style="display:none;margin:0;padding:0 0 0.15em 0;border:0"><td>
+ <span id="user" class="detail" style="font-weight:bold"></span> <span id="date" class="detail"></span> <span id="content"></span></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <c:if test="${model.user.adminRole}">
+ <div id="clearDiv" style="display:none;" class="forward"><a href="#" onclick="clearMessages(); return false;"> <fmt:message key="main.clearchat"/></a></div>
+ </c:if>
+</c:if>
+
+</body>
+</html>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/search.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/search.jsp new file mode 100644 index 00000000..a01f7afe --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/search.jsp @@ -0,0 +1,150 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<%--@elvariable id="command" type="net.sourceforge.subsonic.command.SearchCommand"--%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="<c:url value='/script/scripts.js'/>"></script>
+ <script type="text/javascript" src="<c:url value='/script/prototype.js'/>"></script>
+ <script type="text/javascript" src="<c:url value='/dwr/util.js'/>"></script>
+
+ <script type="text/javascript">
+ function more(rowSelector, moreId) {
+ var rows = $$(rowSelector);
+ for (var i = 0; i < rows.length; i++) {
+ rows[i].show();
+ }
+ $(moreId).hide();
+ }
+ </script>
+
+</head>
+<body class="mainframe bgcolor1">
+
+<h1>
+ <img src="<spring:theme code="searchImage"/>" alt=""/>
+ <fmt:message key="search.title"/>
+</h1>
+
+<form:form commandName="command" method="post" action="search.view" name="searchForm">
+ <table>
+ <tr>
+ <td><fmt:message key="search.query"/></td>
+ <td style="padding-left:0.25em"><form:input path="query" size="35"/></td>
+ <td style="padding-left:0.25em"><input type="submit" onclick="search(0)" value="<fmt:message key="search.search"/>"/></td>
+ </tr>
+ </table>
+
+</form:form>
+
+<c:if test="${command.indexBeingCreated}">
+ <p class="warning"><fmt:message key="search.index"/></p>
+</c:if>
+
+<c:if test="${not command.indexBeingCreated and empty command.artists and empty command.albums and empty command.songs}">
+ <p class="warning"><fmt:message key="search.hits.none"/></p>
+</c:if>
+
+<c:if test="${not empty command.artists}">
+ <h2><fmt:message key="search.hits.artists"/></h2>
+ <table style="border-collapse:collapse">
+ <c:forEach items="${command.artists}" var="match" varStatus="loopStatus">
+
+ <sub:url value="/main.view" var="mainUrl">
+ <sub:param name="path" value="${match.path}"/>
+ </sub:url>
+
+ <tr class="artistRow" ${loopStatus.count > 5 ? "style='display:none'" : ""}>
+ <c:import url="playAddDownload.jsp">
+ <c:param name="id" value="${match.id}"/>
+ <c:param name="playEnabled" value="${command.user.streamRole and not command.partyModeEnabled}"/>
+ <c:param name="addEnabled" value="${command.user.streamRole and (not command.partyModeEnabled or not match.directory)}"/>
+ <c:param name="downloadEnabled" value="${command.user.downloadRole and not command.partyModeEnabled}"/>
+ <c:param name="asTable" value="true"/>
+ </c:import>
+ <td ${loopStatus.count % 2 == 1 ? "class='bgcolor2'" : ""} style="padding-left:0.25em;padding-right:1.25em">
+ <a href="${mainUrl}">${match.name}</a>
+ </td>
+ </tr>
+
+ </c:forEach>
+ </table>
+ <c:if test="${fn:length(command.artists) gt 5}">
+ <div id="moreArtists" class="forward"><a href="javascript:noop()" onclick="more('tr.artistRow', 'moreArtists')"><fmt:message key="search.hits.more"/></a></div>
+ </c:if>
+</c:if>
+
+<c:if test="${not empty command.albums}">
+ <h2><fmt:message key="search.hits.albums"/></h2>
+ <table style="border-collapse:collapse">
+ <c:forEach items="${command.albums}" var="match" varStatus="loopStatus">
+
+ <sub:url value="/main.view" var="mainUrl">
+ <sub:param name="path" value="${match.path}"/>
+ </sub:url>
+
+ <tr class="albumRow" ${loopStatus.count > 5 ? "style='display:none'" : ""}>
+ <c:import url="playAddDownload.jsp">
+ <c:param name="id" value="${match.id}"/>
+ <c:param name="playEnabled" value="${command.user.streamRole and not command.partyModeEnabled}"/>
+ <c:param name="addEnabled" value="${command.user.streamRole and (not command.partyModeEnabled or not match.directory)}"/>
+ <c:param name="downloadEnabled" value="${command.user.downloadRole and not command.partyModeEnabled}"/>
+ <c:param name="asTable" value="true"/>
+ </c:import>
+
+ <td ${loopStatus.count % 2 == 1 ? "class='bgcolor2'" : ""} style="padding-left:0.25em;padding-right:1.25em">
+ <a href="${mainUrl}">${match.albumName}</a>
+ </td>
+
+ <td ${loopStatus.count % 2 == 1 ? "class='bgcolor2'" : ""} style="padding-right:0.25em">
+ <span class="detail">${match.artist}</span>
+ </td>
+ </tr>
+
+ </c:forEach>
+ </table>
+ <c:if test="${fn:length(command.albums) gt 5}">
+ <div id="moreAlbums" class="forward"><a href="javascript:noop()" onclick="more('tr.albumRow', 'moreAlbums')"><fmt:message key="search.hits.more"/></a></div>
+ </c:if>
+</c:if>
+
+
+<c:if test="${not empty command.songs}">
+ <h2><fmt:message key="search.hits.songs"/></h2>
+ <table style="border-collapse:collapse">
+ <c:forEach items="${command.songs}" var="match" varStatus="loopStatus">
+
+ <sub:url value="/main.view" var="mainUrl">
+ <sub:param name="path" value="${match.parentPath}"/>
+ </sub:url>
+
+ <tr class="songRow" ${loopStatus.count > 15 ? "style='display:none'" : ""}>
+ <c:import url="playAddDownload.jsp">
+ <c:param name="id" value="${match.id}"/>
+ <c:param name="playEnabled" value="${command.user.streamRole and not command.partyModeEnabled}"/>
+ <c:param name="addEnabled" value="${command.user.streamRole and (not command.partyModeEnabled or not match.directory)}"/>
+ <c:param name="downloadEnabled" value="${command.user.downloadRole and not command.partyModeEnabled}"/>
+ <c:param name="video" value="${match.video and command.player.web}"/>
+ <c:param name="asTable" value="true"/>
+ </c:import>
+
+ <td ${loopStatus.count % 2 == 1 ? "class='bgcolor2'" : ""} style="padding-left:0.25em;padding-right:1.25em">
+ ${match.title}
+ </td>
+
+ <td ${loopStatus.count % 2 == 1 ? "class='bgcolor2'" : ""} style="padding-right:1.25em">
+ <a href="${mainUrl}"><span class="detail">${match.albumName}</span></a>
+ </td>
+
+ <td ${loopStatus.count % 2 == 1 ? "class='bgcolor2'" : ""} style="padding-right:0.25em">
+ <span class="detail">${match.artist}</span>
+ </td>
+ </tr>
+
+ </c:forEach>
+ </table>
+<c:if test="${fn:length(command.songs) gt 15}">
+ <div id="moreSongs" class="forward"><a href="javascript:noop()" onclick="more('tr.songRow', 'moreSongs')"><fmt:message key="search.hits.more"/></a></div>
+</c:if>
+</c:if>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/settingsHeader.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/settingsHeader.jsp new file mode 100644 index 00000000..6f7f240c --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/settingsHeader.jsp @@ -0,0 +1,32 @@ +
+<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+<%@ include file="include.jsp" %>
+
+<c:set var="categories" value="${param.restricted ? 'personal password player share' : 'musicFolder general advanced personal user player share network transcoding internetRadio podcast'}"/>
+<h1>
+ <img src="<spring:theme code="settingsImage"/>" alt=""/>
+ <fmt:message key="settingsheader.title"/>
+</h1>
+
+<h2>
+<c:forTokens items="${categories}" delims=" " var="cat" varStatus="loopStatus">
+ <c:choose>
+ <c:when test="${loopStatus.count > 1 and (loopStatus.count - 1) % 6 != 0}"> | </c:when>
+ <c:otherwise></h2><h2></c:otherwise>
+ </c:choose>
+
+ <c:url var="url" value="${cat}Settings.view?"/>
+
+ <c:choose>
+ <c:when test="${param.cat eq cat}">
+ <span class="headerSelected"><fmt:message key="settingsheader.${cat}"/></span>
+ </c:when>
+ <c:otherwise>
+ <a href="${url}"><fmt:message key="settingsheader.${cat}"/></a>
+ </c:otherwise>
+ </c:choose>
+
+</c:forTokens>
+</h2>
+
+<p></p>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/shareSettings.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/shareSettings.jsp new file mode 100644 index 00000000..448f4741 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/shareSettings.jsp @@ -0,0 +1,72 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+<%--@elvariable id="model" type="Map"--%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+</head>
+<body class="mainframe bgcolor1">
+
+<c:import url="settingsHeader.jsp">
+ <c:param name="cat" value="share"/>
+ <c:param name="restricted" value="${not model.user.adminRole}"/>
+</c:import>
+
+<form method="post" action="shareSettings.view">
+
+ <table class="indent" style="border-collapse:collapse;white-space:nowrap">
+ <tr>
+ <th style="padding-left:1em"><fmt:message key="sharesettings.name"/></th>
+ <th style="padding-left:1em"><fmt:message key="sharesettings.owner"/></th>
+ <th style="padding-left:1em"><fmt:message key="sharesettings.description"/></th>
+ <th style="padding-left:1em"><fmt:message key="sharesettings.expires"/></th>
+ <th style="padding-left:1em"><fmt:message key="sharesettings.lastvisited"/></th>
+ <th style="padding-left:1em"><fmt:message key="sharesettings.visits"/></th>
+ <th style="padding-left:1em"><fmt:message key="sharesettings.files"/></th>
+ <th style="padding-left:1em"><fmt:message key="sharesettings.expirein"/></th>
+ <th style="padding-left:1em"><fmt:message key="common.delete"/></th>
+ </tr>
+
+ <c:forEach items="${model.shareInfos}" var="shareInfo" varStatus="loopStatus">
+ <c:set var="share" value="${shareInfo.share}"/>
+ <c:choose>
+ <c:when test="${loopStatus.count % 2 == 1}">
+ <c:set var="class" value="class='bgcolor2'"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="class" value=""/>
+ </c:otherwise>
+ </c:choose>
+
+ <sub:url value="main.view" var="albumUrl">
+ <sub:param name="path" value="${shareInfo.dir.path}"/>
+ </sub:url>
+
+ <tr>
+ <td ${class} style="padding-left:1em"><a href="${model.shareBaseUrl}${share.name}" target="_blank">${share.name}</a></td>
+ <td ${class} style="padding-left:1em">${share.username}</td>
+ <td ${class} style="padding-left:1em"><input type="text" name="description[${share.id}]" size="40" value="${share.description}"/></td>
+ <td ${class} style="padding-left:1em"><fmt:formatDate value="${share.expires}" type="date" dateStyle="medium"/></td>
+ <td ${class} style="padding-left:1em"><fmt:formatDate value="${share.lastVisited}" type="date" dateStyle="medium"/></td>
+ <td ${class} style="padding-left:1em; text-align:right">${share.visitCount}</td>
+ <td ${class} style="padding-left:1em"><a href="${albumUrl}" title="${shareInfo.dir.name}"><str:truncateNicely upper="30">${fn:escapeXml(shareInfo.dir.name)}</str:truncateNicely></a></td>
+ <td ${class} style="padding-left:1em">
+ <label><input type="radio" name="expireIn[${share.id}]" value="7"><fmt:message key="sharesettings.expirein.week"/></label>
+ <label><input type="radio" name="expireIn[${share.id}]" value="30"><fmt:message key="sharesettings.expirein.month"/></label>
+ <label><input type="radio" name="expireIn[${share.id}]" value="365"><fmt:message key="sharesettings.expirein.year"/></label>
+ <label><input type="radio" name="expireIn[${share.id}]" value="0"><fmt:message key="sharesettings.expirein.never"/></label>
+ </td>
+ <td ${class} style="padding-left:1em" align="center" style="padding-left:1em"><input type="checkbox" name="delete[${share.id}]" class="checkbox"/></td>
+ </tr>
+ </c:forEach>
+
+ <tr>
+ <td colspan="4" style="padding-top:1.5em">
+ <input type="submit" value="<fmt:message key="common.save"/>" style="margin-right:0.3em">
+ <input type="button" value="<fmt:message key="common.cancel"/>" onclick="location.href='nowPlaying.view'">
+ </td>
+ </tr>
+
+ </table>
+</form>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/starred.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/starred.jsp new file mode 100644 index 00000000..967fc7b7 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/starred.jsp @@ -0,0 +1,131 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <%@ include file="jquery.jsp" %>
+ <script type="text/javascript" src="<c:url value='/dwr/util.js'/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/engine.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/dwr/interface/starService.js"/>"></script>
+ <script type="text/javascript" language="javascript">
+
+ function toggleStar(mediaFileId, imageId) {
+ if ($(imageId).attr("src").indexOf("<spring:theme code="ratingOnImage"/>") != -1) {
+ $(imageId).attr("src", "<spring:theme code="ratingOffImage"/>");
+ starService.unstar(mediaFileId);
+ }
+ else if ($(imageId).attr("src").indexOf("<spring:theme code="ratingOffImage"/>") != -1) {
+ $(imageId).attr("src", "<spring:theme code="ratingOnImage"/>");
+ starService.star(mediaFileId);
+ }
+ }
+ </script>
+</head>
+<body class="mainframe bgcolor1">
+
+<h1>
+ <fmt:message key="starred.title"/>
+</h1>
+
+<c:if test="${empty model.artists and empty model.albums and empty model.songs}">
+ <p style="padding-top: 1em"><em><fmt:message key="starred.empty"/></em></p>
+</c:if>
+
+<c:if test="${not empty model.artists}">
+ <h2><fmt:message key="search.hits.artists"/></h2>
+ <table style="border-collapse:collapse">
+ <c:forEach items="${model.artists}" var="artist" varStatus="loopStatus">
+
+ <sub:url value="/main.view" var="mainUrl">
+ <sub:param name="path" value="${artist.path}"/>
+ </sub:url>
+
+ <tr>
+ <c:import url="playAddDownload.jsp">
+ <c:param name="id" value="${artist.id}"/>
+ <c:param name="playEnabled" value="${model.user.streamRole and not model.partyModeEnabled}"/>
+ <c:param name="addEnabled" value="${model.user.streamRole and (not model.partyModeEnabled or not artist.directory)}"/>
+ <c:param name="downloadEnabled" value="${model.user.downloadRole and not model.partyModeEnabled}"/>
+ <c:param name="starEnabled" value="true"/>
+ <c:param name="starred" value="${not empty artist.starredDate}"/>
+ <c:param name="asTable" value="true"/>
+ </c:import>
+ <td ${loopStatus.count % 2 == 1 ? "class='bgcolor2'" : ""} style="padding-left:0.25em;padding-right:1.25em">
+ <a href="${mainUrl}">${artist.name}</a>
+ </td>
+ </tr>
+ </c:forEach>
+ </table>
+</c:if>
+
+<c:if test="${not empty model.albums}">
+ <h2><fmt:message key="search.hits.albums"/></h2>
+ <table style="border-collapse:collapse">
+ <c:forEach items="${model.albums}" var="album" varStatus="loopStatus">
+
+ <sub:url value="/main.view" var="mainUrl">
+ <sub:param name="path" value="${album.path}"/>
+ </sub:url>
+
+ <tr>
+ <c:import url="playAddDownload.jsp">
+ <c:param name="id" value="${album.id}"/>
+ <c:param name="playEnabled" value="${model.user.streamRole and not model.partyModeEnabled}"/>
+ <c:param name="addEnabled" value="${model.user.streamRole and (not model.partyModeEnabled or not album.directory)}"/>
+ <c:param name="downloadEnabled" value="${model.user.downloadRole and not model.partyModeEnabled}"/>
+ <c:param name="starEnabled" value="true"/>
+ <c:param name="starred" value="${not empty album.starredDate}"/>
+ <c:param name="asTable" value="true"/>
+ </c:import>
+
+ <td ${loopStatus.count % 2 == 1 ? "class='bgcolor2'" : ""} style="padding-left:0.25em;padding-right:1.25em">
+ <a href="${mainUrl}">${album.albumName}</a>
+ </td>
+
+ <td ${loopStatus.count % 2 == 1 ? "class='bgcolor2'" : ""} style="padding-right:0.25em">
+ <span class="detail">${album.artist}</span>
+ </td>
+ </tr>
+
+ </c:forEach>
+ </table>
+</c:if>
+
+<c:if test="${not empty model.songs}">
+ <h2><fmt:message key="search.hits.songs"/></h2>
+ <table style="border-collapse:collapse">
+ <c:forEach items="${model.songs}" var="song" varStatus="loopStatus">
+
+ <sub:url value="/main.view" var="mainUrl">
+ <sub:param name="path" value="${song.parentPath}"/>
+ </sub:url>
+
+ <tr>
+ <c:import url="playAddDownload.jsp">
+ <c:param name="id" value="${song.id}"/>
+ <c:param name="playEnabled" value="${model.user.streamRole and not model.partyModeEnabled}"/>
+ <c:param name="addEnabled" value="${model.user.streamRole and (not model.partyModeEnabled or not song.directory)}"/>
+ <c:param name="downloadEnabled" value="${model.user.downloadRole and not model.partyModeEnabled}"/>
+ <c:param name="starEnabled" value="true"/>
+ <c:param name="starred" value="${not empty song.starredDate}"/>
+ <c:param name="video" value="${song.video and model.player.web}"/>
+ <c:param name="asTable" value="true"/>
+ </c:import>
+
+ <td ${loopStatus.count % 2 == 1 ? "class='bgcolor2'" : ""} style="padding-left:0.25em;padding-right:1.25em">
+ ${song.title}
+ </td>
+
+ <td ${loopStatus.count % 2 == 1 ? "class='bgcolor2'" : ""} style="padding-right:1.25em">
+ <a href="${mainUrl}"><span class="detail">${song.albumName}</span></a>
+ </td>
+
+ <td ${loopStatus.count % 2 == 1 ? "class='bgcolor2'" : ""} style="padding-right:0.25em">
+ <span class="detail">${song.artist}</span>
+ </td>
+ </tr>
+
+ </c:forEach>
+ </table>
+</c:if>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/status.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/status.jsp new file mode 100644 index 00000000..2861022d --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/status.jsp @@ -0,0 +1,93 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <meta http-equiv="CACHE-CONTROL" content="NO-CACHE">
+ <meta http-equiv="REFRESH" content="20;URL=status.view">
+</head>
+<body class="mainframe bgcolor1">
+
+<h1>
+ <img src="<spring:theme code="statusImage"/>" alt="">
+ <fmt:message key="status.title"/>
+</h1>
+
+<table width="100%" class="ruleTable indent">
+ <tr>
+ <th class="ruleTableHeader"><fmt:message key="status.type"/></th>
+ <th class="ruleTableHeader"><fmt:message key="status.player"/></th>
+ <th class="ruleTableHeader"><fmt:message key="status.user"/></th>
+ <th class="ruleTableHeader"><fmt:message key="status.current"/></th>
+ <th class="ruleTableHeader"><fmt:message key="status.transmitted"/></th>
+ <th class="ruleTableHeader"><fmt:message key="status.bitrate"/></th>
+ </tr>
+
+ <c:forEach items="${model.transferStatuses}" var="status">
+
+ <c:choose>
+ <c:when test="${empty status.playerType}">
+ <fmt:message key="common.unknown" var="type"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="type" value="(${status.playerType})"/>
+ </c:otherwise>
+ </c:choose>
+
+ <c:choose>
+ <c:when test="${status.stream}">
+ <fmt:message key="status.stream" var="transferType"/>
+ </c:when>
+ <c:when test="${status.download}">
+ <fmt:message key="status.download" var="transferType"/>
+ </c:when>
+ <c:when test="${status.upload}">
+ <fmt:message key="status.upload" var="transferType"/>
+ </c:when>
+ </c:choose>
+
+ <c:choose>
+ <c:when test="${empty status.username}">
+ <fmt:message key="common.unknown" var="user"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="user" value="${status.username}"/>
+ </c:otherwise>
+ </c:choose>
+
+ <c:choose>
+ <c:when test="${empty status.path}">
+ <fmt:message key="common.unknown" var="current"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="current" value="${status.path}"/>
+ </c:otherwise>
+ </c:choose>
+
+ <sub:url value="/statusChart.view" var="chartUrl">
+ <c:if test="${status.stream}">
+ <sub:param name="type" value="stream"/>
+ </c:if>
+ <c:if test="${status.download}">
+ <sub:param name="type" value="download"/>
+ </c:if>
+ <c:if test="${status.upload}">
+ <sub:param name="type" value="upload"/>
+ </c:if>
+ <sub:param name="index" value="${status.index}"/>
+ </sub:url>
+
+ <tr>
+ <td class="ruleTableCell">${transferType}</td>
+ <td class="ruleTableCell">${status.player}<br>${type}</td>
+ <td class="ruleTableCell">${user}</td>
+ <td class="ruleTableCell">${current}</td>
+ <td class="ruleTableCell">${status.bytes}</td>
+ <td class="ruleTableCell" width="${model.chartWidth}"><img width="${model.chartWidth}" height="${model.chartHeight}" src="${chartUrl}" alt=""></td>
+ </tr>
+ </c:forEach>
+</table>
+
+<div class="forward"><a href="status.view?"><fmt:message key="common.refresh"/></a></div>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/test.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/test.jsp new file mode 100644 index 00000000..64f7c792 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/test.jsp @@ -0,0 +1,20 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<html>
+<head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="<c:url value="/script/prototype.js"/>"></script>
+</head>
+<body>
+
+<div id="tFfBc" style="opacity:0;">
+ <img src="/coverArt.view?size=200" alt="">
+</div>
+
+<ul>
+ <li><a href="#" onclick="new Effect.Opacity('tFfBc', { from: 1, to: 0 }); return false;">Hide this box</a></li>
+ <li><a href="#" onclick="new Effect.Opacity('tFfBc', { from: 0, to: 1 }); return false;">Show this box</a></li>
+</ul>
+
+</body>
+</html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/top.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/top.jsp new file mode 100644 index 00000000..18acb053 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/top.jsp @@ -0,0 +1,98 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<html><head>
+ <%@ include file="head.jsp" %>
+</head>
+
+<body class="bgcolor2 topframe" style="margin:0.4em 1em 0.4em 1em">
+
+<fmt:message key="top.home" var="home"/>
+<fmt:message key="top.now_playing" var="nowPlaying"/>
+<fmt:message key="top.starred" var="starred"/>
+<fmt:message key="top.settings" var="settings"/>
+<fmt:message key="top.status" var="status"/>
+<fmt:message key="top.podcast" var="podcast"/>
+<fmt:message key="top.more" var="more"/>
+<fmt:message key="top.help" var="help"/>
+<fmt:message key="top.search" var="search"/>
+
+<table style="margin:0"><tr valign="middle">
+ <td class="logo" style="padding-right:2em"><a href="help.view?" target="main"><img src="<spring:theme code="logoImage"/>" title="${help}" alt=""></a></td>
+
+ <c:if test="${not model.musicFoldersExist}">
+ <td style="padding-right:2em">
+ <p class="warning"><fmt:message key="top.missing"/></p>
+ </td>
+ </c:if>
+
+ <td>
+ <table><tr align="center">
+ <td style="min-width:4em;padding-right:1.5em">
+ <a href="home.view?" target="main"><img src="<spring:theme code="homeImage"/>" title="${home}" alt="${home}"></a><br>
+ <a href="home.view?" target="main">${home}</a>
+ </td>
+ <td style="min-width:4em;padding-right:1.5em">
+ <a href="nowPlaying.view?" target="main"><img src="<spring:theme code="nowPlayingImage"/>" title="${nowPlaying}" alt="${nowPlaying}"></a><br>
+ <a href="nowPlaying.view?" target="main">${nowPlaying}</a>
+ </td>
+ <td style="min-width:4em;padding-right:1.5em">
+ <a href="starred.view?" target="main"><img src="<spring:theme code="starredImage"/>" title="${starred}" alt="${starred}"></a><br>
+ <a href="starred.view?" target="main">${starred}</a>
+ </td>
+ <td style="min-width:4em;padding-right:1.5em">
+ <a href="podcastReceiver.view?" target="main"><img src="<spring:theme code="podcastLargeImage"/>" title="${podcast}" alt="${podcast}"></a><br>
+ <a href="podcastReceiver.view?" target="main">${podcast}</a>
+ </td>
+ <c:if test="${model.user.settingsRole}">
+ <td style="min-width:4em;padding-right:1.5em">
+ <a href="settings.view?" target="main"><img src="<spring:theme code="settingsImage"/>" title="${settings}" alt="${settings}"></a><br>
+ <a href="settings.view?" target="main">${settings}</a>
+ </td>
+ </c:if>
+ <td style="min-width:4em;padding-right:1.5em">
+ <a href="status.view?" target="main"><img src="<spring:theme code="statusImage"/>" title="${status}" alt="${status}"></a><br>
+ <a href="status.view?" target="main">${status}</a>
+ </td>
+ <td style="min-width:4em;padding-right:1.5em">
+ <a href="more.view?" target="main"><img src="<spring:theme code="moreImage"/>" title="${more}" alt="${more}"></a><br>
+ <a href="more.view?" target="main">${more}</a>
+ </td>
+ <td style="min-width:4em;padding-right:1.5em">
+ <a href="help.view?" target="main"><img src="<spring:theme code="helpImage"/>" title="${help}" alt="${help}"></a><br>
+ <a href="help.view?" target="main">${help}</a>
+ </td>
+
+ <td style="padding-left:1em">
+ <form method="post" action="search.view" target="main" name="searchForm">
+ <table><tr>
+ <td><input type="text" name="query" id="query" size="28" value="${search}" onclick="select();"></td>
+ <td><a href="javascript:document.searchForm.submit()"><img src="<spring:theme code="searchImage"/>" alt="${search}" title="${search}"></a></td>
+ </tr></table>
+ </form>
+ </td>
+
+ <td style="padding-left:15pt;text-align:center;">
+ <p class="detail" style="line-height:1.5">
+ <a href="j_acegi_logout" target="_top"><fmt:message key="top.logout"><fmt:param value="${model.user.username}"/></fmt:message></a>
+ <c:if test="${not model.licensed}">
+ <br>
+ <a href="donate.view" target="main"><img src="<spring:theme code="donateSmallImage"/>" alt=""></a>
+ <a href="donate.view" target="main"><fmt:message key="donate.title"/></a>
+ </c:if>
+ </p>
+ </td>
+
+ <c:if test="${model.newVersionAvailable}">
+ <td style="padding-left:15pt">
+ <p class="warning">
+ <fmt:message key="top.upgrade"><fmt:param value="${model.brand}"/><fmt:param value="${model.latestVersion}"/></fmt:message>
+ </p>
+ </td>
+ </c:if>
+ </tr></table>
+ </td>
+
+</tr></table>
+
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/transcodingSettings.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/transcodingSettings.jsp new file mode 100644 index 00000000..a641cb53 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/transcodingSettings.jsp @@ -0,0 +1,70 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+</head>
+<body class="mainframe bgcolor1">
+
+<c:import url="settingsHeader.jsp">
+ <c:param name="cat" value="transcoding"/>
+</c:import>
+
+<form method="post" action="transcodingSettings.view">
+<table class="indent">
+ <tr>
+ <th><fmt:message key="transcodingsettings.name"/></th>
+ <th><fmt:message key="transcodingsettings.sourceformat"/></th>
+ <th><fmt:message key="transcodingsettings.targetformat"/></th>
+ <th><fmt:message key="transcodingsettings.step1"/></th>
+ <th><fmt:message key="transcodingsettings.step2"/></th>
+ <th style="padding-left:1em"><fmt:message key="common.delete"/></th>
+ </tr>
+
+ <c:forEach items="${model.transcodings}" var="transcoding">
+ <tr>
+ <td><input style="font-family:monospace" type="text" name="name[${transcoding.id}]" size="10" value="${transcoding.name}"/></td>
+ <td><input style="font-family:monospace" type="text" name="sourceFormats[${transcoding.id}]" size="36" value="${transcoding.sourceFormats}"/></td>
+ <td><input style="font-family:monospace" type="text" name="targetFormat[${transcoding.id}]" size="10" value="${transcoding.targetFormat}"/></td>
+ <td><input style="font-family:monospace" type="text" name="step1[${transcoding.id}]" size="60" value="${transcoding.step1}"/></td>
+ <td><input style="font-family:monospace" type="text" name="step2[${transcoding.id}]" size="22" value="${transcoding.step2}"/></td>
+ <td align="center" style="padding-left:1em"><input type="checkbox" name="delete[${transcoding.id}]" class="checkbox"/></td>
+ </tr>
+ </c:forEach>
+
+ <tr>
+ <th colspan="6" align="left" style="padding-top:1em"><fmt:message key="transcodingsettings.add"/></th>
+ </tr>
+
+ <tr>
+ <td><input style="font-family:monospace" type="text" name="name" size="10" value="${model.newTranscoding.name}"/></td>
+ <td><input style="font-family:monospace" type="text" name="sourceFormats" size="36" value="${model.newTranscoding.sourceFormats}"/></td>
+ <td><input style="font-family:monospace" type="text" name="targetFormat" size="10" value="${model.newTranscoding.targetFormat}"/></td>
+ <td><input style="font-family:monospace" type="text" name="step1" size="60" value="${model.newTranscoding.step1}"/></td>
+ <td><input style="font-family:monospace" type="text" name="step2" size="22" value="${model.newTranscoding.step2}"/></td>
+ <td/>
+ </tr>
+
+ <tr>
+ <td colspan="6" style="padding-top:0.1em">
+ <input type="checkbox" id="defaultActive" name="defaultActive" class="checkbox" checked/>
+ <label for="defaultActive"><fmt:message key="transcodingsettings.defaultactive"/></label>
+ </td>
+ </tr>
+</table>
+
+ <p style="padding-top:0.75em">
+ <input type="submit" value="<fmt:message key="common.save"/>" style="margin-right:0.3em">
+ <input type="button" value="<fmt:message key="common.cancel"/>" onclick="location.href='nowPlaying.view'" style="margin-right:1.3em">
+ <a href="http://www.subsonic.org/pages/transcoding.jsp" target="_blank"><fmt:message key="transcodingsettings.recommended"/></a>
+ </p>
+
+</form>
+
+<c:if test="${not empty model.error}">
+ <p class="warning"><fmt:message key="${model.error}"/></p>
+</c:if>
+
+<div style="width:60%">
+ <fmt:message key="transcodingsettings.info"><fmt:param value="${model.transcodeDirectory}"/><fmt:param value="${model.brand}"/></fmt:message>
+</div>
+</body></html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/upload.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/upload.jsp new file mode 100644 index 00000000..eb79d17c --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/upload.jsp @@ -0,0 +1,29 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+</head><body>
+
+<h1><fmt:message key="upload.title"/></h1>
+
+<c:forEach items="${model.uploadedFiles}" var="file">
+ <p><fmt:message key="upload.success"><fmt:param value="${file.path}"/></fmt:message></p>
+</c:forEach>
+
+<c:forEach items="${model.unzippedFiles}" var="file">
+ <fmt:message key="upload.unzipped"><fmt:param value="${file.path}"/></fmt:message><br/>
+</c:forEach>
+
+<c:choose>
+ <c:when test="${not empty model.exception}">
+ <p><fmt:message key="upload.failed"><fmt:param value="${model.exception.message}"/></fmt:message></p>
+ </c:when>
+ <c:when test="${empty model.uploadedFiles}">
+ <p><fmt:message key="upload.empty"/></p>
+ </c:when>
+</c:choose>
+
+<div class="back"><a href="more.view?"><fmt:message key="common.back"/></a></div>
+</body></html>
+
+
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/userSettings.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/userSettings.jsp new file mode 100644 index 00000000..a26c9113 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/userSettings.jsp @@ -0,0 +1,201 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<html><head>
+ <%@ include file="head.jsp" %>
+ <script type="text/javascript" src="<c:url value="/script/scripts.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/prototype.js"/>"></script>
+</head>
+
+<body class="mainframe bgcolor1" onload="enablePasswordChangeFields();">
+<script type="text/javascript" src="<c:url value="/script/wz_tooltip.js"/>"></script>
+<script type="text/javascript" src="<c:url value="/script/tip_balloon.js"/>"></script>
+
+<c:import url="settingsHeader.jsp">
+ <c:param name="cat" value="user"/>
+</c:import>
+
+<script type="text/javascript" language="javascript">
+ function enablePasswordChangeFields() {
+ var changePasswordCheckbox = $("passwordChange");
+ var ldapCheckbox = $("ldapAuthenticated");
+ var passwordChangeTable = $("passwordChangeTable");
+ var passwordChangeCheckboxTable = $("passwordChangeCheckboxTable");
+
+ if (changePasswordCheckbox && changePasswordCheckbox.checked && (ldapCheckbox == null || !ldapCheckbox.checked)) {
+ passwordChangeTable.show();
+ } else {
+ passwordChangeTable.hide();
+ }
+
+ if (changePasswordCheckbox) {
+ if (ldapCheckbox && ldapCheckbox.checked) {
+ passwordChangeCheckboxTable.hide();
+ } else {
+ passwordChangeCheckboxTable.show();
+ }
+ }
+ }
+</script>
+
+<table class="indent">
+ <tr>
+ <td><b><fmt:message key="usersettings.title"/></b></td>
+ <td>
+ <select name="username" onchange="location='userSettings.view?userIndex=' + (selectedIndex - 1);">
+ <option value="">-- <fmt:message key="usersettings.newuser"/> --</option>
+ <c:forEach items="${command.users}" var="user">
+ <option ${user.username eq command.username ? "selected" : ""}
+ value="${user.username}">${user.username}</option>
+ </c:forEach>
+ </select>
+ </td>
+ </tr>
+</table>
+
+<p/>
+
+<form:form method="post" action="userSettings.view" commandName="command">
+ <c:if test="${not command.admin}">
+ <table>
+ <tr>
+ <td><form:checkbox path="adminRole" id="admin" cssClass="checkbox"/></td>
+ <td><label for="admin"><fmt:message key="usersettings.admin"/></label></td>
+ </tr>
+ <tr>
+ <td><form:checkbox path="settingsRole" id="settings" cssClass="checkbox"/></td>
+ <td><label for="settings"><fmt:message key="usersettings.settings"/></label></td>
+ </tr>
+ <tr>
+ <td style="padding-top:1em"><form:checkbox path="streamRole" id="stream" cssClass="checkbox"/></td>
+ <td style="padding-top:1em"><label for="stream"><fmt:message key="usersettings.stream"/></label></td>
+ </tr>
+ <tr>
+ <td><form:checkbox path="jukeboxRole" id="jukebox" cssClass="checkbox"/></td>
+ <td><label for="jukebox"><fmt:message key="usersettings.jukebox"/></label></td>
+ </tr>
+ <tr>
+ <td><form:checkbox path="downloadRole" id="download" cssClass="checkbox"/></td>
+ <td><label for="download"><fmt:message key="usersettings.download"/></label></td>
+ </tr>
+ <tr>
+ <td><form:checkbox path="uploadRole" id="upload" cssClass="checkbox"/></td>
+ <td><label for="upload"><fmt:message key="usersettings.upload"/></label></td>
+ </tr>
+ <tr>
+ <td><form:checkbox path="shareRole" id="share" cssClass="checkbox"/></td>
+ <td><label for="share"><fmt:message key="usersettings.share"/></label></td>
+ </tr>
+ <tr>
+ <td><form:checkbox path="coverArtRole" id="coverArt" cssClass="checkbox"/></td>
+ <td><label for="coverArt"><fmt:message key="usersettings.coverart"/></label></td>
+ </tr>
+ <tr>
+ <td><form:checkbox path="commentRole" id="comment" cssClass="checkbox"/></td>
+ <td><label for="comment"><fmt:message key="usersettings.comment"/></label></td>
+ </tr>
+ <tr>
+ <td><form:checkbox path="podcastRole" id="podcast" cssClass="checkbox"/></td>
+ <td><label for="podcast"><fmt:message key="usersettings.podcast"/></label></td>
+ </tr>
+ </table>
+ </c:if>
+
+ <table class="indent">
+ <tr>
+ <td><fmt:message key="playersettings.maxbitrate"/></td>
+ <td>
+ <form:select path="transcodeSchemeName" cssStyle="width:8em">
+ <c:forEach items="${command.transcodeSchemeHolders}" var="transcodeSchemeHolder">
+ <form:option value="${transcodeSchemeHolder.name}" label="${transcodeSchemeHolder.description}"/>
+ </c:forEach>
+ </form:select>
+ </td>
+ <td><c:import url="helpToolTip.jsp"><c:param name="topic" value="transcode"/></c:import></td>
+ <c:if test="${not command.transcodingSupported}">
+ <td class="warning"><fmt:message key="playersettings.nolame"/></td>
+ </c:if>
+ </tr>
+ </table>
+
+ <c:if test="${not command.new and not command.admin}">
+ <table class="indent">
+ <tr>
+ <td><form:checkbox path="delete" id="delete" cssClass="checkbox"/></td>
+ <td><label for="delete"><fmt:message key="usersettings.delete"/></label></td>
+ </tr>
+ </table>
+ </c:if>
+
+ <c:if test="${command.ldapEnabled and not command.admin}">
+ <table>
+ <tr>
+ <td><form:checkbox path="ldapAuthenticated" id="ldapAuthenticated" cssClass="checkbox" onclick="javascript:enablePasswordChangeFields()"/></td>
+ <td><label for="ldapAuthenticated"><fmt:message key="usersettings.ldap"/></label></td>
+ <td><c:import url="helpToolTip.jsp"><c:param name="topic" value="ldap"/></c:import></td>
+ </tr>
+ </table>
+ </c:if>
+
+ <c:choose>
+ <c:when test="${command.new}">
+
+ <table class="indent">
+ <tr>
+ <td><fmt:message key="usersettings.username"/></td>
+ <td><form:input path="username"/></td>
+ <td class="warning"><form:errors path="username"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="usersettings.email"/></td>
+ <td><form:input path="email"/></td>
+ <td class="warning"><form:errors path="email"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="usersettings.password"/></td>
+ <td><form:password path="password"/></td>
+ <td class="warning"><form:errors path="password"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="usersettings.confirmpassword"/></td>
+ <td><form:password path="confirmPassword"/></td>
+ <td/>
+ </tr>
+ </table>
+ </c:when>
+
+ <c:otherwise>
+ <table id="passwordChangeCheckboxTable">
+ <tr>
+ <td><form:checkbox path="passwordChange" id="passwordChange" onclick="enablePasswordChangeFields();" cssClass="checkbox"/></td>
+ <td><label for="passwordChange"><fmt:message key="usersettings.changepassword"/></label></td>
+ </tr>
+ </table>
+
+ <table id="passwordChangeTable" style="display:none">
+ <tr>
+ <td><fmt:message key="usersettings.newpassword"/></td>
+ <td><form:password path="password" id="path"/></td>
+ <td class="warning"><form:errors path="password"/></td>
+ </tr>
+ <tr>
+ <td><fmt:message key="usersettings.confirmpassword"/></td>
+ <td><form:password path="confirmPassword" id="confirmPassword"/></td>
+ <td/>
+ </tr>
+ </table>
+
+ <table>
+ <tr>
+ <td><fmt:message key="usersettings.email"/></td>
+ <td><form:input path="email"/></td>
+ <td class="warning"><form:errors path="email"/></td>
+ </tr>
+ </table>
+ </c:otherwise>
+ </c:choose>
+
+ <input type="submit" value="<fmt:message key="common.save"/>" style="margin-top:1.5em;margin-right:0.3em">
+ <input type="button" value="<fmt:message key="common.cancel"/>" onclick="location.href='nowPlaying.view'" style="margin-top:1.5em">
+</form:form>
+
+</body></html>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/videoPlayer.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/videoPlayer.jsp new file mode 100644 index 00000000..681a41a8 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/videoPlayer.jsp @@ -0,0 +1,190 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<html>
+<head>
+ <%@ include file="head.jsp" %>
+
+ <sub:url value="videoPlayer.view" var="baseUrl"><sub:param name="id" value="${model.video.id}"/></sub:url>
+ <sub:url value="main.view" var="backUrl"><sub:param name="id" value="${model.video.id}"/></sub:url>
+
+ <sub:url value="/stream" var="streamUrl">
+ <sub:param name="id" value="${model.video.id}"/>
+ </sub:url>
+
+ <script type="text/javascript" src="<c:url value="/script/swfobject.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/prototype.js"/>"></script>
+ <script type="text/javascript" src="<c:url value="/script/scripts.js"/>"></script>
+ <script type="text/javascript" language="javascript">
+
+ var player;
+ var position;
+ var maxBitRate = ${model.maxBitRate};
+ var timeOffset = ${model.timeOffset};
+
+ function init() {
+
+ var flashvars = {
+ id:"player1",
+ skin:"<c:url value="/flash/whotube.zip"/>",
+// plugins:"metaviewer-1",
+ screencolor:"000000",
+ controlbar:"over",
+ autostart:"false",
+ bufferlength:3,
+ backcolor:"<spring:theme code="backgroundColor"/>",
+ frontcolor:"<spring:theme code="textColor"/>",
+ provider:"video"
+ };
+ var params = {
+ allowfullscreen:"true",
+ allowscriptaccess:"always"
+ };
+ var attributes = {
+ id:"player1",
+ name:"player1"
+ };
+
+ var width = "${model.popout ? '100%' : '600'}";
+ var height = "${model.popout ? '85%' : '360'}";
+ swfobject.embedSWF("<c:url value="/flash/jw-player-5.6.swf"/>", "placeholder1", width, height, "9.0.0", false, flashvars, params, attributes);
+ }
+
+ function playerReady(thePlayer) {
+ player = $("player1");
+ player.addModelListener("TIME", "timeListener");
+
+ <c:if test="${not (model.trial and model.trialExpired)}">
+ play();
+ </c:if>
+ }
+
+ function play() {
+ var list = new Array();
+ list[0] = {
+ file:"${streamUrl}&maxBitRate=" + maxBitRate + "&timeOffset=" + timeOffset + "&player=${model.player}",
+ duration:${model.duration} - timeOffset,
+ provider:"video"
+ };
+ player.sendEvent("LOAD", list);
+ player.sendEvent("PLAY");
+ }
+
+ function timeListener(obj) {
+ var newPosition = Math.round(obj.position);
+ if (newPosition != position) {
+ position = newPosition;
+ updatePosition();
+ }
+ }
+
+ function updatePosition() {
+ var pos = getPosition();
+
+ var minutes = Math.round(pos / 60);
+ var seconds = pos % 60;
+
+ var result = minutes + ":";
+ if (seconds < 10) {
+ result += "0";
+ }
+ result += seconds;
+ $("position").innerHTML = result;
+ }
+
+ function changeTimeOffset() {
+ timeOffset = $("timeOffset").getValue();
+ play();
+ }
+
+ function changeBitRate() {
+ maxBitRate = $("maxBitRate").getValue();
+ timeOffset = getPosition();
+ play();
+ }
+
+ function popout() {
+ var url = "${baseUrl}&maxBitRate=" + maxBitRate + "&timeOffset=" + getPosition() + "&popout=true";
+ popupSize(url, "video", 600, 400);
+ window.location.href = "${backUrl}";
+ }
+
+ function popin() {
+ window.opener.location.href = "${baseUrl}&maxBitRate=" + maxBitRate + "&timeOffset=" + getPosition();
+ window.close();
+ }
+
+ function getPosition() {
+ return parseInt(timeOffset) + parseInt(position);
+ }
+
+ </script>
+</head>
+
+<body class="mainframe bgcolor1" style="padding-bottom:0.5em" onload="init();">
+<c:if test="${not model.popout}">
+ <h1>${model.video.title}</h1>
+</c:if>
+
+<c:if test="${model.trial}">
+ <fmt:formatDate value="${model.trialExpires}" dateStyle="long" var="expiryDate"/>
+
+ <p class="warning" style="padding-top:1em">
+ <c:choose>
+ <c:when test="${model.trialExpired}">
+ <fmt:message key="networksettings.trialexpired"><fmt:param>${expiryDate}</fmt:param></fmt:message>
+ </c:when>
+ <c:otherwise>
+ <fmt:message
+ key="networksettings.trialnotexpired"><fmt:param>${expiryDate}</fmt:param></fmt:message>
+ </c:otherwise>
+ </c:choose>
+ </p>
+</c:if>
+
+
+<div id="wrapper" style="padding-top:1em">
+ <div id="placeholder1"><a href="http://www.adobe.com/go/getflashplayer" target="_blank"><fmt:message key="playlist.getflash"/></a></div>
+</div>
+
+<div style="padding-top:0.7em;padding-bottom:0.7em">
+
+ <span id="position" style="padding-right:0.5em">0:00</span>
+ <select id="timeOffset" onchange="changeTimeOffset();" style="padding-left:0.25em;padding-right:0.25em;margin-right:0.5em">
+ <c:forEach items="${model.skipOffsets}" var="skipOffset">
+ <c:choose>
+ <c:when test="${skipOffset.value - skipOffset.value mod 60 eq model.timeOffset - model.timeOffset mod 60}">
+ <option selected="selected" value="${skipOffset.value}">${skipOffset.key}</option>
+ </c:when>
+ <c:otherwise>
+ <option value="${skipOffset.value}">${skipOffset.key}</option>
+ </c:otherwise>
+ </c:choose>
+ </c:forEach>
+ </select>
+
+ <select id="maxBitRate" onchange="changeBitRate();" style="padding-left:0.25em;padding-right:0.25em;margin-right:0.5em">
+ <c:forEach items="${model.bitRates}" var="bitRate">
+ <c:choose>
+ <c:when test="${bitRate eq model.maxBitRate}">
+ <option selected="selected" value="${bitRate}">${bitRate} Kbps</option>
+ </c:when>
+ <c:otherwise>
+ <option value="${bitRate}">${bitRate} Kbps</option>
+ </c:otherwise>
+ </c:choose>
+ </c:forEach>
+ </select>
+</div>
+
+<c:choose>
+ <c:when test="${model.popout}">
+ <div class="back"><a href="javascript:popin();"><fmt:message key="common.back"/></a></div>
+ </c:when>
+ <c:otherwise>
+ <div class="back" style="float:left;padding-right:2em"><a href="${backUrl}"><fmt:message key="common.back"/></a></div>
+ <div class="forward" style="float:left;"><a href="javascript:popout();"><fmt:message key="videoPlayer.popout"/></a></div>
+ </c:otherwise>
+</c:choose>
+
+</body>
+</html>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/browse.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/browse.jsp new file mode 100644 index 00000000..ac1ce096 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/browse.jsp @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
+
+<%@ page language="java" contentType="text/vnd.wap.wml; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<wml>
+
+ <%@ include file="head.jsp" %>
+
+ <card id="main" title="Subsonic" newcontext="false">
+
+ <p><small><b>
+
+ <sub:url value="/wap/playlist.view" var="playUrl">
+ <sub:param name="play" value="${model.parent.path}"/>
+ </sub:url>
+ <sub:url value="/wap/playlist.view" var="addUrl">
+ <sub:param name="add" value="${model.parent.path}"/>
+ </sub:url>
+ <sub:url value="/wap/download.view" var="downloadUrl">
+ <sub:param name="path" value="${model.parent.path}"/>
+ </sub:url>
+
+ <c:choose>
+ <c:when test="${fn:length(model.children) eq 1 and model.children[0].file}">
+ <a href="${playUrl}">[<fmt:message key="wap.browse.playone"/>]</a><br/>
+ <a href="${addUrl}">[<fmt:message key="wap.browse.addone"/>]</a><br/>
+ <c:if test="${model.user.downloadRole}">
+ <a href="${downloadUrl}">[<fmt:message key="wap.browse.downloadone"/>]</a><br/>
+ </c:if>
+ </c:when>
+ <c:otherwise>
+ <a href="${playUrl}">[<fmt:message key="wap.browse.playall"/>]</a><br/>
+ <a href="${addUrl}">[<fmt:message key="wap.browse.addall"/>]</a><br/>
+ <c:if test="${model.user.downloadRole}">
+ <a href="${downloadUrl}">[<fmt:message key="wap.browse.downloadall"/>]</a><br/>
+ </c:if>
+ </c:otherwise>
+ </c:choose>
+
+ <a href="<c:url value="/wap/index.view"/>">[<fmt:message key="common.home"/>]</a><br/>
+ </b></small></p>
+
+ <p><small>
+
+ <c:forEach items="${model.children}" var="child">
+ <sub:url value="/wap/browse.view" var="browseUrl">
+ <sub:param name="path" value="${child.path}"/>
+ </sub:url>
+ <a href="${browseUrl}">${fn:escapeXml(child.title)}</a><br/>
+ </c:forEach>
+
+ </small></p>
+ </card>
+</wml>
+
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/head.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/head.jsp new file mode 100644 index 00000000..d902de1d --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/head.jsp @@ -0,0 +1,10 @@ +<%@ include file="../include.jsp" %>
+
+<head>
+ <meta http-equiv="Cache-Control" content="max-age=0" forua="true"/>
+ <meta http-equiv="Cache-Control" content="must-revalidate" forua="true"/>
+</head>
+
+<template>
+ <do type="prev" name="back" label="<fmt:message key="common.back"/>"><prev/></do>
+</template>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/index.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/index.jsp new file mode 100644 index 00000000..2773a55e --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/index.jsp @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
+
+<%@ page language="java" contentType="text/vnd.wap.wml; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<wml>
+
+ <%@ include file="head.jsp" %>
+
+ <card id="main" title="Subsonic" newcontext="false">
+ <p>
+ <small>
+
+ <c:choose>
+ <c:when test="${empty model.artists}">
+
+ <b>
+ <a href="<c:url value="/wap/playlist.view"/>">[<fmt:message key="wap.index.playlist"/>]</a>
+ </b>
+ <br/>
+ <b>
+ <a href="<c:url value="/wap/search.view"/>">[<fmt:message key="wap.index.search"/>]</a>
+ </b>
+ <br/>
+ <b>
+ <a href="<c:url value="/wap/settings.view"/>">[<fmt:message key="wap.index.settings"/>]</a>
+ </b>
+ <br/>
+ </small>
+ </p>
+ <p>
+ <small>
+ <c:forEach items="${model.indexes}" var="index">
+ <sub:url var="url" value="/wap/index.view">
+ <sub:param name="index" value="${index.index}"/>
+ </sub:url>
+ <a href="${url}">${index.index}</a>
+ </c:forEach>
+ </c:when>
+
+ <c:otherwise>
+ <c:forEach items="${model.artists}" var="artist">
+ <c:forEach items="${artist.musicFiles}" var="mediaFile">
+ <sub:url var="url" value="/wap/browse.view">
+ <sub:param name="path" value="${mediaFile.path}"/>
+ </sub:url>
+ <a href="${url}">${fn:escapeXml(mediaFile.title)}</a>
+ <br/>
+ </c:forEach>
+ </c:forEach>
+ </c:otherwise>
+ </c:choose>
+
+ <c:if test="${model.noMusic}">
+ <fmt:message key="wap.index.missing"/>
+ </c:if>
+
+ </small>
+ </p>
+ </card>
+</wml>
+
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/loadPlaylist.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/loadPlaylist.jsp new file mode 100644 index 00000000..2640cce0 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/loadPlaylist.jsp @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
+
+<%@ page language="java" contentType="text/vnd.wap.wml; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<wml>
+
+ <%@ include file="head.jsp" %>
+
+ <card id="main" title="Subsonic" newcontext="false">
+ <p><small>
+
+ <c:forEach items="${model.playlists}" var="playlist">
+ <sub:url var="url" value="/wap/playlist.view">
+ <sub:param name="load" value="${playlist.id}"/>
+ </sub:url>
+ <b><a href="${url}">${fn:escapeXml(playlist.name)}</a></b><br/>
+ </c:forEach>
+ </small></p>
+
+ </card>
+</wml>
+
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/playlist.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/playlist.jsp new file mode 100644 index 00000000..481e00d3 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/playlist.jsp @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
+
+<%@ page language="java" contentType="text/vnd.wap.wml; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<wml>
+
+ <%@ include file="head.jsp" %>
+
+ <c:if test="${fn:length(model.players) eq 1}">
+ <c:choose>
+ <c:when test="${empty model.players[0].name}">
+ <c:set var="playerName" value=" - Player ${model.players[0].id}"/>
+ </c:when>
+ <c:otherwise>
+ <c:set var="playerName" value=" - ${model.players[0].name}"/>
+ </c:otherwise>
+ </c:choose>
+ </c:if>
+
+
+ <card id="main" title="Subsonic" newcontext="false">
+ <p><small><b><fmt:message key="wap.playlist.title"/>${playerName}</b></small></p>
+ <p><small>
+
+ <c:choose>
+ <c:when test="${empty model.players}">
+ <fmt:message key="wap.playlist.noplayer"/>
+ </c:when>
+ <c:otherwise>
+ <b><a href="<c:url value="/wap/index.view"/>">[<fmt:message key="common.home"/>]</a></b><br/>
+ <b><a href="<c:url value="/wap/loadPlaylist.view"/>">[<fmt:message key="wap.playlist.load"/>]</a></b><br/>
+ <b><a href="<c:url value="/wap/playlist.view?random"/>">[<fmt:message key="wap.playlist.random"/>]</a></b><br/>
+
+ <c:set var="playlist" value="${model.players[0].playlist}"/>
+
+ <c:if test="${not empty playlist.files}">
+ <b><a href="<c:url value="/play.m3u"/>">[<fmt:message key="wap.playlist.play"/>]</a></b><br/>
+ <b><a href="<c:url value="/wap/playlist.view?clear"/>">[<fmt:message key="wap.playlist.clear"/>]</a></b><br/>
+ </small></p>
+ <p><small>
+
+ <c:forEach items="${playlist.files}" var="file" varStatus="loopStatus">
+ <c:set var="isCurrent" value="${(file eq playlist.currentFile) and (loopStatus.count - 1 eq playlist.index)}"/>
+ ${isCurrent ? "<b>" : ""}
+ <a href="<c:url value="/wap/playlist.view?skip=${loopStatus.count - 1}"/>">${fn:escapeXml(file.title)}</a>
+ ${isCurrent ? "</b>" : ""}
+ <br/>
+ </c:forEach>
+ </c:if>
+ </c:otherwise>
+ </c:choose>
+ </small></p>
+ </card>
+</wml>
+
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/search.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/search.jsp new file mode 100644 index 00000000..b35b04a3 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/search.jsp @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
+
+<%@ page language="java" contentType="text/vnd.wap.wml; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<wml>
+ <%@ include file="head.jsp" %>
+ <card id="main" title="Subsonic" newcontext="false">
+ <p>
+ <input name="query" value="" size="10"/>
+ <anchor><fmt:message key="wap.search.title"/>
+ <go href="<c:url value="/wap/searchResult.view"/>" method="get">
+ <postfield name="query" value="$query"/>
+ </go>
+ </anchor>
+ </p>
+ </card>
+</wml>
+
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/searchResult.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/searchResult.jsp new file mode 100644 index 00000000..2267c069 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/searchResult.jsp @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
+
+<%@ page language="java" contentType="text/vnd.wap.wml; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<wml>
+
+ <%@ include file="head.jsp" %>
+ <card id="main" title="Subsonic" newcontext="false">
+ <p><small>
+
+ <c:choose>
+ <c:when test="${model.creatingIndex}">
+ <fmt:message key="wap.searchresult.index"/>
+ </c:when>
+
+ <c:otherwise>
+ <c:forEach items="${model.hits}" var="hit">
+ <sub:url var="url" value="/wap/browse.view">
+ <sub:param name="path" value="${hit.path}"/>
+ </sub:url>
+ <a href="${url}">${fn:escapeXml(hit.title)}</a><br/>
+ </c:forEach>
+ </c:otherwise>
+ </c:choose>
+ </small></p>
+ </card>
+
+</wml>
+
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/settings.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/settings.jsp new file mode 100644 index 00000000..5c44e87d --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/wap/settings.jsp @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
+
+<%@ page language="java" contentType="text/vnd.wap.wml; charset=utf-8" pageEncoding="iso-8859-1"%>
+
+<wml>
+
+ <%@ include file="head.jsp" %>
+ <card id="main" title="Subsonic" newcontext="false">
+ <p><small>
+ <b><a href="<c:url value="/wap/index.view"/>">[<fmt:message key="common.home"/>]</a><br/></b>
+ <b><a href="#player">[<fmt:message key="wap.settings.selectplayer"/>]</a></b>
+ </small></p>
+ </card>
+
+ <card id="player" title="Subsonic" newcontext="false">
+ <p><small>
+
+ <b><a href="<c:url value="/wap/index.view"/>">[<fmt:message key="common.home"/>]</a><br/></b>
+ </small></p><p><small>
+
+ <c:choose>
+ <c:when test="${empty model.playerId}">
+ <fmt:message key="wap.settings.allplayers"/>
+ </c:when>
+ <c:otherwise>
+ <a href="<c:url value="/wap/selectPlayer.view"/>"><fmt:message key="wap.settings.allplayers"/></a>
+ </c:otherwise>
+ </c:choose>
+ <br/>
+
+ <c:forEach items="${model.players}" var="player">
+ <c:choose>
+ <c:when test="${player.id eq model.playerId}">
+ ${player}
+ </c:when>
+ <c:otherwise>
+ <a href="<c:url value="/wap/selectPlayer.view?playerId=${player.id}"/>">${player}</a>
+ </c:otherwise>
+ </c:choose>
+ <br/>
+ </c:forEach>
+ </small></p>
+ </card>
+
+</wml>
+
diff --git a/subsonic-main/src/main/webapp/WEB-INF/jsp/xspfPlaylist.jsp b/subsonic-main/src/main/webapp/WEB-INF/jsp/xspfPlaylist.jsp new file mode 100644 index 00000000..4ee8fb46 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/jsp/xspfPlaylist.jsp @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?>
+<%@ include file="include.jsp" %>
+<%@ page language="java" contentType="text/xml; charset=utf-8" pageEncoding="iso-8859-1" %>
+
+<playlist version="0" xmlns="http://xspf.org/ns/0/">
+ <trackList>
+
+<c:forEach var="song" items="${model.songs}">
+
+ <sub:url value="/stream" var="streamUrl">
+ <sub:param name="path" value="${song.musicFile.path}"/>
+ </sub:url>
+
+ <sub:url value="coverArt.view" var="coverArtUrl">
+ <sub:param name="size" value="200"/>
+ <c:if test="${not empty song.coverArtFile}">
+ <sub:param name="path" value="${song.coverArtFile.path}"/>
+ </c:if>
+ </sub:url>
+
+ <track>
+ <location>${streamUrl}</location>
+ <image>${coverArtUrl}</image>
+ <annotation>${song.musicFile.metaData.artist} - ${song.musicFile.title}</annotation>
+ </track>
+
+</c:forEach>
+
+ </trackList>
+</playlist>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/sub.tld b/subsonic-main/src/main/webapp/WEB-INF/sub.tld new file mode 100644 index 00000000..ef712968 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/sub.tld @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?>
+
+<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
+ version="2.0">
+
+ <description>Subsonic tag library</description>
+ <display-name>Subsonic tag library</display-name>
+ <tlib-version>1.1</tlib-version>
+ <short-name>sub</short-name>
+ <uri>http://subsonic.org/taglib/sub</uri>
+
+ <tag>
+ <description>
+ Creates a URL with optional query parameters. Similar to 'c:url', but
+ you may specify which character encoding to use for the URL query
+ parameters. If no encoding is specified, the following steps are performed:
+ a) Parameter values are encoded as the hexadecimal representation of the UTF-8 bytes of the original string.
+ b) Parameter names are prepended with the suffix "Utf8Hex"
+ </description>
+ <name>url</name>
+ <tag-class>net.sourceforge.subsonic.taglib.UrlTag</tag-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>
+ Name of the exported scoped variable for the
+ processed url. The type of the scoped variable is
+ String.
+ </description>
+ <name>var</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>URL to be processed.</description>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>The encoding to use. Default is ISO-8859-1.</description>
+ <name>encoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <description>Adds a parameter to a containing 'url' tag.</description>
+ <name>param</name>
+ <tag-class>net.sourceforge.subsonic.taglib.ParamTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>Name of the query string parameter.</description>
+ <name>name</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>Value of the parameter.</description>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <description>
+ Converts a byte-count to a formatted string suitable for display to the user, with respect
+ to the current locale.
+ </description>
+ <name>formatBytes</name>
+ <tag-class>net.sourceforge.subsonic.taglib.FormatBytesTag</tag-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>The byte count.</description>
+ <name>bytes</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <description>
+ Renders a Wiki text with markup to HTML, using the Radeox render engine.
+ </description>
+ <name>wiki</name>
+ <tag-class>net.sourceforge.subsonic.taglib.WikiTag</tag-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>The Wiki markup text.</description>
+ <name>text</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <description>
+ Escapes the characters in a string using JavaScript rules.
+ </description>
+ <name>escapeJavaScript</name>
+ <tag-class>net.sourceforge.subsonic.taglib.EscapeJavaScriptTag</tag-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>The string to escape.</description>
+ <name>string</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+</taglib>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/WEB-INF/subsonic-servlet.xml b/subsonic-main/src/main/webapp/WEB-INF/subsonic-servlet.xml new file mode 100644 index 00000000..b36bb0c8 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/subsonic-servlet.xml @@ -0,0 +1,479 @@ +<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+ <bean id="leftController" class="net.sourceforge.subsonic.controller.LeftController">
+ <property name="viewName" value="left"/>
+ <property name="mediaScannerService" ref="mediaScannerService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="musicIndexService" ref="musicIndexService"/>
+ <property name="playerService" ref="playerService"/>
+ <property name="playlistService" ref="playlistService"/>
+ </bean>
+ <bean id="rightController" class="net.sourceforge.subsonic.controller.RightController">
+ <property name="viewName" value="right"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+ <bean id="statusController" class="net.sourceforge.subsonic.controller.StatusController">
+ <property name="viewName" value="status"/>
+ <property name="statusService" ref="statusService"/>
+ </bean>
+ <bean id="mainController" class="net.sourceforge.subsonic.controller.MainController">
+ <property name="viewName" value="main"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="playerService" ref="playerService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="ratingService" ref="musicInfoService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="adService" ref="adService"/>
+ </bean>
+ <bean id="playlistController" class="net.sourceforge.subsonic.controller.PlaylistController">
+ <property name="viewName" value="playlist"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="playlistService" ref="playlistService"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+ <bean id="importPlaylistController" class="net.sourceforge.subsonic.controller.ImportPlaylistController">
+ <property name="viewName" value="importPlaylist"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="playlistService" ref="playlistService"/>
+ </bean>
+ <bean id="topController" class="net.sourceforge.subsonic.controller.TopController">
+ <property name="viewName" value="top"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="versionService" ref="versionService"/>
+ <property name="securityService" ref="securityService"/>
+ </bean>
+ <bean id="helpController" class="net.sourceforge.subsonic.controller.HelpController">
+ <property name="viewName" value="help"/>
+ <property name="versionService" ref="versionService"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+ <bean id="moreController" class="net.sourceforge.subsonic.controller.MoreController">
+ <property name="viewName" value="more"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="playerService" ref="playerService"/>
+ </bean>
+ <bean id="uploadController" class="net.sourceforge.subsonic.controller.UploadController">
+ <property name="viewName" value="upload"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="statusService" ref="statusService"/>
+ <property name="playerService" ref="playerService"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+ <bean id="lyricsController" class="net.sourceforge.subsonic.controller.LyricsController">
+ <property name="viewName" value="lyrics"/>
+ </bean>
+ <bean id="allmusicController" class="net.sourceforge.subsonic.controller.AllmusicController">
+ <property name="viewName" value="allmusic"/>
+ </bean>
+ <bean id="podcastController" class="net.sourceforge.subsonic.controller.PodcastController">
+ <property name="viewName" value="podcast"/>
+ <property name="playlistService" ref="playlistService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="securityService" ref="securityService"/>
+ </bean>
+ <bean id="podcastReceiverController" class="net.sourceforge.subsonic.controller.PodcastReceiverController">
+ <property name="viewName" value="podcastReceiver"/>
+ <property name="podcastService" ref="podcastService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+ <bean id="podcastReceiverAdminController"
+ class="net.sourceforge.subsonic.controller.PodcastReceiverAdminController">
+ <property name="podcastService" ref="podcastService"/>
+ </bean>
+ <bean id="setMusicFileInfoController" class="net.sourceforge.subsonic.controller.SetMusicFileInfoController">
+ <property name="mediaFileService" ref="mediaFileService"/>
+ </bean>
+ <bean id="shareManagementController" class="net.sourceforge.subsonic.controller.ShareManagementController">
+ <property name="settingsService" ref="settingsService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="shareService" ref="shareService"/>
+ <property name="playerService" ref="playerService"/>
+ <property name="securityService" ref="securityService"/>
+ </bean>
+ <bean id="setRatingController" class="net.sourceforge.subsonic.controller.SetRatingController">
+ <property name="ratingService" ref="musicInfoService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="securityService" ref="securityService"/>
+ </bean>
+ <bean id="randomPlayQueueController" class="net.sourceforge.subsonic.controller.RandomPlayQueueController">
+ <property name="viewName" value="reload"/>
+ <property name="playerService" ref="playerService"/>
+ <property name="searchService" ref="searchService"/>
+ <property name="reloadFrames">
+ <list>
+ <bean class="net.sourceforge.subsonic.controller.ReloadFrame">
+ <property name="frame" value="playQueue"/>
+ <property name="view" value="playQueue.view?"/>
+ </bean>
+ <bean class="net.sourceforge.subsonic.controller.ReloadFrame">
+ <property name="frame" value="main"/>
+ <property name="view" value="more.view"/>
+ </bean>
+ </list>
+ </property>
+ </bean>
+ <bean id="changeCoverArtController" class="net.sourceforge.subsonic.controller.ChangeCoverArtController">
+ <property name="viewName" value="changeCoverArt"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ </bean>
+ <bean id="nowPlayingController" class="net.sourceforge.subsonic.controller.NowPlayingController">
+ <property name="playerService" ref="playerService"/>
+ <property name="statusService" ref="statusService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ </bean>
+ <bean id="starredController" class="net.sourceforge.subsonic.controller.StarredController">
+ <property name="viewName" value="starred"/>
+ <property name="playerService" ref="playerService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="mediaFileDao" ref="mediaFileDao"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ </bean>
+ <bean id="searchController" class="net.sourceforge.subsonic.controller.SearchController">
+ <property name="commandClass" value="net.sourceforge.subsonic.command.SearchCommand"/>
+ <property name="successView" value="search"/>
+ <property name="formView" value="search"/>
+ <property name="searchService" ref="searchService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="playerService" ref="playerService"/>
+ </bean>
+ <bean id="settingsController" class="net.sourceforge.subsonic.controller.SettingsController">
+ <property name="securityService" ref="securityService"/>
+ </bean>
+ <bean id="playerSettingsController" class="net.sourceforge.subsonic.controller.PlayerSettingsController">
+ <property name="commandClass" value="net.sourceforge.subsonic.command.PlayerSettingsCommand"/>
+ <property name="successView" value="playerSettings"/>
+ <property name="formView" value="playerSettings"/>
+ <property name="playerService" ref="playerService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="transcodingService" ref="transcodingService"/>
+ </bean>
+ <bean id="shareSettingsController" class="net.sourceforge.subsonic.controller.ShareSettingsController">
+ <property name="viewName" value="shareSettings"/>
+ <property name="shareService" ref="shareService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ </bean>
+ <bean id="musicFolderSettingsController" class="net.sourceforge.subsonic.controller.MusicFolderSettingsController">
+ <property name="commandClass" value="net.sourceforge.subsonic.command.MusicFolderSettingsCommand"/>
+ <property name="successView" value="musicFolderSettings"/>
+ <property name="formView" value="musicFolderSettings"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="mediaScannerService" ref="mediaScannerService"/>
+ <property name="artistDao" ref="artistDao"/>
+ <property name="albumDao" ref="albumDao"/>
+ <property name="mediaFolderDao" ref="mediaFileDao"/>
+ </bean>
+ <bean id="networkSettingsController" class="net.sourceforge.subsonic.controller.NetworkSettingsController">
+ <property name="commandClass" value="net.sourceforge.subsonic.command.NetworkSettingsCommand"/>
+ <property name="successView" value="networkSettings"/>
+ <property name="formView" value="networkSettings"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="networkService" ref="networkService"/>
+ </bean>
+ <bean id="transcodingSettingsController" class="net.sourceforge.subsonic.controller.TranscodingSettingsController">
+ <property name="viewName" value="transcodingSettings"/>
+ <property name="transcodingService" ref="transcodingService"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+ <bean id="internetRadioSettingsController"
+ class="net.sourceforge.subsonic.controller.InternetRadioSettingsController">
+ <property name="viewName" value="internetRadioSettings"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+ <bean id="podcastSettingsController" class="net.sourceforge.subsonic.controller.PodcastSettingsController">
+ <property name="commandClass" value="net.sourceforge.subsonic.command.PodcastSettingsCommand"/>
+ <property name="successView" value="podcastSettings"/>
+ <property name="formView" value="podcastSettings"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="podcastService" ref="podcastService"/>
+ </bean>
+ <bean id="generalSettingsController" class="net.sourceforge.subsonic.controller.GeneralSettingsController">
+ <property name="commandClass" value="net.sourceforge.subsonic.command.GeneralSettingsCommand"/>
+ <property name="successView" value="generalSettings"/>
+ <property name="formView" value="generalSettings"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+ <bean id="advancedSettingsController" class="net.sourceforge.subsonic.controller.AdvancedSettingsController">
+ <property name="commandClass" value="net.sourceforge.subsonic.command.AdvancedSettingsCommand"/>
+ <property name="successView" value="advancedSettings"/>
+ <property name="formView" value="advancedSettings"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+ <bean id="personalSettingsController" class="net.sourceforge.subsonic.controller.PersonalSettingsController">
+ <property name="commandClass" value="net.sourceforge.subsonic.command.PersonalSettingsCommand"/>
+ <property name="successView" value="personalSettings"/>
+ <property name="formView" value="personalSettings"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="securityService" ref="securityService"/>
+ </bean>
+ <bean id="avatarUploadController" class="net.sourceforge.subsonic.controller.AvatarUploadController">
+ <property name="viewName" value="avatarUploadResult"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="securityService" ref="securityService"/>
+ </bean>
+ <bean id="userSettingsController" class="net.sourceforge.subsonic.controller.UserSettingsController">
+ <property name="sessionForm" value="true"/>
+ <property name="commandClass" value="net.sourceforge.subsonic.command.UserSettingsCommand"/>
+ <property name="validator" ref="userSettingsValidator"/>
+ <property name="successView" value="userSettings"/>
+ <property name="formView" value="userSettings"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="transcodingService" ref="transcodingService"/>
+ </bean>
+ <bean id="passwordSettingsController" class="net.sourceforge.subsonic.controller.PasswordSettingsController">
+ <property name="sessionForm" value="true"/>
+ <property name="commandClass" value="net.sourceforge.subsonic.command.PasswordSettingsCommand"/>
+ <property name="validator" ref="passwordSettingsValidator"/>
+ <property name="successView" value="passwordSettings"/>
+ <property name="formView" value="passwordSettings"/>
+ <property name="securityService" ref="securityService"/>
+ </bean>
+ <bean id="homeController" class="net.sourceforge.subsonic.controller.HomeController">
+ <property name="viewName" value="home"/>
+ <property name="ratingService" ref="musicInfoService"/>
+ <property name="mediaScannerService" ref="mediaScannerService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="searchService" ref="searchService"/>
+ <property name="securityService" ref="securityService"/>
+ </bean>
+ <bean id="editTagsController" class="net.sourceforge.subsonic.controller.EditTagsController">
+ <property name="viewName" value="editTags"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="metaDataParserFactory" ref="metaDataParserFactory"/>
+ </bean>
+ <bean id="playQueueController" class="net.sourceforge.subsonic.controller.PlayQueueController">
+ <property name="viewName" value="playQueue"/>
+ <property name="playerService" ref="playerService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+ <bean id="coverArtController" class="net.sourceforge.subsonic.controller.CoverArtController">
+ <property name="securityService" ref="securityService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="artistDao" ref="artistDao"/>
+ <property name="albumDao" ref="albumDao"/>
+ </bean>
+ <bean id="avatarController" class="net.sourceforge.subsonic.controller.AvatarController">
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+ <bean id="proxyController" class="net.sourceforge.subsonic.controller.ProxyController"/>
+ <bean id="statusChartController" class="net.sourceforge.subsonic.controller.StatusChartController">
+ <property name="statusService" ref="statusService"/>
+ </bean>
+ <bean id="userChartController" class="net.sourceforge.subsonic.controller.UserChartController">
+ <property name="securityService" ref="securityService"/>
+ </bean>
+ <bean id="m3uController" class="net.sourceforge.subsonic.controller.M3UController">
+ <property name="playerService" ref="playerService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="transcodingService" ref="transcodingService"/>
+ </bean>
+ <bean id="streamController" class="net.sourceforge.subsonic.controller.StreamController">
+ <property name="playerService" ref="playerService"/>
+ <property name="playlistService" ref="playlistService"/>
+ <property name="statusService" ref="statusService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="searchService" ref="searchService"/>
+ <property name="transcodingService" ref="transcodingService"/>
+ <property name="audioScrobblerService" ref="audioScrobblerService"/>
+ </bean>
+ <bean id="videoPlayerController" class="net.sourceforge.subsonic.controller.VideoPlayerController">
+ <property name="viewName" value="videoPlayer"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="playerService" ref="playerService"/>
+ </bean>
+ <bean id="externalPlayerController" class="net.sourceforge.subsonic.controller.ExternalPlayerController">
+ <property name="viewName" value="externalPlayer"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="playerService" ref="playerService"/>
+ <property name="shareDao" ref="shareDao"/>
+ </bean>
+ <bean id="downloadController" class="net.sourceforge.subsonic.controller.DownloadController">
+ <property name="playerService" ref="playerService"/>
+ <property name="statusService" ref="statusService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="playlistService" ref="playlistService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ </bean>
+ <bean id="donateController" class="net.sourceforge.subsonic.controller.DonateController">
+ <property name="commandClass" value="net.sourceforge.subsonic.command.DonateCommand"/>
+ <property name="successView" value="donate"/>
+ <property name="formView" value="donate"/>
+ <property name="validator" ref="donateValidator"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+ <bean id="multiController" class="net.sourceforge.subsonic.controller.MultiController">
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ <property name="playlistService" ref="playlistService"/>
+ </bean>
+ <bean id="wapController" class="net.sourceforge.subsonic.controller.WapController">
+ <property name="settingsService" ref="settingsService"/>
+ <property name="playerService" ref="playerService"/>
+ <property name="playlistService" ref="playlistService"/>
+ <property name="searchService" ref="searchService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="musicIndexService" ref="musicIndexService"/>
+ </bean>
+ <bean id="restController" class="net.sourceforge.subsonic.controller.RESTController">
+ <property name="settingsService" ref="settingsService"/>
+ <property name="securityService" ref="securityService"/>
+ <property name="playerService" ref="playerService"/>
+ <property name="mediaFileService" ref="mediaFileService"/>
+ <property name="transcodingService" ref="transcodingService"/>
+ <property name="statusService" ref="statusService"/>
+ <property name="searchService" ref="searchService"/>
+ <property name="jukeboxService" ref="jukeboxService"/>
+ <property name="audioScrobblerService" ref="audioScrobblerService"/>
+ <property name="playlistService" ref="playlistService"/>
+ <property name="playQueueService" ref="ajaxPlayQueueService"/>
+ <property name="ratingService" ref="musicInfoService"/>
+ <property name="chatService" ref="ajaxChatService"/>
+ <property name="lyricsService" ref="ajaxLyricsService"/>
+ <property name="podcastService" ref="podcastService"/>
+ <property name="shareService" ref="shareService"/>
+ <property name="mediaFileDao" ref="mediaFileDao"/>
+ <property name="artistDao" ref="artistDao"/>
+ <property name="albumDao" ref="albumDao"/>
+ <property name="downloadController" ref="downloadController"/>
+ <property name="streamController" ref="streamController"/>
+ <property name="coverArtController" ref="coverArtController"/>
+ <property name="avatarController" ref="avatarController"/>
+ <property name="userSettingsController" ref="userSettingsController"/>
+ <property name="leftController" ref="leftController"/>
+ <property name="homeController" ref="homeController"/>
+ </bean>
+ <bean id="dbController" class="net.sourceforge.subsonic.controller.DBController">
+ <property name="viewName" value="db"/>
+ <property name="daoHelper" ref="daoHelper"/>
+ </bean>
+ <bean id="donateValidator" class="net.sourceforge.subsonic.validator.DonateValidator">
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+ <bean id="userSettingsValidator" class="net.sourceforge.subsonic.validator.UserSettingsValidator">
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+ <bean id="passwordSettingsValidator" class="net.sourceforge.subsonic.validator.PasswordSettingsValidator"/>
+
+ <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
+ <property name="alwaysUseFullPath" value="true"/>
+ <property name="mappings">
+ <props>
+ <prop key="/main.view">mainController</prop>
+ <prop key="/playlist.view">playlistController</prop>
+ <prop key="/help.view">helpController</prop>
+ <prop key="/lyrics.view">lyricsController</prop>
+ <prop key="/left.view">leftController</prop>
+ <prop key="/right.view">rightController</prop>
+ <prop key="/status.view">statusController</prop>
+ <prop key="/more.view">moreController</prop>
+ <prop key="/upload.view">uploadController</prop>
+ <prop key="/importPlaylist.view">importPlaylistController</prop>
+ <prop key="/exportPlaylist.view">multiController</prop>
+ <prop key="/setMusicFileInfo.view">setMusicFileInfoController</prop>
+ <prop key="/createShare.view">shareManagementController</prop>
+ <prop key="/setRating.view">setRatingController</prop>
+ <prop key="/top.view">topController</prop>
+ <prop key="/randomPlayQueue.view">randomPlayQueueController</prop>
+ <prop key="/changeCoverArt.view">changeCoverArtController</prop>
+ <prop key="/login.view">multiController</prop>
+ <prop key="/recover.view">multiController</prop>
+ <prop key="/accessDenied.view">multiController</prop>
+ <prop key="/notFound.view">multiController</prop>
+ <prop key="/gettingStarted.view">multiController</prop>
+ <prop key="/index.view">multiController</prop>
+ <prop key="/videoPlayer.view">videoPlayerController</prop>
+ <prop key="/nowPlaying.view">nowPlayingController</prop>
+ <prop key="/starred.view">starredController</prop>
+ <prop key="/search.view">searchController</prop>
+ <prop key="/settings.view">settingsController</prop>
+ <prop key="/playerSettings.view">playerSettingsController</prop>
+ <prop key="/shareSettings.view">shareSettingsController</prop>
+ <prop key="/musicFolderSettings.view">musicFolderSettingsController</prop>
+ <prop key="/networkSettings.view">networkSettingsController</prop>
+ <prop key="/transcodingSettings.view">transcodingSettingsController</prop>
+ <prop key="/internetRadioSettings.view">internetRadioSettingsController</prop>
+ <prop key="/podcastSettings.view">podcastSettingsController</prop>
+ <prop key="/generalSettings.view">generalSettingsController</prop>
+ <prop key="/advancedSettings.view">advancedSettingsController</prop>
+ <prop key="/personalSettings.view">personalSettingsController</prop>
+ <prop key="/avatarUpload.view">avatarUploadController</prop>
+ <prop key="/userSettings.view">userSettingsController</prop>
+ <prop key="/passwordSettings.view">passwordSettingsController</prop>
+ <prop key="/allmusic.view">allmusicController</prop>
+ <prop key="/home.view">homeController</prop>
+ <prop key="/editTags.view">editTagsController</prop>
+ <prop key="/playQueue.view">playQueueController</prop>
+ <prop key="/coverArt.view">coverArtController</prop>
+ <prop key="/avatar.view">avatarController</prop>
+ <prop key="/proxy.view">proxyController</prop>
+ <prop key="/statusChart.view">statusChartController</prop>
+ <prop key="/userChart.view">userChartController</prop>
+ <prop key="/download.view">downloadController</prop>
+ <prop key="/donate.view">donateController</prop>
+ <prop key="/db.view">dbController</prop>
+ <prop key="/test.view">multiController</prop>
+ <prop key="/podcastReceiver.view">podcastReceiverController</prop>
+ <prop key="/podcastReceiverAdmin.view">podcastReceiverAdminController</prop>
+ <prop key="/podcast.view">podcastController</prop>
+ <prop key="/podcast/**">podcastController</prop>
+ <prop key="/wap/download.view">downloadController</prop>
+ <prop key="/wap/**">wapController</prop>
+ <prop key="/rest/**">restController</prop>
+ <prop key="/play.m3u">m3uController</prop>
+ <prop key="/stream/**">streamController</prop>
+ <prop key="/share/**">externalPlayerController</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
+ <property name="basename" value="net.sourceforge.subsonic.i18n.ResourceBundle"/>
+ </bean>
+
+ <bean id="themeSource" class="net.sourceforge.subsonic.theme.SubsonicThemeSource">
+ <property name="basenamePrefix" value="net.sourceforge.subsonic.theme."/>
+ <property name="defaultResourceBundle" value="net.sourceforge.subsonic.theme.default"/>
+ </bean>
+
+ <bean id="localeResolver"
+ class="net.sourceforge.subsonic.i18n.SubsonicLocaleResolver">
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+
+ <bean id="themeResolver"
+ class="net.sourceforge.subsonic.theme.SubsonicThemeResolver">
+ <property name="securityService" ref="securityService"/>
+ <property name="settingsService" ref="settingsService"/>
+ </bean>
+
+ <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
+ <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
+ <property name="prefix" value="/WEB-INF/jsp/"/>
+ <property name="suffix" value=".jsp"/>
+ </bean>
+
+</beans>
diff --git a/subsonic-main/src/main/webapp/WEB-INF/web.xml b/subsonic-main/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..bf484e28 --- /dev/null +++ b/subsonic-main/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,207 @@ +<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app id="subsonic" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+
+ <display-name>Subsonic Music Streamer</display-name>
+
+ <!-- Location of application context. Used by ContextLoaderListener. -->
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>
+ /WEB-INF/applicationContext-service.xml
+ /WEB-INF/applicationContext-security.xml
+ /WEB-INF/applicationContext-cache.xml
+ </param-value>
+ </context-param>
+
+ <listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+ </listener>
+ <listener>
+ <listener-class>net.sf.ehcache.constructs.web.ShutdownListener</listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>subsonic</servlet-name>
+ <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet>
+ <display-name>DWR Servlet</display-name>
+ <servlet-name>dwr-invoker</servlet-name>
+ <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>subsonic</servlet-name>
+ <url-pattern>*.view</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>subsonic</servlet-name>
+ <url-pattern>/podcast</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>subsonic</servlet-name>
+ <url-pattern>/wap</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>subsonic</servlet-name>
+ <url-pattern>/play.m3u</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>subsonic</servlet-name>
+ <url-pattern>/stream/*</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>subsonic</servlet-name>
+ <url-pattern>/rest/*</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>subsonic</servlet-name>
+ <url-pattern>/share/*</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>dwr-invoker</servlet-name>
+ <url-pattern>/dwr/*</url-pattern>
+ </servlet-mapping>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ <welcome-file>index.jsp</welcome-file>
+ </welcome-file-list>
+
+ <error-page>
+ <exception-type>java.lang.Throwable</exception-type>
+ <location>/error.jsp</location>
+ </error-page>
+
+ <filter>
+ <filter-name>BootstrapVerificationFilter</filter-name>
+ <filter-class>net.sourceforge.subsonic.filter.BootstrapVerificationFilter</filter-class>
+ </filter>
+ <filter-mapping>
+ <filter-name>BootstrapVerificationFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <filter>
+ <filter-name>ParameterDecodingFilter</filter-name>
+ <filter-class>net.sourceforge.subsonic.filter.ParameterDecodingFilter</filter-class>
+ </filter>
+ <filter-mapping>
+ <filter-name>ParameterDecodingFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <filter>
+ <filter-name>RequestEncodingFilter</filter-name>
+ <filter-class>net.sourceforge.subsonic.filter.RequestEncodingFilter</filter-class>
+ <init-param>
+ <param-name>encoding</param-name>
+ <param-value>UTF-8</param-value>
+ </init-param>
+ </filter>
+ <filter-mapping>
+ <filter-name>RequestEncodingFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <filter>
+ <description>Sets HTTP headers to enable browser caching.</description>
+ <filter-name>CacheFilter</filter-name>
+ <filter-class>net.sourceforge.subsonic.filter.ResponseHeaderFilter</filter-class>
+ <init-param>
+ <param-name>Cache-Control</param-name>
+ <param-value>max-age=36000</param-value>
+ </init-param>
+ </filter>
+
+ <filter>
+ <description>Sets HTTP headers to disable browser caching.</description>
+ <filter-name>NoCacheFilter</filter-name>
+ <filter-class>net.sourceforge.subsonic.filter.ResponseHeaderFilter</filter-class>
+ <init-param>
+ <param-name>Cache-Control</param-name>
+ <param-value>no-cache, post-check=0, pre-check=0</param-value>
+ </init-param>
+ <init-param>
+ <param-name>Pragma</param-name>
+ <param-value>no-cache</param-value>
+ </init-param>
+ <init-param>
+ <param-name>Expires</param-name>
+ <param-value>Thu, 01 Dec 1994 16:00:00 GMT</param-value>
+ </init-param>
+ </filter>
+
+ <filter>
+ <description>The "Expires" HTTP header is set to avoid overly eager browser caching of
+ pages that implements LastModified.</description>
+ <filter-name>ExpiresFilter</filter-name>
+ <filter-class>net.sourceforge.subsonic.filter.ResponseHeaderFilter</filter-class>
+ <init-param>
+ <param-name>Expires</param-name>
+ <param-value>Thu, 01 Dec 1994 16:00:00 GMT</param-value>
+ </init-param>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>CacheFilter</filter-name>
+ <url-pattern>/icons/*</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>CacheFilter</filter-name>
+ <url-pattern>/style/*</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>NoCacheFilter</filter-name>
+ <url-pattern>/statusChart.view</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>NoCacheFilter</filter-name>
+ <url-pattern>/userChart.view</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>NoCacheFilter</filter-name>
+ <url-pattern>/playQueue.view</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>NoCacheFilter</filter-name>
+ <url-pattern>/podcastReceiver.view</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>NoCacheFilter</filter-name>
+ <url-pattern>/help.view</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>NoCacheFilter</filter-name>
+ <url-pattern>/top.view</url-pattern>
+ </filter-mapping>
+ <filter-mapping>
+ <filter-name>NoCacheFilter</filter-name>
+ <url-pattern>/home.view</url-pattern>
+ </filter-mapping>
+
+ <filter-mapping>
+ <filter-name>ExpiresFilter</filter-name>
+ <url-pattern>/left.view</url-pattern>
+ </filter-mapping>
+
+ <filter>
+ <filter-name>AcegiFilter</filter-name>
+ <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
+ <init-param>
+ <param-name>targetClass</param-name>
+ <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
+ </init-param>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>AcegiFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+</web-app>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/ad/omakasa.html b/subsonic-main/src/main/webapp/ad/omakasa.html new file mode 100644 index 00000000..12145df8 --- /dev/null +++ b/subsonic-main/src/main/webapp/ad/omakasa.html @@ -0,0 +1,5 @@ +<html> +<body topmargin=0 leftmargin=0 marginheight=0 marginwidth=0> +<script type='text/javascript'>amazon_ad_tag = 'subsonic-20'; amazon_ad_width = '120'; amazon_ad_height = '240'; amazon_ad_link_target = 'new';</script><script type='text/javascript' src='http://www.assoc-amazon.com/s/ads.js'></script> +</body> +</html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/crossdomain.xml b/subsonic-main/src/main/webapp/crossdomain.xml new file mode 100644 index 00000000..7f6057fa --- /dev/null +++ b/subsonic-main/src/main/webapp/crossdomain.xml @@ -0,0 +1,6 @@ +<?xml version="1.0"?> +<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"> + +<cross-domain-policy> + <allow-access-from domain="*" /> +</cross-domain-policy>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/error.jsp b/subsonic-main/src/main/webapp/error.jsp new file mode 100644 index 00000000..39d38a53 --- /dev/null +++ b/subsonic-main/src/main/webapp/error.jsp @@ -0,0 +1,48 @@ +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="iso-8859-1" isErrorPage="true" %>
+<%@ page import="java.io.*"%>
+
+<html><head>
+ <!--[if lt IE 7.]>
+ <script defer type="text/javascript" src="script/pngfix.js"></script>
+ <![endif]-->
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <link rel="stylesheet" href="style/default.css" type="text/css"/>
+</head>
+
+<body>
+<h1><img src="icons/error.png" alt=""/> Error</h1>
+
+<p>
+ Subsonic encountered an internal error. You can report this error in the
+ <a href="http://forum.subsonic.org" target="_blank">Subsonic Forum</a>.
+ Please include the information below.
+</p>
+
+<%
+ StringWriter sw = new StringWriter();
+ exception.printStackTrace(new PrintWriter(sw));
+
+ long totalMemory = Runtime.getRuntime().totalMemory();
+ long freeMemory = Runtime.getRuntime().freeMemory();
+ long usedMemory = totalMemory - freeMemory;
+%>
+
+<table class="ruleTable indent">
+ <tr><td class="ruleTableHeader">Exception</td>
+ <td class="ruleTableCell"><%=exception.getClass().getName()%></td></tr>
+ <tr><td class="ruleTableHeader">Message</td>
+ <td class="ruleTableCell"><%=exception.getMessage()%></td></tr>
+ <tr><td class="ruleTableHeader">Java version</td>
+ <td class="ruleTableCell"><%=System.getProperty("java.vendor") + ' ' + System.getProperty("java.version")%></td></tr>
+ <tr><td class="ruleTableHeader">Operating system</td>
+ <td class="ruleTableCell"><%=System.getProperty("os.name") + ' ' + System.getProperty("os.version")%></td></tr>
+ <tr><td class="ruleTableHeader">Server</td>
+ <td class="ruleTableCell"><%=application.getServerInfo()%></td></tr>
+ <tr><td class="ruleTableHeader">Memory</td>
+ <td class="ruleTableCell">Used <%=usedMemory/1024L/1024L%> of <%=totalMemory/1024L/1024L%> MB</td></tr>
+ <tr><td class="ruleTableHeader" style="vertical-align:top;">Stack trace</td>
+ <td class="ruleTableCell" style="white-space:pre"><%=sw.getBuffer()%></td></tr>
+</table>
+
+</body>
+</html>
diff --git a/subsonic-main/src/main/webapp/flash/jw-player-5.6.swf b/subsonic-main/src/main/webapp/flash/jw-player-5.6.swf Binary files differnew file mode 100644 index 00000000..b98411bb --- /dev/null +++ b/subsonic-main/src/main/webapp/flash/jw-player-5.6.swf diff --git a/subsonic-main/src/main/webapp/flash/whotube.zip b/subsonic-main/src/main/webapp/flash/whotube.zip Binary files differnew file mode 100644 index 00000000..f78a1acc --- /dev/null +++ b/subsonic-main/src/main/webapp/flash/whotube.zip diff --git a/subsonic-main/src/main/webapp/icons/add.gif b/subsonic-main/src/main/webapp/icons/add.gif Binary files differnew file mode 100644 index 00000000..d1ff937f --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/add.gif diff --git a/subsonic-main/src/main/webapp/icons/android.png b/subsonic-main/src/main/webapp/icons/android.png Binary files differnew file mode 100644 index 00000000..747ee31c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/android.png diff --git a/subsonic-main/src/main/webapp/icons/back.gif b/subsonic-main/src/main/webapp/icons/back.gif Binary files differnew file mode 100644 index 00000000..81721dc1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/back.gif diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/add.png b/subsonic-main/src/main/webapp/icons/buuftheme/add.png Binary files differnew file mode 100644 index 00000000..9b4e0c1f --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/add.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/android.png b/subsonic-main/src/main/webapp/icons/buuftheme/android.png Binary files differnew file mode 100644 index 00000000..279b31b0 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/android.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/back.png b/subsonic-main/src/main/webapp/icons/buuftheme/back.png Binary files differnew file mode 100644 index 00000000..9f955e98 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/back.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/background_main.png b/subsonic-main/src/main/webapp/icons/buuftheme/background_main.png Binary files differnew file mode 100644 index 00000000..357ab473 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/background_main.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/clear_rating.png b/subsonic-main/src/main/webapp/icons/buuftheme/clear_rating.png Binary files differnew file mode 100644 index 00000000..4a83edbd --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/clear_rating.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/donate.png b/subsonic-main/src/main/webapp/icons/buuftheme/donate.png Binary files differnew file mode 100644 index 00000000..3b693839 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/donate.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/donate_small.png b/subsonic-main/src/main/webapp/icons/buuftheme/donate_small.png Binary files differnew file mode 100644 index 00000000..f01e447a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/donate_small.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/down.png b/subsonic-main/src/main/webapp/icons/buuftheme/down.png Binary files differnew file mode 100644 index 00000000..9b2aae76 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/down.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/download.png b/subsonic-main/src/main/webapp/icons/buuftheme/download.png Binary files differnew file mode 100644 index 00000000..0ca87330 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/download.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/error.png b/subsonic-main/src/main/webapp/icons/buuftheme/error.png Binary files differnew file mode 100644 index 00000000..bec7cc39 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/error.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/favicon.ico b/subsonic-main/src/main/webapp/icons/buuftheme/favicon.ico Binary files differnew file mode 100644 index 00000000..5fe21f0c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/forward.png b/subsonic-main/src/main/webapp/icons/buuftheme/forward.png Binary files differnew file mode 100644 index 00000000..7bc6d2bc --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/forward.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/gpl.png b/subsonic-main/src/main/webapp/icons/buuftheme/gpl.png Binary files differnew file mode 100644 index 00000000..cd3deb71 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/gpl.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/help.png b/subsonic-main/src/main/webapp/icons/buuftheme/help.png Binary files differnew file mode 100644 index 00000000..8dbbb633 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/help.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/help_small.png b/subsonic-main/src/main/webapp/icons/buuftheme/help_small.png Binary files differnew file mode 100644 index 00000000..4d2f25a1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/help_small.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/home.png b/subsonic-main/src/main/webapp/icons/buuftheme/home.png Binary files differnew file mode 100644 index 00000000..36a27453 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/home.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/home_hover.png b/subsonic-main/src/main/webapp/icons/buuftheme/home_hover.png Binary files differnew file mode 100644 index 00000000..cff7ebc4 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/home_hover.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/list_heading.png b/subsonic-main/src/main/webapp/icons/buuftheme/list_heading.png Binary files differnew file mode 100644 index 00000000..437c55ab --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/list_heading.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/log.png b/subsonic-main/src/main/webapp/icons/buuftheme/log.png Binary files differnew file mode 100644 index 00000000..d7d13bae --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/log.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/logo.png b/subsonic-main/src/main/webapp/icons/buuftheme/logo.png Binary files differnew file mode 100644 index 00000000..0ac76190 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/logo.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/more.png b/subsonic-main/src/main/webapp/icons/buuftheme/more.png Binary files differnew file mode 100644 index 00000000..a679d8b3 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/more.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/now_playing.png b/subsonic-main/src/main/webapp/icons/buuftheme/now_playing.png Binary files differnew file mode 100644 index 00000000..472e6cca --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/paypal.gif b/subsonic-main/src/main/webapp/icons/buuftheme/paypal.gif Binary files differnew file mode 100644 index 00000000..6d8c7f99 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/paypal.gif diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/phone.png b/subsonic-main/src/main/webapp/icons/buuftheme/phone.png Binary files differnew file mode 100644 index 00000000..8727f23a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/phone.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/play.png b/subsonic-main/src/main/webapp/icons/buuftheme/play.png Binary files differnew file mode 100644 index 00000000..29baf96f --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/play.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/playing.png b/subsonic-main/src/main/webapp/icons/buuftheme/playing.png Binary files differnew file mode 100644 index 00000000..a870cc1d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/playing.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/podcast.png b/subsonic-main/src/main/webapp/icons/buuftheme/podcast.png Binary files differnew file mode 100644 index 00000000..927d9ae3 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/podcast.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/podcast_small.png b/subsonic-main/src/main/webapp/icons/buuftheme/podcast_small.png Binary files differnew file mode 100644 index 00000000..61741833 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/podcast_small.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/progress.png b/subsonic-main/src/main/webapp/icons/buuftheme/progress.png Binary files differnew file mode 100644 index 00000000..ddd5a913 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/progress.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/random.png b/subsonic-main/src/main/webapp/icons/buuftheme/random.png Binary files differnew file mode 100644 index 00000000..d892b383 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/random.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/rating_half.png b/subsonic-main/src/main/webapp/icons/buuftheme/rating_half.png Binary files differnew file mode 100644 index 00000000..4024923c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/rating_half.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/rating_off.png b/subsonic-main/src/main/webapp/icons/buuftheme/rating_off.png Binary files differnew file mode 100644 index 00000000..97640ef2 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/rating_off.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/rating_on.png b/subsonic-main/src/main/webapp/icons/buuftheme/rating_on.png Binary files differnew file mode 100644 index 00000000..cfdc2628 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/rating_on.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/remove.png b/subsonic-main/src/main/webapp/icons/buuftheme/remove.png Binary files differnew file mode 100644 index 00000000..391d89f7 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/remove.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/search.png b/subsonic-main/src/main/webapp/icons/buuftheme/search.png Binary files differnew file mode 100644 index 00000000..1e81fd02 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/search.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/settings.png b/subsonic-main/src/main/webapp/icons/buuftheme/settings.png Binary files differnew file mode 100644 index 00000000..6d520fa3 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/settings.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/status.png b/subsonic-main/src/main/webapp/icons/buuftheme/status.png Binary files differnew file mode 100644 index 00000000..1ace9646 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/status.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/subair.png b/subsonic-main/src/main/webapp/icons/buuftheme/subair.png Binary files differnew file mode 100644 index 00000000..a8a36dbe --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/subair.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/up.png b/subsonic-main/src/main/webapp/icons/buuftheme/up.png Binary files differnew file mode 100644 index 00000000..e2f0193c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/up.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/upload.png b/subsonic-main/src/main/webapp/icons/buuftheme/upload.png Binary files differnew file mode 100644 index 00000000..25af770e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/upload.png diff --git a/subsonic-main/src/main/webapp/icons/buuftheme/wap.png b/subsonic-main/src/main/webapp/icons/buuftheme/wap.png Binary files differnew file mode 100644 index 00000000..7a3b688c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/buuftheme/wap.png diff --git a/subsonic-main/src/main/webapp/icons/clearRating.png b/subsonic-main/src/main/webapp/icons/clearRating.png Binary files differnew file mode 100644 index 00000000..a41afa13 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/clearRating.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/add.png b/subsonic-main/src/main/webapp/icons/coolandclean/add.png Binary files differnew file mode 100644 index 00000000..1b2b3e57 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/add.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/back.png b/subsonic-main/src/main/webapp/icons/coolandclean/back.png Binary files differnew file mode 100644 index 00000000..187916f2 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/back.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/background.png b/subsonic-main/src/main/webapp/icons/coolandclean/background.png Binary files differnew file mode 100644 index 00000000..2de28330 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/background.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/background_main.png b/subsonic-main/src/main/webapp/icons/coolandclean/background_main.png Binary files differnew file mode 100644 index 00000000..78d50118 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/background_main.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/clear_rating.png b/subsonic-main/src/main/webapp/icons/coolandclean/clear_rating.png Binary files differnew file mode 100644 index 00000000..711fa862 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/clear_rating.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/donate.png b/subsonic-main/src/main/webapp/icons/coolandclean/donate.png Binary files differnew file mode 100644 index 00000000..f9c17ceb --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/donate.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/down.png b/subsonic-main/src/main/webapp/icons/coolandclean/down.png Binary files differnew file mode 100644 index 00000000..eeb09a15 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/down.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/download.png b/subsonic-main/src/main/webapp/icons/coolandclean/download.png Binary files differnew file mode 100644 index 00000000..a0551ff7 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/download.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/error.png b/subsonic-main/src/main/webapp/icons/coolandclean/error.png Binary files differnew file mode 100644 index 00000000..3416f146 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/error.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/favicon.ico b/subsonic-main/src/main/webapp/icons/coolandclean/favicon.ico Binary files differnew file mode 100644 index 00000000..d568f347 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/forward.png b/subsonic-main/src/main/webapp/icons/coolandclean/forward.png Binary files differnew file mode 100644 index 00000000..d4541d69 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/forward.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/help.png b/subsonic-main/src/main/webapp/icons/coolandclean/help.png Binary files differnew file mode 100644 index 00000000..3e1efec9 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/help.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/help_small.png b/subsonic-main/src/main/webapp/icons/coolandclean/help_small.png Binary files differnew file mode 100644 index 00000000..c1967b47 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/help_small.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/home.png b/subsonic-main/src/main/webapp/icons/coolandclean/home.png Binary files differnew file mode 100644 index 00000000..0b0a9dff --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/home.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/home_hover.png b/subsonic-main/src/main/webapp/icons/coolandclean/home_hover.png Binary files differnew file mode 100644 index 00000000..91b069c9 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/home_hover.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/list_heading.png b/subsonic-main/src/main/webapp/icons/coolandclean/list_heading.png Binary files differnew file mode 100644 index 00000000..3b1d2623 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/list_heading.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/log.png b/subsonic-main/src/main/webapp/icons/coolandclean/log.png Binary files differnew file mode 100644 index 00000000..8cd79b89 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/log.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/logo.png b/subsonic-main/src/main/webapp/icons/coolandclean/logo.png Binary files differnew file mode 100644 index 00000000..b393527e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/logo.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/more.png b/subsonic-main/src/main/webapp/icons/coolandclean/more.png Binary files differnew file mode 100644 index 00000000..1825f36e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/more.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/now_playing.png b/subsonic-main/src/main/webapp/icons/coolandclean/now_playing.png Binary files differnew file mode 100644 index 00000000..30997a6c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/paypal.gif b/subsonic-main/src/main/webapp/icons/coolandclean/paypal.gif Binary files differnew file mode 100644 index 00000000..2a587165 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/paypal.gif diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/phone.png b/subsonic-main/src/main/webapp/icons/coolandclean/phone.png Binary files differnew file mode 100644 index 00000000..d8d85646 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/phone.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/play.png b/subsonic-main/src/main/webapp/icons/coolandclean/play.png Binary files differnew file mode 100644 index 00000000..bb81db5e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/play.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/playing.png b/subsonic-main/src/main/webapp/icons/coolandclean/playing.png Binary files differnew file mode 100644 index 00000000..a12e02aa --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/playing.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/podcast.png b/subsonic-main/src/main/webapp/icons/coolandclean/podcast.png Binary files differnew file mode 100644 index 00000000..cb0c6967 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/podcast.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/podcast_small.png b/subsonic-main/src/main/webapp/icons/coolandclean/podcast_small.png Binary files differnew file mode 100644 index 00000000..81a851b7 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/podcast_small.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/progress.png b/subsonic-main/src/main/webapp/icons/coolandclean/progress.png Binary files differnew file mode 100644 index 00000000..ddd5a913 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/progress.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/random.png b/subsonic-main/src/main/webapp/icons/coolandclean/random.png Binary files differnew file mode 100644 index 00000000..4316a393 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/random.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/rating_half.png b/subsonic-main/src/main/webapp/icons/coolandclean/rating_half.png Binary files differnew file mode 100644 index 00000000..d8550838 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/rating_half.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/rating_off.png b/subsonic-main/src/main/webapp/icons/coolandclean/rating_off.png Binary files differnew file mode 100644 index 00000000..a0d9bbb1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/rating_off.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/rating_on.png b/subsonic-main/src/main/webapp/icons/coolandclean/rating_on.png Binary files differnew file mode 100644 index 00000000..b3e99d1d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/rating_on.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/remove.png b/subsonic-main/src/main/webapp/icons/coolandclean/remove.png Binary files differnew file mode 100644 index 00000000..f2280eae --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/remove.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/search.png b/subsonic-main/src/main/webapp/icons/coolandclean/search.png Binary files differnew file mode 100644 index 00000000..0f7b5360 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/search.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/settings.png b/subsonic-main/src/main/webapp/icons/coolandclean/settings.png Binary files differnew file mode 100644 index 00000000..a38f5915 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/settings.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/status.png b/subsonic-main/src/main/webapp/icons/coolandclean/status.png Binary files differnew file mode 100644 index 00000000..d0e5b4d4 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/status.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/up.png b/subsonic-main/src/main/webapp/icons/coolandclean/up.png Binary files differnew file mode 100644 index 00000000..4dc14491 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/up.png diff --git a/subsonic-main/src/main/webapp/icons/coolandclean/upload.png b/subsonic-main/src/main/webapp/icons/coolandclean/upload.png Binary files differnew file mode 100644 index 00000000..81920b18 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/coolandclean/upload.png diff --git a/subsonic-main/src/main/webapp/icons/current.gif b/subsonic-main/src/main/webapp/icons/current.gif Binary files differnew file mode 100644 index 00000000..4176913d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/current.gif diff --git a/subsonic-main/src/main/webapp/icons/denim/add.png b/subsonic-main/src/main/webapp/icons/denim/add.png Binary files differnew file mode 100644 index 00000000..26e12f87 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/add.png diff --git a/subsonic-main/src/main/webapp/icons/denim/back.png b/subsonic-main/src/main/webapp/icons/denim/back.png Binary files differnew file mode 100644 index 00000000..295ec91b --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/back.png diff --git a/subsonic-main/src/main/webapp/icons/denim/clear_rating.png b/subsonic-main/src/main/webapp/icons/denim/clear_rating.png Binary files differnew file mode 100644 index 00000000..64d78601 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/clear_rating.png diff --git a/subsonic-main/src/main/webapp/icons/denim/donate.png b/subsonic-main/src/main/webapp/icons/denim/donate.png Binary files differnew file mode 100644 index 00000000..f9c17ceb --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/donate.png diff --git a/subsonic-main/src/main/webapp/icons/denim/down.png b/subsonic-main/src/main/webapp/icons/denim/down.png Binary files differnew file mode 100644 index 00000000..5635af51 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/down.png diff --git a/subsonic-main/src/main/webapp/icons/denim/download.png b/subsonic-main/src/main/webapp/icons/denim/download.png Binary files differnew file mode 100644 index 00000000..1b24ae83 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/download.png diff --git a/subsonic-main/src/main/webapp/icons/denim/error.png b/subsonic-main/src/main/webapp/icons/denim/error.png Binary files differnew file mode 100644 index 00000000..c7d60958 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/error.png diff --git a/subsonic-main/src/main/webapp/icons/denim/favicon.ico b/subsonic-main/src/main/webapp/icons/denim/favicon.ico Binary files differnew file mode 100644 index 00000000..ab7802d8 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/denim/forward.png b/subsonic-main/src/main/webapp/icons/denim/forward.png Binary files differnew file mode 100644 index 00000000..b88d5106 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/forward.png diff --git a/subsonic-main/src/main/webapp/icons/denim/help.png b/subsonic-main/src/main/webapp/icons/denim/help.png Binary files differnew file mode 100644 index 00000000..de1a0f6d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/help.png diff --git a/subsonic-main/src/main/webapp/icons/denim/help_small.png b/subsonic-main/src/main/webapp/icons/denim/help_small.png Binary files differnew file mode 100644 index 00000000..824519e9 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/help_small.png diff --git a/subsonic-main/src/main/webapp/icons/denim/home.png b/subsonic-main/src/main/webapp/icons/denim/home.png Binary files differnew file mode 100644 index 00000000..7f4a4d58 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/home.png diff --git a/subsonic-main/src/main/webapp/icons/denim/log.png b/subsonic-main/src/main/webapp/icons/denim/log.png Binary files differnew file mode 100644 index 00000000..a4fa9297 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/log.png diff --git a/subsonic-main/src/main/webapp/icons/denim/logo.png b/subsonic-main/src/main/webapp/icons/denim/logo.png Binary files differnew file mode 100644 index 00000000..82191180 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/logo.png diff --git a/subsonic-main/src/main/webapp/icons/denim/more.png b/subsonic-main/src/main/webapp/icons/denim/more.png Binary files differnew file mode 100644 index 00000000..bfc8dbb8 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/more.png diff --git a/subsonic-main/src/main/webapp/icons/denim/now_playing.png b/subsonic-main/src/main/webapp/icons/denim/now_playing.png Binary files differnew file mode 100644 index 00000000..42931eff --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/denim/paypal.gif b/subsonic-main/src/main/webapp/icons/denim/paypal.gif Binary files differnew file mode 100644 index 00000000..2a587165 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/paypal.gif diff --git a/subsonic-main/src/main/webapp/icons/denim/phone.png b/subsonic-main/src/main/webapp/icons/denim/phone.png Binary files differnew file mode 100644 index 00000000..693c8620 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/phone.png diff --git a/subsonic-main/src/main/webapp/icons/denim/play.png b/subsonic-main/src/main/webapp/icons/denim/play.png Binary files differnew file mode 100644 index 00000000..cbcb8d40 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/play.png diff --git a/subsonic-main/src/main/webapp/icons/denim/playing.png b/subsonic-main/src/main/webapp/icons/denim/playing.png Binary files differnew file mode 100644 index 00000000..8b620c2a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/playing.png diff --git a/subsonic-main/src/main/webapp/icons/denim/podcast.png b/subsonic-main/src/main/webapp/icons/denim/podcast.png Binary files differnew file mode 100644 index 00000000..033d32c7 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/podcast.png diff --git a/subsonic-main/src/main/webapp/icons/denim/podcast_small.png b/subsonic-main/src/main/webapp/icons/denim/podcast_small.png Binary files differnew file mode 100644 index 00000000..87d2fe25 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/podcast_small.png diff --git a/subsonic-main/src/main/webapp/icons/denim/progress.png b/subsonic-main/src/main/webapp/icons/denim/progress.png Binary files differnew file mode 100644 index 00000000..13b465ba --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/progress.png diff --git a/subsonic-main/src/main/webapp/icons/denim/random.png b/subsonic-main/src/main/webapp/icons/denim/random.png Binary files differnew file mode 100644 index 00000000..2b0fdb06 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/random.png diff --git a/subsonic-main/src/main/webapp/icons/denim/rating_half.png b/subsonic-main/src/main/webapp/icons/denim/rating_half.png Binary files differnew file mode 100644 index 00000000..08ab0d39 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/rating_half.png diff --git a/subsonic-main/src/main/webapp/icons/denim/rating_off.png b/subsonic-main/src/main/webapp/icons/denim/rating_off.png Binary files differnew file mode 100644 index 00000000..a0d9bbb1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/rating_off.png diff --git a/subsonic-main/src/main/webapp/icons/denim/rating_on.png b/subsonic-main/src/main/webapp/icons/denim/rating_on.png Binary files differnew file mode 100644 index 00000000..8c4d6602 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/rating_on.png diff --git a/subsonic-main/src/main/webapp/icons/denim/remove.png b/subsonic-main/src/main/webapp/icons/denim/remove.png Binary files differnew file mode 100644 index 00000000..c0afb187 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/remove.png diff --git a/subsonic-main/src/main/webapp/icons/denim/search.png b/subsonic-main/src/main/webapp/icons/denim/search.png Binary files differnew file mode 100644 index 00000000..6dea8731 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/search.png diff --git a/subsonic-main/src/main/webapp/icons/denim/settings.png b/subsonic-main/src/main/webapp/icons/denim/settings.png Binary files differnew file mode 100644 index 00000000..547bef7b --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/settings.png diff --git a/subsonic-main/src/main/webapp/icons/denim/status.png b/subsonic-main/src/main/webapp/icons/denim/status.png Binary files differnew file mode 100644 index 00000000..f9c4503f --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/status.png diff --git a/subsonic-main/src/main/webapp/icons/denim/up.png b/subsonic-main/src/main/webapp/icons/denim/up.png Binary files differnew file mode 100644 index 00000000..ee5ad884 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/up.png diff --git a/subsonic-main/src/main/webapp/icons/denim/upload.png b/subsonic-main/src/main/webapp/icons/denim/upload.png Binary files differnew file mode 100644 index 00000000..cf3f38da --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/denim/upload.png diff --git a/subsonic-main/src/main/webapp/icons/donate.png b/subsonic-main/src/main/webapp/icons/donate.png Binary files differnew file mode 100644 index 00000000..3b00577e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/donate.png diff --git a/subsonic-main/src/main/webapp/icons/donate_small.png b/subsonic-main/src/main/webapp/icons/donate_small.png Binary files differnew file mode 100644 index 00000000..3a8c311d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/donate_small.png diff --git a/subsonic-main/src/main/webapp/icons/down.gif b/subsonic-main/src/main/webapp/icons/down.gif Binary files differnew file mode 100644 index 00000000..091805f6 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/down.gif diff --git a/subsonic-main/src/main/webapp/icons/download.gif b/subsonic-main/src/main/webapp/icons/download.gif Binary files differnew file mode 100644 index 00000000..3fcdfd00 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/download.gif diff --git a/subsonic-main/src/main/webapp/icons/error.png b/subsonic-main/src/main/webapp/icons/error.png Binary files differnew file mode 100644 index 00000000..45b64a79 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/error.png diff --git a/subsonic-main/src/main/webapp/icons/favicon.ico b/subsonic-main/src/main/webapp/icons/favicon.ico Binary files differnew file mode 100644 index 00000000..d2c13383 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/forward.gif b/subsonic-main/src/main/webapp/icons/forward.gif Binary files differnew file mode 100644 index 00000000..dfccecb9 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/forward.gif diff --git a/subsonic-main/src/main/webapp/icons/gpl.png b/subsonic-main/src/main/webapp/icons/gpl.png Binary files differnew file mode 100644 index 00000000..b06e0439 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/gpl.png diff --git a/subsonic-main/src/main/webapp/icons/groove/add.png b/subsonic-main/src/main/webapp/icons/groove/add.png Binary files differnew file mode 100644 index 00000000..10657ea1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/add.png diff --git a/subsonic-main/src/main/webapp/icons/groove/back.png b/subsonic-main/src/main/webapp/icons/groove/back.png Binary files differnew file mode 100644 index 00000000..7e1355fd --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/back.png diff --git a/subsonic-main/src/main/webapp/icons/groove/background_main.png b/subsonic-main/src/main/webapp/icons/groove/background_main.png Binary files differnew file mode 100644 index 00000000..27c223fa --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/background_main.png diff --git a/subsonic-main/src/main/webapp/icons/groove/background_main_blank.png b/subsonic-main/src/main/webapp/icons/groove/background_main_blank.png Binary files differnew file mode 100644 index 00000000..d0866f7e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/background_main_blank.png diff --git a/subsonic-main/src/main/webapp/icons/groove/clear_rating.png b/subsonic-main/src/main/webapp/icons/groove/clear_rating.png Binary files differnew file mode 100644 index 00000000..8cbdc24d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/clear_rating.png diff --git a/subsonic-main/src/main/webapp/icons/groove/donate.png b/subsonic-main/src/main/webapp/icons/groove/donate.png Binary files differnew file mode 100644 index 00000000..f9c17ceb --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/donate.png diff --git a/subsonic-main/src/main/webapp/icons/groove/down.png b/subsonic-main/src/main/webapp/icons/groove/down.png Binary files differnew file mode 100644 index 00000000..748c5143 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/down.png diff --git a/subsonic-main/src/main/webapp/icons/groove/download.png b/subsonic-main/src/main/webapp/icons/groove/download.png Binary files differnew file mode 100644 index 00000000..748c5143 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/download.png diff --git a/subsonic-main/src/main/webapp/icons/groove/error.png b/subsonic-main/src/main/webapp/icons/groove/error.png Binary files differnew file mode 100644 index 00000000..decb2c1d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/error.png diff --git a/subsonic-main/src/main/webapp/icons/groove/favicon.ico b/subsonic-main/src/main/webapp/icons/groove/favicon.ico Binary files differnew file mode 100644 index 00000000..82690e7a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/groove/forward.png b/subsonic-main/src/main/webapp/icons/groove/forward.png Binary files differnew file mode 100644 index 00000000..4ac6e864 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/forward.png diff --git a/subsonic-main/src/main/webapp/icons/groove/help.png b/subsonic-main/src/main/webapp/icons/groove/help.png Binary files differnew file mode 100644 index 00000000..b9e23c4c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/help.png diff --git a/subsonic-main/src/main/webapp/icons/groove/help_small.png b/subsonic-main/src/main/webapp/icons/groove/help_small.png Binary files differnew file mode 100644 index 00000000..80a8da30 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/help_small.png diff --git a/subsonic-main/src/main/webapp/icons/groove/home.png b/subsonic-main/src/main/webapp/icons/groove/home.png Binary files differnew file mode 100644 index 00000000..f79e99d9 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/home.png diff --git a/subsonic-main/src/main/webapp/icons/groove/log.png b/subsonic-main/src/main/webapp/icons/groove/log.png Binary files differnew file mode 100644 index 00000000..37f2bcd6 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/log.png diff --git a/subsonic-main/src/main/webapp/icons/groove/logo.png b/subsonic-main/src/main/webapp/icons/groove/logo.png Binary files differnew file mode 100644 index 00000000..9f1f5a86 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/logo.png diff --git a/subsonic-main/src/main/webapp/icons/groove/more.png b/subsonic-main/src/main/webapp/icons/groove/more.png Binary files differnew file mode 100644 index 00000000..4ed374dc --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/more.png diff --git a/subsonic-main/src/main/webapp/icons/groove/now_playing.png b/subsonic-main/src/main/webapp/icons/groove/now_playing.png Binary files differnew file mode 100644 index 00000000..4fa0b813 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/groove/paypal.gif b/subsonic-main/src/main/webapp/icons/groove/paypal.gif Binary files differnew file mode 100644 index 00000000..2a587165 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/paypal.gif diff --git a/subsonic-main/src/main/webapp/icons/groove/phone.png b/subsonic-main/src/main/webapp/icons/groove/phone.png Binary files differnew file mode 100644 index 00000000..693c8620 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/phone.png diff --git a/subsonic-main/src/main/webapp/icons/groove/play.png b/subsonic-main/src/main/webapp/icons/groove/play.png Binary files differnew file mode 100644 index 00000000..1735f2b4 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/play.png diff --git a/subsonic-main/src/main/webapp/icons/groove/playing.png b/subsonic-main/src/main/webapp/icons/groove/playing.png Binary files differnew file mode 100644 index 00000000..739cbf92 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/playing.png diff --git a/subsonic-main/src/main/webapp/icons/groove/podcast.png b/subsonic-main/src/main/webapp/icons/groove/podcast.png Binary files differnew file mode 100644 index 00000000..bd9f0364 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/podcast.png diff --git a/subsonic-main/src/main/webapp/icons/groove/podcast_small.png b/subsonic-main/src/main/webapp/icons/groove/podcast_small.png Binary files differnew file mode 100644 index 00000000..9379394d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/podcast_small.png diff --git a/subsonic-main/src/main/webapp/icons/groove/progress.png b/subsonic-main/src/main/webapp/icons/groove/progress.png Binary files differnew file mode 100644 index 00000000..7c760d04 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/progress.png diff --git a/subsonic-main/src/main/webapp/icons/groove/random.png b/subsonic-main/src/main/webapp/icons/groove/random.png Binary files differnew file mode 100644 index 00000000..d8e3a679 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/random.png diff --git a/subsonic-main/src/main/webapp/icons/groove/rating_half.png b/subsonic-main/src/main/webapp/icons/groove/rating_half.png Binary files differnew file mode 100644 index 00000000..08c51e26 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/rating_half.png diff --git a/subsonic-main/src/main/webapp/icons/groove/rating_off.png b/subsonic-main/src/main/webapp/icons/groove/rating_off.png Binary files differnew file mode 100644 index 00000000..a0d9bbb1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/rating_off.png diff --git a/subsonic-main/src/main/webapp/icons/groove/rating_on.png b/subsonic-main/src/main/webapp/icons/groove/rating_on.png Binary files differnew file mode 100644 index 00000000..1c1239fa --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/rating_on.png diff --git a/subsonic-main/src/main/webapp/icons/groove/remove.png b/subsonic-main/src/main/webapp/icons/groove/remove.png Binary files differnew file mode 100644 index 00000000..e4d8e203 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/remove.png diff --git a/subsonic-main/src/main/webapp/icons/groove/search.png b/subsonic-main/src/main/webapp/icons/groove/search.png Binary files differnew file mode 100644 index 00000000..9e350fb0 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/search.png diff --git a/subsonic-main/src/main/webapp/icons/groove/settings.png b/subsonic-main/src/main/webapp/icons/groove/settings.png Binary files differnew file mode 100644 index 00000000..7bca5d5a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/settings.png diff --git a/subsonic-main/src/main/webapp/icons/groove/status.png b/subsonic-main/src/main/webapp/icons/groove/status.png Binary files differnew file mode 100644 index 00000000..69e94efd --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/status.png diff --git a/subsonic-main/src/main/webapp/icons/groove/up.png b/subsonic-main/src/main/webapp/icons/groove/up.png Binary files differnew file mode 100644 index 00000000..2f730914 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/up.png diff --git a/subsonic-main/src/main/webapp/icons/groove/upload.png b/subsonic-main/src/main/webapp/icons/groove/upload.png Binary files differnew file mode 100644 index 00000000..2f730914 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/groove/upload.png diff --git a/subsonic-main/src/main/webapp/icons/hd/background.png b/subsonic-main/src/main/webapp/icons/hd/background.png Binary files differnew file mode 100644 index 00000000..fa6dc078 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hd/background.png diff --git a/subsonic-main/src/main/webapp/icons/help.png b/subsonic-main/src/main/webapp/icons/help.png Binary files differnew file mode 100644 index 00000000..22801b8f --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/help.png diff --git a/subsonic-main/src/main/webapp/icons/help_small.png b/subsonic-main/src/main/webapp/icons/help_small.png Binary files differnew file mode 100644 index 00000000..f25fc3fb --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/help_small.png diff --git a/subsonic-main/src/main/webapp/icons/hicon/favicon.ico b/subsonic-main/src/main/webapp/icons/hicon/favicon.ico Binary files differnew file mode 100644 index 00000000..65dd49b4 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hicon/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/hicon/help.png b/subsonic-main/src/main/webapp/icons/hicon/help.png Binary files differnew file mode 100644 index 00000000..5104c843 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hicon/help.png diff --git a/subsonic-main/src/main/webapp/icons/hicon/home.png b/subsonic-main/src/main/webapp/icons/hicon/home.png Binary files differnew file mode 100644 index 00000000..ddb635ee --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hicon/home.png diff --git a/subsonic-main/src/main/webapp/icons/hicon/more.png b/subsonic-main/src/main/webapp/icons/hicon/more.png Binary files differnew file mode 100644 index 00000000..c2d88744 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hicon/more.png diff --git a/subsonic-main/src/main/webapp/icons/hicon/now_playing.png b/subsonic-main/src/main/webapp/icons/hicon/now_playing.png Binary files differnew file mode 100644 index 00000000..96d8166e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hicon/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/hicon/podcast_large.png b/subsonic-main/src/main/webapp/icons/hicon/podcast_large.png Binary files differnew file mode 100644 index 00000000..cc1e8863 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hicon/podcast_large.png diff --git a/subsonic-main/src/main/webapp/icons/hicon/settings.png b/subsonic-main/src/main/webapp/icons/hicon/settings.png Binary files differnew file mode 100644 index 00000000..d253f9e8 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hicon/settings.png diff --git a/subsonic-main/src/main/webapp/icons/hicon/status.png b/subsonic-main/src/main/webapp/icons/hicon/status.png Binary files differnew file mode 100644 index 00000000..c478dc9c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hicon/status.png diff --git a/subsonic-main/src/main/webapp/icons/hicon/subsonic.png b/subsonic-main/src/main/webapp/icons/hicon/subsonic.png Binary files differnew file mode 100644 index 00000000..083f929e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hicon/subsonic.png diff --git a/subsonic-main/src/main/webapp/icons/hiconi/Untitled-1.ico b/subsonic-main/src/main/webapp/icons/hiconi/Untitled-1.ico Binary files differnew file mode 100644 index 00000000..10aecae7 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hiconi/Untitled-1.ico diff --git a/subsonic-main/src/main/webapp/icons/hiconi/help.png b/subsonic-main/src/main/webapp/icons/hiconi/help.png Binary files differnew file mode 100644 index 00000000..c62172ff --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hiconi/help.png diff --git a/subsonic-main/src/main/webapp/icons/hiconi/home.png b/subsonic-main/src/main/webapp/icons/hiconi/home.png Binary files differnew file mode 100644 index 00000000..0899225c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hiconi/home.png diff --git a/subsonic-main/src/main/webapp/icons/hiconi/more.png b/subsonic-main/src/main/webapp/icons/hiconi/more.png Binary files differnew file mode 100644 index 00000000..5b021d97 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hiconi/more.png diff --git a/subsonic-main/src/main/webapp/icons/hiconi/now_playing.png b/subsonic-main/src/main/webapp/icons/hiconi/now_playing.png Binary files differnew file mode 100644 index 00000000..901d7f22 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hiconi/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/hiconi/podcast_large.png b/subsonic-main/src/main/webapp/icons/hiconi/podcast_large.png Binary files differnew file mode 100644 index 00000000..258794dd --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hiconi/podcast_large.png diff --git a/subsonic-main/src/main/webapp/icons/hiconi/settings.png b/subsonic-main/src/main/webapp/icons/hiconi/settings.png Binary files differnew file mode 100644 index 00000000..a889eabc --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hiconi/settings.png diff --git a/subsonic-main/src/main/webapp/icons/hiconi/status.png b/subsonic-main/src/main/webapp/icons/hiconi/status.png Binary files differnew file mode 100644 index 00000000..6934303d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hiconi/status.png diff --git a/subsonic-main/src/main/webapp/icons/hiconi/subsonic.png b/subsonic-main/src/main/webapp/icons/hiconi/subsonic.png Binary files differnew file mode 100644 index 00000000..d3aa3d7b --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hiconi/subsonic.png diff --git a/subsonic-main/src/main/webapp/icons/hitech/bg.jpg b/subsonic-main/src/main/webapp/icons/hitech/bg.jpg Binary files differnew file mode 100644 index 00000000..38e290bc --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hitech/bg.jpg diff --git a/subsonic-main/src/main/webapp/icons/hitech/bg2.jpg b/subsonic-main/src/main/webapp/icons/hitech/bg2.jpg Binary files differnew file mode 100644 index 00000000..4d86e3a1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hitech/bg2.jpg diff --git a/subsonic-main/src/main/webapp/icons/hitech/favicon.ico b/subsonic-main/src/main/webapp/icons/hitech/favicon.ico Binary files differnew file mode 100644 index 00000000..3b94d2bd --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hitech/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/hitech/help.png b/subsonic-main/src/main/webapp/icons/hitech/help.png Binary files differnew file mode 100644 index 00000000..d3558111 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hitech/help.png diff --git a/subsonic-main/src/main/webapp/icons/hitech/home.png b/subsonic-main/src/main/webapp/icons/hitech/home.png Binary files differnew file mode 100644 index 00000000..99703bee --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hitech/home.png diff --git a/subsonic-main/src/main/webapp/icons/hitech/more.png b/subsonic-main/src/main/webapp/icons/hitech/more.png Binary files differnew file mode 100644 index 00000000..e98c9875 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hitech/more.png diff --git a/subsonic-main/src/main/webapp/icons/hitech/now_playing.png b/subsonic-main/src/main/webapp/icons/hitech/now_playing.png Binary files differnew file mode 100644 index 00000000..1682aac2 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hitech/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/hitech/podcast_large.png b/subsonic-main/src/main/webapp/icons/hitech/podcast_large.png Binary files differnew file mode 100644 index 00000000..0cd41713 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hitech/podcast_large.png diff --git a/subsonic-main/src/main/webapp/icons/hitech/settings.png b/subsonic-main/src/main/webapp/icons/hitech/settings.png Binary files differnew file mode 100644 index 00000000..f736b988 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hitech/settings.png diff --git a/subsonic-main/src/main/webapp/icons/hitech/status.png b/subsonic-main/src/main/webapp/icons/hitech/status.png Binary files differnew file mode 100644 index 00000000..2cfebe96 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hitech/status.png diff --git a/subsonic-main/src/main/webapp/icons/hitech/subsonic.png b/subsonic-main/src/main/webapp/icons/hitech/subsonic.png Binary files differnew file mode 100644 index 00000000..44305b32 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/hitech/subsonic.png diff --git a/subsonic-main/src/main/webapp/icons/home.png b/subsonic-main/src/main/webapp/icons/home.png Binary files differnew file mode 100644 index 00000000..7e87c701 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/home.png diff --git a/subsonic-main/src/main/webapp/icons/log.png b/subsonic-main/src/main/webapp/icons/log.png Binary files differnew file mode 100644 index 00000000..8b2c6f4a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/log.png diff --git a/subsonic-main/src/main/webapp/icons/midnight/back.png b/subsonic-main/src/main/webapp/icons/midnight/back.png Binary files differnew file mode 100644 index 00000000..a07f3d89 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnight/back.png diff --git a/subsonic-main/src/main/webapp/icons/midnight/forward.png b/subsonic-main/src/main/webapp/icons/midnight/forward.png Binary files differnew file mode 100644 index 00000000..000658bc --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnight/forward.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/error.png b/subsonic-main/src/main/webapp/icons/midnightfun/error.png Binary files differnew file mode 100644 index 00000000..e0440842 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/error.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/favicon.ico b/subsonic-main/src/main/webapp/icons/midnightfun/favicon.ico Binary files differnew file mode 100644 index 00000000..17730887 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_Now_Playing.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_Now_Playing.png Binary files differnew file mode 100644 index 00000000..30997a6c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_Now_Playing.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_add.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_add.png Binary files differnew file mode 100644 index 00000000..e1fa11f8 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_add.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_back.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_back.png Binary files differnew file mode 100644 index 00000000..5b07c5e5 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_back.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_background.gif b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_background.gif Binary files differnew file mode 100644 index 00000000..3b697cea --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_background.gif diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_clear_Rating.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_clear_Rating.png Binary files differnew file mode 100644 index 00000000..bc59f297 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_clear_Rating.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_donate.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_donate.png Binary files differnew file mode 100644 index 00000000..2453adbe --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_donate.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_down.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_down.png Binary files differnew file mode 100644 index 00000000..2dd28e91 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_down.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_download.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_download.png Binary files differnew file mode 100644 index 00000000..18ab592a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_download.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_form_controls.jpg b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_form_controls.jpg Binary files differnew file mode 100644 index 00000000..6a2219b8 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_form_controls.jpg diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_form_controls_hover.jpg b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_form_controls_hover.jpg Binary files differnew file mode 100644 index 00000000..d37fcc92 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_form_controls_hover.jpg diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_forward.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_forward.png Binary files differnew file mode 100644 index 00000000..70cfd5f2 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_forward.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_help.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_help.png Binary files differnew file mode 100644 index 00000000..209f1d28 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_help.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_help_small.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_help_small.png Binary files differnew file mode 100644 index 00000000..352fd541 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_help_small.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_home.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_home.png Binary files differnew file mode 100644 index 00000000..32727e76 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_home.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_home_hover.jpg b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_home_hover.jpg Binary files differnew file mode 100644 index 00000000..b06edcfb --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_home_hover.jpg diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_log.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_log.png Binary files differnew file mode 100644 index 00000000..722ff9f1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_log.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_logo.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_logo.png Binary files differnew file mode 100644 index 00000000..d3cbbdf1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_logo.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_logo_favicon.ico b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_logo_favicon.ico Binary files differnew file mode 100644 index 00000000..db665a4e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_logo_favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_more.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_more.png Binary files differnew file mode 100644 index 00000000..4ed5365e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_more.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_paypal.gif b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_paypal.gif Binary files differnew file mode 100644 index 00000000..2a587165 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_paypal.gif diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_phone.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_phone.png Binary files differnew file mode 100644 index 00000000..28e2c561 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_phone.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_play.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_play.png Binary files differnew file mode 100644 index 00000000..bbb0f473 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_play.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_playing.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_playing.png Binary files differnew file mode 100644 index 00000000..a1d9feda --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_playing.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_podcast.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_podcast.png Binary files differnew file mode 100644 index 00000000..27845212 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_podcast.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_podcast_small.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_podcast_small.png Binary files differnew file mode 100644 index 00000000..bd1d73d7 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_podcast_small.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_random.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_random.png Binary files differnew file mode 100644 index 00000000..05032585 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_random.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_remove.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_remove.png Binary files differnew file mode 100644 index 00000000..278879fd --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_remove.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_search.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_search.png Binary files differnew file mode 100644 index 00000000..130094f2 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_search.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_settings.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_settings.png Binary files differnew file mode 100644 index 00000000..a0c28f21 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_settings.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_status.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_status.png Binary files differnew file mode 100644 index 00000000..6f8e175b --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_status.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_table.jpg b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_table.jpg Binary files differnew file mode 100644 index 00000000..2f53038a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_table.jpg diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_text_back.jpg b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_text_back.jpg Binary files differnew file mode 100644 index 00000000..c70073e2 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_text_back.jpg diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_up.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_up.png Binary files differnew file mode 100644 index 00000000..c6bd1fb2 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_up.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_upload.png b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_upload.png Binary files differnew file mode 100644 index 00000000..c4488ad4 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/midnightfun_upload.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/progress.png b/subsonic-main/src/main/webapp/icons/midnightfun/progress.png Binary files differnew file mode 100644 index 00000000..ddd5a913 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/progress.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/ratingHalf.png b/subsonic-main/src/main/webapp/icons/midnightfun/ratingHalf.png Binary files differnew file mode 100644 index 00000000..ba171709 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/ratingHalf.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/ratingOff.png b/subsonic-main/src/main/webapp/icons/midnightfun/ratingOff.png Binary files differnew file mode 100644 index 00000000..bdd052ab --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/ratingOff.png diff --git a/subsonic-main/src/main/webapp/icons/midnightfun/ratingOn.png b/subsonic-main/src/main/webapp/icons/midnightfun/ratingOn.png Binary files differnew file mode 100644 index 00000000..d9588501 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/midnightfun/ratingOn.png diff --git a/subsonic-main/src/main/webapp/icons/monochrome/subdot.png b/subsonic-main/src/main/webapp/icons/monochrome/subdot.png Binary files differnew file mode 100644 index 00000000..54623ab6 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/monochrome/subdot.png diff --git a/subsonic-main/src/main/webapp/icons/more.png b/subsonic-main/src/main/webapp/icons/more.png Binary files differnew file mode 100644 index 00000000..cd5a20f6 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/more.png diff --git a/subsonic-main/src/main/webapp/icons/now_playing.png b/subsonic-main/src/main/webapp/icons/now_playing.png Binary files differnew file mode 100644 index 00000000..a63e630d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/paypal.gif b/subsonic-main/src/main/webapp/icons/paypal.gif Binary files differnew file mode 100644 index 00000000..d017250a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/paypal.gif diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/add.png b/subsonic-main/src/main/webapp/icons/pinkpanther/add.png Binary files differnew file mode 100644 index 00000000..26e12f87 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/add.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/back.png b/subsonic-main/src/main/webapp/icons/pinkpanther/back.png Binary files differnew file mode 100644 index 00000000..295ec91b --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/back.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/clear_rating.png b/subsonic-main/src/main/webapp/icons/pinkpanther/clear_rating.png Binary files differnew file mode 100644 index 00000000..64d78601 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/clear_rating.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/donate.png b/subsonic-main/src/main/webapp/icons/pinkpanther/donate.png Binary files differnew file mode 100644 index 00000000..f9c17ceb --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/donate.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/down.png b/subsonic-main/src/main/webapp/icons/pinkpanther/down.png Binary files differnew file mode 100644 index 00000000..5635af51 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/down.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/download.png b/subsonic-main/src/main/webapp/icons/pinkpanther/download.png Binary files differnew file mode 100644 index 00000000..1b24ae83 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/download.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/error.png b/subsonic-main/src/main/webapp/icons/pinkpanther/error.png Binary files differnew file mode 100644 index 00000000..c7d60958 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/error.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/favicon.ico b/subsonic-main/src/main/webapp/icons/pinkpanther/favicon.ico Binary files differnew file mode 100644 index 00000000..4348b09e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/forward.png b/subsonic-main/src/main/webapp/icons/pinkpanther/forward.png Binary files differnew file mode 100644 index 00000000..b88d5106 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/forward.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/help.png b/subsonic-main/src/main/webapp/icons/pinkpanther/help.png Binary files differnew file mode 100644 index 00000000..de1a0f6d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/help.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/help_small.png b/subsonic-main/src/main/webapp/icons/pinkpanther/help_small.png Binary files differnew file mode 100644 index 00000000..824519e9 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/help_small.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/home.png b/subsonic-main/src/main/webapp/icons/pinkpanther/home.png Binary files differnew file mode 100644 index 00000000..7f4a4d58 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/home.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/log.png b/subsonic-main/src/main/webapp/icons/pinkpanther/log.png Binary files differnew file mode 100644 index 00000000..a4fa9297 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/log.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/logo.png b/subsonic-main/src/main/webapp/icons/pinkpanther/logo.png Binary files differnew file mode 100644 index 00000000..9bf1eb83 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/logo.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/more.png b/subsonic-main/src/main/webapp/icons/pinkpanther/more.png Binary files differnew file mode 100644 index 00000000..bfc8dbb8 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/more.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/now_playing.png b/subsonic-main/src/main/webapp/icons/pinkpanther/now_playing.png Binary files differnew file mode 100644 index 00000000..42931eff --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/paypal.gif b/subsonic-main/src/main/webapp/icons/pinkpanther/paypal.gif Binary files differnew file mode 100644 index 00000000..2a587165 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/paypal.gif diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/phone.png b/subsonic-main/src/main/webapp/icons/pinkpanther/phone.png Binary files differnew file mode 100644 index 00000000..693c8620 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/phone.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/play.png b/subsonic-main/src/main/webapp/icons/pinkpanther/play.png Binary files differnew file mode 100644 index 00000000..cbcb8d40 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/play.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/playing.png b/subsonic-main/src/main/webapp/icons/pinkpanther/playing.png Binary files differnew file mode 100644 index 00000000..8b620c2a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/playing.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/podcast.png b/subsonic-main/src/main/webapp/icons/pinkpanther/podcast.png Binary files differnew file mode 100644 index 00000000..033d32c7 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/podcast.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/podcast_small.png b/subsonic-main/src/main/webapp/icons/pinkpanther/podcast_small.png Binary files differnew file mode 100644 index 00000000..87d2fe25 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/podcast_small.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/progress.png b/subsonic-main/src/main/webapp/icons/pinkpanther/progress.png Binary files differnew file mode 100644 index 00000000..13b465ba --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/progress.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/random.png b/subsonic-main/src/main/webapp/icons/pinkpanther/random.png Binary files differnew file mode 100644 index 00000000..2b0fdb06 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/random.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/rating_half.png b/subsonic-main/src/main/webapp/icons/pinkpanther/rating_half.png Binary files differnew file mode 100644 index 00000000..08ab0d39 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/rating_half.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/rating_off.png b/subsonic-main/src/main/webapp/icons/pinkpanther/rating_off.png Binary files differnew file mode 100644 index 00000000..a0d9bbb1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/rating_off.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/rating_on.png b/subsonic-main/src/main/webapp/icons/pinkpanther/rating_on.png Binary files differnew file mode 100644 index 00000000..8c4d6602 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/rating_on.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/remove.png b/subsonic-main/src/main/webapp/icons/pinkpanther/remove.png Binary files differnew file mode 100644 index 00000000..c0afb187 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/remove.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/search.png b/subsonic-main/src/main/webapp/icons/pinkpanther/search.png Binary files differnew file mode 100644 index 00000000..6dea8731 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/search.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/settings.png b/subsonic-main/src/main/webapp/icons/pinkpanther/settings.png Binary files differnew file mode 100644 index 00000000..547bef7b --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/settings.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/status.png b/subsonic-main/src/main/webapp/icons/pinkpanther/status.png Binary files differnew file mode 100644 index 00000000..f9c4503f --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/status.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/up.png b/subsonic-main/src/main/webapp/icons/pinkpanther/up.png Binary files differnew file mode 100644 index 00000000..ee5ad884 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/up.png diff --git a/subsonic-main/src/main/webapp/icons/pinkpanther/upload.png b/subsonic-main/src/main/webapp/icons/pinkpanther/upload.png Binary files differnew file mode 100644 index 00000000..cf3f38da --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/pinkpanther/upload.png diff --git a/subsonic-main/src/main/webapp/icons/play.gif b/subsonic-main/src/main/webapp/icons/play.gif Binary files differnew file mode 100644 index 00000000..d1ccbcf4 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/play.gif diff --git a/subsonic-main/src/main/webapp/icons/podcast.png b/subsonic-main/src/main/webapp/icons/podcast.png Binary files differnew file mode 100644 index 00000000..c8afc597 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/podcast.png diff --git a/subsonic-main/src/main/webapp/icons/podcast_large.png b/subsonic-main/src/main/webapp/icons/podcast_large.png Binary files differnew file mode 100644 index 00000000..e95eb343 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/podcast_large.png diff --git a/subsonic-main/src/main/webapp/icons/progress.png b/subsonic-main/src/main/webapp/icons/progress.png Binary files differnew file mode 100644 index 00000000..ddd5a913 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/progress.png diff --git a/subsonic-main/src/main/webapp/icons/random.png b/subsonic-main/src/main/webapp/icons/random.png Binary files differnew file mode 100644 index 00000000..f25fc3fb --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/random.png diff --git a/subsonic-main/src/main/webapp/icons/ratingHalf.png b/subsonic-main/src/main/webapp/icons/ratingHalf.png Binary files differnew file mode 100644 index 00000000..d8550838 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ratingHalf.png diff --git a/subsonic-main/src/main/webapp/icons/ratingOff.png b/subsonic-main/src/main/webapp/icons/ratingOff.png Binary files differnew file mode 100644 index 00000000..a0d9bbb1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ratingOff.png diff --git a/subsonic-main/src/main/webapp/icons/ratingOn.png b/subsonic-main/src/main/webapp/icons/ratingOn.png Binary files differnew file mode 100644 index 00000000..b3e99d1d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ratingOn.png diff --git a/subsonic-main/src/main/webapp/icons/remove.gif b/subsonic-main/src/main/webapp/icons/remove.gif Binary files differnew file mode 100644 index 00000000..b7656a88 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/remove.gif diff --git a/subsonic-main/src/main/webapp/icons/ripserver/add.gif b/subsonic-main/src/main/webapp/icons/ripserver/add.gif Binary files differnew file mode 100644 index 00000000..3902057c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/add.gif diff --git a/subsonic-main/src/main/webapp/icons/ripserver/back.gif b/subsonic-main/src/main/webapp/icons/ripserver/back.gif Binary files differnew file mode 100644 index 00000000..c91d92c0 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/back.gif diff --git a/subsonic-main/src/main/webapp/icons/ripserver/background.png b/subsonic-main/src/main/webapp/icons/ripserver/background.png Binary files differnew file mode 100644 index 00000000..2d4a5c7a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/background.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/clearRating.png b/subsonic-main/src/main/webapp/icons/ripserver/clearRating.png Binary files differnew file mode 100644 index 00000000..59a5ca41 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/clearRating.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/current.gif b/subsonic-main/src/main/webapp/icons/ripserver/current.gif Binary files differnew file mode 100644 index 00000000..8591e1b6 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/current.gif diff --git a/subsonic-main/src/main/webapp/icons/ripserver/donate.png b/subsonic-main/src/main/webapp/icons/ripserver/donate.png Binary files differnew file mode 100644 index 00000000..87fb25e1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/donate.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/down.gif b/subsonic-main/src/main/webapp/icons/ripserver/down.gif Binary files differnew file mode 100644 index 00000000..903bfc29 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/down.gif diff --git a/subsonic-main/src/main/webapp/icons/ripserver/download.gif b/subsonic-main/src/main/webapp/icons/ripserver/download.gif Binary files differnew file mode 100644 index 00000000..b9623b25 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/download.gif diff --git a/subsonic-main/src/main/webapp/icons/ripserver/error.png b/subsonic-main/src/main/webapp/icons/ripserver/error.png Binary files differnew file mode 100644 index 00000000..00d9f2c6 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/error.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/favicon.ico b/subsonic-main/src/main/webapp/icons/ripserver/favicon.ico Binary files differnew file mode 100644 index 00000000..127d5078 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/ripserver/forward.gif b/subsonic-main/src/main/webapp/icons/ripserver/forward.gif Binary files differnew file mode 100644 index 00000000..44199a6d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/forward.gif diff --git a/subsonic-main/src/main/webapp/icons/ripserver/help.png b/subsonic-main/src/main/webapp/icons/ripserver/help.png Binary files differnew file mode 100644 index 00000000..cee3d4a0 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/help.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/help_small.png b/subsonic-main/src/main/webapp/icons/ripserver/help_small.png Binary files differnew file mode 100644 index 00000000..36a20b64 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/help_small.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/home.png b/subsonic-main/src/main/webapp/icons/ripserver/home.png Binary files differnew file mode 100644 index 00000000..36eb1c58 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/home.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/log.png b/subsonic-main/src/main/webapp/icons/ripserver/log.png Binary files differnew file mode 100644 index 00000000..8b2c6f4a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/log.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/more.png b/subsonic-main/src/main/webapp/icons/ripserver/more.png Binary files differnew file mode 100644 index 00000000..aee57a10 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/more.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/now_playing.png b/subsonic-main/src/main/webapp/icons/ripserver/now_playing.png Binary files differnew file mode 100644 index 00000000..671c4074 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/paypal.gif b/subsonic-main/src/main/webapp/icons/ripserver/paypal.gif Binary files differnew file mode 100644 index 00000000..d017250a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/paypal.gif diff --git a/subsonic-main/src/main/webapp/icons/ripserver/play.gif b/subsonic-main/src/main/webapp/icons/ripserver/play.gif Binary files differnew file mode 100644 index 00000000..e42ed160 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/play.gif diff --git a/subsonic-main/src/main/webapp/icons/ripserver/podcast.png b/subsonic-main/src/main/webapp/icons/ripserver/podcast.png Binary files differnew file mode 100644 index 00000000..f4574525 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/podcast.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/podcast_large.png b/subsonic-main/src/main/webapp/icons/ripserver/podcast_large.png Binary files differnew file mode 100644 index 00000000..f4574525 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/podcast_large.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/progress.png b/subsonic-main/src/main/webapp/icons/ripserver/progress.png Binary files differnew file mode 100644 index 00000000..ddd5a913 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/progress.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/random.png b/subsonic-main/src/main/webapp/icons/ripserver/random.png Binary files differnew file mode 100644 index 00000000..ee9750f0 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/random.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/ratingHalf.png b/subsonic-main/src/main/webapp/icons/ripserver/ratingHalf.png Binary files differnew file mode 100644 index 00000000..ba171709 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/ratingHalf.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/ratingOff.png b/subsonic-main/src/main/webapp/icons/ripserver/ratingOff.png Binary files differnew file mode 100644 index 00000000..bdd052ab --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/ratingOff.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/ratingOn.png b/subsonic-main/src/main/webapp/icons/ripserver/ratingOn.png Binary files differnew file mode 100644 index 00000000..d9588501 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/ratingOn.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/remove.gif b/subsonic-main/src/main/webapp/icons/ripserver/remove.gif Binary files differnew file mode 100644 index 00000000..33b9414f --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/remove.gif diff --git a/subsonic-main/src/main/webapp/icons/ripserver/search.png b/subsonic-main/src/main/webapp/icons/ripserver/search.png Binary files differnew file mode 100644 index 00000000..b6dd2039 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/search.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/settings.png b/subsonic-main/src/main/webapp/icons/ripserver/settings.png Binary files differnew file mode 100644 index 00000000..c6f2ed15 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/settings.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/status.png b/subsonic-main/src/main/webapp/icons/ripserver/status.png Binary files differnew file mode 100644 index 00000000..fdbc7fd5 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/status.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/subsonic_black.png b/subsonic-main/src/main/webapp/icons/ripserver/subsonic_black.png Binary files differnew file mode 100644 index 00000000..421b61d1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/subsonic_black.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/subsonic_white.png b/subsonic-main/src/main/webapp/icons/ripserver/subsonic_white.png Binary files differnew file mode 100644 index 00000000..3089427f --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/subsonic_white.png diff --git a/subsonic-main/src/main/webapp/icons/ripserver/up.gif b/subsonic-main/src/main/webapp/icons/ripserver/up.gif Binary files differnew file mode 100644 index 00000000..7474ee2e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/up.gif diff --git a/subsonic-main/src/main/webapp/icons/ripserver/upload.gif b/subsonic-main/src/main/webapp/icons/ripserver/upload.gif Binary files differnew file mode 100644 index 00000000..43b98d96 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/upload.gif diff --git a/subsonic-main/src/main/webapp/icons/ripserver/wap.png b/subsonic-main/src/main/webapp/icons/ripserver/wap.png Binary files differnew file mode 100644 index 00000000..0d67e2de --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/ripserver/wap.png diff --git a/subsonic-main/src/main/webapp/icons/search.png b/subsonic-main/src/main/webapp/icons/search.png Binary files differnew file mode 100644 index 00000000..7fbfb6f5 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/search.png diff --git a/subsonic-main/src/main/webapp/icons/settings.png b/subsonic-main/src/main/webapp/icons/settings.png Binary files differnew file mode 100644 index 00000000..9173cbf7 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/settings.png diff --git a/subsonic-main/src/main/webapp/icons/share_facebook.png b/subsonic-main/src/main/webapp/icons/share_facebook.png Binary files differnew file mode 100644 index 00000000..30f4d6ce --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/share_facebook.png diff --git a/subsonic-main/src/main/webapp/icons/share_googleplus.png b/subsonic-main/src/main/webapp/icons/share_googleplus.png Binary files differnew file mode 100644 index 00000000..fff340f2 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/share_googleplus.png diff --git a/subsonic-main/src/main/webapp/icons/share_twitter.png b/subsonic-main/src/main/webapp/icons/share_twitter.png Binary files differnew file mode 100644 index 00000000..8b5eeace --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/share_twitter.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/add.png b/subsonic-main/src/main/webapp/icons/simplify/add.png Binary files differnew file mode 100644 index 00000000..9428fc87 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/add.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/back.png b/subsonic-main/src/main/webapp/icons/simplify/back.png Binary files differnew file mode 100644 index 00000000..05df3b64 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/back.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/clear_rating.png b/subsonic-main/src/main/webapp/icons/simplify/clear_rating.png Binary files differnew file mode 100644 index 00000000..4d028588 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/clear_rating.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/donate.png b/subsonic-main/src/main/webapp/icons/simplify/donate.png Binary files differnew file mode 100644 index 00000000..f9c17ceb --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/donate.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/down.png b/subsonic-main/src/main/webapp/icons/simplify/down.png Binary files differnew file mode 100644 index 00000000..fe798e45 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/down.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/download.png b/subsonic-main/src/main/webapp/icons/simplify/download.png Binary files differnew file mode 100644 index 00000000..dbebf431 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/download.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/error.png b/subsonic-main/src/main/webapp/icons/simplify/error.png Binary files differnew file mode 100644 index 00000000..c7d60958 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/error.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/favicon.ico b/subsonic-main/src/main/webapp/icons/simplify/favicon.ico Binary files differnew file mode 100644 index 00000000..685c131f --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/simplify/forward.png b/subsonic-main/src/main/webapp/icons/simplify/forward.png Binary files differnew file mode 100644 index 00000000..99b0ec04 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/forward.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/help.png b/subsonic-main/src/main/webapp/icons/simplify/help.png Binary files differnew file mode 100644 index 00000000..fafc0ac5 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/help.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/help_small.png b/subsonic-main/src/main/webapp/icons/simplify/help_small.png Binary files differnew file mode 100644 index 00000000..063af3e4 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/help_small.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/home.png b/subsonic-main/src/main/webapp/icons/simplify/home.png Binary files differnew file mode 100644 index 00000000..5bbee5cd --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/home.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/log.png b/subsonic-main/src/main/webapp/icons/simplify/log.png Binary files differnew file mode 100644 index 00000000..60d07c2b --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/log.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/logo.png b/subsonic-main/src/main/webapp/icons/simplify/logo.png Binary files differnew file mode 100644 index 00000000..553a2bf0 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/logo.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/more.png b/subsonic-main/src/main/webapp/icons/simplify/more.png Binary files differnew file mode 100644 index 00000000..378e05f2 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/more.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/now_playing.png b/subsonic-main/src/main/webapp/icons/simplify/now_playing.png Binary files differnew file mode 100644 index 00000000..10cc8cfc --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/paypal.gif b/subsonic-main/src/main/webapp/icons/simplify/paypal.gif Binary files differnew file mode 100644 index 00000000..2a587165 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/paypal.gif diff --git a/subsonic-main/src/main/webapp/icons/simplify/phone.png b/subsonic-main/src/main/webapp/icons/simplify/phone.png Binary files differnew file mode 100644 index 00000000..693c8620 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/phone.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/play.png b/subsonic-main/src/main/webapp/icons/simplify/play.png Binary files differnew file mode 100644 index 00000000..76bc8586 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/play.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/playing.png b/subsonic-main/src/main/webapp/icons/simplify/playing.png Binary files differnew file mode 100644 index 00000000..e46576de --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/playing.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/podcast.png b/subsonic-main/src/main/webapp/icons/simplify/podcast.png Binary files differnew file mode 100644 index 00000000..51004d5f --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/podcast.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/podcast_small.png b/subsonic-main/src/main/webapp/icons/simplify/podcast_small.png Binary files differnew file mode 100644 index 00000000..9af49252 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/podcast_small.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/progress.png b/subsonic-main/src/main/webapp/icons/simplify/progress.png Binary files differnew file mode 100644 index 00000000..13b465ba --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/progress.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/random.png b/subsonic-main/src/main/webapp/icons/simplify/random.png Binary files differnew file mode 100644 index 00000000..dfb9ec6e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/random.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/rating_half.png b/subsonic-main/src/main/webapp/icons/simplify/rating_half.png Binary files differnew file mode 100644 index 00000000..08ab0d39 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/rating_half.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/rating_off.png b/subsonic-main/src/main/webapp/icons/simplify/rating_off.png Binary files differnew file mode 100644 index 00000000..a0d9bbb1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/rating_off.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/rating_on.png b/subsonic-main/src/main/webapp/icons/simplify/rating_on.png Binary files differnew file mode 100644 index 00000000..8c4d6602 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/rating_on.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/remove.png b/subsonic-main/src/main/webapp/icons/simplify/remove.png Binary files differnew file mode 100644 index 00000000..c0afb187 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/remove.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/search.png b/subsonic-main/src/main/webapp/icons/simplify/search.png Binary files differnew file mode 100644 index 00000000..4607c1bd --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/search.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/settings.png b/subsonic-main/src/main/webapp/icons/simplify/settings.png Binary files differnew file mode 100644 index 00000000..ff2efcd9 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/settings.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/status.png b/subsonic-main/src/main/webapp/icons/simplify/status.png Binary files differnew file mode 100644 index 00000000..487c309b --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/status.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/up.png b/subsonic-main/src/main/webapp/icons/simplify/up.png Binary files differnew file mode 100644 index 00000000..0b2a5f0b --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/up.png diff --git a/subsonic-main/src/main/webapp/icons/simplify/upload.png b/subsonic-main/src/main/webapp/icons/simplify/upload.png Binary files differnew file mode 100644 index 00000000..078db7c2 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/simplify/upload.png diff --git a/subsonic-main/src/main/webapp/icons/slick/favicon.ico b/subsonic-main/src/main/webapp/icons/slick/favicon.ico Binary files differnew file mode 100644 index 00000000..c7eb8409 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/slick/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/slick/help.png b/subsonic-main/src/main/webapp/icons/slick/help.png Binary files differnew file mode 100644 index 00000000..bb22b95d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/slick/help.png diff --git a/subsonic-main/src/main/webapp/icons/slick/home.png b/subsonic-main/src/main/webapp/icons/slick/home.png Binary files differnew file mode 100644 index 00000000..6b729b81 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/slick/home.png diff --git a/subsonic-main/src/main/webapp/icons/slick/more.png b/subsonic-main/src/main/webapp/icons/slick/more.png Binary files differnew file mode 100644 index 00000000..5244ad4a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/slick/more.png diff --git a/subsonic-main/src/main/webapp/icons/slick/now_playing.png b/subsonic-main/src/main/webapp/icons/slick/now_playing.png Binary files differnew file mode 100644 index 00000000..0c9836a4 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/slick/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/slick/podcast_large.png b/subsonic-main/src/main/webapp/icons/slick/podcast_large.png Binary files differnew file mode 100644 index 00000000..694636ba --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/slick/podcast_large.png diff --git a/subsonic-main/src/main/webapp/icons/slick/settings.png b/subsonic-main/src/main/webapp/icons/slick/settings.png Binary files differnew file mode 100644 index 00000000..d62f6f98 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/slick/settings.png diff --git a/subsonic-main/src/main/webapp/icons/slick/status.png b/subsonic-main/src/main/webapp/icons/slick/status.png Binary files differnew file mode 100644 index 00000000..f1dcd989 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/slick/status.png diff --git a/subsonic-main/src/main/webapp/icons/slick/subsonic.png b/subsonic-main/src/main/webapp/icons/slick/subsonic.png Binary files differnew file mode 100644 index 00000000..7d839665 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/slick/subsonic.png diff --git a/subsonic-main/src/main/webapp/icons/slick/top_bg.jpg b/subsonic-main/src/main/webapp/icons/slick/top_bg.jpg Binary files differnew file mode 100644 index 00000000..a095ae2e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/slick/top_bg.jpg diff --git a/subsonic-main/src/main/webapp/icons/sonic/add.png b/subsonic-main/src/main/webapp/icons/sonic/add.png Binary files differnew file mode 100644 index 00000000..14695eb2 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/add.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/back.png b/subsonic-main/src/main/webapp/icons/sonic/back.png Binary files differnew file mode 100644 index 00000000..3aa8dce5 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/back.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/clear_rating.png b/subsonic-main/src/main/webapp/icons/sonic/clear_rating.png Binary files differnew file mode 100644 index 00000000..5d0104e7 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/clear_rating.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/donate.png b/subsonic-main/src/main/webapp/icons/sonic/donate.png Binary files differnew file mode 100644 index 00000000..f9c17ceb --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/donate.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/down.png b/subsonic-main/src/main/webapp/icons/sonic/down.png Binary files differnew file mode 100644 index 00000000..064a3659 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/down.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/download.png b/subsonic-main/src/main/webapp/icons/sonic/download.png Binary files differnew file mode 100644 index 00000000..752ad374 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/download.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/error.png b/subsonic-main/src/main/webapp/icons/sonic/error.png Binary files differnew file mode 100644 index 00000000..c7d60958 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/error.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/favicon.ico b/subsonic-main/src/main/webapp/icons/sonic/favicon.ico Binary files differnew file mode 100644 index 00000000..ef507a55 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/sonic/forward.png b/subsonic-main/src/main/webapp/icons/sonic/forward.png Binary files differnew file mode 100644 index 00000000..7af499e1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/forward.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/help.png b/subsonic-main/src/main/webapp/icons/sonic/help.png Binary files differnew file mode 100644 index 00000000..4f00214f --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/help.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/help_small.png b/subsonic-main/src/main/webapp/icons/sonic/help_small.png Binary files differnew file mode 100644 index 00000000..cf98d072 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/help_small.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/home.png b/subsonic-main/src/main/webapp/icons/sonic/home.png Binary files differnew file mode 100644 index 00000000..50fe549d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/home.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/log.png b/subsonic-main/src/main/webapp/icons/sonic/log.png Binary files differnew file mode 100644 index 00000000..7764ae53 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/log.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/logo.png b/subsonic-main/src/main/webapp/icons/sonic/logo.png Binary files differnew file mode 100644 index 00000000..68aca05c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/logo.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/more.png b/subsonic-main/src/main/webapp/icons/sonic/more.png Binary files differnew file mode 100644 index 00000000..66775f30 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/more.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/now_playing.png b/subsonic-main/src/main/webapp/icons/sonic/now_playing.png Binary files differnew file mode 100644 index 00000000..da58451e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/paypal.gif b/subsonic-main/src/main/webapp/icons/sonic/paypal.gif Binary files differnew file mode 100644 index 00000000..2a587165 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/paypal.gif diff --git a/subsonic-main/src/main/webapp/icons/sonic/phone.png b/subsonic-main/src/main/webapp/icons/sonic/phone.png Binary files differnew file mode 100644 index 00000000..c2c4f494 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/phone.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/play.png b/subsonic-main/src/main/webapp/icons/sonic/play.png Binary files differnew file mode 100644 index 00000000..782ceae1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/play.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/playing.png b/subsonic-main/src/main/webapp/icons/sonic/playing.png Binary files differnew file mode 100644 index 00000000..4983700a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/playing.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/podcast.png b/subsonic-main/src/main/webapp/icons/sonic/podcast.png Binary files differnew file mode 100644 index 00000000..98511ad4 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/podcast.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/podcast_small.png b/subsonic-main/src/main/webapp/icons/sonic/podcast_small.png Binary files differnew file mode 100644 index 00000000..d5fa56bd --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/podcast_small.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/progress.png b/subsonic-main/src/main/webapp/icons/sonic/progress.png Binary files differnew file mode 100644 index 00000000..13b465ba --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/progress.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/random.png b/subsonic-main/src/main/webapp/icons/sonic/random.png Binary files differnew file mode 100644 index 00000000..6289938c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/random.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/rating_half.png b/subsonic-main/src/main/webapp/icons/sonic/rating_half.png Binary files differnew file mode 100644 index 00000000..08ab0d39 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/rating_half.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/rating_off.png b/subsonic-main/src/main/webapp/icons/sonic/rating_off.png Binary files differnew file mode 100644 index 00000000..a0d9bbb1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/rating_off.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/rating_on.png b/subsonic-main/src/main/webapp/icons/sonic/rating_on.png Binary files differnew file mode 100644 index 00000000..8c4d6602 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/rating_on.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/remove.png b/subsonic-main/src/main/webapp/icons/sonic/remove.png Binary files differnew file mode 100644 index 00000000..4f9c28a0 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/remove.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/search.png b/subsonic-main/src/main/webapp/icons/sonic/search.png Binary files differnew file mode 100644 index 00000000..4228f6bc --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/search.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/settings.png b/subsonic-main/src/main/webapp/icons/sonic/settings.png Binary files differnew file mode 100644 index 00000000..9897b183 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/settings.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/status.png b/subsonic-main/src/main/webapp/icons/sonic/status.png Binary files differnew file mode 100644 index 00000000..21ce5615 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/status.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/up.png b/subsonic-main/src/main/webapp/icons/sonic/up.png Binary files differnew file mode 100644 index 00000000..19155c33 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/up.png diff --git a/subsonic-main/src/main/webapp/icons/sonic/upload.png b/subsonic-main/src/main/webapp/icons/sonic/upload.png Binary files differnew file mode 100644 index 00000000..eb082cbc --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic/upload.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/add.png b/subsonic-main/src/main/webapp/icons/sonic_blue/add.png Binary files differnew file mode 100644 index 00000000..d16e3473 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/add.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/back.png b/subsonic-main/src/main/webapp/icons/sonic_blue/back.png Binary files differnew file mode 100644 index 00000000..abf1177f --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/back.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/clear_rating.png b/subsonic-main/src/main/webapp/icons/sonic_blue/clear_rating.png Binary files differnew file mode 100644 index 00000000..64d78601 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/clear_rating.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/donate.png b/subsonic-main/src/main/webapp/icons/sonic_blue/donate.png Binary files differnew file mode 100644 index 00000000..f9c17ceb --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/donate.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/down.png b/subsonic-main/src/main/webapp/icons/sonic_blue/down.png Binary files differnew file mode 100644 index 00000000..16efb09d --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/down.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/download.png b/subsonic-main/src/main/webapp/icons/sonic_blue/download.png Binary files differnew file mode 100644 index 00000000..6667c702 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/download.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/error.png b/subsonic-main/src/main/webapp/icons/sonic_blue/error.png Binary files differnew file mode 100644 index 00000000..c7d60958 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/error.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/favicon.ico b/subsonic-main/src/main/webapp/icons/sonic_blue/favicon.ico Binary files differnew file mode 100644 index 00000000..ef507a55 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/forward.png b/subsonic-main/src/main/webapp/icons/sonic_blue/forward.png Binary files differnew file mode 100644 index 00000000..d288c0ce --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/forward.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/help.png b/subsonic-main/src/main/webapp/icons/sonic_blue/help.png Binary files differnew file mode 100644 index 00000000..1ca1f3de --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/help.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/help_small.png b/subsonic-main/src/main/webapp/icons/sonic_blue/help_small.png Binary files differnew file mode 100644 index 00000000..88283157 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/help_small.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/home.png b/subsonic-main/src/main/webapp/icons/sonic_blue/home.png Binary files differnew file mode 100644 index 00000000..47acba54 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/home.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/log.png b/subsonic-main/src/main/webapp/icons/sonic_blue/log.png Binary files differnew file mode 100644 index 00000000..a4fa9297 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/log.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/logo.png b/subsonic-main/src/main/webapp/icons/sonic_blue/logo.png Binary files differnew file mode 100644 index 00000000..947d6e25 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/logo.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/more.png b/subsonic-main/src/main/webapp/icons/sonic_blue/more.png Binary files differnew file mode 100644 index 00000000..53fb8bb8 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/more.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/now_playing.png b/subsonic-main/src/main/webapp/icons/sonic_blue/now_playing.png Binary files differnew file mode 100644 index 00000000..42931eff --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/paypal.gif b/subsonic-main/src/main/webapp/icons/sonic_blue/paypal.gif Binary files differnew file mode 100644 index 00000000..2a587165 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/paypal.gif diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/phone.png b/subsonic-main/src/main/webapp/icons/sonic_blue/phone.png Binary files differnew file mode 100644 index 00000000..83b16afb --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/phone.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/play.png b/subsonic-main/src/main/webapp/icons/sonic_blue/play.png Binary files differnew file mode 100644 index 00000000..a6e692a2 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/play.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/playing.png b/subsonic-main/src/main/webapp/icons/sonic_blue/playing.png Binary files differnew file mode 100644 index 00000000..44882736 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/playing.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/podcast.png b/subsonic-main/src/main/webapp/icons/sonic_blue/podcast.png Binary files differnew file mode 100644 index 00000000..d5cd0f46 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/podcast.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/podcast_small.png b/subsonic-main/src/main/webapp/icons/sonic_blue/podcast_small.png Binary files differnew file mode 100644 index 00000000..87d2fe25 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/podcast_small.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/progress.png b/subsonic-main/src/main/webapp/icons/sonic_blue/progress.png Binary files differnew file mode 100644 index 00000000..13b465ba --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/progress.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/random.png b/subsonic-main/src/main/webapp/icons/sonic_blue/random.png Binary files differnew file mode 100644 index 00000000..2b0fdb06 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/random.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/rating_half.png b/subsonic-main/src/main/webapp/icons/sonic_blue/rating_half.png Binary files differnew file mode 100644 index 00000000..08ab0d39 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/rating_half.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/rating_off.png b/subsonic-main/src/main/webapp/icons/sonic_blue/rating_off.png Binary files differnew file mode 100644 index 00000000..a0d9bbb1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/rating_off.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/rating_on.png b/subsonic-main/src/main/webapp/icons/sonic_blue/rating_on.png Binary files differnew file mode 100644 index 00000000..8c4d6602 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/rating_on.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/remove.png b/subsonic-main/src/main/webapp/icons/sonic_blue/remove.png Binary files differnew file mode 100644 index 00000000..56599a81 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/remove.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/search.png b/subsonic-main/src/main/webapp/icons/sonic_blue/search.png Binary files differnew file mode 100644 index 00000000..9c9b3e73 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/search.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/settings.png b/subsonic-main/src/main/webapp/icons/sonic_blue/settings.png Binary files differnew file mode 100644 index 00000000..e3a528a0 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/settings.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/status.png b/subsonic-main/src/main/webapp/icons/sonic_blue/status.png Binary files differnew file mode 100644 index 00000000..f99cba27 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/status.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/up.png b/subsonic-main/src/main/webapp/icons/sonic_blue/up.png Binary files differnew file mode 100644 index 00000000..98b4a78c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/up.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_blue/upload.png b/subsonic-main/src/main/webapp/icons/sonic_blue/upload.png Binary files differnew file mode 100644 index 00000000..ecfad1a9 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_blue/upload.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/add.png b/subsonic-main/src/main/webapp/icons/sonic_white/add.png Binary files differnew file mode 100644 index 00000000..3579c354 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/add.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/back.png b/subsonic-main/src/main/webapp/icons/sonic_white/back.png Binary files differnew file mode 100644 index 00000000..0fa80d9a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/back.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/clear_rating.png b/subsonic-main/src/main/webapp/icons/sonic_white/clear_rating.png Binary files differnew file mode 100644 index 00000000..5d0104e7 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/clear_rating.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/donate.png b/subsonic-main/src/main/webapp/icons/sonic_white/donate.png Binary files differnew file mode 100644 index 00000000..f9c17ceb --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/donate.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/down.png b/subsonic-main/src/main/webapp/icons/sonic_white/down.png Binary files differnew file mode 100644 index 00000000..f509be10 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/down.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/download.png b/subsonic-main/src/main/webapp/icons/sonic_white/download.png Binary files differnew file mode 100644 index 00000000..ee5ebb58 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/download.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/error.png b/subsonic-main/src/main/webapp/icons/sonic_white/error.png Binary files differnew file mode 100644 index 00000000..c7d60958 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/error.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/favicon.ico b/subsonic-main/src/main/webapp/icons/sonic_white/favicon.ico Binary files differnew file mode 100644 index 00000000..ef507a55 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/favicon.ico diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/forward.png b/subsonic-main/src/main/webapp/icons/sonic_white/forward.png Binary files differnew file mode 100644 index 00000000..cce6e6f4 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/forward.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/help.png b/subsonic-main/src/main/webapp/icons/sonic_white/help.png Binary files differnew file mode 100644 index 00000000..7380ec10 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/help.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/help_small.png b/subsonic-main/src/main/webapp/icons/sonic_white/help_small.png Binary files differnew file mode 100644 index 00000000..cf98d072 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/help_small.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/home.png b/subsonic-main/src/main/webapp/icons/sonic_white/home.png Binary files differnew file mode 100644 index 00000000..882b7f4a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/home.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/log.png b/subsonic-main/src/main/webapp/icons/sonic_white/log.png Binary files differnew file mode 100644 index 00000000..7764ae53 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/log.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/logo.png b/subsonic-main/src/main/webapp/icons/sonic_white/logo.png Binary files differnew file mode 100644 index 00000000..68aca05c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/logo.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/more.png b/subsonic-main/src/main/webapp/icons/sonic_white/more.png Binary files differnew file mode 100644 index 00000000..17274a6b --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/more.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/now_playing.png b/subsonic-main/src/main/webapp/icons/sonic_white/now_playing.png Binary files differnew file mode 100644 index 00000000..da58451e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/now_playing.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/paypal.gif b/subsonic-main/src/main/webapp/icons/sonic_white/paypal.gif Binary files differnew file mode 100644 index 00000000..2a587165 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/paypal.gif diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/phone.png b/subsonic-main/src/main/webapp/icons/sonic_white/phone.png Binary files differnew file mode 100644 index 00000000..c2c4f494 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/phone.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/play.png b/subsonic-main/src/main/webapp/icons/sonic_white/play.png Binary files differnew file mode 100644 index 00000000..7ee33876 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/play.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/playing.png b/subsonic-main/src/main/webapp/icons/sonic_white/playing.png Binary files differnew file mode 100644 index 00000000..554d0404 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/playing.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/podcast.png b/subsonic-main/src/main/webapp/icons/sonic_white/podcast.png Binary files differnew file mode 100644 index 00000000..9d7b47dd --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/podcast.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/podcast_small.png b/subsonic-main/src/main/webapp/icons/sonic_white/podcast_small.png Binary files differnew file mode 100644 index 00000000..d5fa56bd --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/podcast_small.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/progress.png b/subsonic-main/src/main/webapp/icons/sonic_white/progress.png Binary files differnew file mode 100644 index 00000000..13b465ba --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/progress.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/random.png b/subsonic-main/src/main/webapp/icons/sonic_white/random.png Binary files differnew file mode 100644 index 00000000..6289938c --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/random.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/rating_half.png b/subsonic-main/src/main/webapp/icons/sonic_white/rating_half.png Binary files differnew file mode 100644 index 00000000..08ab0d39 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/rating_half.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/rating_off.png b/subsonic-main/src/main/webapp/icons/sonic_white/rating_off.png Binary files differnew file mode 100644 index 00000000..a0d9bbb1 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/rating_off.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/rating_on.png b/subsonic-main/src/main/webapp/icons/sonic_white/rating_on.png Binary files differnew file mode 100644 index 00000000..8c4d6602 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/rating_on.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/remove.png b/subsonic-main/src/main/webapp/icons/sonic_white/remove.png Binary files differnew file mode 100644 index 00000000..7c63ab7e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/remove.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/search.png b/subsonic-main/src/main/webapp/icons/sonic_white/search.png Binary files differnew file mode 100644 index 00000000..6b885f91 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/search.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/settings.png b/subsonic-main/src/main/webapp/icons/sonic_white/settings.png Binary files differnew file mode 100644 index 00000000..707e0a20 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/settings.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/status.png b/subsonic-main/src/main/webapp/icons/sonic_white/status.png Binary files differnew file mode 100644 index 00000000..53f13830 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/status.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/up.png b/subsonic-main/src/main/webapp/icons/sonic_white/up.png Binary files differnew file mode 100644 index 00000000..1e7260ca --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/up.png diff --git a/subsonic-main/src/main/webapp/icons/sonic_white/upload.png b/subsonic-main/src/main/webapp/icons/sonic_white/upload.png Binary files differnew file mode 100644 index 00000000..8dc0cfcb --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/sonic_white/upload.png diff --git a/subsonic-main/src/main/webapp/icons/spinner.gif b/subsonic-main/src/main/webapp/icons/spinner.gif Binary files differnew file mode 100644 index 00000000..e192ca89 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/spinner.gif diff --git a/subsonic-main/src/main/webapp/icons/star_off.png b/subsonic-main/src/main/webapp/icons/star_off.png Binary files differnew file mode 100644 index 00000000..ada53fc3 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/star_off.png diff --git a/subsonic-main/src/main/webapp/icons/starred.png b/subsonic-main/src/main/webapp/icons/starred.png Binary files differnew file mode 100644 index 00000000..5476c401 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/starred.png diff --git a/subsonic-main/src/main/webapp/icons/status.png b/subsonic-main/src/main/webapp/icons/status.png Binary files differnew file mode 100644 index 00000000..8df38463 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/status.png diff --git a/subsonic-main/src/main/webapp/icons/subair.png b/subsonic-main/src/main/webapp/icons/subair.png Binary files differnew file mode 100644 index 00000000..a8a36dbe --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/subair.png diff --git a/subsonic-main/src/main/webapp/icons/subsonic_black.png b/subsonic-main/src/main/webapp/icons/subsonic_black.png Binary files differnew file mode 100644 index 00000000..21448a8e --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/subsonic_black.png diff --git a/subsonic-main/src/main/webapp/icons/subsonic_white.png b/subsonic-main/src/main/webapp/icons/subsonic_white.png Binary files differnew file mode 100644 index 00000000..65db730a --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/subsonic_white.png diff --git a/subsonic-main/src/main/webapp/icons/up.gif b/subsonic-main/src/main/webapp/icons/up.gif Binary files differnew file mode 100644 index 00000000..20223146 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/up.gif diff --git a/subsonic-main/src/main/webapp/icons/upload.gif b/subsonic-main/src/main/webapp/icons/upload.gif Binary files differnew file mode 100644 index 00000000..b1605639 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/upload.gif diff --git a/subsonic-main/src/main/webapp/icons/wap.png b/subsonic-main/src/main/webapp/icons/wap.png Binary files differnew file mode 100644 index 00000000..ea734215 --- /dev/null +++ b/subsonic-main/src/main/webapp/icons/wap.png diff --git a/subsonic-main/src/main/webapp/index.html b/subsonic-main/src/main/webapp/index.html new file mode 100644 index 00000000..5c6cb4b7 --- /dev/null +++ b/subsonic-main/src/main/webapp/index.html @@ -0,0 +1,10 @@ +<html> + +<head> + <meta http-equiv="refresh" content="0;URL=index.view"> +</head> + +<body> +</body> + +</html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/index.jsp b/subsonic-main/src/main/webapp/index.jsp new file mode 100644 index 00000000..f9f5cd30 --- /dev/null +++ b/subsonic-main/src/main/webapp/index.jsp @@ -0,0 +1,10 @@ +<html>
+
+<head>
+ <meta http-equiv="refresh" content="0;URL=index.view">
+</head>
+
+<body>
+</body>
+
+</html>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/AC_OETags.js b/subsonic-main/src/main/webapp/script/AC_OETags.js new file mode 100644 index 00000000..6482d168 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/AC_OETags.js @@ -0,0 +1,269 @@ +// Flash Player Version Detection - Rev 1.5 +// Detect Client Browser type +// Copyright(c) 2005-2006 Adobe Macromedia Software, LLC. All rights reserved. +var isIE = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false; +var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false; +var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false; + +function ControlVersion() +{ + var version; + var axo; + var e; + + // NOTE : new ActiveXObject(strFoo) throws an exception if strFoo isn't in the registry + + try { + // version will be set for 7.X or greater players + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"); + version = axo.GetVariable("$version"); + } catch (e) { + } + + if (!version) + { + try { + // version will be set for 6.X players only + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"); + + // installed player is some revision of 6.0 + // GetVariable("$version") crashes for versions 6.0.22 through 6.0.29, + // so we have to be careful. + + // default to the first public version + version = "WIN 6,0,21,0"; + + // throws if AllowScripAccess does not exist (introduced in 6.0r47) + axo.AllowScriptAccess = "always"; + + // safe to call for 6.0r47 or greater + version = axo.GetVariable("$version"); + + } catch (e) { + } + } + + if (!version) + { + try { + // version will be set for 4.X or 5.X player + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3"); + version = axo.GetVariable("$version"); + } catch (e) { + } + } + + if (!version) + { + try { + // version will be set for 3.X player + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3"); + version = "WIN 3,0,18,0"; + } catch (e) { + } + } + + if (!version) + { + try { + // version will be set for 2.X player + axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); + version = "WIN 2,0,0,11"; + } catch (e) { + version = -1; + } + } + + return version; +} + +// JavaScript helper required to detect Flash Player PlugIn version information +function GetSwfVer(){ + // NS/Opera version >= 3 check for Flash plugin in plugin array + var flashVer = -1; + + if (navigator.plugins != null && navigator.plugins.length > 0) { + if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) { + var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : ""; + var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description; + var descArray = flashDescription.split(" "); + var tempArrayMajor = descArray[2].split("."); + var versionMajor = tempArrayMajor[0]; + var versionMinor = tempArrayMajor[1]; + if ( descArray[3] != "" ) { + tempArrayMinor = descArray[3].split("r"); + } else { + tempArrayMinor = descArray[4].split("r"); + } + var versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0; + var flashVer = versionMajor + "." + versionMinor + "." + versionRevision; + } + } + // MSN/WebTV 2.6 supports Flash 4 + else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.6") != -1) flashVer = 4; + // WebTV 2.5 supports Flash 3 + else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.5") != -1) flashVer = 3; + // older WebTV supports Flash 2 + else if (navigator.userAgent.toLowerCase().indexOf("webtv") != -1) flashVer = 2; + else if ( isIE && isWin && !isOpera ) { + flashVer = ControlVersion(); + } + return flashVer; +} + +// When called with reqMajorVer, reqMinorVer, reqRevision returns true if that version or greater is available +function DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision) +{ + versionStr = GetSwfVer(); + if (versionStr == -1 ) { + return false; + } else if (versionStr != 0) { + if(isIE && isWin && !isOpera) { + // Given "WIN 2,0,0,11" + tempArray = versionStr.split(" "); // ["WIN", "2,0,0,11"] + tempString = tempArray[1]; // "2,0,0,11" + versionArray = tempString.split(","); // ['2', '0', '0', '11'] + } else { + versionArray = versionStr.split("."); + } + var versionMajor = versionArray[0]; + var versionMinor = versionArray[1]; + var versionRevision = versionArray[2]; + + // is the major.revision >= requested major.revision AND the minor version >= requested minor + if (versionMajor > parseFloat(reqMajorVer)) { + return true; + } else if (versionMajor == parseFloat(reqMajorVer)) { + if (versionMinor > parseFloat(reqMinorVer)) + return true; + else if (versionMinor == parseFloat(reqMinorVer)) { + if (versionRevision >= parseFloat(reqRevision)) + return true; + } + } + return false; + } +} + +function AC_AddExtension(src, ext) +{ + if (src.indexOf('?') != -1) + return src.replace(/\?/, ext+'?'); + else + return src + ext; +} + +function AC_Generateobj(objAttrs, params, embedAttrs) +{ + var str = ''; + if (isIE && isWin && !isOpera) + { + str += '<object '; + for (var i in objAttrs) + str += i + '="' + objAttrs[i] + '" '; + for (var i in params) + str += '><param name="' + i + '" value="' + params[i] + '" /> '; + str += '></object>'; + } else { + str += '<embed '; + for (var i in embedAttrs) + str += i + '="' + embedAttrs[i] + '" '; + str += '> </embed>'; + } + + document.write(str); +} + +function AC_FL_RunContent(){ + var ret = + AC_GetArgs + ( arguments, ".swf", "movie", "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" + , "application/x-shockwave-flash" + ); + AC_Generateobj(ret.objAttrs, ret.params, ret.embedAttrs); +} + +function AC_GetArgs(args, ext, srcParamName, classid, mimeType){ + var ret = new Object(); + ret.embedAttrs = new Object(); + ret.params = new Object(); + ret.objAttrs = new Object(); + for (var i=0; i < args.length; i=i+2){ + var currArg = args[i].toLowerCase(); + + switch (currArg){ + case "classid": + break; + case "pluginspage": + ret.embedAttrs[args[i]] = args[i+1]; + break; + case "src": + case "movie": + args[i+1] = AC_AddExtension(args[i+1], ext); + ret.embedAttrs["src"] = args[i+1]; + ret.params[srcParamName] = args[i+1]; + break; + case "onafterupdate": + case "onbeforeupdate": + case "onblur": + case "oncellchange": + case "onclick": + case "ondblClick": + case "ondrag": + case "ondragend": + case "ondragenter": + case "ondragleave": + case "ondragover": + case "ondrop": + case "onfinish": + case "onfocus": + case "onhelp": + case "onmousedown": + case "onmouseup": + case "onmouseover": + case "onmousemove": + case "onmouseout": + case "onkeypress": + case "onkeydown": + case "onkeyup": + case "onload": + case "onlosecapture": + case "onpropertychange": + case "onreadystatechange": + case "onrowsdelete": + case "onrowenter": + case "onrowexit": + case "onrowsinserted": + case "onstart": + case "onscroll": + case "onbeforeeditfocus": + case "onactivate": + case "onbeforedeactivate": + case "ondeactivate": + case "type": + case "codebase": + ret.objAttrs[args[i]] = args[i+1]; + break; + case "id": + case "width": + case "height": + case "align": + case "vspace": + case "hspace": + case "class": + case "title": + case "accesskey": + case "name": + case "tabindex": + ret.embedAttrs[args[i]] = ret.objAttrs[args[i]] = args[i+1]; + break; + default: + ret.embedAttrs[args[i]] = ret.params[args[i]] = args[i+1]; + } + } + ret.objAttrs["classid"] = classid; + if (mimeType) ret.embedAttrs["type"] = mimeType; + return ret; +} + + diff --git a/subsonic-main/src/main/webapp/script/builder.js b/subsonic-main/src/main/webapp/script/builder.js new file mode 100644 index 00000000..dba8beca --- /dev/null +++ b/subsonic-main/src/main/webapp/script/builder.js @@ -0,0 +1,136 @@ +// script.aculo.us builder.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008 + +// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +var Builder = { + NODEMAP: { + AREA: 'map', + CAPTION: 'table', + COL: 'table', + COLGROUP: 'table', + LEGEND: 'fieldset', + OPTGROUP: 'select', + OPTION: 'select', + PARAM: 'object', + TBODY: 'table', + TD: 'table', + TFOOT: 'table', + TH: 'table', + THEAD: 'table', + TR: 'table' + }, + // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken, + // due to a Firefox bug + node: function(elementName) { + elementName = elementName.toUpperCase(); + + // try innerHTML approach + var parentTag = this.NODEMAP[elementName] || 'div'; + var parentElement = document.createElement(parentTag); + try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 + parentElement.innerHTML = "<" + elementName + "></" + elementName + ">"; + } catch(e) {} + var element = parentElement.firstChild || null; + + // see if browser added wrapping tags + if(element && (element.tagName.toUpperCase() != elementName)) + element = element.getElementsByTagName(elementName)[0]; + + // fallback to createElement approach + if(!element) element = document.createElement(elementName); + + // abort if nothing could be created + if(!element) return; + + // attributes (or text) + if(arguments[1]) + if(this._isStringOrNumber(arguments[1]) || + (arguments[1] instanceof Array) || + arguments[1].tagName) { + this._children(element, arguments[1]); + } else { + var attrs = this._attributes(arguments[1]); + if(attrs.length) { + try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707 + parentElement.innerHTML = "<" +elementName + " " + + attrs + "></" + elementName + ">"; + } catch(e) {} + element = parentElement.firstChild || null; + // workaround firefox 1.0.X bug + if(!element) { + element = document.createElement(elementName); + for(attr in arguments[1]) + element[attr == 'class' ? 'className' : attr] = arguments[1][attr]; + } + if(element.tagName.toUpperCase() != elementName) + element = parentElement.getElementsByTagName(elementName)[0]; + } + } + + // text, or array of children + if(arguments[2]) + this._children(element, arguments[2]); + + return $(element); + }, + _text: function(text) { + return document.createTextNode(text); + }, + + ATTR_MAP: { + 'className': 'class', + 'htmlFor': 'for' + }, + + _attributes: function(attributes) { + var attrs = []; + for(attribute in attributes) + attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) + + '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'"') + '"'); + return attrs.join(" "); + }, + _children: function(element, children) { + if(children.tagName) { + element.appendChild(children); + return; + } + if(typeof children=='object') { // array can hold nodes and text + children.flatten().each( function(e) { + if(typeof e=='object') + element.appendChild(e); + else + if(Builder._isStringOrNumber(e)) + element.appendChild(Builder._text(e)); + }); + } else + if(Builder._isStringOrNumber(children)) + element.appendChild(Builder._text(children)); + }, + _isStringOrNumber: function(param) { + return(typeof param=='string' || typeof param=='number'); + }, + build: function(html) { + var element = this.node('div'); + $(element).update(html.strip()); + return element.down(); + }, + dump: function(scope) { + if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope + + var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " + + "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " + + "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+ + "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+ + "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+ + "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/); + + tags.each( function(tag){ + scope[tag] = function() { + return Builder.node.apply(Builder, [tag].concat($A(arguments))); + }; + }); + } +};
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/controls.js b/subsonic-main/src/main/webapp/script/controls.js new file mode 100644 index 00000000..c56ccb79 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/controls.js @@ -0,0 +1,965 @@ +// script.aculo.us controls.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008 + +// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan) +// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com) +// Contributors: +// Richard Livsey +// Rahul Bhargava +// Rob Wills +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// Autocompleter.Base handles all the autocompletion functionality +// that's independent of the data source for autocompletion. This +// includes drawing the autocompletion menu, observing keyboard +// and mouse events, and similar. +// +// Specific autocompleters need to provide, at the very least, +// a getUpdatedChoices function that will be invoked every time +// the text inside the monitored textbox changes. This method +// should get the text for which to provide autocompletion by +// invoking this.getToken(), NOT by directly accessing +// this.element.value. This is to allow incremental tokenized +// autocompletion. Specific auto-completion logic (AJAX, etc) +// belongs in getUpdatedChoices. +// +// Tokenized incremental autocompletion is enabled automatically +// when an autocompleter is instantiated with the 'tokens' option +// in the options parameter, e.g.: +// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); +// will incrementally autocomplete with a comma as the token. +// Additionally, ',' in the above example can be replaced with +// a token array, e.g. { tokens: [',', '\n'] } which +// enables autocompletion on multiple tokens. This is most +// useful when one of the tokens is \n (a newline), as it +// allows smart autocompletion after linebreaks. + +if(typeof Effect == 'undefined') + throw("controls.js requires including script.aculo.us' effects.js library"); + +var Autocompleter = { }; +Autocompleter.Base = Class.create({ + baseInitialize: function(element, update, options) { + element = $(element); + this.element = element; + this.update = $(update); + this.hasFocus = false; + this.changed = false; + this.active = false; + this.index = 0; + this.entryCount = 0; + this.oldElementValue = this.element.value; + + if(this.setOptions) + this.setOptions(options); + else + this.options = options || { }; + + this.options.paramName = this.options.paramName || this.element.name; + this.options.tokens = this.options.tokens || []; + this.options.frequency = this.options.frequency || 0.4; + this.options.minChars = this.options.minChars || 1; + this.options.onShow = this.options.onShow || + function(element, update){ + if(!update.style.position || update.style.position=='absolute') { + update.style.position = 'absolute'; + Position.clone(element, update, { + setHeight: false, + offsetTop: element.offsetHeight + }); + } + Effect.Appear(update,{duration:0.15}); + }; + this.options.onHide = this.options.onHide || + function(element, update){ new Effect.Fade(update,{duration:0.15}) }; + + if(typeof(this.options.tokens) == 'string') + this.options.tokens = new Array(this.options.tokens); + // Force carriage returns as token delimiters anyway + if (!this.options.tokens.include('\n')) + this.options.tokens.push('\n'); + + this.observer = null; + + this.element.setAttribute('autocomplete','off'); + + Element.hide(this.update); + + Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); + Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); + }, + + show: function() { + if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); + if(!this.iefix && + (Prototype.Browser.IE) && + (Element.getStyle(this.update, 'position')=='absolute')) { + new Insertion.After(this.update, + '<iframe id="' + this.update.id + '_iefix" '+ + 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + + 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>'); + this.iefix = $(this.update.id+'_iefix'); + } + if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); + }, + + fixIEOverlapping: function() { + Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); + this.iefix.style.zIndex = 1; + this.update.style.zIndex = 2; + Element.show(this.iefix); + }, + + hide: function() { + this.stopIndicator(); + if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); + if(this.iefix) Element.hide(this.iefix); + }, + + startIndicator: function() { + if(this.options.indicator) Element.show(this.options.indicator); + }, + + stopIndicator: function() { + if(this.options.indicator) Element.hide(this.options.indicator); + }, + + onKeyPress: function(event) { + if(this.active) + switch(event.keyCode) { + case Event.KEY_TAB: + case Event.KEY_RETURN: + this.selectEntry(); + Event.stop(event); + case Event.KEY_ESC: + this.hide(); + this.active = false; + Event.stop(event); + return; + case Event.KEY_LEFT: + case Event.KEY_RIGHT: + return; + case Event.KEY_UP: + this.markPrevious(); + this.render(); + Event.stop(event); + return; + case Event.KEY_DOWN: + this.markNext(); + this.render(); + Event.stop(event); + return; + } + else + if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || + (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; + + this.changed = true; + this.hasFocus = true; + + if(this.observer) clearTimeout(this.observer); + this.observer = + setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); + }, + + activate: function() { + this.changed = false; + this.hasFocus = true; + this.getUpdatedChoices(); + }, + + onHover: function(event) { + var element = Event.findElement(event, 'LI'); + if(this.index != element.autocompleteIndex) + { + this.index = element.autocompleteIndex; + this.render(); + } + Event.stop(event); + }, + + onClick: function(event) { + var element = Event.findElement(event, 'LI'); + this.index = element.autocompleteIndex; + this.selectEntry(); + this.hide(); + }, + + onBlur: function(event) { + // needed to make click events working + setTimeout(this.hide.bind(this), 250); + this.hasFocus = false; + this.active = false; + }, + + render: function() { + if(this.entryCount > 0) { + for (var i = 0; i < this.entryCount; i++) + this.index==i ? + Element.addClassName(this.getEntry(i),"selected") : + Element.removeClassName(this.getEntry(i),"selected"); + if(this.hasFocus) { + this.show(); + this.active = true; + } + } else { + this.active = false; + this.hide(); + } + }, + + markPrevious: function() { + if(this.index > 0) this.index--; + else this.index = this.entryCount-1; + this.getEntry(this.index).scrollIntoView(true); + }, + + markNext: function() { + if(this.index < this.entryCount-1) this.index++; + else this.index = 0; + this.getEntry(this.index).scrollIntoView(false); + }, + + getEntry: function(index) { + return this.update.firstChild.childNodes[index]; + }, + + getCurrentEntry: function() { + return this.getEntry(this.index); + }, + + selectEntry: function() { + this.active = false; + this.updateElement(this.getCurrentEntry()); + }, + + updateElement: function(selectedElement) { + if (this.options.updateElement) { + this.options.updateElement(selectedElement); + return; + } + var value = ''; + if (this.options.select) { + var nodes = $(selectedElement).select('.' + this.options.select) || []; + if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); + } else + value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); + + var bounds = this.getTokenBounds(); + if (bounds[0] != -1) { + var newValue = this.element.value.substr(0, bounds[0]); + var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); + if (whitespace) + newValue += whitespace[0]; + this.element.value = newValue + value + this.element.value.substr(bounds[1]); + } else { + this.element.value = value; + } + this.oldElementValue = this.element.value; + this.element.focus(); + + if (this.options.afterUpdateElement) + this.options.afterUpdateElement(this.element, selectedElement); + }, + + updateChoices: function(choices) { + if(!this.changed && this.hasFocus) { + this.update.innerHTML = choices; + Element.cleanWhitespace(this.update); + Element.cleanWhitespace(this.update.down()); + + if(this.update.firstChild && this.update.down().childNodes) { + this.entryCount = + this.update.down().childNodes.length; + for (var i = 0; i < this.entryCount; i++) { + var entry = this.getEntry(i); + entry.autocompleteIndex = i; + this.addObservers(entry); + } + } else { + this.entryCount = 0; + } + + this.stopIndicator(); + this.index = 0; + + if(this.entryCount==1 && this.options.autoSelect) { + this.selectEntry(); + this.hide(); + } else { + this.render(); + } + } + }, + + addObservers: function(element) { + Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); + Event.observe(element, "click", this.onClick.bindAsEventListener(this)); + }, + + onObserverEvent: function() { + this.changed = false; + this.tokenBounds = null; + if(this.getToken().length>=this.options.minChars) { + this.getUpdatedChoices(); + } else { + this.active = false; + this.hide(); + } + this.oldElementValue = this.element.value; + }, + + getToken: function() { + var bounds = this.getTokenBounds(); + return this.element.value.substring(bounds[0], bounds[1]).strip(); + }, + + getTokenBounds: function() { + if (null != this.tokenBounds) return this.tokenBounds; + var value = this.element.value; + if (value.strip().empty()) return [-1, 0]; + var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); + var offset = (diff == this.oldElementValue.length ? 1 : 0); + var prevTokenPos = -1, nextTokenPos = value.length; + var tp; + for (var index = 0, l = this.options.tokens.length; index < l; ++index) { + tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); + if (tp > prevTokenPos) prevTokenPos = tp; + tp = value.indexOf(this.options.tokens[index], diff + offset); + if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; + } + return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); + } +}); + +Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { + var boundary = Math.min(newS.length, oldS.length); + for (var index = 0; index < boundary; ++index) + if (newS[index] != oldS[index]) + return index; + return boundary; +}; + +Ajax.Autocompleter = Class.create(Autocompleter.Base, { + initialize: function(element, update, url, options) { + this.baseInitialize(element, update, options); + this.options.asynchronous = true; + this.options.onComplete = this.onComplete.bind(this); + this.options.defaultParams = this.options.parameters || null; + this.url = url; + }, + + getUpdatedChoices: function() { + this.startIndicator(); + + var entry = encodeURIComponent(this.options.paramName) + '=' + + encodeURIComponent(this.getToken()); + + this.options.parameters = this.options.callback ? + this.options.callback(this.element, entry) : entry; + + if(this.options.defaultParams) + this.options.parameters += '&' + this.options.defaultParams; + + new Ajax.Request(this.url, this.options); + }, + + onComplete: function(request) { + this.updateChoices(request.responseText); + } +}); + +// The local array autocompleter. Used when you'd prefer to +// inject an array of autocompletion options into the page, rather +// than sending out Ajax queries, which can be quite slow sometimes. +// +// The constructor takes four parameters. The first two are, as usual, +// the id of the monitored textbox, and id of the autocompletion menu. +// The third is the array you want to autocomplete from, and the fourth +// is the options block. +// +// Extra local autocompletion options: +// - choices - How many autocompletion choices to offer +// +// - partialSearch - If false, the autocompleter will match entered +// text only at the beginning of strings in the +// autocomplete array. Defaults to true, which will +// match text at the beginning of any *word* in the +// strings in the autocomplete array. If you want to +// search anywhere in the string, additionally set +// the option fullSearch to true (default: off). +// +// - fullSsearch - Search anywhere in autocomplete array strings. +// +// - partialChars - How many characters to enter before triggering +// a partial match (unlike minChars, which defines +// how many characters are required to do any match +// at all). Defaults to 2. +// +// - ignoreCase - Whether to ignore case when autocompleting. +// Defaults to true. +// +// It's possible to pass in a custom function as the 'selector' +// option, if you prefer to write your own autocompletion logic. +// In that case, the other options above will not apply unless +// you support them. + +Autocompleter.Local = Class.create(Autocompleter.Base, { + initialize: function(element, update, array, options) { + this.baseInitialize(element, update, options); + this.options.array = array; + }, + + getUpdatedChoices: function() { + this.updateChoices(this.options.selector(this)); + }, + + setOptions: function(options) { + this.options = Object.extend({ + choices: 10, + partialSearch: true, + partialChars: 2, + ignoreCase: true, + fullSearch: false, + selector: function(instance) { + var ret = []; // Beginning matches + var partial = []; // Inside matches + var entry = instance.getToken(); + var count = 0; + + for (var i = 0; i < instance.options.array.length && + ret.length < instance.options.choices ; i++) { + + var elem = instance.options.array[i]; + var foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase()) : + elem.indexOf(entry); + + while (foundPos != -1) { + if (foundPos == 0 && elem.length != entry.length) { + ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + + elem.substr(entry.length) + "</li>"); + break; + } else if (entry.length >= instance.options.partialChars && + instance.options.partialSearch && foundPos != -1) { + if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { + partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" + + elem.substr(foundPos, entry.length) + "</strong>" + elem.substr( + foundPos + entry.length) + "</li>"); + break; + } + } + + foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : + elem.indexOf(entry, foundPos + 1); + + } + } + if (partial.length) + ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); + return "<ul>" + ret.join('') + "</ul>"; + } + }, options || { }); + } +}); + +// AJAX in-place editor and collection editor +// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007). + +// Use this if you notice weird scrolling problems on some browsers, +// the DOM might be a bit confused when this gets called so do this +// waits 1 ms (with setTimeout) until it does the activation +Field.scrollFreeActivate = function(field) { + setTimeout(function() { + Field.activate(field); + }, 1); +}; + +Ajax.InPlaceEditor = Class.create({ + initialize: function(element, url, options) { + this.url = url; + this.element = element = $(element); + this.prepareOptions(); + this._controls = { }; + arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! + Object.extend(this.options, options || { }); + if (!this.options.formId && this.element.id) { + this.options.formId = this.element.id + '-inplaceeditor'; + if ($(this.options.formId)) + this.options.formId = ''; + } + if (this.options.externalControl) + this.options.externalControl = $(this.options.externalControl); + if (!this.options.externalControl) + this.options.externalControlOnly = false; + this._originalBackground = this.element.getStyle('background-color') || 'transparent'; + this.element.title = this.options.clickToEditText; + this._boundCancelHandler = this.handleFormCancellation.bind(this); + this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); + this._boundFailureHandler = this.handleAJAXFailure.bind(this); + this._boundSubmitHandler = this.handleFormSubmission.bind(this); + this._boundWrapperHandler = this.wrapUp.bind(this); + this.registerListeners(); + }, + checkForEscapeOrReturn: function(e) { + if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; + if (Event.KEY_ESC == e.keyCode) + this.handleFormCancellation(e); + else if (Event.KEY_RETURN == e.keyCode) + this.handleFormSubmission(e); + }, + createControl: function(mode, handler, extraClasses) { + var control = this.options[mode + 'Control']; + var text = this.options[mode + 'Text']; + if ('button' == control) { + var btn = document.createElement('input'); + btn.type = 'submit'; + btn.value = text; + btn.className = 'editor_' + mode + '_button'; + if ('cancel' == mode) + btn.onclick = this._boundCancelHandler; + this._form.appendChild(btn); + this._controls[mode] = btn; + } else if ('link' == control) { + var link = document.createElement('a'); + link.href = '#'; + link.appendChild(document.createTextNode(text)); + link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; + link.className = 'editor_' + mode + '_link'; + if (extraClasses) + link.className += ' ' + extraClasses; + this._form.appendChild(link); + this._controls[mode] = link; + } + }, + createEditField: function() { + var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); + var fld; + if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { + fld = document.createElement('input'); + fld.type = 'text'; + var size = this.options.size || this.options.cols || 0; + if (0 < size) fld.size = size; + } else { + fld = document.createElement('textarea'); + fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); + fld.cols = this.options.cols || 40; + } + fld.name = this.options.paramName; + fld.value = text; // No HTML breaks conversion anymore + fld.className = 'editor_field'; + if (this.options.submitOnBlur) + fld.onblur = this._boundSubmitHandler; + this._controls.editor = fld; + if (this.options.loadTextURL) + this.loadExternalText(); + this._form.appendChild(this._controls.editor); + }, + createForm: function() { + var ipe = this; + function addText(mode, condition) { + var text = ipe.options['text' + mode + 'Controls']; + if (!text || condition === false) return; + ipe._form.appendChild(document.createTextNode(text)); + }; + this._form = $(document.createElement('form')); + this._form.id = this.options.formId; + this._form.addClassName(this.options.formClassName); + this._form.onsubmit = this._boundSubmitHandler; + this.createEditField(); + if ('textarea' == this._controls.editor.tagName.toLowerCase()) + this._form.appendChild(document.createElement('br')); + if (this.options.onFormCustomization) + this.options.onFormCustomization(this, this._form); + addText('Before', this.options.okControl || this.options.cancelControl); + this.createControl('ok', this._boundSubmitHandler); + addText('Between', this.options.okControl && this.options.cancelControl); + this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); + addText('After', this.options.okControl || this.options.cancelControl); + }, + destroy: function() { + if (this._oldInnerHTML) + this.element.innerHTML = this._oldInnerHTML; + this.leaveEditMode(); + this.unregisterListeners(); + }, + enterEditMode: function(e) { + if (this._saving || this._editing) return; + this._editing = true; + this.triggerCallback('onEnterEditMode'); + if (this.options.externalControl) + this.options.externalControl.hide(); + this.element.hide(); + this.createForm(); + this.element.parentNode.insertBefore(this._form, this.element); + if (!this.options.loadTextURL) + this.postProcessEditField(); + if (e) Event.stop(e); + }, + enterHover: function(e) { + if (this.options.hoverClassName) + this.element.addClassName(this.options.hoverClassName); + if (this._saving) return; + this.triggerCallback('onEnterHover'); + }, + getText: function() { + return this.element.innerHTML.unescapeHTML(); + }, + handleAJAXFailure: function(transport) { + this.triggerCallback('onFailure', transport); + if (this._oldInnerHTML) { + this.element.innerHTML = this._oldInnerHTML; + this._oldInnerHTML = null; + } + }, + handleFormCancellation: function(e) { + this.wrapUp(); + if (e) Event.stop(e); + }, + handleFormSubmission: function(e) { + var form = this._form; + var value = $F(this._controls.editor); + this.prepareSubmission(); + var params = this.options.callback(form, value) || ''; + if (Object.isString(params)) + params = params.toQueryParams(); + params.editorId = this.element.id; + if (this.options.htmlResponse) { + var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); + Object.extend(options, { + parameters: params, + onComplete: this._boundWrapperHandler, + onFailure: this._boundFailureHandler + }); + new Ajax.Updater({ success: this.element }, this.url, options); + } else { + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: params, + onComplete: this._boundWrapperHandler, + onFailure: this._boundFailureHandler + }); + new Ajax.Request(this.url, options); + } + if (e) Event.stop(e); + }, + leaveEditMode: function() { + this.element.removeClassName(this.options.savingClassName); + this.removeForm(); + this.leaveHover(); + this.element.style.backgroundColor = this._originalBackground; + this.element.show(); + if (this.options.externalControl) + this.options.externalControl.show(); + this._saving = false; + this._editing = false; + this._oldInnerHTML = null; + this.triggerCallback('onLeaveEditMode'); + }, + leaveHover: function(e) { + if (this.options.hoverClassName) + this.element.removeClassName(this.options.hoverClassName); + if (this._saving) return; + this.triggerCallback('onLeaveHover'); + }, + loadExternalText: function() { + this._form.addClassName(this.options.loadingClassName); + this._controls.editor.disabled = true; + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + this._form.removeClassName(this.options.loadingClassName); + var text = transport.responseText; + if (this.options.stripLoadedTextTags) + text = text.stripTags(); + this._controls.editor.value = text; + this._controls.editor.disabled = false; + this.postProcessEditField(); + }.bind(this), + onFailure: this._boundFailureHandler + }); + new Ajax.Request(this.options.loadTextURL, options); + }, + postProcessEditField: function() { + var fpc = this.options.fieldPostCreation; + if (fpc) + $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); + }, + prepareOptions: function() { + this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); + Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); + [this._extraDefaultOptions].flatten().compact().each(function(defs) { + Object.extend(this.options, defs); + }.bind(this)); + }, + prepareSubmission: function() { + this._saving = true; + this.removeForm(); + this.leaveHover(); + this.showSaving(); + }, + registerListeners: function() { + this._listeners = { }; + var listener; + $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { + listener = this[pair.value].bind(this); + this._listeners[pair.key] = listener; + if (!this.options.externalControlOnly) + this.element.observe(pair.key, listener); + if (this.options.externalControl) + this.options.externalControl.observe(pair.key, listener); + }.bind(this)); + }, + removeForm: function() { + if (!this._form) return; + this._form.remove(); + this._form = null; + this._controls = { }; + }, + showSaving: function() { + this._oldInnerHTML = this.element.innerHTML; + this.element.innerHTML = this.options.savingText; + this.element.addClassName(this.options.savingClassName); + this.element.style.backgroundColor = this._originalBackground; + this.element.show(); + }, + triggerCallback: function(cbName, arg) { + if ('function' == typeof this.options[cbName]) { + this.options[cbName](this, arg); + } + }, + unregisterListeners: function() { + $H(this._listeners).each(function(pair) { + if (!this.options.externalControlOnly) + this.element.stopObserving(pair.key, pair.value); + if (this.options.externalControl) + this.options.externalControl.stopObserving(pair.key, pair.value); + }.bind(this)); + }, + wrapUp: function(transport) { + this.leaveEditMode(); + // Can't use triggerCallback due to backward compatibility: requires + // binding + direct element + this._boundComplete(transport, this.element); + } +}); + +Object.extend(Ajax.InPlaceEditor.prototype, { + dispose: Ajax.InPlaceEditor.prototype.destroy +}); + +Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { + initialize: function($super, element, url, options) { + this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; + $super(element, url, options); + }, + + createEditField: function() { + var list = document.createElement('select'); + list.name = this.options.paramName; + list.size = 1; + this._controls.editor = list; + this._collection = this.options.collection || []; + if (this.options.loadCollectionURL) + this.loadCollection(); + else + this.checkForExternalText(); + this._form.appendChild(this._controls.editor); + }, + + loadCollection: function() { + this._form.addClassName(this.options.loadingClassName); + this.showLoadingText(this.options.loadingCollectionText); + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + var js = transport.responseText.strip(); + if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check + throw('Server returned an invalid collection representation.'); + this._collection = eval(js); + this.checkForExternalText(); + }.bind(this), + onFailure: this.onFailure + }); + new Ajax.Request(this.options.loadCollectionURL, options); + }, + + showLoadingText: function(text) { + this._controls.editor.disabled = true; + var tempOption = this._controls.editor.firstChild; + if (!tempOption) { + tempOption = document.createElement('option'); + tempOption.value = ''; + this._controls.editor.appendChild(tempOption); + tempOption.selected = true; + } + tempOption.update((text || '').stripScripts().stripTags()); + }, + + checkForExternalText: function() { + this._text = this.getText(); + if (this.options.loadTextURL) + this.loadExternalText(); + else + this.buildOptionList(); + }, + + loadExternalText: function() { + this.showLoadingText(this.options.loadingText); + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + this._text = transport.responseText.strip(); + this.buildOptionList(); + }.bind(this), + onFailure: this.onFailure + }); + new Ajax.Request(this.options.loadTextURL, options); + }, + + buildOptionList: function() { + this._form.removeClassName(this.options.loadingClassName); + this._collection = this._collection.map(function(entry) { + return 2 === entry.length ? entry : [entry, entry].flatten(); + }); + var marker = ('value' in this.options) ? this.options.value : this._text; + var textFound = this._collection.any(function(entry) { + return entry[0] == marker; + }.bind(this)); + this._controls.editor.update(''); + var option; + this._collection.each(function(entry, index) { + option = document.createElement('option'); + option.value = entry[0]; + option.selected = textFound ? entry[0] == marker : 0 == index; + option.appendChild(document.createTextNode(entry[1])); + this._controls.editor.appendChild(option); + }.bind(this)); + this._controls.editor.disabled = false; + Field.scrollFreeActivate(this._controls.editor); + } +}); + +//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** +//**** This only exists for a while, in order to let **** +//**** users adapt to the new API. Read up on the new **** +//**** API and convert your code to it ASAP! **** + +Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { + if (!options) return; + function fallback(name, expr) { + if (name in options || expr === undefined) return; + options[name] = expr; + }; + fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : + options.cancelLink == options.cancelButton == false ? false : undefined))); + fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : + options.okLink == options.okButton == false ? false : undefined))); + fallback('highlightColor', options.highlightcolor); + fallback('highlightEndColor', options.highlightendcolor); +}; + +Object.extend(Ajax.InPlaceEditor, { + DefaultOptions: { + ajaxOptions: { }, + autoRows: 3, // Use when multi-line w/ rows == 1 + cancelControl: 'link', // 'link'|'button'|false + cancelText: 'cancel', + clickToEditText: 'Click to edit', + externalControl: null, // id|elt + externalControlOnly: false, + fieldPostCreation: 'activate', // 'activate'|'focus'|false + formClassName: 'inplaceeditor-form', + formId: null, // id|elt + highlightColor: '#ffff99', + highlightEndColor: '#ffffff', + hoverClassName: '', + htmlResponse: true, + loadingClassName: 'inplaceeditor-loading', + loadingText: 'Loading...', + okControl: 'button', // 'link'|'button'|false + okText: 'ok', + paramName: 'value', + rows: 1, // If 1 and multi-line, uses autoRows + savingClassName: 'inplaceeditor-saving', + savingText: 'Saving...', + size: 0, + stripLoadedTextTags: false, + submitOnBlur: false, + textAfterControls: '', + textBeforeControls: '', + textBetweenControls: '' + }, + DefaultCallbacks: { + callback: function(form) { + return Form.serialize(form); + }, + onComplete: function(transport, element) { + // For backward compatibility, this one is bound to the IPE, and passes + // the element directly. It was too often customized, so we don't break it. + new Effect.Highlight(element, { + startcolor: this.options.highlightColor, keepBackgroundImage: true }); + }, + onEnterEditMode: null, + onEnterHover: function(ipe) { + ipe.element.style.backgroundColor = ipe.options.highlightColor; + if (ipe._effect) + ipe._effect.cancel(); + }, + onFailure: function(transport, ipe) { + alert('Error communication with the server: ' + transport.responseText.stripTags()); + }, + onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. + onLeaveEditMode: null, + onLeaveHover: function(ipe) { + ipe._effect = new Effect.Highlight(ipe.element, { + startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, + restorecolor: ipe._originalBackground, keepBackgroundImage: true + }); + } + }, + Listeners: { + click: 'enterEditMode', + keydown: 'checkForEscapeOrReturn', + mouseover: 'enterHover', + mouseout: 'leaveHover' + } +}); + +Ajax.InPlaceCollectionEditor.DefaultOptions = { + loadingCollectionText: 'Loading options...' +}; + +// Delayed observer, like Form.Element.Observer, +// but waits for delay after last key input +// Ideal for live-search fields + +Form.Element.DelayedObserver = Class.create({ + initialize: function(element, delay, callback) { + this.delay = delay || 0.5; + this.element = $(element); + this.callback = callback; + this.timer = null; + this.lastValue = $F(this.element); + Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); + }, + delayedListener: function(event) { + if(this.lastValue == $F(this.element)) return; + if(this.timer) clearTimeout(this.timer); + this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); + this.lastValue = $F(this.element); + }, + onTimerEvent: function() { + this.timer = null; + this.callback(this.element, $F(this.element)); + } +});
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/effects.js b/subsonic-main/src/main/webapp/script/effects.js new file mode 100644 index 00000000..f31a81a0 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/effects.js @@ -0,0 +1,1130 @@ +// script.aculo.us effects.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008 + +// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Contributors: +// Justin Palmer (http://encytemedia.com/) +// Mark Pilgrim (http://diveintomark.org/) +// Martin Bialasinki +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// converts rgb() and #xxx to #xxxxxx format, +// returns self (or first argument) if not convertable +String.prototype.parseColor = function() { + var color = '#'; + if (this.slice(0,4) == 'rgb(') { + var cols = this.slice(4,this.length-1).split(','); + var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); + } else { + if (this.slice(0,1) == '#') { + if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); + if (this.length==7) color = this.toLowerCase(); + } + } + return (color.length==7 ? color : (arguments[0] || this)); +}; + +/*--------------------------------------------------------------------------*/ + +Element.collectTextNodes = function(element) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); + }).flatten().join(''); +}; + +Element.collectTextNodesIgnoreClass = function(element, className) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? + Element.collectTextNodesIgnoreClass(node, className) : '')); + }).flatten().join(''); +}; + +Element.setContentZoom = function(element, percent) { + element = $(element); + element.setStyle({fontSize: (percent/100) + 'em'}); + if (Prototype.Browser.WebKit) window.scrollBy(0,0); + return element; +}; + +Element.getInlineOpacity = function(element){ + return $(element).style.opacity || ''; +}; + +Element.forceRerendering = function(element) { + try { + element = $(element); + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch(e) { } +}; + +/*--------------------------------------------------------------------------*/ + +var Effect = { + _elementDoesNotExistError: { + name: 'ElementDoesNotExistError', + message: 'The specified DOM element does not exist, but is required for this effect to operate' + }, + Transitions: { + linear: Prototype.K, + sinoidal: function(pos) { + return (-Math.cos(pos*Math.PI)/2) + .5; + }, + reverse: function(pos) { + return 1-pos; + }, + flicker: function(pos) { + var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4; + return pos > 1 ? 1 : pos; + }, + wobble: function(pos) { + return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5; + }, + pulse: function(pos, pulses) { + return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5; + }, + spring: function(pos) { + return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); + }, + none: function(pos) { + return 0; + }, + full: function(pos) { + return 1; + } + }, + DefaultOptions: { + duration: 1.0, // seconds + fps: 100, // 100= assume 66fps max. + sync: false, // true for combining + from: 0.0, + to: 1.0, + delay: 0.0, + queue: 'parallel' + }, + tagifyText: function(element) { + var tagifyStyle = 'position:relative'; + if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; + + element = $(element); + $A(element.childNodes).each( function(child) { + if (child.nodeType==3) { + child.nodeValue.toArray().each( function(character) { + element.insertBefore( + new Element('span', {style: tagifyStyle}).update( + character == ' ' ? String.fromCharCode(160) : character), + child); + }); + Element.remove(child); + } + }); + }, + multiple: function(element, effect) { + var elements; + if (((typeof element == 'object') || + Object.isFunction(element)) && + (element.length)) + elements = element; + else + elements = $(element).childNodes; + + var options = Object.extend({ + speed: 0.1, + delay: 0.0 + }, arguments[2] || { }); + var masterDelay = options.delay; + + $A(elements).each( function(element, index) { + new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); + }); + }, + PAIRS: { + 'slide': ['SlideDown','SlideUp'], + 'blind': ['BlindDown','BlindUp'], + 'appear': ['Appear','Fade'] + }, + toggle: function(element, effect) { + element = $(element); + effect = (effect || 'appear').toLowerCase(); + var options = Object.extend({ + queue: { position:'end', scope:(element.id || 'global'), limit: 1 } + }, arguments[2] || { }); + Effect[element.visible() ? + Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); + } +}; + +Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; + +/* ------------- core effects ------------- */ + +Effect.ScopedQueue = Class.create(Enumerable, { + initialize: function() { + this.effects = []; + this.interval = null; + }, + _each: function(iterator) { + this.effects._each(iterator); + }, + add: function(effect) { + var timestamp = new Date().getTime(); + + var position = Object.isString(effect.options.queue) ? + effect.options.queue : effect.options.queue.position; + + switch(position) { + case 'front': + // move unstarted effects after this effect + this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { + e.startOn += effect.finishOn; + e.finishOn += effect.finishOn; + }); + break; + case 'with-last': + timestamp = this.effects.pluck('startOn').max() || timestamp; + break; + case 'end': + // start effect after last queued effect has finished + timestamp = this.effects.pluck('finishOn').max() || timestamp; + break; + } + + effect.startOn += timestamp; + effect.finishOn += timestamp; + + if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) + this.effects.push(effect); + + if (!this.interval) + this.interval = setInterval(this.loop.bind(this), 15); + }, + remove: function(effect) { + this.effects = this.effects.reject(function(e) { return e==effect }); + if (this.effects.length == 0) { + clearInterval(this.interval); + this.interval = null; + } + }, + loop: function() { + var timePos = new Date().getTime(); + for(var i=0, len=this.effects.length;i<len;i++) + this.effects[i] && this.effects[i].loop(timePos); + } +}); + +Effect.Queues = { + instances: $H(), + get: function(queueName) { + if (!Object.isString(queueName)) return queueName; + + return this.instances.get(queueName) || + this.instances.set(queueName, new Effect.ScopedQueue()); + } +}; +Effect.Queue = Effect.Queues.get('global'); + +Effect.Base = Class.create({ + position: null, + start: function(options) { + function codeForEvent(options,eventName){ + return ( + (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') + + (options[eventName] ? 'this.options.'+eventName+'(this);' : '') + ); + } + if (options && options.transition === false) options.transition = Effect.Transitions.linear; + this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { }); + this.currentFrame = 0; + this.state = 'idle'; + this.startOn = this.options.delay*1000; + this.finishOn = this.startOn+(this.options.duration*1000); + this.fromToDelta = this.options.to-this.options.from; + this.totalTime = this.finishOn-this.startOn; + this.totalFrames = this.options.fps*this.options.duration; + + this.render = (function() { + function dispatch(effect, eventName) { + if (effect.options[eventName + 'Internal']) + effect.options[eventName + 'Internal'](effect); + if (effect.options[eventName]) + effect.options[eventName](effect); + } + + return function(pos) { + if (this.state === "idle") { + this.state = "running"; + dispatch(this, 'beforeSetup'); + if (this.setup) this.setup(); + dispatch(this, 'afterSetup'); + } + if (this.state === "running") { + pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from; + this.position = pos; + dispatch(this, 'beforeUpdate'); + if (this.update) this.update(pos); + dispatch(this, 'afterUpdate'); + } + }; + })(); + + this.event('beforeStart'); + if (!this.options.sync) + Effect.Queues.get(Object.isString(this.options.queue) ? + 'global' : this.options.queue.scope).add(this); + }, + loop: function(timePos) { + if (timePos >= this.startOn) { + if (timePos >= this.finishOn) { + this.render(1.0); + this.cancel(); + this.event('beforeFinish'); + if (this.finish) this.finish(); + this.event('afterFinish'); + return; + } + var pos = (timePos - this.startOn) / this.totalTime, + frame = (pos * this.totalFrames).round(); + if (frame > this.currentFrame) { + this.render(pos); + this.currentFrame = frame; + } + } + }, + cancel: function() { + if (!this.options.sync) + Effect.Queues.get(Object.isString(this.options.queue) ? + 'global' : this.options.queue.scope).remove(this); + this.state = 'finished'; + }, + event: function(eventName) { + if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); + if (this.options[eventName]) this.options[eventName](this); + }, + inspect: function() { + var data = $H(); + for(property in this) + if (!Object.isFunction(this[property])) data.set(property, this[property]); + return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>'; + } +}); + +Effect.Parallel = Class.create(Effect.Base, { + initialize: function(effects) { + this.effects = effects || []; + this.start(arguments[1]); + }, + update: function(position) { + this.effects.invoke('render', position); + }, + finish: function(position) { + this.effects.each( function(effect) { + effect.render(1.0); + effect.cancel(); + effect.event('beforeFinish'); + if (effect.finish) effect.finish(position); + effect.event('afterFinish'); + }); + } +}); + +Effect.Tween = Class.create(Effect.Base, { + initialize: function(object, from, to) { + object = Object.isString(object) ? $(object) : object; + var args = $A(arguments), method = args.last(), + options = args.length == 5 ? args[3] : null; + this.method = Object.isFunction(method) ? method.bind(object) : + Object.isFunction(object[method]) ? object[method].bind(object) : + function(value) { object[method] = value }; + this.start(Object.extend({ from: from, to: to }, options || { })); + }, + update: function(position) { + this.method(position); + } +}); + +Effect.Event = Class.create(Effect.Base, { + initialize: function() { + this.start(Object.extend({ duration: 0 }, arguments[0] || { })); + }, + update: Prototype.emptyFunction +}); + +Effect.Opacity = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + // make this work on IE on elements without 'layout' + if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + var options = Object.extend({ + from: this.element.getOpacity() || 0.0, + to: 1.0 + }, arguments[1] || { }); + this.start(options); + }, + update: function(position) { + this.element.setOpacity(position); + } +}); + +Effect.Move = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + x: 0, + y: 0, + mode: 'relative' + }, arguments[1] || { }); + this.start(options); + }, + setup: function() { + this.element.makePositioned(); + this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); + this.originalTop = parseFloat(this.element.getStyle('top') || '0'); + if (this.options.mode == 'absolute') { + this.options.x = this.options.x - this.originalLeft; + this.options.y = this.options.y - this.originalTop; + } + }, + update: function(position) { + this.element.setStyle({ + left: (this.options.x * position + this.originalLeft).round() + 'px', + top: (this.options.y * position + this.originalTop).round() + 'px' + }); + } +}); + +// for backwards compatibility +Effect.MoveBy = function(element, toTop, toLeft) { + return new Effect.Move(element, + Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); +}; + +Effect.Scale = Class.create(Effect.Base, { + initialize: function(element, percent) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + scaleX: true, + scaleY: true, + scaleContent: true, + scaleFromCenter: false, + scaleMode: 'box', // 'box' or 'contents' or { } with provided values + scaleFrom: 100.0, + scaleTo: percent + }, arguments[2] || { }); + this.start(options); + }, + setup: function() { + this.restoreAfterFinish = this.options.restoreAfterFinish || false; + this.elementPositioning = this.element.getStyle('position'); + + this.originalStyle = { }; + ['top','left','width','height','fontSize'].each( function(k) { + this.originalStyle[k] = this.element.style[k]; + }.bind(this)); + + this.originalTop = this.element.offsetTop; + this.originalLeft = this.element.offsetLeft; + + var fontSize = this.element.getStyle('font-size') || '100%'; + ['em','px','%','pt'].each( function(fontSizeType) { + if (fontSize.indexOf(fontSizeType)>0) { + this.fontSize = parseFloat(fontSize); + this.fontSizeType = fontSizeType; + } + }.bind(this)); + + this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; + + this.dims = null; + if (this.options.scaleMode=='box') + this.dims = [this.element.offsetHeight, this.element.offsetWidth]; + if (/^content/.test(this.options.scaleMode)) + this.dims = [this.element.scrollHeight, this.element.scrollWidth]; + if (!this.dims) + this.dims = [this.options.scaleMode.originalHeight, + this.options.scaleMode.originalWidth]; + }, + update: function(position) { + var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); + if (this.options.scaleContent && this.fontSize) + this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); + this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); + }, + finish: function(position) { + if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); + }, + setDimensions: function(height, width) { + var d = { }; + if (this.options.scaleX) d.width = width.round() + 'px'; + if (this.options.scaleY) d.height = height.round() + 'px'; + if (this.options.scaleFromCenter) { + var topd = (height - this.dims[0])/2; + var leftd = (width - this.dims[1])/2; + if (this.elementPositioning == 'absolute') { + if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; + if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; + } else { + if (this.options.scaleY) d.top = -topd + 'px'; + if (this.options.scaleX) d.left = -leftd + 'px'; + } + } + this.element.setStyle(d); + } +}); + +Effect.Highlight = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); + this.start(options); + }, + setup: function() { + // Prevent executing on elements not in the layout flow + if (this.element.getStyle('display')=='none') { this.cancel(); return; } + // Disable background image during the effect + this.oldStyle = { }; + if (!this.options.keepBackgroundImage) { + this.oldStyle.backgroundImage = this.element.getStyle('background-image'); + this.element.setStyle({backgroundImage: 'none'}); + } + if (!this.options.endcolor) + this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); + if (!this.options.restorecolor) + this.options.restorecolor = this.element.getStyle('background-color'); + // init color calculations + this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); + this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); + }, + update: function(position) { + this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ + return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); + }, + finish: function() { + this.element.setStyle(Object.extend(this.oldStyle, { + backgroundColor: this.options.restorecolor + })); + } +}); + +Effect.ScrollTo = function(element) { + var options = arguments[1] || { }, + scrollOffsets = document.viewport.getScrollOffsets(), + elementOffsets = $(element).cumulativeOffset(); + + if (options.offset) elementOffsets[1] += options.offset; + + return new Effect.Tween(null, + scrollOffsets.top, + elementOffsets[1], + options, + function(p){ scrollTo(scrollOffsets.left, p.round()); } + ); +}; + +/* ------------- combination effects ------------- */ + +Effect.Fade = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + var options = Object.extend({ + from: element.getOpacity() || 1.0, + to: 0.0, + afterFinishInternal: function(effect) { + if (effect.options.to!=0) return; + effect.element.hide().setStyle({opacity: oldOpacity}); + } + }, arguments[1] || { }); + return new Effect.Opacity(element,options); +}; + +Effect.Appear = function(element) { + element = $(element); + var options = Object.extend({ + from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), + to: 1.0, + // force Safari to render floated elements properly + afterFinishInternal: function(effect) { + effect.element.forceRerendering(); + }, + beforeSetup: function(effect) { + effect.element.setOpacity(effect.options.from).show(); + }}, arguments[1] || { }); + return new Effect.Opacity(element,options); +}; + +Effect.Puff = function(element) { + element = $(element); + var oldStyle = { + opacity: element.getInlineOpacity(), + position: element.getStyle('position'), + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height + }; + return new Effect.Parallel( + [ new Effect.Scale(element, 200, + { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], + Object.extend({ duration: 1.0, + beforeSetupInternal: function(effect) { + Position.absolutize(effect.effects[0].element); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().setStyle(oldStyle); } + }, arguments[1] || { }) + ); +}; + +Effect.BlindUp = function(element) { + element = $(element); + element.makeClipping(); + return new Effect.Scale(element, 0, + Object.extend({ scaleContent: false, + scaleX: false, + restoreAfterFinish: true, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }, arguments[1] || { }) + ); +}; + +Effect.BlindDown = function(element) { + element = $(element); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: 0, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + } + }, arguments[1] || { })); +}; + +Effect.SwitchOff = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + return new Effect.Appear(element, Object.extend({ + duration: 0.4, + from: 0, + transition: Effect.Transitions.flicker, + afterFinishInternal: function(effect) { + new Effect.Scale(effect.element, 1, { + duration: 0.3, scaleFromCenter: true, + scaleX: false, scaleContent: false, restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); + } + }); + } + }, arguments[1] || { })); +}; + +Effect.DropOut = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left'), + opacity: element.getInlineOpacity() }; + return new Effect.Parallel( + [ new Effect.Move(element, {x: 0, y: 100, sync: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 }) ], + Object.extend( + { duration: 0.5, + beforeSetup: function(effect) { + effect.effects[0].element.makePositioned(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); + } + }, arguments[1] || { })); +}; + +Effect.Shake = function(element) { + element = $(element); + var options = Object.extend({ + distance: 20, + duration: 0.5 + }, arguments[1] || {}); + var distance = parseFloat(options.distance); + var split = parseFloat(options.duration) / 10.0; + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left') }; + return new Effect.Move(element, + { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { + effect.element.undoPositioned().setStyle(oldStyle); + }}); }}); }}); }}); }}); }}); +}; + +Effect.SlideDown = function(element) { + element = $(element).cleanWhitespace(); + // SlideDown need to have the content of the element wrapped in a container element with fixed height! + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: window.opera ? 0 : 1, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if (window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } + }, arguments[1] || { }) + ); +}; + +Effect.SlideUp = function(element) { + element = $(element).cleanWhitespace(); + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, window.opera ? 0 : 1, + Object.extend({ scaleContent: false, + scaleX: false, + scaleMode: 'box', + scaleFrom: 100, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if (window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); + } + }, arguments[1] || { }) + ); +}; + +// Bug in opera makes the TD containing this element expand for a instance after finish +Effect.Squish = function(element) { + return new Effect.Scale(element, window.opera ? 1 : 0, { + restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }); +}; + +Effect.Grow = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.full + }, arguments[1] || { }); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var initialMoveX, initialMoveY; + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + initialMoveX = initialMoveY = moveX = moveY = 0; + break; + case 'top-right': + initialMoveX = dims.width; + initialMoveY = moveY = 0; + moveX = -dims.width; + break; + case 'bottom-left': + initialMoveX = moveX = 0; + initialMoveY = dims.height; + moveY = -dims.height; + break; + case 'bottom-right': + initialMoveX = dims.width; + initialMoveY = dims.height; + moveX = -dims.width; + moveY = -dims.height; + break; + case 'center': + initialMoveX = dims.width / 2; + initialMoveY = dims.height / 2; + moveX = -dims.width / 2; + moveY = -dims.height / 2; + break; + } + + return new Effect.Move(element, { + x: initialMoveX, + y: initialMoveY, + duration: 0.01, + beforeSetup: function(effect) { + effect.element.hide().makeClipping().makePositioned(); + }, + afterFinishInternal: function(effect) { + new Effect.Parallel( + [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), + new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), + new Effect.Scale(effect.element, 100, { + scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, + sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) + ], Object.extend({ + beforeSetup: function(effect) { + effect.effects[0].element.setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); + } + }, options) + ); + } + }); +}; + +Effect.Shrink = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.none + }, arguments[1] || { }); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + moveX = moveY = 0; + break; + case 'top-right': + moveX = dims.width; + moveY = 0; + break; + case 'bottom-left': + moveX = 0; + moveY = dims.height; + break; + case 'bottom-right': + moveX = dims.width; + moveY = dims.height; + break; + case 'center': + moveX = dims.width / 2; + moveY = dims.height / 2; + break; + } + + return new Effect.Parallel( + [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), + new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), + new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) + ], Object.extend({ + beforeStartInternal: function(effect) { + effect.effects[0].element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } + }, options) + ); +}; + +Effect.Pulsate = function(element) { + element = $(element); + var options = arguments[1] || { }, + oldOpacity = element.getInlineOpacity(), + transition = options.transition || Effect.Transitions.linear, + reverser = function(pos){ + return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5); + }; + + return new Effect.Opacity(element, + Object.extend(Object.extend({ duration: 2.0, from: 0, + afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } + }, options), {transition: reverser})); +}; + +Effect.Fold = function(element) { + element = $(element); + var oldStyle = { + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height }; + element.makeClipping(); + return new Effect.Scale(element, 5, Object.extend({ + scaleContent: false, + scaleX: false, + afterFinishInternal: function(effect) { + new Effect.Scale(element, 1, { + scaleContent: false, + scaleY: false, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().setStyle(oldStyle); + } }); + }}, arguments[1] || { })); +}; + +Effect.Morph = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + style: { } + }, arguments[1] || { }); + + if (!Object.isString(options.style)) this.style = $H(options.style); + else { + if (options.style.include(':')) + this.style = options.style.parseStyle(); + else { + this.element.addClassName(options.style); + this.style = $H(this.element.getStyles()); + this.element.removeClassName(options.style); + var css = this.element.getStyles(); + this.style = this.style.reject(function(style) { + return style.value == css[style.key]; + }); + options.afterFinishInternal = function(effect) { + effect.element.addClassName(effect.options.style); + effect.transforms.each(function(transform) { + effect.element.style[transform.style] = ''; + }); + }; + } + } + this.start(options); + }, + + setup: function(){ + function parseColor(color){ + if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; + color = color.parseColor(); + return $R(0,2).map(function(i){ + return parseInt( color.slice(i*2+1,i*2+3), 16 ); + }); + } + this.transforms = this.style.map(function(pair){ + var property = pair[0], value = pair[1], unit = null; + + if (value.parseColor('#zzzzzz') != '#zzzzzz') { + value = value.parseColor(); + unit = 'color'; + } else if (property == 'opacity') { + value = parseFloat(value); + if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + } else if (Element.CSS_LENGTH.test(value)) { + var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); + value = parseFloat(components[1]); + unit = (components.length == 3) ? components[2] : null; + } + + var originalValue = this.element.getStyle(property); + return { + style: property.camelize(), + originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), + targetValue: unit=='color' ? parseColor(value) : value, + unit: unit + }; + }.bind(this)).reject(function(transform){ + return ( + (transform.originalValue == transform.targetValue) || + ( + transform.unit != 'color' && + (isNaN(transform.originalValue) || isNaN(transform.targetValue)) + ) + ); + }); + }, + update: function(position) { + var style = { }, transform, i = this.transforms.length; + while(i--) + style[(transform = this.transforms[i]).style] = + transform.unit=='color' ? '#'+ + (Math.round(transform.originalValue[0]+ + (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + + (Math.round(transform.originalValue[1]+ + (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + + (Math.round(transform.originalValue[2]+ + (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : + (transform.originalValue + + (transform.targetValue - transform.originalValue) * position).toFixed(3) + + (transform.unit === null ? '' : transform.unit); + this.element.setStyle(style, true); + } +}); + +Effect.Transform = Class.create({ + initialize: function(tracks){ + this.tracks = []; + this.options = arguments[1] || { }; + this.addTracks(tracks); + }, + addTracks: function(tracks){ + tracks.each(function(track){ + track = $H(track); + var data = track.values().first(); + this.tracks.push($H({ + ids: track.keys().first(), + effect: Effect.Morph, + options: { style: data } + })); + }.bind(this)); + return this; + }, + play: function(){ + return new Effect.Parallel( + this.tracks.map(function(track){ + var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); + var elements = [$(ids) || $$(ids)].flatten(); + return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); + }).flatten(), + this.options + ); + } +}); + +Element.CSS_PROPERTIES = $w( + 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + + 'fontSize fontWeight height left letterSpacing lineHeight ' + + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ + 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + + 'right textIndent top width wordSpacing zIndex'); + +Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; + +String.__parseStyleElement = document.createElement('div'); +String.prototype.parseStyle = function(){ + var style, styleRules = $H(); + if (Prototype.Browser.WebKit) + style = new Element('div',{style:this}).style; + else { + String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>'; + style = String.__parseStyleElement.childNodes[0].style; + } + + Element.CSS_PROPERTIES.each(function(property){ + if (style[property]) styleRules.set(property, style[property]); + }); + + if (Prototype.Browser.IE && this.include('opacity')) + styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); + + return styleRules; +}; + +if (document.defaultView && document.defaultView.getComputedStyle) { + Element.getStyles = function(element) { + var css = document.defaultView.getComputedStyle($(element), null); + return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { + styles[property] = css[property]; + return styles; + }); + }; +} else { + Element.getStyles = function(element) { + element = $(element); + var css = element.currentStyle, styles; + styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { + results[property] = css[property]; + return results; + }); + if (!styles.opacity) styles.opacity = element.getOpacity(); + return styles; + }; +} + +Effect.Methods = { + morph: function(element, style) { + element = $(element); + new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); + return element; + }, + visualEffect: function(element, effect, options) { + element = $(element); + var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); + new Effect[klass](element, options); + return element; + }, + highlight: function(element, options) { + element = $(element); + new Effect.Highlight(element, options); + return element; + } +}; + +$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ + 'pulsate shake puff squish switchOff dropOut').each( + function(effect) { + Effect.Methods[effect] = function(element, options){ + element = $(element); + Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); + return element; + }; + } +); + +$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( + function(f) { Effect.Methods[f] = Element[f]; } +); + +Element.addMethods(Effect.Methods);
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/FancyZoom.js b/subsonic-main/src/main/webapp/script/fancyzoom/FancyZoom.js new file mode 100644 index 00000000..c98624fa --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/FancyZoom.js @@ -0,0 +1,761 @@ +// FancyZoom.js - v1.1 - http://www.fancyzoom.com +// +// Copyright (c) 2008 Cabel Sasser / Panic Inc +// All rights reserved. +// +// Requires: FancyZoomHTML.js +// Instructions: Include JS files in page, call setupZoom() in onLoad. That's it! +// Any <a href> links to images will be updated to zoom inline. +// Add rel="nozoom" to your <a href> to disable zooming for an image. +// +// Redistribution and use of this effect in source form, with or without modification, +// are permitted provided that the following conditions are met: +// +// * USE OF SOURCE ON COMMERCIAL (FOR-PROFIT) WEBSITE REQUIRES ONE-TIME LICENSE FEE PER DOMAIN. +// Reasonably priced! Visit www.fancyzoom.com for licensing instructions. Thanks! +// +// * Non-commercial (personal) website use is permitted without license/payment! +// +// * Redistribution of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution of source code and derived works cannot be sold without specific +// written prior permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +var includeCaption = true; // Turn on the "caption" feature, and write out the caption HTML +var zoomTime = 5; // Milliseconds between frames of zoom animation +var zoomSteps = 15; // Number of zoom animation frames +var includeFade = 1; // Set to 1 to fade the image in / out as it zooms +var minBorder = 90; // Amount of padding between large, scaled down images, and the window edges +var shadowSettings = '0px 5px 25px rgba(0, 0, 0, '; // Blur, radius, color of shadow for compatible browsers + +// Location of the zoom and shadow images +var zoomImagesURI; + +// Init. Do not add anything below this line, unless it's something awesome. + +var myWidth = 0, myHeight = 0, myScroll = 0; myScrollWidth = 0; myScrollHeight = 0; +var zoomOpen = false, preloadFrame = 1, preloadActive = false, preloadTime = 0, imgPreload = new Image(); +var preloadAnimTimer = 0; + +var zoomActive = new Array(); var zoomTimer = new Array(); +var zoomOrigW = new Array(); var zoomOrigH = new Array(); +var zoomOrigX = new Array(); var zoomOrigY = new Array(); + +var zoomID = "ZoomBox"; +var theID = "ZoomImage"; +var zoomCaption = "ZoomCaption"; +var zoomCaptionDiv = "ZoomCapDiv"; + +if (navigator.userAgent.indexOf("MSIE") != -1) { + var browserIsIE = true; +} + +// Zoom: Setup The Page! Called in your <body>'s onLoad handler. + +function setupZoom(baseURI) { + zoomImagesURI = baseURI + 'script/fancyzoom/images/'; + + prepZooms(); + insertZoomHTML(); + zoomdiv = document.getElementById(zoomID); + zoomimg = document.getElementById(theID); +} + +// Zoom: Inject Javascript functions into hrefs with a "zoom" rel. +// This is done at page load time via an onLoad() handler. + +function prepZooms() { + if (! document.getElementsByTagName) { + return; + } + var links = document.getElementsByTagName("a"); + for (i = 0; i < links.length; i++) { + if (links[i].getAttribute("href")) { + if (links[i].getAttribute("rel") == "zoom") { + links[i].onclick = function (event) { return zoomClick(this, event); }; + links[i].onmouseover = function () { zoomPreload(this); }; + } + } + } +} + +// Zoom: Load an image into an image object. When done loading, function sets preloadActive to false, +// so other bits know that they can proceed with the zoom. +// Preloaded image is stored in imgPreload and swapped out in the zoom function. + +function zoomPreload(from) { + + var theimage = from.getAttribute("href"); + + // Only preload if we have to, i.e. the image isn't this image already + + if (imgPreload.src.indexOf(from.getAttribute("href").substr(from.getAttribute("href").lastIndexOf("/"))) == -1) { + preloadActive = true; + imgPreload = new Image(); + + // Set a function to fire when the preload is complete, setting flags along the way. + + imgPreload.onload = function() { + preloadActive = false; + } + + // Load it! + imgPreload.src = theimage; + } +} + +// Zoom: Start the preloading animation cycle. + +function preloadAnimStart() { + preloadTime = new Date(); + document.getElementById("ZoomSpin").style.left = (myWidth / 2) + 'px'; + document.getElementById("ZoomSpin").style.top = ((myHeight / 2) + myScroll) + 'px'; + document.getElementById("ZoomSpin").style.visibility = "visible"; + preloadFrame = 1; + document.getElementById("SpinImage").src = zoomImagesURI+'zoom-spin-'+preloadFrame+'.png'; + preloadAnimTimer = setInterval("preloadAnim()", 100); +} + +// Zoom: Display and ANIMATE the jibber-jabber widget. Once preloadActive is false, bail and zoom it up! + +function preloadAnim(from) { + if (preloadActive != false) { + document.getElementById("SpinImage").src = zoomImagesURI+'zoom-spin-'+preloadFrame+'.png'; + preloadFrame++; + if (preloadFrame > 12) preloadFrame = 1; + } else { + document.getElementById("ZoomSpin").style.visibility = "hidden"; + clearInterval(preloadAnimTimer); + preloadAnimTimer = 0; + zoomIn(preloadFrom); + } +} + +// ZOOM CLICK: We got a click! Should we do the zoom? Or wait for the preload to complete? +// todo?: Double check that imgPreload src = clicked src + +function zoomClick(from, evt) { + + var shift = getShift(evt); + + // Check for Command / Alt key. If pressed, pass them through -- don't zoom! + if (! evt && window.event && (window.event.metaKey || window.event.altKey)) { + return true; + } else if (evt && (evt.metaKey|| evt.altKey)) { + return true; + } + + // Get browser dimensions + getSize(); + + // If preloading still, wait, and display the spinner. + if (preloadActive == true) { + // But only display the spinner if it's not already being displayed! + if (preloadAnimTimer == 0) { + preloadFrom = from; + preloadAnimStart(); + } + } else { + // Otherwise, we're loaded: do the zoom! + zoomIn(from, shift); + } + + return false; + +} + +// Zoom: Move an element in to endH endW, using zoomHost as a starting point. +// "from" is an object reference to the href that spawned the zoom. + +function zoomIn(from, shift) { + + zoomimg.src = from.getAttribute("href"); + + // Determine the zoom settings from where we came from, the element in the <a>. + // If there's no element in the <a>, or we can't get the width, make stuff up + + if (from.childNodes[0].width) { + startW = from.childNodes[0].width; + startH = from.childNodes[0].height; + startPos = findElementPos(from.childNodes[0]); + } else { + startW = 50; + startH = 12; + startPos = findElementPos(from); + } + + hostX = startPos[0]; + hostY = startPos[1]; + + // Make up for a scrolled containing div. + // TODO: This HAS to move into findElementPos. + + if (document.getElementById('scroller')) { + hostX = hostX - document.getElementById('scroller').scrollLeft; + } + + // Determine the target zoom settings from the preloaded image object + + endW = imgPreload.width; + endH = imgPreload.height; + + // Start! But only if we're not zooming already! + + if (zoomActive[theID] != true) { + + // Clear everything out just in case something is already open + + if (document.getElementById("ShadowBox")) { + document.getElementById("ShadowBox").style.visibility = "hidden"; + } else if (! browserIsIE) { + + // Wipe timer if shadow is fading in still + if (fadeActive["ZoomImage"]) { + clearInterval(fadeTimer["ZoomImage"]); + fadeActive["ZoomImage"] = false; + fadeTimer["ZoomImage"] = false; + } + + document.getElementById("ZoomImage").style.webkitBoxShadow = shadowSettings + '0.0)'; + } + + document.getElementById("ZoomClose").style.visibility = "hidden"; + + // Setup the CAPTION, if existing. Hide it first, set the text. + + if (includeCaption) { + document.getElementById(zoomCaptionDiv).style.visibility = "hidden"; + if (from.getAttribute('title') && includeCaption) { + // Yes, there's a caption, set it up + document.getElementById(zoomCaption).innerHTML = from.getAttribute('title'); + } else { + document.getElementById(zoomCaption).innerHTML = ""; + } + } + + // Store original position in an array for future zoomOut. + + zoomOrigW[theID] = startW; + zoomOrigH[theID] = startH; + zoomOrigX[theID] = hostX; + zoomOrigY[theID] = hostY; + + // Now set the starting dimensions + + zoomimg.style.width = startW + 'px'; + zoomimg.style.height = startH + 'px'; + zoomdiv.style.left = hostX + 'px'; + zoomdiv.style.top = hostY + 'px'; + + // Show the zooming image container, make it invisible + + if (includeFade == 1) { + setOpacity(0, zoomID); + } + zoomdiv.style.visibility = "visible"; + + // If it's too big to fit in the window, shrink the width and height to fit (with ratio). + + sizeRatio = endW / endH; + if (endW > myWidth - minBorder) { + endW = myWidth - minBorder; + endH = endW / sizeRatio; + } + if (endH > myHeight - minBorder) { + endH = myHeight - minBorder; + endW = endH * sizeRatio; + } + + zoomChangeX = ((myWidth / 2) - (endW / 2) - hostX); + zoomChangeY = (((myHeight / 2) - (endH / 2) - hostY) + myScroll); + zoomChangeW = (endW - startW); + zoomChangeH = (endH - startH); + + // Shift key? + + if (shift) { + tempSteps = zoomSteps * 7; + } else { + tempSteps = zoomSteps; + } + + // Setup Zoom + + zoomCurrent = 0; + + // Setup Fade with Zoom, If Requested + + if (includeFade == 1) { + fadeCurrent = 0; + fadeAmount = (0 - 100) / tempSteps; + } else { + fadeAmount = 0; + } + + // Do It! + + zoomTimer[theID] = setInterval("zoomElement('"+zoomID+"', '"+theID+"', "+zoomCurrent+", "+startW+", "+zoomChangeW+", "+startH+", "+zoomChangeH+", "+hostX+", "+zoomChangeX+", "+hostY+", "+zoomChangeY+", "+tempSteps+", "+includeFade+", "+fadeAmount+", 'zoomDoneIn(zoomID)')", zoomTime); + zoomActive[theID] = true; + } +} + +// Zoom it back out. + +function zoomOut(from, evt) { + + // Get shift key status. + // IE events don't seem to get passed through the function, so grab it from the window. + + if (getShift(evt)) { + tempSteps = zoomSteps * 7; + } else { + tempSteps = zoomSteps; + } + + // Check to see if something is happening/open + + if (zoomActive[theID] != true) { + + // First, get rid of the shadow if necessary. + + if (document.getElementById("ShadowBox")) { + document.getElementById("ShadowBox").style.visibility = "hidden"; + } else if (! browserIsIE) { + + // Wipe timer if shadow is fading in still + if (fadeActive["ZoomImage"]) { + clearInterval(fadeTimer["ZoomImage"]); + fadeActive["ZoomImage"] = false; + fadeTimer["ZoomImage"] = false; + } + + document.getElementById("ZoomImage").style.webkitBoxShadow = shadowSettings + '0.0)'; + } + + // ..and the close box... + + document.getElementById("ZoomClose").style.visibility = "hidden"; + + // ...and the caption if necessary! + + if (includeCaption && document.getElementById(zoomCaption).innerHTML != "") { + // fadeElementSetup(zoomCaptionDiv, 100, 0, 5, 1); + document.getElementById(zoomCaptionDiv).style.visibility = "hidden"; + } + + // Now, figure out where we came from, to get back there + + startX = parseInt(zoomdiv.style.left); + startY = parseInt(zoomdiv.style.top); + startW = zoomimg.width; + startH = zoomimg.height; + zoomChangeX = zoomOrigX[theID] - startX; + zoomChangeY = zoomOrigY[theID] - startY; + zoomChangeW = zoomOrigW[theID] - startW; + zoomChangeH = zoomOrigH[theID] - startH; + + // Setup Zoom + + zoomCurrent = 0; + + // Setup Fade with Zoom, If Requested + + if (includeFade == 1) { + fadeCurrent = 0; + fadeAmount = (100 - 0) / tempSteps; + } else { + fadeAmount = 0; + } + + // Do It! + + zoomTimer[theID] = setInterval("zoomElement('"+zoomID+"', '"+theID+"', "+zoomCurrent+", "+startW+", "+zoomChangeW+", "+startH+", "+zoomChangeH+", "+startX+", "+zoomChangeX+", "+startY+", "+zoomChangeY+", "+tempSteps+", "+includeFade+", "+fadeAmount+", 'zoomDone(zoomID, theID)')", zoomTime); + zoomActive[theID] = true; + } +} + +// Finished Zooming In + +function zoomDoneIn(zoomdiv, theID) { + + // Note that it's open + + zoomOpen = true; + zoomdiv = document.getElementById(zoomdiv); + + // Position the table shadow behind the zoomed in image, and display it + + if (document.getElementById("ShadowBox")) { + + setOpacity(0, "ShadowBox"); + shadowdiv = document.getElementById("ShadowBox"); + + shadowLeft = parseInt(zoomdiv.style.left) - 13; + shadowTop = parseInt(zoomdiv.style.top) - 8; + shadowWidth = zoomdiv.offsetWidth + 26; + shadowHeight = zoomdiv.offsetHeight + 26; + + shadowdiv.style.width = shadowWidth + 'px'; + shadowdiv.style.height = shadowHeight + 'px'; + shadowdiv.style.left = shadowLeft + 'px'; + shadowdiv.style.top = shadowTop + 'px'; + + document.getElementById("ShadowBox").style.visibility = "visible"; + fadeElementSetup("ShadowBox", 0, 100, 5); + + } else if (! browserIsIE) { + // Or, do a fade of the modern shadow + fadeElementSetup("ZoomImage", 0, .8, 5, 0, "shadow"); + } + + // Position and display the CAPTION, if existing + + if (includeCaption && document.getElementById(zoomCaption).innerHTML != "") { + // setOpacity(0, zoomCaptionDiv); + zoomcapd = document.getElementById(zoomCaptionDiv); + zoomcapd.style.top = parseInt(zoomdiv.style.top) + (zoomdiv.offsetHeight + 15) + 'px'; + zoomcapd.style.left = (myWidth / 2) - (zoomcapd.offsetWidth / 2) + 'px'; + zoomcapd.style.visibility = "visible"; + // fadeElementSetup(zoomCaptionDiv, 0, 100, 5); + } + + // Display Close Box (fade it if it's not IE) + + if (!browserIsIE) setOpacity(0, "ZoomClose"); + document.getElementById("ZoomClose").style.visibility = "visible"; + if (!browserIsIE) fadeElementSetup("ZoomClose", 0, 100, 5); + + // Get keypresses + document.onkeypress = getKey; + +} + +// Finished Zooming Out + +function zoomDone(zoomdiv, theID) { + + // No longer open + + zoomOpen = false; + + // Clear stuff out, clean up + + zoomOrigH[theID] = ""; + zoomOrigW[theID] = ""; + document.getElementById(zoomdiv).style.visibility = "hidden"; + zoomActive[theID] == false; + + // Stop getting keypresses + + document.onkeypress = null; + +} + +// Actually zoom the element + +function zoomElement(zoomdiv, theID, zoomCurrent, zoomStartW, zoomChangeW, zoomStartH, zoomChangeH, zoomStartX, zoomChangeX, zoomStartY, zoomChangeY, zoomSteps, includeFade, fadeAmount, execWhenDone) { + + // console.log("Zooming Step #"+zoomCurrent+ " of "+zoomSteps+" (zoom " + zoomStartW + "/" + zoomChangeW + ") (zoom " + zoomStartH + "/" + zoomChangeH + ") (zoom " + zoomStartX + "/" + zoomChangeX + ") (zoom " + zoomStartY + "/" + zoomChangeY + ") Fade: "+fadeAmount); + + // Test if we're done, or if we continue + + if (zoomCurrent == (zoomSteps + 1)) { + zoomActive[theID] = false; + clearInterval(zoomTimer[theID]); + + if (execWhenDone != "") { + eval(execWhenDone); + } + } else { + + // Do the Fade! + + if (includeFade == 1) { + if (fadeAmount < 0) { + setOpacity(Math.abs(zoomCurrent * fadeAmount), zoomdiv); + } else { + setOpacity(100 - (zoomCurrent * fadeAmount), zoomdiv); + } + } + + // Calculate this step's difference, and move it! + + moveW = cubicInOut(zoomCurrent, zoomStartW, zoomChangeW, zoomSteps); + moveH = cubicInOut(zoomCurrent, zoomStartH, zoomChangeH, zoomSteps); + moveX = cubicInOut(zoomCurrent, zoomStartX, zoomChangeX, zoomSteps); + moveY = cubicInOut(zoomCurrent, zoomStartY, zoomChangeY, zoomSteps); + + document.getElementById(zoomdiv).style.left = moveX + 'px'; + document.getElementById(zoomdiv).style.top = moveY + 'px'; + zoomimg.style.width = moveW + 'px'; + zoomimg.style.height = moveH + 'px'; + + zoomCurrent++; + + clearInterval(zoomTimer[theID]); + zoomTimer[theID] = setInterval("zoomElement('"+zoomdiv+"', '"+theID+"', "+zoomCurrent+", "+zoomStartW+", "+zoomChangeW+", "+zoomStartH+", "+zoomChangeH+", "+zoomStartX+", "+zoomChangeX+", "+zoomStartY+", "+zoomChangeY+", "+zoomSteps+", "+includeFade+", "+fadeAmount+", '"+execWhenDone+"')", zoomTime); + } +} + +// Zoom Utility: Get Key Press when image is open, and act accordingly + +function getKey(evt) { + if (! evt) { + theKey = event.keyCode; + } else { + theKey = evt.keyCode; + } + + if (theKey == 27) { // ESC + zoomOut(this, evt); + } +} + +//////////////////////////// +// +// FADE Functions +// + +function fadeOut(elem) { + if (elem.id) { + fadeElementSetup(elem.id, 100, 0, 10); + } +} + +function fadeIn(elem) { + if (elem.id) { + fadeElementSetup(elem.id, 0, 100, 10); + } +} + +// Fade: Initialize the fade function + +var fadeActive = new Array(); +var fadeQueue = new Array(); +var fadeTimer = new Array(); +var fadeClose = new Array(); +var fadeMode = new Array(); + +function fadeElementSetup(theID, fdStart, fdEnd, fdSteps, fdClose, fdMode) { + + // alert("Fading: "+theID+" Steps: "+fdSteps+" Mode: "+fdMode); + + if (fadeActive[theID] == true) { + // Already animating, queue up this command + fadeQueue[theID] = new Array(theID, fdStart, fdEnd, fdSteps); + } else { + fadeSteps = fdSteps; + fadeCurrent = 0; + fadeAmount = (fdStart - fdEnd) / fadeSteps; + fadeTimer[theID] = setInterval("fadeElement('"+theID+"', '"+fadeCurrent+"', '"+fadeAmount+"', '"+fadeSteps+"')", 15); + fadeActive[theID] = true; + fadeMode[theID] = fdMode; + + if (fdClose == 1) { + fadeClose[theID] = true; + } else { + fadeClose[theID] = false; + } + } +} + +// Fade: Do the fade. This function will call itself, modifying the parameters, so +// many instances can run concurrently. Can fade using opacity, or fade using a box-shadow. + +function fadeElement(theID, fadeCurrent, fadeAmount, fadeSteps) { + + if (fadeCurrent == fadeSteps) { + + // We're done, so clear. + + clearInterval(fadeTimer[theID]); + fadeActive[theID] = false; + fadeTimer[theID] = false; + + // Should we close it once the fade is complete? + + if (fadeClose[theID] == true) { + document.getElementById(theID).style.visibility = "hidden"; + } + + // Hang on.. did a command queue while we were working? If so, make it happen now + + if (fadeQueue[theID] && fadeQueue[theID] != false) { + fadeElementSetup(fadeQueue[theID][0], fadeQueue[theID][1], fadeQueue[theID][2], fadeQueue[theID][3]); + fadeQueue[theID] = false; + } + } else { + + fadeCurrent++; + + // Now actually do the fade adjustment. + + if (fadeMode[theID] == "shadow") { + + // Do a special fade on the webkit-box-shadow of the object + + if (fadeAmount < 0) { + document.getElementById(theID).style.webkitBoxShadow = shadowSettings + (Math.abs(fadeCurrent * fadeAmount)) + ')'; + } else { + document.getElementById(theID).style.webkitBoxShadow = shadowSettings + (100 - (fadeCurrent * fadeAmount)) + ')'; + } + + } else { + + // Set the opacity depending on if we're adding or subtracting (pos or neg) + + if (fadeAmount < 0) { + setOpacity(Math.abs(fadeCurrent * fadeAmount), theID); + } else { + setOpacity(100 - (fadeCurrent * fadeAmount), theID); + } + } + + // Keep going, and send myself the updated variables + clearInterval(fadeTimer[theID]); + fadeTimer[theID] = setInterval("fadeElement('"+theID+"', '"+fadeCurrent+"', '"+fadeAmount+"', '"+fadeSteps+"')", 15); + } +} + +//////////////////////////// +// +// UTILITY functions +// + +// Utility: Set the opacity, compatible with a number of browsers. Value from 0 to 100. + +function setOpacity(opacity, theID) { + + var object = document.getElementById(theID).style; + + // If it's 100, set it to 99 for Firefox. + + if (navigator.userAgent.indexOf("Firefox") != -1) { + if (opacity == 100) { opacity = 99.9999; } // This is majorly awkward + } + + // Multi-browser opacity setting + + object.filter = "alpha(opacity=" + opacity + ")"; // IE/Win + object.opacity = (opacity / 100); // Safari 1.2, Firefox+Mozilla + +} + +// Utility: Math functions for animation calucations - From http://www.robertpenner.com/easing/ +// +// t = time, b = begin, c = change, d = duration +// time = current frame, begin is fixed, change is basically finish - begin, duration is fixed (frames), + +function linear(t, b, c, d) +{ + return c*t/d + b; +} + +function sineInOut(t, b, c, d) +{ + return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; +} + +function cubicIn(t, b, c, d) { + return c*(t/=d)*t*t + b; +} + +function cubicOut(t, b, c, d) { + return c*((t=t/d-1)*t*t + 1) + b; +} + +function cubicInOut(t, b, c, d) +{ + if ((t/=d/2) < 1) return c/2*t*t*t + b; + return c/2*((t-=2)*t*t + 2) + b; +} + +function bounceOut(t, b, c, d) +{ + if ((t/=d) < (1/2.75)){ + return c*(7.5625*t*t) + b; + } else if (t < (2/2.75)){ + return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; + } else if (t < (2.5/2.75)){ + return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; + } else { + return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; + } +} + + +// Utility: Get the size of the window, and set myWidth and myHeight +// Credit to quirksmode.org + +function getSize() { + + // Window Size + + if (self.innerHeight) { // Everyone but IE + myWidth = window.innerWidth; + myHeight = window.innerHeight; + myScroll = window.pageYOffset; + } else if (document.documentElement && document.documentElement.clientHeight) { // IE6 Strict + myWidth = document.documentElement.clientWidth; + myHeight = document.documentElement.clientHeight; + myScroll = document.documentElement.scrollTop; + } else if (document.body) { // Other IE, such as IE7 + myWidth = document.body.clientWidth; + myHeight = document.body.clientHeight; + myScroll = document.body.scrollTop; + } + + // Page size w/offscreen areas + + if (window.innerHeight && window.scrollMaxY) { + myScrollWidth = document.body.scrollWidth; + myScrollHeight = window.innerHeight + window.scrollMaxY; + } else if (document.body.scrollHeight > document.body.offsetHeight) { // All but Explorer Mac + myScrollWidth = document.body.scrollWidth; + myScrollHeight = document.body.scrollHeight; + } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari + myScrollWidth = document.body.offsetWidth; + myScrollHeight = document.body.offsetHeight; + } +} + +// Utility: Get Shift Key Status +// IE events don't seem to get passed through the function, so grab it from the window. + +function getShift(evt) { + var shift = false; + if (! evt && window.event) { + shift = window.event.shiftKey; + } else if (evt) { + shift = evt.shiftKey; + if (shift) evt.stopPropagation(); // Prevents Firefox from doing shifty things + } + return shift; +} + +// Utility: Find the Y position of an element on a page. Return Y and X as an array + +function findElementPos(elemFind) +{ + var elemX = 0; + var elemY = 0; + do { + elemX += elemFind.offsetLeft; + elemY += elemFind.offsetTop; + } while ( elemFind = elemFind.offsetParent ) + + return Array(elemX, elemY); +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/FancyZoomHTML.js b/subsonic-main/src/main/webapp/script/fancyzoom/FancyZoomHTML.js new file mode 100644 index 00000000..7644a9a8 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/FancyZoomHTML.js @@ -0,0 +1,318 @@ +// FancyZoomHTML.js - v1.0 +// Used to draw necessary HTML elements for FancyZoom +// +// Copyright (c) 2008 Cabel Sasser / Panic Inc +// All rights reserved. + +function insertZoomHTML() { + + // All of this junk creates the three <div>'s used to hold the closebox, image, and zoom shadow. + + var inBody = document.getElementsByTagName("body").item(0); + + // WAIT SPINNER + + var inSpinbox = document.createElement("div"); + inSpinbox.setAttribute('id', 'ZoomSpin'); + inSpinbox.style.position = 'absolute'; + inSpinbox.style.left = '10px'; + inSpinbox.style.top = '10px'; + inSpinbox.style.visibility = 'hidden'; + inSpinbox.style.zIndex = '525'; + inBody.insertBefore(inSpinbox, inBody.firstChild); + + var inSpinImage = document.createElement("img"); + inSpinImage.setAttribute('id', 'SpinImage'); + inSpinImage.setAttribute('src', zoomImagesURI+'zoom-spin-1.png'); + inSpinbox.appendChild(inSpinImage); + + // ZOOM IMAGE + // + // <div id="ZoomBox"> + // <a href="javascript:zoomOut();"><img src="/images/spacer.gif" id="ZoomImage" border="0"></a> <!-- THE IMAGE --> + // <div id="ZoomClose"> + // <a href="javascript:zoomOut();"><img src="/images/closebox.png" width="30" height="30" border="0"></a> + // </div> + // </div> + + var inZoombox = document.createElement("div"); + inZoombox.setAttribute('id', 'ZoomBox'); + + inZoombox.style.position = 'absolute'; + inZoombox.style.left = '10px'; + inZoombox.style.top = '10px'; + inZoombox.style.visibility = 'hidden'; + inZoombox.style.zIndex = '499'; + + inBody.insertBefore(inZoombox, inSpinbox.nextSibling); + + var inImage1 = document.createElement("img"); + inImage1.onclick = function (event) { zoomOut(this, event); return false; }; + inImage1.setAttribute('src',zoomImagesURI+'spacer.gif'); + inImage1.setAttribute('id','ZoomImage'); + inImage1.setAttribute('border', '0'); + // inImage1.setAttribute('onMouseOver', 'zoomMouseOver();') + // inImage1.setAttribute('onMouseOut', 'zoomMouseOut();') + + // This must be set first, so we can later test it using webkitBoxShadow. + inImage1.setAttribute('style', '-webkit-box-shadow: '+shadowSettings+'0.0)'); + inImage1.style.display = 'block'; + inImage1.style.width = '10px'; + inImage1.style.height = '10px'; + inImage1.style.cursor = 'pointer'; // -webkit-zoom-out? + inZoombox.appendChild(inImage1); + + var inClosebox = document.createElement("div"); + inClosebox.setAttribute('id', 'ZoomClose'); + inClosebox.style.position = 'absolute'; + + // In MSIE, we need to put the close box inside the image. + // It's 2008 and I'm having to do a browser detect? Sigh. + if (browserIsIE) { + inClosebox.style.left = '-1px'; + inClosebox.style.top = '0px'; + } else { + inClosebox.style.left = '-15px'; + inClosebox.style.top = '-15px'; + } + + inClosebox.style.visibility = 'hidden'; + inZoombox.appendChild(inClosebox); + + var inImage2 = document.createElement("img"); + inImage2.onclick = function (event) { zoomOut(this, event); return false; }; + inImage2.setAttribute('src',zoomImagesURI+'closebox.png'); + inImage2.setAttribute('width','30'); + inImage2.setAttribute('height','30'); + inImage2.setAttribute('border','0'); + inImage2.style.cursor = 'pointer'; + inClosebox.appendChild(inImage2); + + // SHADOW + // Only draw the table-based shadow if the programatic webkitBoxShadow fails! + // Also, don't draw it if we're IE -- it wouldn't look quite right anyway. + + if (! document.getElementById('ZoomImage').style.webkitBoxShadow && ! browserIsIE) { + + // SHADOW BASE + + var inFixedBox = document.createElement("div"); + inFixedBox.setAttribute('id', 'ShadowBox'); + inFixedBox.style.position = 'absolute'; + inFixedBox.style.left = '50px'; + inFixedBox.style.top = '50px'; + inFixedBox.style.width = '100px'; + inFixedBox.style.height = '100px'; + inFixedBox.style.visibility = 'hidden'; + inFixedBox.style.zIndex = '498'; + inBody.insertBefore(inFixedBox, inZoombox.nextSibling); + + // SHADOW + // Now, the shadow table. Skip if not compatible, or irrevelant with -box-shadow. + + // <div id="ShadowBox"><table border="0" width="100%" height="100%" cellpadding="0" cellspacing="0"> X + // <tr height="25"> + // <td width="27"><img src="/images/zoom-shadow1.png" width="27" height="25"></td> + // <td background="/images/zoom-shadow2.png"> </td> + // <td width="27"><img src="/images/zoom-shadow3.png" width="27" height="25"></td> + // </tr> + + var inShadowTable = document.createElement("table"); + inShadowTable.setAttribute('border', '0'); + inShadowTable.setAttribute('width', '100%'); + inShadowTable.setAttribute('height', '100%'); + inShadowTable.setAttribute('cellpadding', '0'); + inShadowTable.setAttribute('cellspacing', '0'); + inFixedBox.appendChild(inShadowTable); + + var inShadowTbody = document.createElement("tbody"); // Needed for IE (for HTML4). + inShadowTable.appendChild(inShadowTbody); + + var inRow1 = document.createElement("tr"); + inRow1.style.height = '25px'; + inShadowTbody.appendChild(inRow1); + + var inCol1 = document.createElement("td"); + inCol1.style.width = '27px'; + inRow1.appendChild(inCol1); + var inShadowImg1 = document.createElement("img"); + inShadowImg1.setAttribute('src', zoomImagesURI+'zoom-shadow1.png'); + inShadowImg1.setAttribute('width', '27'); + inShadowImg1.setAttribute('height', '25'); + inShadowImg1.style.display = 'block'; + inCol1.appendChild(inShadowImg1); + + var inCol2 = document.createElement("td"); + inCol2.setAttribute('background', zoomImagesURI+'zoom-shadow2.png'); + inRow1.appendChild(inCol2); + // inCol2.innerHTML = '<img src='; + var inSpacer1 = document.createElement("img"); + inSpacer1.setAttribute('src',zoomImagesURI+'spacer.gif'); + inSpacer1.setAttribute('height', '1'); + inSpacer1.setAttribute('width', '1'); + inSpacer1.style.display = 'block'; + inCol2.appendChild(inSpacer1); + + var inCol3 = document.createElement("td"); + inCol3.style.width = '27px'; + inRow1.appendChild(inCol3); + var inShadowImg3 = document.createElement("img"); + inShadowImg3.setAttribute('src', zoomImagesURI+'zoom-shadow3.png'); + inShadowImg3.setAttribute('width', '27'); + inShadowImg3.setAttribute('height', '25'); + inShadowImg3.style.display = 'block'; + inCol3.appendChild(inShadowImg3); + + // <tr> + // <td background="/images/zoom-shadow4.png"> </td> + // <td bgcolor="#ffffff"> </td> + // <td background="/images/zoom-shadow5.png"> </td> + // </tr> + + inRow2 = document.createElement("tr"); + inShadowTbody.appendChild(inRow2); + + var inCol4 = document.createElement("td"); + inCol4.setAttribute('background', zoomImagesURI+'zoom-shadow4.png'); + inRow2.appendChild(inCol4); + // inCol4.innerHTML = ' '; + var inSpacer2 = document.createElement("img"); + inSpacer2.setAttribute('src',zoomImagesURI+'spacer.gif'); + inSpacer2.setAttribute('height', '1'); + inSpacer2.setAttribute('width', '1'); + inSpacer2.style.display = 'block'; + inCol4.appendChild(inSpacer2); + + var inCol5 = document.createElement("td"); + inCol5.setAttribute('bgcolor', '#ffffff'); + inRow2.appendChild(inCol5); + // inCol5.innerHTML = ' '; + var inSpacer3 = document.createElement("img"); + inSpacer3.setAttribute('src',zoomImagesURI+'spacer.gif'); + inSpacer3.setAttribute('height', '1'); + inSpacer3.setAttribute('width', '1'); + inSpacer3.style.display = 'block'; + inCol5.appendChild(inSpacer3); + + var inCol6 = document.createElement("td"); + inCol6.setAttribute('background', zoomImagesURI+'zoom-shadow5.png'); + inRow2.appendChild(inCol6); + // inCol6.innerHTML = ' '; + var inSpacer4 = document.createElement("img"); + inSpacer4.setAttribute('src',zoomImagesURI+'spacer.gif'); + inSpacer4.setAttribute('height', '1'); + inSpacer4.setAttribute('width', '1'); + inSpacer4.style.display = 'block'; + inCol6.appendChild(inSpacer4); + + // <tr height="26"> + // <td width="27"><img src="/images/zoom-shadow6.png" width="27" height="26"</td> + // <td background="/images/zoom-shadow7.png"> </td> + // <td width="27"><img src="/images/zoom-shadow8.png" width="27" height="26"></td> + // </tr> + // </table> + + var inRow3 = document.createElement("tr"); + inRow3.style.height = '26px'; + inShadowTbody.appendChild(inRow3); + + var inCol7 = document.createElement("td"); + inCol7.style.width = '27px'; + inRow3.appendChild(inCol7); + var inShadowImg7 = document.createElement("img"); + inShadowImg7.setAttribute('src', zoomImagesURI+'zoom-shadow6.png'); + inShadowImg7.setAttribute('width', '27'); + inShadowImg7.setAttribute('height', '26'); + inShadowImg7.style.display = 'block'; + inCol7.appendChild(inShadowImg7); + + var inCol8 = document.createElement("td"); + inCol8.setAttribute('background', zoomImagesURI+'zoom-shadow7.png'); + inRow3.appendChild(inCol8); + // inCol8.innerHTML = ' '; + var inSpacer5 = document.createElement("img"); + inSpacer5.setAttribute('src',zoomImagesURI+'spacer.gif'); + inSpacer5.setAttribute('height', '1'); + inSpacer5.setAttribute('width', '1'); + inSpacer5.style.display = 'block'; + inCol8.appendChild(inSpacer5); + + var inCol9 = document.createElement("td"); + inCol9.style.width = '27px'; + inRow3.appendChild(inCol9); + var inShadowImg9 = document.createElement("img"); + inShadowImg9.setAttribute('src', zoomImagesURI+'zoom-shadow8.png'); + inShadowImg9.setAttribute('width', '27'); + inShadowImg9.setAttribute('height', '26'); + inShadowImg9.style.display = 'block'; + inCol9.appendChild(inShadowImg9); + } + + if (includeCaption) { + + // CAPTION + // + // <div id="ZoomCapDiv" style="margin-left: 13px; margin-right: 13px;"> + // <table border="1" cellpadding="0" cellspacing="0"> + // <tr height="26"> + // <td><img src="zoom-caption-l.png" width="13" height="26"></td> + // <td rowspan="3" background="zoom-caption-fill.png"><div id="ZoomCaption"></div></td> + // <td><img src="zoom-caption-r.png" width="13" height="26"></td> + // </tr> + // </table> + // </div> + + var inCapDiv = document.createElement("div"); + inCapDiv.setAttribute('id', 'ZoomCapDiv'); + inCapDiv.style.position = 'absolute'; + inCapDiv.style.visibility = 'hidden'; + inCapDiv.style.marginLeft = 'auto'; + inCapDiv.style.marginRight = 'auto'; + inCapDiv.style.zIndex = '501'; + + inBody.insertBefore(inCapDiv, inZoombox.nextSibling); + + var inCapTable = document.createElement("table"); + inCapTable.setAttribute('border', '0'); + inCapTable.setAttribute('cellPadding', '0'); // Wow. These honestly need to + inCapTable.setAttribute('cellSpacing', '0'); // be intercapped to work in IE. WTF? + inCapDiv.appendChild(inCapTable); + + var inTbody = document.createElement("tbody"); // Needed for IE (for HTML4). + inCapTable.appendChild(inTbody); + + var inCapRow1 = document.createElement("tr"); + inTbody.appendChild(inCapRow1); + + var inCapCol1 = document.createElement("td"); + inCapCol1.setAttribute('align', 'right'); + inCapRow1.appendChild(inCapCol1); + var inCapImg1 = document.createElement("img"); + inCapImg1.setAttribute('src', zoomImagesURI+'zoom-caption-l.png'); + inCapImg1.setAttribute('width', '13'); + inCapImg1.setAttribute('height', '26'); + inCapImg1.style.display = 'block'; + inCapCol1.appendChild(inCapImg1); + + var inCapCol2 = document.createElement("td"); + inCapCol2.setAttribute('background', zoomImagesURI+'zoom-caption-fill.png'); + inCapCol2.setAttribute('id', 'ZoomCaption'); + inCapCol2.setAttribute('valign', 'middle'); + inCapCol2.style.fontSize = '14px'; + inCapCol2.style.fontFamily = 'Helvetica'; + inCapCol2.style.fontWeight = 'bold'; + inCapCol2.style.color = '#ffffff'; + inCapCol2.style.textShadow = '0px 2px 4px #000000'; + inCapCol2.style.whiteSpace = 'nowrap'; + inCapRow1.appendChild(inCapCol2); + + var inCapCol3 = document.createElement("td"); + inCapRow1.appendChild(inCapCol3); + var inCapImg2 = document.createElement("img"); + inCapImg2.setAttribute('src', zoomImagesURI+'zoom-caption-r.png'); + inCapImg2.setAttribute('width', '13'); + inCapImg2.setAttribute('height', '26'); + inCapImg2.style.display = 'block'; + inCapCol3.appendChild(inCapImg2); + } +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/closebox.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/closebox.png Binary files differnew file mode 100644 index 00000000..4de4396d --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/closebox.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/spacer.gif b/subsonic-main/src/main/webapp/script/fancyzoom/images/spacer.gif Binary files differnew file mode 100644 index 00000000..5bfd67a2 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/spacer.gif diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-caption-fill.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-caption-fill.png Binary files differnew file mode 100644 index 00000000..1e341533 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-caption-fill.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-caption-l.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-caption-l.png Binary files differnew file mode 100644 index 00000000..a63ea481 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-caption-l.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-caption-r.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-caption-r.png Binary files differnew file mode 100644 index 00000000..15980d58 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-caption-r.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow1.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow1.png Binary files differnew file mode 100644 index 00000000..8b48000b --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow1.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow2.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow2.png Binary files differnew file mode 100644 index 00000000..09209f37 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow2.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow3.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow3.png Binary files differnew file mode 100644 index 00000000..7636fec2 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow3.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow4.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow4.png Binary files differnew file mode 100644 index 00000000..c7f148d9 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow4.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow5.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow5.png Binary files differnew file mode 100644 index 00000000..2a75b82a --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow5.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow6.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow6.png Binary files differnew file mode 100644 index 00000000..65801aa0 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow6.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow7.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow7.png Binary files differnew file mode 100644 index 00000000..cb447608 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow7.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow8.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow8.png Binary files differnew file mode 100644 index 00000000..f1c6acdb --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-shadow8.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-1.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-1.png Binary files differnew file mode 100644 index 00000000..5615629c --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-1.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-10.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-10.png Binary files differnew file mode 100644 index 00000000..77595dbd --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-10.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-11.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-11.png Binary files differnew file mode 100644 index 00000000..c2147d56 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-11.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-12.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-12.png Binary files differnew file mode 100644 index 00000000..cf027248 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-12.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-2.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-2.png Binary files differnew file mode 100644 index 00000000..95eaae89 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-2.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-3.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-3.png Binary files differnew file mode 100644 index 00000000..9e2b9cb3 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-3.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-4.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-4.png Binary files differnew file mode 100644 index 00000000..a39c0fc0 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-4.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-5.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-5.png Binary files differnew file mode 100644 index 00000000..80bea63b --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-5.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-6.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-6.png Binary files differnew file mode 100644 index 00000000..b962e5f7 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-6.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-7.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-7.png Binary files differnew file mode 100644 index 00000000..9b6e489f --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-7.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-8.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-8.png Binary files differnew file mode 100644 index 00000000..fe147d5f --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-8.png diff --git a/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-9.png b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-9.png Binary files differnew file mode 100644 index 00000000..b321b1c7 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/fancyzoom/images/zoom-spin-9.png diff --git a/subsonic-main/src/main/webapp/script/jquery-1.7.1.min.js b/subsonic-main/src/main/webapp/script/jquery-1.7.1.min.js new file mode 100644 index 00000000..198b3ff0 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/jquery-1.7.1.min.js @@ -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);
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/jquery-ui-1.8.18.custom.min.js b/subsonic-main/src/main/webapp/script/jquery-ui-1.8.18.custom.min.js new file mode 100644 index 00000000..f00a62f1 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/jquery-ui-1.8.18.custom.min.js @@ -0,0 +1,356 @@ +/*! + * jQuery UI 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI + */(function(a,b){function d(b){return!a(b).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}function c(b,c){var e=b.nodeName.toLowerCase();if("area"===e){var f=b.parentNode,g=f.name,h;if(!b.href||!g||f.nodeName.toLowerCase()!=="map")return!1;h=a("img[usemap=#"+g+"]")[0];return!!h&&d(h)}return(/input|select|textarea|button|object/.test(e)?!b.disabled:"a"==e?b.href||c:c)&&d(b)}a.ui=a.ui||{};a.ui.version||(a.extend(a.ui,{version:"1.8.18",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}}),a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(b,c){return typeof b=="number"?this.each(function(){var d=this;setTimeout(function(){a(d).focus(),c&&c.call(d)},b)}):this._focus.apply(this,arguments)},scrollParent:function(){var b;a.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?b=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.curCSS(this,"position",1))&&/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0):b=this.parents().filter(function(){return/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!b.length?a(document):b},zIndex:function(c){if(c!==b)return this.css("zIndex",c);if(this.length){var d=a(this[0]),e,f;while(d.length&&d[0]!==document){e=d.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){f=parseInt(d.css("zIndex"),10);if(!isNaN(f)&&f!==0)return f}d=d.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),a.each(["Width","Height"],function(c,d){function h(b,c,d,f){a.each(e,function(){c-=parseFloat(a.curCSS(b,"padding"+this,!0))||0,d&&(c-=parseFloat(a.curCSS(b,"border"+this+"Width",!0))||0),f&&(c-=parseFloat(a.curCSS(b,"margin"+this,!0))||0)});return c}var e=d==="Width"?["Left","Right"]:["Top","Bottom"],f=d.toLowerCase(),g={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+d]=function(c){if(c===b)return g["inner"+d].call(this);return this.each(function(){a(this).css(f,h(this,c)+"px")})},a.fn["outer"+d]=function(b,c){if(typeof b!="number")return g["outer"+d].call(this,b);return this.each(function(){a(this).css(f,h(this,b,!0,c)+"px")})}}),a.extend(a.expr[":"],{data:function(b,c,d){return!!a.data(b,d[3])},focusable:function(b){return c(b,!isNaN(a.attr(b,"tabindex")))},tabbable:function(b){var d=a.attr(b,"tabindex"),e=isNaN(d);return(e||d>=0)&&c(b,!e)}}),a(function(){var b=document.body,c=b.appendChild(c=document.createElement("div"));c.offsetHeight,a.extend(c.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),a.support.minHeight=c.offsetHeight===100,a.support.selectstart="onselectstart"in c,b.removeChild(c).style.display="none"}),a.extend(a.ui,{plugin:{add:function(b,c,d){var e=a.ui[b].prototype;for(var f in d)e.plugins[f]=e.plugins[f]||[],e.plugins[f].push([c,d[f]])},call:function(a,b,c){var d=a.plugins[b];if(!!d&&!!a.element[0].parentNode)for(var e=0;e<d.length;e++)a.options[d[e][0]]&&d[e][1].apply(a.element,c)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(b,c){if(a(b).css("overflow")==="hidden")return!1;var d=c&&c==="left"?"scrollLeft":"scrollTop",e=!1;if(b[d]>0)return!0;b[d]=1,e=b[d]>0,b[d]=0;return e},isOverAxis:function(a,b,c){return a>b&&a<b+c},isOver:function(b,c,d,e,f,g){return a.ui.isOverAxis(b,d,f)&&a.ui.isOverAxis(c,e,g)}}))})(jQuery);/*! + * jQuery UI Widget 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Widget + */(function(a,b){if(a.cleanData){var c=a.cleanData;a.cleanData=function(b){for(var d=0,e;(e=b[d])!=null;d++)try{a(e).triggerHandler("remove")}catch(f){}c(b)}}else{var d=a.fn.remove;a.fn.remove=function(b,c){return this.each(function(){c||(!b||a.filter(b,[this]).length)&&a("*",this).add([this]).each(function(){try{a(this).triggerHandler("remove")}catch(b){}});return d.call(a(this),b,c)})}}a.widget=function(b,c,d){var e=b.split(".")[0],f;b=b.split(".")[1],f=e+"-"+b,d||(d=c,c=a.Widget),a.expr[":"][f]=function(c){return!!a.data(c,b)},a[e]=a[e]||{},a[e][b]=function(a,b){arguments.length&&this._createWidget(a,b)};var g=new c;g.options=a.extend(!0,{},g.options),a[e][b].prototype=a.extend(!0,g,{namespace:e,widgetName:b,widgetEventPrefix:a[e][b].prototype.widgetEventPrefix||b,widgetBaseClass:f},d),a.widget.bridge(b,a[e][b])},a.widget.bridge=function(c,d){a.fn[c]=function(e){var f=typeof e=="string",g=Array.prototype.slice.call(arguments,1),h=this;e=!f&&g.length?a.extend.apply(null,[!0,e].concat(g)):e;if(f&&e.charAt(0)==="_")return h;f?this.each(function(){var d=a.data(this,c),f=d&&a.isFunction(d[e])?d[e].apply(d,g):d;if(f!==d&&f!==b){h=f;return!1}}):this.each(function(){var b=a.data(this,c);b?b.option(e||{})._init():a.data(this,c,new d(e,this))});return h}},a.Widget=function(a,b){arguments.length&&this._createWidget(a,b)},a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:!1},_createWidget:function(b,c){a.data(c,this.widgetName,this),this.element=a(c),this.options=a.extend(!0,{},this.options,this._getCreateOptions(),b);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()}),this._create(),this._trigger("create"),this._init()},_getCreateOptions:function(){return a.metadata&&a.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName),this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled "+"ui-state-disabled")},widget:function(){return this.element},option:function(c,d){var e=c;if(arguments.length===0)return a.extend({},this.options);if(typeof c=="string"){if(d===b)return this.options[c];e={},e[c]=d}this._setOptions(e);return this},_setOptions:function(b){var c=this;a.each(b,function(a,b){c._setOption(a,b)});return this},_setOption:function(a,b){this.options[a]=b,a==="disabled"&&this.widget()[b?"addClass":"removeClass"](this.widgetBaseClass+"-disabled"+" "+"ui-state-disabled").attr("aria-disabled",b);return this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_trigger:function(b,c,d){var e,f,g=this.options[b];d=d||{},c=a.Event(c),c.type=(b===this.widgetEventPrefix?b:this.widgetEventPrefix+b).toLowerCase(),c.target=this.element[0],f=c.originalEvent;if(f)for(e in f)e in c||(c[e]=f[e]);this.element.trigger(c,d);return!(a.isFunction(g)&&g.call(this.element[0],c,d)===!1||c.isDefaultPrevented())}}})(jQuery);/*! + * jQuery UI Mouse 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Mouse + * + * Depends: + * jquery.ui.widget.js + */(function(a,b){var c=!1;a(document).mouseup(function(a){c=!1}),a.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var b=this;this.element.bind("mousedown."+this.widgetName,function(a){return b._mouseDown(a)}).bind("click."+this.widgetName,function(c){if(!0===a.data(c.target,b.widgetName+".preventClickEvent")){a.removeData(c.target,b.widgetName+".preventClickEvent"),c.stopImmediatePropagation();return!1}}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(b){if(!c){this._mouseStarted&&this._mouseUp(b),this._mouseDownEvent=b;var d=this,e=b.which==1,f=typeof this.options.cancel=="string"&&b.target.nodeName?a(b.target).closest(this.options.cancel).length:!1;if(!e||f||!this._mouseCapture(b))return!0;this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){d.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)){this._mouseStarted=this._mouseStart(b)!==!1;if(!this._mouseStarted){b.preventDefault();return!0}}!0===a.data(b.target,this.widgetName+".preventClickEvent")&&a.removeData(b.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(a){return d._mouseMove(a)},this._mouseUpDelegate=function(a){return d._mouseUp(a)},a(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),b.preventDefault(),c=!0;return!0}},_mouseMove:function(b){if(a.browser.msie&&!(document.documentMode>=9)&&!b.button)return this._mouseUp(b);if(this._mouseStarted){this._mouseDrag(b);return b.preventDefault()}this._mouseDistanceMet(b)&&this._mouseDelayMet(b)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,b)!==!1,this._mouseStarted?this._mouseDrag(b):this._mouseUp(b));return!this._mouseStarted},_mouseUp:function(b){a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,b.target==this._mouseDownEvent.target&&a.data(b.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(b));return!1},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(a){return this.mouseDelayMet},_mouseStart:function(a){},_mouseDrag:function(a){},_mouseStop:function(a){},_mouseCapture:function(a){return!0}})})(jQuery);/* + * jQuery UI Position 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Position + */(function(a,b){a.ui=a.ui||{};var c=/left|center|right/,d=/top|center|bottom/,e="center",f={},g=a.fn.position,h=a.fn.offset;a.fn.position=function(b){if(!b||!b.of)return g.apply(this,arguments);b=a.extend({},b);var h=a(b.of),i=h[0],j=(b.collision||"flip").split(" "),k=b.offset?b.offset.split(" "):[0,0],l,m,n;i.nodeType===9?(l=h.width(),m=h.height(),n={top:0,left:0}):i.setTimeout?(l=h.width(),m=h.height(),n={top:h.scrollTop(),left:h.scrollLeft()}):i.preventDefault?(b.at="left top",l=m=0,n={top:b.of.pageY,left:b.of.pageX}):(l=h.outerWidth(),m=h.outerHeight(),n=h.offset()),a.each(["my","at"],function(){var a=(b[this]||"").split(" ");a.length===1&&(a=c.test(a[0])?a.concat([e]):d.test(a[0])?[e].concat(a):[e,e]),a[0]=c.test(a[0])?a[0]:e,a[1]=d.test(a[1])?a[1]:e,b[this]=a}),j.length===1&&(j[1]=j[0]),k[0]=parseInt(k[0],10)||0,k.length===1&&(k[1]=k[0]),k[1]=parseInt(k[1],10)||0,b.at[0]==="right"?n.left+=l:b.at[0]===e&&(n.left+=l/2),b.at[1]==="bottom"?n.top+=m:b.at[1]===e&&(n.top+=m/2),n.left+=k[0],n.top+=k[1];return this.each(function(){var c=a(this),d=c.outerWidth(),g=c.outerHeight(),h=parseInt(a.curCSS(this,"marginLeft",!0))||0,i=parseInt(a.curCSS(this,"marginTop",!0))||0,o=d+h+(parseInt(a.curCSS(this,"marginRight",!0))||0),p=g+i+(parseInt(a.curCSS(this,"marginBottom",!0))||0),q=a.extend({},n),r;b.my[0]==="right"?q.left-=d:b.my[0]===e&&(q.left-=d/2),b.my[1]==="bottom"?q.top-=g:b.my[1]===e&&(q.top-=g/2),f.fractions||(q.left=Math.round(q.left),q.top=Math.round(q.top)),r={left:q.left-h,top:q.top-i},a.each(["left","top"],function(c,e){a.ui.position[j[c]]&&a.ui.position[j[c]][e](q,{targetWidth:l,targetHeight:m,elemWidth:d,elemHeight:g,collisionPosition:r,collisionWidth:o,collisionHeight:p,offset:k,my:b.my,at:b.at})}),a.fn.bgiframe&&c.bgiframe(),c.offset(a.extend(q,{using:b.using}))})},a.ui.position={fit:{left:function(b,c){var d=a(window),e=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft();b.left=e>0?b.left-e:Math.max(b.left-c.collisionPosition.left,b.left)},top:function(b,c){var d=a(window),e=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop();b.top=e>0?b.top-e:Math.max(b.top-c.collisionPosition.top,b.top)}},flip:{left:function(b,c){if(c.at[0]!==e){var d=a(window),f=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft(),g=c.my[0]==="left"?-c.elemWidth:c.my[0]==="right"?c.elemWidth:0,h=c.at[0]==="left"?c.targetWidth:-c.targetWidth,i=-2*c.offset[0];b.left+=c.collisionPosition.left<0?g+h+i:f>0?g+h+i:0}},top:function(b,c){if(c.at[1]!==e){var d=a(window),f=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop(),g=c.my[1]==="top"?-c.elemHeight:c.my[1]==="bottom"?c.elemHeight:0,h=c.at[1]==="top"?c.targetHeight:-c.targetHeight,i=-2*c.offset[1];b.top+=c.collisionPosition.top<0?g+h+i:f>0?g+h+i:0}}}},a.offset.setOffset||(a.offset.setOffset=function(b,c){/static/.test(a.curCSS(b,"position"))&&(b.style.position="relative");var d=a(b),e=d.offset(),f=parseInt(a.curCSS(b,"top",!0),10)||0,g=parseInt(a.curCSS(b,"left",!0),10)||0,h={top:c.top-e.top+f,left:c.left-e.left+g};"using"in c?c.using.call(b,h):d.css(h)},a.fn.offset=function(b){var c=this[0];if(!c||!c.ownerDocument)return null;if(b)return this.each(function(){a.offset.setOffset(this,b)});return h.call(this)}),function(){var b=document.getElementsByTagName("body")[0],c=document.createElement("div"),d,e,g,h,i;d=document.createElement(b?"div":"body"),g={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},b&&a.extend(g,{position:"absolute",left:"-1000px",top:"-1000px"});for(var j in g)d.style[j]=g[j];d.appendChild(c),e=b||document.documentElement,e.insertBefore(d,e.firstChild),c.style.cssText="position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;",h=a(c).offset(function(a,b){return b}).offset(),d.innerHTML="",e.removeChild(d),i=h.top+h.left+(b?2e3:0),f.fractions=i>21&&i<22}()})(jQuery);/* + * jQuery UI Draggable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Draggables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */(function(a,b){a.widget("ui.draggable",a.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1},_create:function(){this.options.helper=="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},destroy:function(){if(!!this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy();return this}},_mouseCapture:function(b){var c=this.options;if(this.helper||c.disabled||a(b.target).is(".ui-resizable-handle"))return!1;this.handle=this._getHandle(b);if(!this.handle)return!1;c.iframeFix&&a(c.iframeFix===!0?"iframe":c.iframeFix).each(function(){a('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(a(this).offset()).appendTo("body")});return!0},_mouseStart:function(b){var c=this.options;this.helper=this._createHelper(b),this._cacheHelperProportions(),a.ui.ddmanager&&(a.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,c.cursorAt&&this._adjustOffsetFromHelper(c.cursorAt),c.containment&&this._setContainment();if(this._trigger("start",b)===!1){this._clear();return!1}this._cacheHelperProportions(),a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this.helper.addClass("ui-draggable-dragging"),this._mouseDrag(b,!0),a.ui.ddmanager&&a.ui.ddmanager.dragStart(this,b);return!0},_mouseDrag:function(b,c){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute");if(!c){var d=this._uiHash();if(this._trigger("drag",b,d)===!1){this._mouseUp({});return!1}this.position=d.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";a.ui.ddmanager&&a.ui.ddmanager.drag(this,b);return!1},_mouseStop:function(b){var c=!1;a.ui.ddmanager&&!this.options.dropBehaviour&&(c=a.ui.ddmanager.drop(this,b)),this.dropped&&(c=this.dropped,this.dropped=!1);if((!this.element[0]||!this.element[0].parentNode)&&this.options.helper=="original")return!1;if(this.options.revert=="invalid"&&!c||this.options.revert=="valid"&&c||this.options.revert===!0||a.isFunction(this.options.revert)&&this.options.revert.call(this.element,c)){var d=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){d._trigger("stop",b)!==!1&&d._clear()})}else this._trigger("stop",b)!==!1&&this._clear();return!1},_mouseUp:function(b){this.options.iframeFix===!0&&a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),a.ui.ddmanager&&a.ui.ddmanager.dragStop(this,b);return a.ui.mouse.prototype._mouseUp.call(this,b)},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(b){var c=!this.options.handle||!a(this.options.handle,this.element).length?!0:!1;a(this.options.handle,this.element).find("*").andSelf().each(function(){this==b.target&&(c=!0)});return c},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b])):c.helper=="clone"?this.element.clone().removeAttr("id"):this.element;d.parents("body").length||d.appendTo(c.appendTo=="parent"?this.element[0].parentNode:c.appendTo),d[0]!=this.element[0]&&!/(fixed|absolute)/.test(d.css("position"))&&d.css("position","absolute");return d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[b.containment=="document"?0:a(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,b.containment=="document"?0:a(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(b.containment=="document"?0:a(window).scrollLeft())+a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(b.containment=="document"?0:a(window).scrollTop())+(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(b.containment)&&b.containment.constructor!=Array){var c=a(b.containment),d=c[0];if(!d)return;var e=c.offset(),f=a(d).css("overflow")!="hidden";this.containment=[(parseInt(a(d).css("borderLeftWidth"),10)||0)+(parseInt(a(d).css("paddingLeft"),10)||0),(parseInt(a(d).css("borderTopWidth"),10)||0)+(parseInt(a(d).css("paddingTop"),10)||0),(f?Math.max(d.scrollWidth,d.offsetWidth):d.offsetWidth)-(parseInt(a(d).css("borderLeftWidth"),10)||0)-(parseInt(a(d).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(f?Math.max(d.scrollHeight,d.offsetHeight):d.offsetHeight)-(parseInt(a(d).css("borderTopWidth"),10)||0)-(parseInt(a(d).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=c}else b.containment.constructor==Array&&(this.containment=b.containment)},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName),f=b.pageX,g=b.pageY;if(this.originalPosition){var h;if(this.containment){if(this.relative_container){var i=this.relative_container.offset();h=[this.containment[0]+i.left,this.containment[1]+i.top,this.containment[2]+i.left,this.containment[3]+i.top]}else h=this.containment;b.pageX-this.offset.click.left<h[0]&&(f=h[0]+this.offset.click.left),b.pageY-this.offset.click.top<h[1]&&(g=h[1]+this.offset.click.top),b.pageX-this.offset.click.left>h[2]&&(f=h[2]+this.offset.click.left),b.pageY-this.offset.click.top>h[3]&&(g=h[3]+this.offset.click.top)}if(c.grid){var j=c.grid[1]?this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1]:this.originalPageY;g=h?j-this.offset.click.top<h[1]||j-this.offset.click.top>h[3]?j-this.offset.click.top<h[1]?j+c.grid[1]:j-c.grid[1]:j:j;var k=c.grid[0]?this.originalPageX+Math.round((f-this.originalPageX)/c.grid[0])*c.grid[0]:this.originalPageX;f=h?k-this.offset.click.left<h[0]||k-this.offset.click.left>h[2]?k-this.offset.click.left<h[0]?k+c.grid[0]:k-c.grid[0]:k:k}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:d.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:d.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(b,c,d){d=d||this._uiHash(),a.ui.plugin.call(this,b,[c,d]),b=="drag"&&(this.positionAbs=this._convertPositionTo("absolute"));return a.Widget.prototype._trigger.call(this,b,c,d)},plugins:{},_uiHash:function(a){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),a.extend(a.ui.draggable,{version:"1.8.18"}),a.ui.plugin.add("draggable","connectToSortable",{start:function(b,c){var d=a(this).data("draggable"),e=d.options,f=a.extend({},c,{item:d.element});d.sortables=[],a(e.connectToSortable).each(function(){var c=a.data(this,"sortable");c&&!c.options.disabled&&(d.sortables.push({instance:c,shouldRevert:c.options.revert}),c.refreshPositions(),c._trigger("activate",b,f))})},stop:function(b,c){var d=a(this).data("draggable"),e=a.extend({},c,{item:d.element});a.each(d.sortables,function(){this.instance.isOver?(this.instance.isOver=0,d.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=!0),this.instance._mouseStop(b),this.instance.options.helper=this.instance.options._helper,d.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",b,e))})},drag:function(b,c){var d=a(this).data("draggable"),e=this,f=function(b){var c=this.offset.click.top,d=this.offset.click.left,e=this.positionAbs.top,f=this.positionAbs.left,g=b.height,h=b.width,i=b.top,j=b.left;return a.ui.isOver(e+c,f+d,i,j,g,h)};a.each(d.sortables,function(f){this.instance.positionAbs=d.positionAbs,this.instance.helperProportions=d.helperProportions,this.instance.offset.click=d.offset.click,this.instance._intersectsWith(this.instance.containerCache)?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=a(e).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return c.helper[0]},b.target=this.instance.currentItem[0],this.instance._mouseCapture(b,!0),this.instance._mouseStart(b,!0,!0),this.instance.offset.click.top=d.offset.click.top,this.instance.offset.click.left=d.offset.click.left,this.instance.offset.parent.left-=d.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=d.offset.parent.top-this.instance.offset.parent.top,d._trigger("toSortable",b),d.dropped=this.instance.element,d.currentItem=d.element,this.instance.fromOutside=d),this.instance.currentItem&&this.instance._mouseDrag(b)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",b,this.instance._uiHash(this.instance)),this.instance._mouseStop(b,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),d._trigger("fromSortable",b),d.dropped=!1)})}}),a.ui.plugin.add("draggable","cursor",{start:function(b,c){var d=a("body"),e=a(this).data("draggable").options;d.css("cursor")&&(e._cursor=d.css("cursor")),d.css("cursor",e.cursor)},stop:function(b,c){var d=a(this).data("draggable").options;d._cursor&&a("body").css("cursor",d._cursor)}}),a.ui.plugin.add("draggable","opacity",{start:function(b,c){var d=a(c.helper),e=a(this).data("draggable").options;d.css("opacity")&&(e._opacity=d.css("opacity")),d.css("opacity",e.opacity)},stop:function(b,c){var d=a(this).data("draggable").options;d._opacity&&a(c.helper).css("opacity",d._opacity)}}),a.ui.plugin.add("draggable","scroll",{start:function(b,c){var d=a(this).data("draggable");d.scrollParent[0]!=document&&d.scrollParent[0].tagName!="HTML"&&(d.overflowOffset=d.scrollParent.offset())},drag:function(b,c){var d=a(this).data("draggable"),e=d.options,f=!1;if(d.scrollParent[0]!=document&&d.scrollParent[0].tagName!="HTML"){if(!e.axis||e.axis!="x")d.overflowOffset.top+d.scrollParent[0].offsetHeight-b.pageY<e.scrollSensitivity?d.scrollParent[0].scrollTop=f=d.scrollParent[0].scrollTop+e.scrollSpeed:b.pageY-d.overflowOffset.top<e.scrollSensitivity&&(d.scrollParent[0].scrollTop=f=d.scrollParent[0].scrollTop-e.scrollSpeed);if(!e.axis||e.axis!="y")d.overflowOffset.left+d.scrollParent[0].offsetWidth-b.pageX<e.scrollSensitivity?d.scrollParent[0].scrollLeft=f=d.scrollParent[0].scrollLeft+e.scrollSpeed:b.pageX-d.overflowOffset.left<e.scrollSensitivity&&(d.scrollParent[0].scrollLeft=f=d.scrollParent[0].scrollLeft-e.scrollSpeed)}else{if(!e.axis||e.axis!="x")b.pageY-a(document).scrollTop()<e.scrollSensitivity?f=a(document).scrollTop(a(document).scrollTop()-e.scrollSpeed):a(window).height()-(b.pageY-a(document).scrollTop())<e.scrollSensitivity&&(f=a(document).scrollTop(a(document).scrollTop()+e.scrollSpeed));if(!e.axis||e.axis!="y")b.pageX-a(document).scrollLeft()<e.scrollSensitivity?f=a(document).scrollLeft(a(document).scrollLeft()-e.scrollSpeed):a(window).width()-(b.pageX-a(document).scrollLeft())<e.scrollSensitivity&&(f=a(document).scrollLeft(a(document).scrollLeft()+e.scrollSpeed))}f!==!1&&a.ui.ddmanager&&!e.dropBehaviour&&a.ui.ddmanager.prepareOffsets(d,b)}}),a.ui.plugin.add("draggable","snap",{start:function(b,c){var d=a(this).data("draggable"),e=d.options;d.snapElements=[],a(e.snap.constructor!=String?e.snap.items||":data(draggable)":e.snap).each(function(){var b=a(this),c=b.offset();this!=d.element[0]&&d.snapElements.push({item:this,width:b.outerWidth(),height:b.outerHeight(),top:c.top,left:c.left})})},drag:function(b,c){var d=a(this).data("draggable"),e=d.options,f=e.snapTolerance,g=c.offset.left,h=g+d.helperProportions.width,i=c.offset.top,j=i+d.helperProportions.height;for(var k=d.snapElements.length-1;k>=0;k--){var l=d.snapElements[k].left,m=l+d.snapElements[k].width,n=d.snapElements[k].top,o=n+d.snapElements[k].height;if(!(l-f<g&&g<m+f&&n-f<i&&i<o+f||l-f<g&&g<m+f&&n-f<j&&j<o+f||l-f<h&&h<m+f&&n-f<i&&i<o+f||l-f<h&&h<m+f&&n-f<j&&j<o+f)){d.snapElements[k].snapping&&d.options.snap.release&&d.options.snap.release.call(d.element,b,a.extend(d._uiHash(),{snapItem:d.snapElements[k].item})),d.snapElements[k].snapping=!1;continue}if(e.snapMode!="inner"){var p=Math.abs(n-j)<=f,q=Math.abs(o-i)<=f,r=Math.abs(l-h)<=f,s=Math.abs(m-g)<=f;p&&(c.position.top=d._convertPositionTo("relative",{top:n-d.helperProportions.height,left:0}).top-d.margins.top),q&&(c.position.top=d._convertPositionTo("relative",{top:o,left:0}).top-d.margins.top),r&&(c.position.left=d._convertPositionTo("relative",{top:0,left:l-d.helperProportions.width}).left-d.margins.left),s&&(c.position.left=d._convertPositionTo("relative",{top:0,left:m}).left-d.margins.left)}var t=p||q||r||s;if(e.snapMode!="outer"){var p=Math.abs(n-i)<=f,q=Math.abs(o-j)<=f,r=Math.abs(l-g)<=f,s=Math.abs(m-h)<=f;p&&(c.position.top=d._convertPositionTo("relative",{top:n,left:0}).top-d.margins.top),q&&(c.position.top=d._convertPositionTo("relative",{top:o-d.helperProportions.height,left:0}).top-d.margins.top),r&&(c.position.left=d._convertPositionTo("relative",{top:0,left:l}).left-d.margins.left),s&&(c.position.left=d._convertPositionTo("relative",{top:0,left:m-d.helperProportions.width}).left-d.margins.left)}!d.snapElements[k].snapping&&(p||q||r||s||t)&&d.options.snap.snap&&d.options.snap.snap.call(d.element,b,a.extend(d._uiHash(),{snapItem:d.snapElements[k].item})),d.snapElements[k].snapping=p||q||r||s||t}}}),a.ui.plugin.add("draggable","stack",{start:function(b,c){var d=a(this).data("draggable").options,e=a.makeArray(a(d.stack)).sort(function(b,c){return(parseInt(a(b).css("zIndex"),10)||0)-(parseInt(a(c).css("zIndex"),10)||0)});if(!!e.length){var f=parseInt(e[0].style.zIndex)||0;a(e).each(function(a){this.style.zIndex=f+a}),this[0].style.zIndex=f+e.length}}}),a.ui.plugin.add("draggable","zIndex",{start:function(b,c){var d=a(c.helper),e=a(this).data("draggable").options;d.css("zIndex")&&(e._zIndex=d.css("zIndex")),d.css("zIndex",e.zIndex)},stop:function(b,c){var d=a(this).data("draggable").options;d._zIndex&&a(c.helper).css("zIndex",d._zIndex)}})})(jQuery);/* + * jQuery UI Droppable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Droppables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.mouse.js + * jquery.ui.draggable.js + */(function(a,b){a.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect"},_create:function(){var b=this.options,c=b.accept;this.isover=0,this.isout=1,this.accept=a.isFunction(c)?c:function(a){return a.is(c)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},a.ui.ddmanager.droppables[b.scope]=a.ui.ddmanager.droppables[b.scope]||[],a.ui.ddmanager.droppables[b.scope].push(this),b.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){var b=a.ui.ddmanager.droppables[this.options.scope];for(var c=0;c<b.length;c++)b[c]==this&&b.splice(c,1);this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable");return this},_setOption:function(b,c){b=="accept"&&(this.accept=a.isFunction(c)?c:function(a){return a.is(c)}),a.Widget.prototype._setOption.apply(this,arguments)},_activate:function(b){var c=a.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),c&&this._trigger("activate",b,this.ui(c))},_deactivate:function(b){var c=a.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),c&&this._trigger("deactivate",b,this.ui(c))},_over:function(b){var c=a.ui.ddmanager.current;!!c&&(c.currentItem||c.element)[0]!=this.element[0]&&this.accept.call(this.element[0],c.currentItem||c.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",b,this.ui(c)))},_out:function(b){var c=a.ui.ddmanager.current;!!c&&(c.currentItem||c.element)[0]!=this.element[0]&&this.accept.call(this.element[0],c.currentItem||c.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",b,this.ui(c)))},_drop:function(b,c){var d=c||a.ui.ddmanager.current;if(!d||(d.currentItem||d.element)[0]==this.element[0])return!1;var e=!1;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var b=a.data(this,"droppable");if(b.options.greedy&&!b.options.disabled&&b.options.scope==d.options.scope&&b.accept.call(b.element[0],d.currentItem||d.element)&&a.ui.intersect(d,a.extend(b,{offset:b.element.offset()}),b.options.tolerance)){e=!0;return!1}});if(e)return!1;if(this.accept.call(this.element[0],d.currentItem||d.element)){this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",b,this.ui(d));return this.element}return!1},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}}),a.extend(a.ui.droppable,{version:"1.8.18"}),a.ui.intersect=function(b,c,d){if(!c.offset)return!1;var e=(b.positionAbs||b.position.absolute).left,f=e+b.helperProportions.width,g=(b.positionAbs||b.position.absolute).top,h=g+b.helperProportions.height,i=c.offset.left,j=i+c.proportions.width,k=c.offset.top,l=k+c.proportions.height;switch(d){case"fit":return i<=e&&f<=j&&k<=g&&h<=l;case"intersect":return i<e+b.helperProportions.width/2&&f-b.helperProportions.width/2<j&&k<g+b.helperProportions.height/2&&h-b.helperProportions.height/2<l;case"pointer":var m=(b.positionAbs||b.position.absolute).left+(b.clickOffset||b.offset.click).left,n=(b.positionAbs||b.position.absolute).top+(b.clickOffset||b.offset.click).top,o=a.ui.isOver(n,m,k,i,c.proportions.height,c.proportions.width);return o;case"touch":return(g>=k&&g<=l||h>=k&&h<=l||g<k&&h>l)&&(e>=i&&e<=j||f>=i&&f<=j||e<i&&f>j);default:return!1}},a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(b,c){var d=a.ui.ddmanager.droppables[b.options.scope]||[],e=c?c.type:null,f=(b.currentItem||b.element).find(":data(droppable)").andSelf();droppablesLoop:for(var g=0;g<d.length;g++){if(d[g].options.disabled||b&&!d[g].accept.call(d[g].element[0],b.currentItem||b.element))continue;for(var h=0;h<f.length;h++)if(f[h]==d[g].element[0]){d[g].proportions.height=0;continue droppablesLoop}d[g].visible=d[g].element.css("display")!="none";if(!d[g].visible)continue;e=="mousedown"&&d[g]._activate.call(d[g],c),d[g].offset=d[g].element.offset(),d[g].proportions={width:d[g].element[0].offsetWidth,height:d[g].element[0].offsetHeight}}},drop:function(b,c){var d=!1;a.each(a.ui.ddmanager.droppables[b.options.scope]||[],function(){!this.options||(!this.options.disabled&&this.visible&&a.ui.intersect(b,this,this.options.tolerance)&&(d=this._drop.call(this,c)||d),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],b.currentItem||b.element)&&(this.isout=1,this.isover=0,this._deactivate.call(this,c)))});return d},dragStart:function(b,c){b.element.parents(":not(body,html)").bind("scroll.droppable",function(){b.options.refreshPositions||a.ui.ddmanager.prepareOffsets(b,c)})},drag:function(b,c){b.options.refreshPositions&&a.ui.ddmanager.prepareOffsets(b,c),a.each(a.ui.ddmanager.droppables[b.options.scope]||[],function(){if(!(this.options.disabled||this.greedyChild||!this.visible)){var d=a.ui.intersect(b,this,this.options.tolerance),e=!d&&this.isover==1?"isout":d&&this.isover==0?"isover":null;if(!e)return;var f;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");g.length&&(f=a.data(g[0],"droppable"),f.greedyChild=e=="isover"?1:0)}f&&e=="isover"&&(f.isover=0,f.isout=1,f._out.call(f,c)),this[e]=1,this[e=="isout"?"isover":"isout"]=0,this[e=="isover"?"_over":"_out"].call(this,c),f&&e=="isout"&&(f.isout=0,f.isover=1,f._over.call(f,c))}})},dragStop:function(b,c){b.element.parents(":not(body,html)").unbind("scroll.droppable"),b.options.refreshPositions||a.ui.ddmanager.prepareOffsets(b,c)}}})(jQuery);/* + * jQuery UI Resizable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */(function(a,b){a.widget("ui.resizable",a.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var b=this,c=this.options;this.element.addClass("ui-resizable"),a.extend(this,{_aspectRatio:!!c.aspectRatio,aspectRatio:c.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:c.helper||c.ghost||c.animate?c.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(a('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=c.handles||(a(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var d=this.handles.split(",");this.handles={};for(var e=0;e<d.length;e++){var f=a.trim(d[e]),g="ui-resizable-"+f,h=a('<div class="ui-resizable-handle '+g+'"></div>');/sw|se|ne|nw/.test(f)&&h.css({zIndex:++c.zIndex}),"se"==f&&h.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[f]=".ui-resizable-"+f,this.element.append(h)}}this._renderAxis=function(b){b=b||this.element;for(var c in this.handles){this.handles[c].constructor==String&&(this.handles[c]=a(this.handles[c],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var d=a(this.handles[c],this.element),e=0;e=/sw|ne|nw|se|n|s/.test(c)?d.outerHeight():d.outerWidth();var f=["padding",/ne|nw|n/.test(c)?"Top":/se|sw|s/.test(c)?"Bottom":/^e$/.test(c)?"Right":"Left"].join("");b.css(f,e),this._proportionallyResize()}if(!a(this.handles[c]).length)continue}},this._renderAxis(this.element),this._handles=a(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!b.resizing){if(this.className)var a=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=a&&a[1]?a[1]:"se"}}),c.autoHide&&(this._handles.hide(),a(this.element).addClass("ui-resizable-autohide").hover(function(){c.disabled||(a(this).removeClass("ui-resizable-autohide"),b._handles.show())},function(){c.disabled||b.resizing||(a(this).addClass("ui-resizable-autohide"),b._handles.hide())})),this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(b){a(b).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){b(this.element);var c=this.element;c.after(this.originalElement.css({position:c.css("position"),width:c.outerWidth(),height:c.outerHeight(),top:c.css("top"),left:c.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle),b(this.originalElement);return this},_mouseCapture:function(b){var c=!1;for(var d in this.handles)a(this.handles[d])[0]==b.target&&(c=!0);return!this.options.disabled&&c},_mouseStart:function(b){var d=this.options,e=this.element.position(),f=this.element;this.resizing=!0,this.documentScroll={top:a(document).scrollTop(),left:a(document).scrollLeft()},(f.is(".ui-draggable")||/absolute/.test(f.css("position")))&&f.css({position:"absolute",top:e.top,left:e.left}),this._renderProxy();var g=c(this.helper.css("left")),h=c(this.helper.css("top"));d.containment&&(g+=a(d.containment).scrollLeft()||0,h+=a(d.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:g,top:h},this.size=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalSize=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalPosition={left:g,top:h},this.sizeDiff={width:f.outerWidth()-f.width(),height:f.outerHeight()-f.height()},this.originalMousePosition={left:b.pageX,top:b.pageY},this.aspectRatio=typeof d.aspectRatio=="number"?d.aspectRatio:this.originalSize.width/this.originalSize.height||1;var i=a(".ui-resizable-"+this.axis).css("cursor");a("body").css("cursor",i=="auto"?this.axis+"-resize":i),f.addClass("ui-resizable-resizing"),this._propagate("start",b);return!0},_mouseDrag:function(b){var c=this.helper,d=this.options,e={},f=this,g=this.originalMousePosition,h=this.axis,i=b.pageX-g.left||0,j=b.pageY-g.top||0,k=this._change[h];if(!k)return!1;var l=k.apply(this,[b,i,j]),m=a.browser.msie&&a.browser.version<7,n=this.sizeDiff;this._updateVirtualBoundaries(b.shiftKey);if(this._aspectRatio||b.shiftKey)l=this._updateRatio(l,b);l=this._respectSize(l,b),this._propagate("resize",b),c.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",b,this.ui());return!1},_mouseStop:function(b){this.resizing=!1;var c=this.options,d=this;if(this._helper){var e=this._proportionallyResizeElements,f=e.length&&/textarea/i.test(e[0].nodeName),g=f&&a.ui.hasScroll(e[0],"left")?0:d.sizeDiff.height,h=f?0:d.sizeDiff.width,i={width:d.helper.width()-h,height:d.helper.height()-g},j=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,k=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;c.animate||this.element.css(a.extend(i,{top:k,left:j})),d.helper.height(d.size.height),d.helper.width(d.size.width),this._helper&&!c.animate&&this._proportionallyResize()}a("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",b),this._helper&&this.helper.remove();return!1},_updateVirtualBoundaries:function(a){var b=this.options,c,e,f,g,h;h={minWidth:d(b.minWidth)?b.minWidth:0,maxWidth:d(b.maxWidth)?b.maxWidth:Infinity,minHeight:d(b.minHeight)?b.minHeight:0,maxHeight:d(b.maxHeight)?b.maxHeight:Infinity};if(this._aspectRatio||a)c=h.minHeight*this.aspectRatio,f=h.minWidth/this.aspectRatio,e=h.maxHeight*this.aspectRatio,g=h.maxWidth/this.aspectRatio,c>h.minWidth&&(h.minWidth=c),f>h.minHeight&&(h.minHeight=f),e<h.maxWidth&&(h.maxWidth=e),g<h.maxHeight&&(h.maxHeight=g);this._vBoundaries=h},_updateCache:function(a){var b=this.options;this.offset=this.helper.offset(),d(a.left)&&(this.position.left=a.left),d(a.top)&&(this.position.top=a.top),d(a.height)&&(this.size.height=a.height),d(a.width)&&(this.size.width=a.width)},_updateRatio:function(a,b){var c=this.options,e=this.position,f=this.size,g=this.axis;d(a.height)?a.width=a.height*this.aspectRatio:d(a.width)&&(a.height=a.width/this.aspectRatio),g=="sw"&&(a.left=e.left+(f.width-a.width),a.top=null),g=="nw"&&(a.top=e.top+(f.height-a.height),a.left=e.left+(f.width-a.width));return a},_respectSize:function(a,b){var c=this.helper,e=this._vBoundaries,f=this._aspectRatio||b.shiftKey,g=this.axis,h=d(a.width)&&e.maxWidth&&e.maxWidth<a.width,i=d(a.height)&&e.maxHeight&&e.maxHeight<a.height,j=d(a.width)&&e.minWidth&&e.minWidth>a.width,k=d(a.height)&&e.minHeight&&e.minHeight>a.height;j&&(a.width=e.minWidth),k&&(a.height=e.minHeight),h&&(a.width=e.maxWidth),i&&(a.height=e.maxHeight);var l=this.originalPosition.left+this.originalSize.width,m=this.position.top+this.size.height,n=/sw|nw|w/.test(g),o=/nw|ne|n/.test(g);j&&n&&(a.left=l-e.minWidth),h&&n&&(a.left=l-e.maxWidth),k&&o&&(a.top=m-e.minHeight),i&&o&&(a.top=m-e.maxHeight);var p=!a.width&&!a.height;p&&!a.left&&a.top?a.top=null:p&&!a.top&&a.left&&(a.left=null);return a},_proportionallyResize:function(){var b=this.options;if(!!this._proportionallyResizeElements.length){var c=this.helper||this.element;for(var d=0;d<this._proportionallyResizeElements.length;d++){var e=this._proportionallyResizeElements[d];if(!this.borderDif){var f=[e.css("borderTopWidth"),e.css("borderRightWidth"),e.css("borderBottomWidth"),e.css("borderLeftWidth")],g=[e.css("paddingTop"),e.css("paddingRight"),e.css("paddingBottom"),e.css("paddingLeft")];this.borderDif=a.map(f,function(a,b){var c=parseInt(a,10)||0,d=parseInt(g[b],10)||0;return c+d})}if(a.browser.msie&&(!!a(c).is(":hidden")||!!a(c).parents(":hidden").length))continue;e.css({height:c.height()-this.borderDif[0]-this.borderDif[2]||0,width:c.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var b=this.element,c=this.options;this.elementOffset=b.offset();if(this._helper){this.helper=this.helper||a('<div style="overflow:hidden;"></div>');var d=a.browser.msie&&a.browser.version<7,e=d?1:0,f=d?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+f,height:this.element.outerHeight()+f,position:"absolute",left:this.elementOffset.left-e+"px",top:this.elementOffset.top-e+"px",zIndex:++c.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(a,b,c){return{width:this.originalSize.width+b}},w:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{left:f.left+b,width:e.width-b}},n:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{top:f.top+c,height:e.height-c}},s:function(a,b,c){return{height:this.originalSize.height+c}},se:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},sw:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,c,d]))},ne:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},nw:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,c,d]))}},_propagate:function(b,c){a.ui.plugin.call(this,b,[c,this.ui()]),b!="resize"&&this._trigger(b,c,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),a.extend(a.ui.resizable,{version:"1.8.18"}),a.ui.plugin.add("resizable","alsoResize",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=function(b){a(b).each(function(){var b=a(this);b.data("resizable-alsoresize",{width:parseInt(b.width(),10),height:parseInt(b.height(),10),left:parseInt(b.css("left"),10),top:parseInt(b.css("top"),10)})})};typeof e.alsoResize=="object"&&!e.alsoResize.parentNode?e.alsoResize.length?(e.alsoResize=e.alsoResize[0],f(e.alsoResize)):a.each(e.alsoResize,function(a){f(a)}):f(e.alsoResize)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.originalSize,g=d.originalPosition,h={height:d.size.height-f.height||0,width:d.size.width-f.width||0,top:d.position.top-g.top||0,left:d.position.left-g.left||0},i=function(b,d){a(b).each(function(){var b=a(this),e=a(this).data("resizable-alsoresize"),f={},g=d&&d.length?d:b.parents(c.originalElement[0]).length?["width","height"]:["width","height","top","left"];a.each(g,function(a,b){var c=(e[b]||0)+(h[b]||0);c&&c>=0&&(f[b]=c||null)}),b.css(f)})};typeof e.alsoResize=="object"&&!e.alsoResize.nodeType?a.each(e.alsoResize,function(a,b){i(a,b)}):i(e.alsoResize)},stop:function(b,c){a(this).removeData("resizable-alsoresize")}}),a.ui.plugin.add("resizable","animate",{stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d._proportionallyResizeElements,g=f.length&&/textarea/i.test(f[0].nodeName),h=g&&a.ui.hasScroll(f[0],"left")?0:d.sizeDiff.height,i=g?0:d.sizeDiff.width,j={width:d.size.width-i,height:d.size.height-h},k=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,l=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;d.element.animate(a.extend(j,l&&k?{top:l,left:k}:{}),{duration:e.animateDuration,easing:e.animateEasing,step:function(){var c={width:parseInt(d.element.css("width"),10),height:parseInt(d.element.css("height"),10),top:parseInt(d.element.css("top"),10),left:parseInt(d.element.css("left"),10)};f&&f.length&&a(f[0]).css({width:c.width,height:c.height}),d._updateCache(c),d._propagate("resize",b)}})}}),a.ui.plugin.add("resizable","containment",{start:function(b,d){var e=a(this).data("resizable"),f=e.options,g=e.element,h=f.containment,i=h instanceof a?h.get(0):/parent/.test(h)?g.parent().get(0):h;if(!!i){e.containerElement=a(i);if(/document/.test(h)||h==document)e.containerOffset={left:0,top:0},e.containerPosition={left:0,top:0},e.parentData={element:a(document),left:0,top:0,width:a(document).width(),height:a(document).height()||document.body.parentNode.scrollHeight};else{var j=a(i),k=[];a(["Top","Right","Left","Bottom"]).each(function(a,b){k[a]=c(j.css("padding"+b))}),e.containerOffset=j.offset(),e.containerPosition=j.position(),e.containerSize={height:j.innerHeight()-k[3],width:j.innerWidth()-k[1]};var l=e.containerOffset,m=e.containerSize.height,n=e.containerSize.width,o=a.ui.hasScroll(i,"left")?i.scrollWidth:n,p=a.ui.hasScroll(i)?i.scrollHeight:m;e.parentData={element:i,left:l.left,top:l.top,width:o,height:p}}}},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.containerSize,g=d.containerOffset,h=d.size,i=d.position,j=d._aspectRatio||b.shiftKey,k={top:0,left:0},l=d.containerElement;l[0]!=document&&/static/.test(l.css("position"))&&(k=g),i.left<(d._helper?g.left:0)&&(d.size.width=d.size.width+(d._helper?d.position.left-g.left:d.position.left-k.left),j&&(d.size.height=d.size.width/e.aspectRatio),d.position.left=e.helper?g.left:0),i.top<(d._helper?g.top:0)&&(d.size.height=d.size.height+(d._helper?d.position.top-g.top:d.position.top),j&&(d.size.width=d.size.height*e.aspectRatio),d.position.top=d._helper?g.top:0),d.offset.left=d.parentData.left+d.position.left,d.offset.top=d.parentData.top+d.position.top;var m=Math.abs((d._helper?d.offset.left-k.left:d.offset.left-k.left)+d.sizeDiff.width),n=Math.abs((d._helper?d.offset.top-k.top:d.offset.top-g.top)+d.sizeDiff.height),o=d.containerElement.get(0)==d.element.parent().get(0),p=/relative|absolute/.test(d.containerElement.css("position"));o&&p&&(m-=d.parentData.left),m+d.size.width>=d.parentData.width&&(d.size.width=d.parentData.width-m,j&&(d.size.height=d.size.width/d.aspectRatio)),n+d.size.height>=d.parentData.height&&(d.size.height=d.parentData.height-n,j&&(d.size.width=d.size.height*d.aspectRatio))},stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.position,g=d.containerOffset,h=d.containerPosition,i=d.containerElement,j=a(d.helper),k=j.offset(),l=j.outerWidth()-d.sizeDiff.width,m=j.outerHeight()-d.sizeDiff.height;d._helper&&!e.animate&&/relative/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m}),d._helper&&!e.animate&&/static/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m})}}),a.ui.plugin.add("resizable","ghost",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size;d.ghost=d.originalElement.clone(),d.ghost.css({opacity:.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof e.ghost=="string"?e.ghost:""),d.ghost.appendTo(d.helper)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})},stop:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.helper&&d.helper.get(0).removeChild(d.ghost.get(0))}}),a.ui.plugin.add("resizable","grid",{resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size,g=d.originalSize,h=d.originalPosition,i=d.axis,j=e._aspectRatio||b.shiftKey;e.grid=typeof e.grid=="number"?[e.grid,e.grid]:e.grid;var k=Math.round((f.width-g.width)/(e.grid[0]||1))*(e.grid[0]||1),l=Math.round((f.height-g.height)/(e.grid[1]||1))*(e.grid[1]||1);/^(se|s|e)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l):/^(ne)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l):/^(sw)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.left=h.left-k):(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l,d.position.left=h.left-k)}});var c=function(a){return parseInt(a,10)||0},d=function(a){return!isNaN(parseInt(a,10))}})(jQuery);/* + * jQuery UI Selectable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */(function(a,b){a.widget("ui.selectable",a.ui.mouse,{options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var b=this;this.element.addClass("ui-selectable"),this.dragged=!1;var c;this.refresh=function(){c=a(b.options.filter,b.element[0]),c.addClass("ui-selectee"),c.each(function(){var b=a(this),c=b.offset();a.data(this,"selectable-item",{element:this,$element:b,left:c.left,top:c.top,right:c.left+b.outerWidth(),bottom:c.top+b.outerHeight(),startselected:!1,selected:b.hasClass("ui-selected"),selecting:b.hasClass("ui-selecting"),unselecting:b.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=c.addClass("ui-selectee"),this._mouseInit(),this.helper=a("<div class='ui-selectable-helper'></div>")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable"),this._mouseDestroy();return this},_mouseStart:function(b){var c=this;this.opos=[b.pageX,b.pageY];if(!this.options.disabled){var d=this.options;this.selectees=a(d.filter,this.element[0]),this._trigger("start",b),a(d.appendTo).append(this.helper),this.helper.css({left:b.clientX,top:b.clientY,width:0,height:0}),d.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var d=a.data(this,"selectable-item");d.startselected=!0,!b.metaKey&&!b.ctrlKey&&(d.$element.removeClass("ui-selected"),d.selected=!1,d.$element.addClass("ui-unselecting"),d.unselecting=!0,c._trigger("unselecting",b,{unselecting:d.element}))}),a(b.target).parents().andSelf().each(function(){var d=a.data(this,"selectable-item");if(d){var e=!b.metaKey&&!b.ctrlKey||!d.$element.hasClass("ui-selected");d.$element.removeClass(e?"ui-unselecting":"ui-selected").addClass(e?"ui-selecting":"ui-unselecting"),d.unselecting=!e,d.selecting=e,d.selected=e,e?c._trigger("selecting",b,{selecting:d.element}):c._trigger("unselecting",b,{unselecting:d.element});return!1}})}},_mouseDrag:function(b){var c=this;this.dragged=!0;if(!this.options.disabled){var d=this.options,e=this.opos[0],f=this.opos[1],g=b.pageX,h=b.pageY;if(e>g){var i=g;g=e,e=i}if(f>h){var i=h;h=f,f=i}this.helper.css({left:e,top:f,width:g-e,height:h-f}),this.selectees.each(function(){var i=a.data(this,"selectable-item");if(!!i&&i.element!=c.element[0]){var j=!1;d.tolerance=="touch"?j=!(i.left>g||i.right<e||i.top>h||i.bottom<f):d.tolerance=="fit"&&(j=i.left>e&&i.right<g&&i.top>f&&i.bottom<h),j?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,c._trigger("selecting",b,{selecting:i.element}))):(i.selecting&&((b.metaKey||b.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),c._trigger("unselecting",b,{unselecting:i.element}))),i.selected&&!b.metaKey&&!b.ctrlKey&&!i.startselected&&(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,c._trigger("unselecting",b,{unselecting:i.element})))}});return!1}},_mouseStop:function(b){var c=this;this.dragged=!1;var d=this.options;a(".ui-unselecting",this.element[0]).each(function(){var d=a.data(this,"selectable-item");d.$element.removeClass("ui-unselecting"),d.unselecting=!1,d.startselected=!1,c._trigger("unselected",b,{unselected:d.element})}),a(".ui-selecting",this.element[0]).each(function(){var d=a.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("ui-selected"),d.selecting=!1,d.selected=!0,d.startselected=!0,c._trigger("selected",b,{selected:d.element})}),this._trigger("stop",b),this.helper.remove();return!1}}),a.extend(a.ui.selectable,{version:"1.8.18"})})(jQuery);/* + * jQuery UI Sortable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Sortables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */(function(a,b){a.widget("ui.sortable",a.ui.mouse,{widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var a=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},destroy:function(){a.Widget.prototype.destroy.call(this),this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var b=this.items.length-1;b>=0;b--)this.items[b].item.removeData(this.widgetName+"-item");return this},_setOption:function(b,c){b==="disabled"?(this.options[b]=c,this.widget()[c?"addClass":"removeClass"]("ui-sortable-disabled")):a.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(b,c){var d=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(b);var e=null,f=this,g=a(b.target).parents().each(function(){if(a.data(this,d.widgetName+"-item")==f){e=a(this);return!1}});a.data(b.target,d.widgetName+"-item")==f&&(e=a(b.target));if(!e)return!1;if(this.options.handle&&!c){var h=!1;a(this.options.handle,e).find("*").andSelf().each(function(){this==b.target&&(h=!0)});if(!h)return!1}this.currentItem=e,this._removeCurrentsFromItems();return!0},_mouseStart:function(b,c,d){var e=this.options,f=this;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(b),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,e.cursorAt&&this._adjustOffsetFromHelper(e.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),e.containment&&this._setContainment(),e.cursor&&(a("body").css("cursor")&&(this._storedCursor=a("body").css("cursor")),a("body").css("cursor",e.cursor)),e.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",e.opacity)),e.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",e.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",b,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!d)for(var g=this.containers.length-1;g>=0;g--)this.containers[g]._trigger("activate",b,f._uiHash(this));a.ui.ddmanager&&(a.ui.ddmanager.current=this),a.ui.ddmanager&&!e.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(b);return!0},_mouseDrag:function(b){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var c=this.options,d=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-b.pageY<c.scrollSensitivity?this.scrollParent[0].scrollTop=d=this.scrollParent[0].scrollTop+c.scrollSpeed:b.pageY-this.overflowOffset.top<c.scrollSensitivity&&(this.scrollParent[0].scrollTop=d=this.scrollParent[0].scrollTop-c.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-b.pageX<c.scrollSensitivity?this.scrollParent[0].scrollLeft=d=this.scrollParent[0].scrollLeft+c.scrollSpeed:b.pageX-this.overflowOffset.left<c.scrollSensitivity&&(this.scrollParent[0].scrollLeft=d=this.scrollParent[0].scrollLeft-c.scrollSpeed)):(b.pageY-a(document).scrollTop()<c.scrollSensitivity?d=a(document).scrollTop(a(document).scrollTop()-c.scrollSpeed):a(window).height()-(b.pageY-a(document).scrollTop())<c.scrollSensitivity&&(d=a(document).scrollTop(a(document).scrollTop()+c.scrollSpeed)),b.pageX-a(document).scrollLeft()<c.scrollSensitivity?d=a(document).scrollLeft(a(document).scrollLeft()-c.scrollSpeed):a(window).width()-(b.pageX-a(document).scrollLeft())<c.scrollSensitivity&&(d=a(document).scrollLeft(a(document).scrollLeft()+c.scrollSpeed))),d!==!1&&a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(var e=this.items.length-1;e>=0;e--){var f=this.items[e],g=f.item[0],h=this._intersectsWithPointer(f);if(!h)continue;if(g!=this.currentItem[0]&&this.placeholder[h==1?"next":"prev"]()[0]!=g&&!a.ui.contains(this.placeholder[0],g)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0],g):!0)){this.direction=h==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(f))this._rearrange(b,f);else break;this._trigger("change",b,this._uiHash());break}}this._contactContainers(b),a.ui.ddmanager&&a.ui.ddmanager.drag(this,b),this._trigger("sort",b,this._uiHash()),this.lastPositionAbs=this.positionAbs;return!1},_mouseStop:function(b,c){if(!!b){a.ui.ddmanager&&!this.options.dropBehaviour&&a.ui.ddmanager.drop(this,b);if(this.options.revert){var d=this,e=d.placeholder.offset();d.reverting=!0,a(this.helper).animate({left:e.left-this.offset.parent.left-d.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:e.top-this.offset.parent.top-d.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){d._clear(b)})}else this._clear(b,c);return!1}},cancel:function(){var b=this;if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("deactivate",null,b._uiHash(this)),this.containers[c].containerCache.over&&(this.containers[c]._trigger("out",null,b._uiHash(this)),this.containers[c].containerCache.over=0)}this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),a.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?a(this.domPosition.prev).after(this.currentItem):a(this.domPosition.parent).prepend(this.currentItem));return this},serialize:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];b=b||{},a(c).each(function(){var c=(a(b.item||this).attr(b.attribute||"id")||"").match(b.expression||/(.+)[-=_](.+)/);c&&d.push((b.key||c[1]+"[]")+"="+(b.key&&b.expression?c[1]:c[2]))}),!d.length&&b.key&&d.push(b.key+"=");return d.join("&")},toArray:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];b=b||{},c.each(function(){d.push(a(b.item||this).attr(b.attribute||"id")||"")});return d},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,d=this.positionAbs.top,e=d+this.helperProportions.height,f=a.left,g=f+a.width,h=a.top,i=h+a.height,j=this.offset.click.top,k=this.offset.click.left,l=d+j>h&&d+j<i&&b+k>f&&b+k<g;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?l:f<b+this.helperProportions.width/2&&c-this.helperProportions.width/2<g&&h<d+this.helperProportions.height/2&&e-this.helperProportions.height/2<i},_intersectsWithPointer:function(b){var c=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,b.top,b.height),d=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,b.left,b.width),e=c&&d,f=this._getDragVerticalDirection(),g=this._getDragHorizontalDirection();if(!e)return!1;return this.floating?g&&g=="right"||f=="down"?2:1:f&&(f=="down"?2:1)},_intersectsWithSides:function(b){var c=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,b.top+b.height/2,b.height),d=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,b.left+b.width/2,b.width),e=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();return this.floating&&f?f=="right"&&d||f=="left"&&!d:e&&(e=="down"&&c||e=="up"&&!c)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a),this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(b){var c=this,d=[],e=[],f=this._connectWith();if(f&&b)for(var g=f.length-1;g>=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&e.push([a.isFunction(j.options.items)?j.options.items.call(j.element):a(j.options.items,j.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),j])}}e.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var g=e.length-1;g>=0;g--)e[g][0].each(function(){d.push(this)});return a(d)},_removeCurrentsFromItems:function(){var a=this.currentItem.find(":data("+this.widgetName+"-item)");for(var b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(b){this.items=[],this.containers=[this];var c=this.items,d=this,e=[[a.isFunction(this.options.items)?this.options.items.call(this.element[0],b,{item:this.currentItem}):a(this.options.items,this.element),this]],f=this._connectWith();if(f&&this.ready)for(var g=f.length-1;g>=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&(e.push([a.isFunction(j.options.items)?j.options.items.call(j.element[0],b,{item:this.currentItem}):a(j.options.items,j.element),j]),this.containers.push(j))}}for(var g=e.length-1;g>=0;g--){var k=e[g][1],l=e[g][0];for(var i=0,m=l.length;i<m;i++){var n=a(l[i]);n.data(this.widgetName+"-item",k),c.push({item:n,instance:k,width:0,height:0,left:0,top:0})}}},refreshPositions:function(b){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());for(var c=this.items.length-1;c>=0;c--){var d=this.items[c];if(d.instance!=this.currentContainer&&this.currentContainer&&d.item[0]!=this.currentItem[0])continue;var e=this.options.toleranceElement?a(this.options.toleranceElement,d.item):d.item;b||(d.width=e.outerWidth(),d.height=e.outerHeight());var f=e.offset();d.left=f.left,d.top=f.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var c=this.containers.length-1;c>=0;c--){var f=this.containers[c].element.offset();this.containers[c].containerCache.left=f.left,this.containers[c].containerCache.top=f.top,this.containers[c].containerCache.width=this.containers[c].element.outerWidth(),this.containers[c].containerCache.height=this.containers[c].element.outerHeight()}return this},_createPlaceholder:function(b){var c=b||this,d=c.options;if(!d.placeholder||d.placeholder.constructor==String){var e=d.placeholder;d.placeholder={element:function(){var b=a(document.createElement(c.currentItem[0].nodeName)).addClass(e||c.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];e||(b.style.visibility="hidden");return b},update:function(a,b){if(!e||!!d.forcePlaceholderSize)b.height()||b.height(c.currentItem.innerHeight()-parseInt(c.currentItem.css("paddingTop")||0,10)-parseInt(c.currentItem.css("paddingBottom")||0,10)),b.width()||b.width(c.currentItem.innerWidth()-parseInt(c.currentItem.css("paddingLeft")||0,10)-parseInt(c.currentItem.css("paddingRight")||0,10))}}}c.placeholder=a(d.placeholder.element.call(c.element,c.currentItem)),c.currentItem.after(c.placeholder),d.placeholder.update(c,c.placeholder)},_contactContainers:function(b){var c=null,d=null;for(var e=this.containers.length-1;e>=0;e--){if(a.ui.contains(this.currentItem[0],this.containers[e].element[0]))continue;if(this._intersectsWith(this.containers[e].containerCache)){if(c&&a.ui.contains(this.containers[e].element[0],c.element[0]))continue;c=this.containers[e],d=e}else this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",b,this._uiHash(this)),this.containers[e].containerCache.over=0)}if(!!c)if(this.containers.length===1)this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1;else if(this.currentContainer!=this.containers[d]){var f=1e4,g=null,h=this.positionAbs[this.containers[d].floating?"left":"top"];for(var i=this.items.length-1;i>=0;i--){if(!a.ui.contains(this.containers[d].element[0],this.items[i].item[0]))continue;var j=this.items[i][this.containers[d].floating?"left":"top"];Math.abs(j-h)<f&&(f=Math.abs(j-h),g=this.items[i])}if(!g&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[d],g?this._rearrange(b,g,null,!0):this._rearrange(b,null,this.containers[d].element,!0),this._trigger("change",b,this._uiHash()),this.containers[d]._trigger("change",b,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1}},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b,this.currentItem])):c.helper=="clone"?this.currentItem.clone():this.currentItem;d.parents("body").length||a(c.appendTo!="parent"?c.appendTo:this.currentItem[0].parentNode)[0].appendChild(d[0]),d[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(d[0].style.width==""||c.forceHelperSize)&&d.width(this.currentItem.width()),(d[0].style.height==""||c.forceHelperSize)&&d.height(this.currentItem.height());return d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(b.containment)){var c=a(b.containment)[0],d=a(b.containment).offset(),e=a(c).css("overflow")!="hidden";this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(e?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(e?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var f=b.pageX,g=b.pageY;if(this.originalPosition){this.containment&&(b.pageX-this.offset.click.left<this.containment[0]&&(f=this.containment[0]+this.offset.click.left),b.pageY-this.offset.click.top<this.containment[1]&&(g=this.containment[1]+this.offset.click.top),b.pageX-this.offset.click.left>this.containment[2]&&(f=this.containment[2]+this.offset.click.left),b.pageY-this.offset.click.top>this.containment[3]&&(g=this.containment[3]+this.offset.click.top));if(c.grid){var h=this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1];g=this.containment?h-this.offset.click.top<this.containment[1]||h-this.offset.click.top>this.containment[3]?h-this.offset.click.top<this.containment[1]?h+c.grid[1]:h-c.grid[1]:h:h;var i=this.originalPageX+Math.round((f-this.originalPageX)/c.grid[0])*c.grid[0];f=this.containment?i-this.offset.click.left<this.containment[0]||i-this.offset.click.left>this.containment[2]?i-this.offset.click.left<this.containment[0]?i+c.grid[0]:i-c.grid[0]:i:i}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:d.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:d.scrollLeft())}},_rearrange:function(a,b,c,d){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var e=this,f=this.counter;window.setTimeout(function(){f==e.counter&&e.refreshPositions(!d)},0)},_clear:function(b,c){this.reverting=!1;var d=[],e=this;!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var f in this._storedCSS)if(this._storedCSS[f]=="auto"||this._storedCSS[f]=="static")this._storedCSS[f]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!c&&d.push(function(a){this._trigger("receive",a,this._uiHash(this.fromOutside))}),(this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!c&&d.push(function(a){this._trigger("update",a,this._uiHash())});if(!a.ui.contains(this.element[0],this.currentItem[0])){c||d.push(function(a){this._trigger("remove",a,this._uiHash())});for(var f=this.containers.length-1;f>=0;f--)a.ui.contains(this.containers[f].element[0],this.currentItem[0])&&!c&&(d.push(function(a){return function(b){a._trigger("receive",b,this._uiHash(this))}}.call(this,this.containers[f])),d.push(function(a){return function(b){a._trigger("update",b,this._uiHash(this))}}.call(this,this.containers[f])))}for(var f=this.containers.length-1;f>=0;f--)c||d.push(function(a){return function(b){a._trigger("deactivate",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over&&(d.push(function(a){return function(b){a._trigger("out",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over=0);this._storedCursor&&a("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!c){this._trigger("beforeStop",b,this._uiHash());for(var f=0;f<d.length;f++)d[f].call(this,b);this._trigger("stop",b,this._uiHash())}return!1}c||this._trigger("beforeStop",b,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!=this.currentItem[0]&&this.helper.remove(),this.helper=null;if(!c){for(var f=0;f<d.length;f++)d[f].call(this,b);this._trigger("stop",b,this._uiHash())}this.fromOutside=!1;return!0},_trigger:function(){a.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(b){var c=b||this;return{helper:c.helper,placeholder:c.placeholder||a([]),position:c.position,originalPosition:c.originalPosition,offset:c.positionAbs,item:c.currentItem,sender:b?b.element:null}}}),a.extend(a.ui.sortable,{version:"1.8.18"})})(jQuery);/* + * jQuery UI Accordion 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Accordion + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */(function(a,b){a.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:!0,clearStyle:!1,collapsible:!1,event:"click",fillSpace:!1,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:!1,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var b=this,c=b.options;b.running=0,b.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix"),b.headers=b.element.find(c.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){c.disabled||a(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){c.disabled||a(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){c.disabled||a(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){c.disabled||a(this).removeClass("ui-state-focus")}),b.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");if(c.navigation){var d=b.element.find("a").filter(c.navigationFilter).eq(0);if(d.length){var e=d.closest(".ui-accordion-header");e.length?b.active=e:b.active=d.closest(".ui-accordion-content").prev()}}b.active=b._findActive(b.active||c.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top"),b.active.next().addClass("ui-accordion-content-active"),b._createIcons(),b.resize(),b.element.attr("role","tablist"),b.headers.attr("role","tab").bind("keydown.accordion",function(a){return b._keydown(a)}).next().attr("role","tabpanel"),b.headers.not(b.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide(),b.active.length?b.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):b.headers.eq(0).attr("tabIndex",0),a.browser.safari||b.headers.find("a").attr("tabIndex",-1),c.event&&b.headers.bind(c.event.split(" ").join(".accordion ")+".accordion",function(a){b._clickHandler.call(b,a,this),a.preventDefault()})},_createIcons:function(){var b=this.options;b.icons&&(a("<span></span>").addClass("ui-icon "+b.icons.header).prependTo(this.headers),this.active.children(".ui-icon").toggleClass(b.icons.header).toggleClass(b.icons.headerSelected),this.element.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.children(".ui-icon").remove(),this.element.removeClass("ui-accordion-icons")},destroy:function(){var b=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex"),this.headers.find("a").removeAttr("tabIndex"),this._destroyIcons();var c=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");(b.autoHeight||b.fillHeight)&&c.css("height","");return a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments),b=="active"&&this.activate(c),b=="icons"&&(this._destroyIcons(),c&&this._createIcons()),b=="disabled"&&this.headers.add(this.headers.next())[c?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(b){if(!(this.options.disabled||b.altKey||b.ctrlKey)){var c=a.ui.keyCode,d=this.headers.length,e=this.headers.index(b.target),f=!1;switch(b.keyCode){case c.RIGHT:case c.DOWN:f=this.headers[(e+1)%d];break;case c.LEFT:case c.UP:f=this.headers[(e-1+d)%d];break;case c.SPACE:case c.ENTER:this._clickHandler({target:b.target},b.target),b.preventDefault()}if(f){a(b.target).attr("tabIndex",-1),a(f).attr("tabIndex",0),f.focus();return!1}return!0}},resize:function(){var b=this.options,c;if(b.fillSpace){if(a.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}c=this.element.parent().height(),a.browser.msie&&this.element.parent().css("overflow",d),this.headers.each(function(){c-=a(this).outerHeight(!0)}),this.headers.next().each(function(){a(this).height(Math.max(0,c-a(this).innerHeight()+a(this).height()))}).css("overflow","auto")}else b.autoHeight&&(c=0,this.headers.next().each(function(){c=Math.max(c,a(this).height("").height())}).height(c));return this},activate:function(a){this.options.active=a;var b=this._findActive(a)[0];this._clickHandler({target:b},b);return this},_findActive:function(b){return b?typeof b=="number"?this.headers.filter(":eq("+b+")"):this.headers.not(this.headers.not(b)):b===!1?a([]):this.headers.filter(":eq(0)")},_clickHandler:function(b,c){var d=this.options;if(!d.disabled){if(!b.target){if(!d.collapsible)return;this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header),this.active.next().addClass("ui-accordion-content-active");var e=this.active.next(),f={options:d,newHeader:a([]),oldHeader:d.active,newContent:a([]),oldContent:e},g=this.active=a([]);this._toggle(g,e,f);return}var h=a(b.currentTarget||c),i=h[0]===this.active[0];d.active=d.collapsible&&i?!1:this.headers.index(h);if(this.running||!d.collapsible&&i)return;var j=this.active,g=h.next(),e=this.active.next(),f={options:d,newHeader:i&&d.collapsible?a([]):h,oldHeader:this.active,newContent:i&&d.collapsible?a([]):g,oldContent:e},k=this.headers.index(this.active[0])>this.headers.index(h[0]);this.active=i?a([]):h,this._toggle(g,e,f,i,k),j.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header),i||(h.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected),h.next().addClass("ui-accordion-content-active"));return}},_toggle:function(b,c,d,e,f){var g=this,h=g.options;g.toShow=b,g.toHide=c,g.data=d;var i=function(){if(!!g)return g._completed.apply(g,arguments)};g._trigger("changestart",null,g.data),g.running=c.size()===0?b.size():c.size();if(h.animated){var j={};h.collapsible&&e?j={toShow:a([]),toHide:c,complete:i,down:f,autoHeight:h.autoHeight||h.fillSpace}:j={toShow:b,toHide:c,complete:i,down:f,autoHeight:h.autoHeight||h.fillSpace},h.proxied||(h.proxied=h.animated),h.proxiedDuration||(h.proxiedDuration=h.duration),h.animated=a.isFunction(h.proxied)?h.proxied(j):h.proxied,h.duration=a.isFunction(h.proxiedDuration)?h.proxiedDuration(j):h.proxiedDuration;var k=a.ui.accordion.animations,l=h.duration,m=h.animated;m&&!k[m]&&!a.easing[m]&&(m="slide"),k[m]||(k[m]=function(a){this.slide(a,{easing:m,duration:l||700})}),k[m](j)}else h.collapsible&&e?b.toggle():(c.hide(),b.show()),i(!0);c.prev().attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).blur(),b.prev().attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;this.running||(this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""}),this.toHide.removeClass("ui-accordion-content-active"),this.toHide.length&&(this.toHide.parent()[0].className=this.toHide.parent()[0].className),this._trigger("change",null,this.data))}}),a.extend(a.ui.accordion,{version:"1.8.18",animations:{slide:function(b,c){b=a.extend({easing:"swing",duration:300},b,c);if(!b.toHide.size())b.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},b);else{if(!b.toShow.size()){b.toHide.animate({height:"hide",paddingTop:"hide",paddingBottom:"hide"},b);return}var d=b.toShow.css("overflow"),e=0,f={},g={},h=["height","paddingTop","paddingBottom"],i,j=b.toShow;i=j[0].style.width,j.width(j.parent().width()-parseFloat(j.css("paddingLeft"))-parseFloat(j.css("paddingRight"))-(parseFloat(j.css("borderLeftWidth"))||0)-(parseFloat(j.css("borderRightWidth"))||0)),a.each(h,function(c,d){g[d]="hide";var e=(""+a.css(b.toShow[0],d)).match(/^([\d+-.]+)(.*)$/);f[d]={value:e[1],unit:e[2]||"px"}}),b.toShow.css({height:0,overflow:"hidden"}).show(),b.toHide.filter(":hidden").each(b.complete).end().filter(":visible").animate(g,{step:function(a,c){c.prop=="height"&&(e=c.end-c.start===0?0:(c.now-c.start)/(c.end-c.start)),b.toShow[0].style[c.prop]=e*f[c.prop].value+f[c.prop].unit},duration:b.duration,easing:b.easing,complete:function(){b.autoHeight||b.toShow.css("height",""),b.toShow.css({width:i,overflow:d}),b.complete()}})}},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1e3:200})}}})})(jQuery);/* + * jQuery UI Autocomplete 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */(function(a,b){var c=0;a.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var b=this,c=this.element[0].ownerDocument,d;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!b.options.disabled&&!b.element.propAttr("readOnly")){d=!1;var e=a.ui.keyCode;switch(c.keyCode){case e.PAGE_UP:b._move("previousPage",c);break;case e.PAGE_DOWN:b._move("nextPage",c);break;case e.UP:b._move("previous",c),c.preventDefault();break;case e.DOWN:b._move("next",c),c.preventDefault();break;case e.ENTER:case e.NUMPAD_ENTER:b.menu.active&&(d=!0,c.preventDefault());case e.TAB:if(!b.menu.active)return;b.menu.select(c);break;case e.ESCAPE:b.element.val(b.term),b.close(c);break;default:clearTimeout(b.searching),b.searching=setTimeout(function(){b.term!=b.element.val()&&(b.selectedItem=null,b.search(null,c))},b.options.delay)}}}).bind("keypress.autocomplete",function(a){d&&(d=!1,a.preventDefault())}).bind("focus.autocomplete",function(){b.options.disabled||(b.selectedItem=null,b.previous=b.element.val())}).bind("blur.autocomplete",function(a){b.options.disabled||(clearTimeout(b.searching),b.closing=setTimeout(function(){b.close(a),b._change(a)},150))}),this._initSource(),this.response=function(){return b._response.apply(b,arguments)},this.menu=a("<ul></ul>").addClass("ui-autocomplete").appendTo(a(this.options.appendTo||"body",c)[0]).mousedown(function(c){var d=b.menu.element[0];a(c.target).closest(".ui-menu-item").length||setTimeout(function(){a(document).one("mousedown",function(c){c.target!==b.element[0]&&c.target!==d&&!a.ui.contains(d,c.target)&&b.close()})},1),setTimeout(function(){clearTimeout(b.closing)},13)}).menu({focus:function(a,c){var d=c.item.data("item.autocomplete");!1!==b._trigger("focus",a,{item:d})&&/^key/.test(a.originalEvent.type)&&b.element.val(d.value)},selected:function(a,d){var e=d.item.data("item.autocomplete"),f=b.previous;b.element[0]!==c.activeElement&&(b.element.focus(),b.previous=f,setTimeout(function(){b.previous=f,b.selectedItem=e},1)),!1!==b._trigger("select",a,{item:e})&&b.element.val(e.value),b.term=b.element.val(),b.close(a),b.selectedItem=e},blur:function(a,c){b.menu.element.is(":visible")&&b.element.val()!==b.term&&b.element.val(b.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu"),a.fn.bgiframe&&this.menu.element.bgiframe(),b.beforeunloadHandler=function(){b.element.removeAttr("autocomplete")},a(window).bind("beforeunload",b.beforeunloadHandler)},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup"),this.menu.element.remove(),a(window).unbind("beforeunload",this.beforeunloadHandler),a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments),b==="source"&&this._initSource(),b==="appendTo"&&this.menu.element.appendTo(a(c||"body",this.element[0].ownerDocument)[0]),b==="disabled"&&c&&this.xhr&&this.xhr.abort()},_initSource:function(){var b=this,d,e;a.isArray(this.options.source)?(d=this.options.source,this.source=function(b,c){c(a.ui.autocomplete.filter(d,b.term))}):typeof this.options.source=="string"?(e=this.options.source,this.source=function(d,f){b.xhr&&b.xhr.abort(),b.xhr=a.ajax({url:e,data:d,dataType:"json",context:{autocompleteRequest:++c},success:function(a,b){this.autocompleteRequest===c&&f(a)},error:function(){this.autocompleteRequest===c&&f([])}})}):this.source=this.options.source},search:function(a,b){a=a!=null?a:this.element.val(),this.term=this.element.val();if(a.length<this.options.minLength)return this.close(b);clearTimeout(this.closing);if(this._trigger("search",b)!==!1)return this._search(a)},_search:function(a){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.source({term:a},this.response)},_response:function(a){!this.options.disabled&&a&&a.length?(a=this._normalize(a),this._suggest(a),this._trigger("open")):this.close(),this.pending--,this.pending||this.element.removeClass("ui-autocomplete-loading")},close:function(a){clearTimeout(this.closing),this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.deactivate(),this._trigger("close",a))},_change:function(a){this.previous!==this.element.val()&&this._trigger("change",a,{item:this.selectedItem})},_normalize:function(b){if(b.length&&b[0].label&&b[0].value)return b;return a.map(b,function(b){if(typeof b=="string")return{label:b,value:b};return a.extend({label:b.label||b.value,value:b.value||b.label},b)})},_suggest:function(b){var c=this.menu.element.empty().zIndex(this.element.zIndex()+1);this._renderMenu(c,b),this.menu.deactivate(),this.menu.refresh(),c.show(),this._resizeMenu(),c.position(a.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next(new a.Event("mouseover"))},_resizeMenu:function(){var a=this.menu.element;a.outerWidth(Math.max(a.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(b,c){var d=this;a.each(c,function(a,c){d._renderItem(b,c)})},_renderItem:function(b,c){return a("<li></li>").data("item.autocomplete",c).append(a("<a></a>").text(c.label)).appendTo(b)},_move:function(a,b){if(!this.menu.element.is(":visible"))this.search(null,b);else{if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term),this.menu.deactivate();return}this.menu[a](b)}},widget:function(){return this.menu.element}}),a.extend(a.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")},filter:function(b,c){var d=new RegExp(a.ui.autocomplete.escapeRegex(c),"i");return a.grep(b,function(a){return d.test(a.label||a.value||a)})}})})(jQuery),function(a){a.widget("ui.menu",{_create:function(){var b=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(c){!a(c.target).closest(".ui-menu-item a").length||(c.preventDefault(),b.select(c))}),this.refresh()},refresh:function(){var b=this,c=this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem");c.children("a").addClass("ui-corner-all").attr("tabindex",-1).mouseenter(function(c){b.activate(c,a(this).parent())}).mouseleave(function(){b.deactivate()})},activate:function(a,b){this.deactivate();if(this.hasScroll()){var c=b.offset().top-this.element.offset().top,d=this.element.scrollTop(),e=this.element.height();c<0?this.element.scrollTop(d+c):c>=e&&this.element.scrollTop(d+c-e+b.height())}this.active=b.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end(),this._trigger("focus",a,{item:b})},deactivate:function(){!this.active||(this.active.children("a").removeClass("ui-state-hover").removeAttr("id"),this._trigger("blur"),this.active=null)},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(a,b,c){if(!this.active)this.activate(c,this.element.children(b));else{var d=this.active[a+"All"](".ui-menu-item").eq(0);d.length?this.activate(c,d):this.activate(c,this.element.children(b))}},nextPage:function(b){if(this.hasScroll()){if(!this.active||this.last()){this.activate(b,this.element.children(".ui-menu-item:first"));return}var c=this.active.offset().top,d=this.element.height(),e=this.element.children(".ui-menu-item").filter(function(){var b=a(this).offset().top-c-d+a(this).height();return b<10&&b>-10});e.length||(e=this.element.children(".ui-menu-item:last")),this.activate(b,e)}else this.activate(b,this.element.children(".ui-menu-item").filter(!this.active||this.last()?":first":":last"))},previousPage:function(b){if(this.hasScroll()){if(!this.active||this.first()){this.activate(b,this.element.children(".ui-menu-item:last"));return}var c=this.active.offset().top,d=this.element.height();result=this.element.children(".ui-menu-item").filter(function(){var b=a(this).offset().top-c+d-a(this).height();return b<10&&b>-10}),result.length||(result=this.element.children(".ui-menu-item:first")),this.activate(b,result)}else this.activate(b,this.element.children(".ui-menu-item").filter(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()<this.element[a.fn.prop?"prop":"attr"]("scrollHeight")},select:function(a){this._trigger("selected",a,{item:this.active})}})}(jQuery);/* + * jQuery UI Button 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Button + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */(function(a,b){var c,d,e,f,g="ui-button ui-widget ui-state-default ui-corner-all",h="ui-state-hover ui-state-active ",i="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",j=function(){var b=a(this).find(":ui-button");setTimeout(function(){b.button("refresh")},1)},k=function(b){var c=b.name,d=b.form,e=a([]);c&&(d?e=a(d).find("[name='"+c+"']"):e=a("[name='"+c+"']",b.ownerDocument).filter(function(){return!this.form}));return e};a.widget("ui.button",{options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset.button").bind("reset.button",j),typeof this.options.disabled!="boolean"?this.options.disabled=!!this.element.propAttr("disabled"):this.element.propAttr("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var b=this,h=this.options,i=this.type==="checkbox"||this.type==="radio",l="ui-state-hover"+(i?"":" ui-state-active"),m="ui-state-focus";h.label===null&&(h.label=this.buttonElement.html()),this.buttonElement.addClass(g).attr("role","button").bind("mouseenter.button",function(){h.disabled||(a(this).addClass("ui-state-hover"),this===c&&a(this).addClass("ui-state-active"))}).bind("mouseleave.button",function(){h.disabled||a(this).removeClass(l)}).bind("click.button",function(a){h.disabled&&(a.preventDefault(),a.stopImmediatePropagation())}),this.element.bind("focus.button",function(){b.buttonElement.addClass(m)}).bind("blur.button",function(){b.buttonElement.removeClass(m)}),i&&(this.element.bind("change.button",function(){f||b.refresh()}),this.buttonElement.bind("mousedown.button",function(a){h.disabled||(f=!1,d=a.pageX,e=a.pageY)}).bind("mouseup.button",function(a){!h.disabled&&(d!==a.pageX||e!==a.pageY)&&(f=!0)})),this.type==="checkbox"?this.buttonElement.bind("click.button",function(){if(h.disabled||f)return!1;a(this).toggleClass("ui-state-active"),b.buttonElement.attr("aria-pressed",b.element[0].checked)}):this.type==="radio"?this.buttonElement.bind("click.button",function(){if(h.disabled||f)return!1;a(this).addClass("ui-state-active"),b.buttonElement.attr("aria-pressed","true");var c=b.element[0];k(c).not(c).map(function(){return a(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown.button",function(){if(h.disabled)return!1;a(this).addClass("ui-state-active"),c=this,a(document).one("mouseup",function(){c=null})}).bind("mouseup.button",function(){if(h.disabled)return!1;a(this).removeClass("ui-state-active")}).bind("keydown.button",function(b){if(h.disabled)return!1;(b.keyCode==a.ui.keyCode.SPACE||b.keyCode==a.ui.keyCode.ENTER)&&a(this).addClass("ui-state-active")}).bind("keyup.button",function(){a(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(b){b.keyCode===a.ui.keyCode.SPACE&&a(this).click()})),this._setOption("disabled",h.disabled),this._resetButton()},_determineButtonType:function(){this.element.is(":checkbox")?this.type="checkbox":this.element.is(":radio")?this.type="radio":this.element.is("input")?this.type="input":this.type="button";if(this.type==="checkbox"||this.type==="radio"){var a=this.element.parents().filter(":last"),b="label[for='"+this.element.attr("id")+"']";this.buttonElement=a.find(b),this.buttonElement.length||(a=a.length?a.siblings():this.element.siblings(),this.buttonElement=a.filter(b),this.buttonElement.length||(this.buttonElement=a.find(b))),this.element.addClass("ui-helper-hidden-accessible");var c=this.element.is(":checked");c&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.attr("aria-pressed",c)}else this.buttonElement=this.element},widget:function(){return this.buttonElement},destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(g+" "+h+" "+i).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title"),a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments);b==="disabled"?c?this.element.propAttr("disabled",!0):this.element.propAttr("disabled",!1):this._resetButton()},refresh:function(){var b=this.element.is(":disabled");b!==this.options.disabled&&this._setOption("disabled",b),this.type==="radio"?k(this.element[0]).each(function(){a(this).is(":checked")?a(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):a(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):this.type==="checkbox"&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if(this.type==="input")this.options.label&&this.element.val(this.options.label);else{var b=this.buttonElement.removeClass(i),c=a("<span></span>",this.element[0].ownerDocument).addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,e=d.primary&&d.secondary,f=[];d.primary||d.secondary?(this.options.text&&f.push("ui-button-text-icon"+(e?"s":d.primary?"-primary":"-secondary")),d.primary&&b.prepend("<span class='ui-button-icon-primary ui-icon "+d.primary+"'></span>"),d.secondary&&b.append("<span class='ui-button-icon-secondary ui-icon "+d.secondary+"'></span>"),this.options.text||(f.push(e?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||b.attr("title",c))):f.push("ui-button-text-only"),b.addClass(f.join(" "))}}}),a.widget("ui.buttonset",{options:{items:":button, :submit, :reset, :checkbox, :radio, a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c),a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){var b=this.element.css("direction")==="rtl";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(b?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(b?"ui-corner-left":"ui-corner-right").end().end()},destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy"),a.Widget.prototype.destroy.call(this)}})})(jQuery);/* + * jQuery UI Dialog 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.button.js + * jquery.ui.draggable.js + * jquery.ui.mouse.js + * jquery.ui.position.js + * jquery.ui.resizable.js + */(function(a,b){var c="ui-dialog ui-widget ui-widget-content ui-corner-all ",d={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},e={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0},f=a.attrFn||{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0,click:!0};a.widget("ui.dialog",{options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",collision:"fit",using:function(b){var c=a(this).css(b).offset().top;c<0&&a(this).css("top",b.top-c)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.options.title=this.options.title||this.originalTitle;var b=this,d=b.options,e=d.title||" ",f=a.ui.dialog.getTitleId(b.element),g=(b.uiDialog=a("<div></div>")).appendTo(document.body).hide().addClass(c+d.dialogClass).css({zIndex:d.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(c){d.closeOnEscape&&!c.isDefaultPrevented()&&c.keyCode&&c.keyCode===a.ui.keyCode.ESCAPE&&(b.close(c),c.preventDefault())}).attr({role:"dialog","aria-labelledby":f}).mousedown(function(a){b.moveToTop(!1,a)}),h=b.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g),i=(b.uiDialogTitlebar=a("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g),j=a('<a href="#"></a>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){j.addClass("ui-state-hover")},function(){j.removeClass("ui-state-hover")}).focus(function(){j.addClass("ui-state-focus")}).blur(function(){j.removeClass("ui-state-focus")}).click(function(a){b.close(a);return!1}).appendTo(i),k=(b.uiDialogTitlebarCloseText=a("<span></span>")).addClass("ui-icon ui-icon-closethick").text(d.closeText).appendTo(j),l=a("<span></span>").addClass("ui-dialog-title").attr("id",f).html(e).prependTo(i);a.isFunction(d.beforeclose)&&!a.isFunction(d.beforeClose)&&(d.beforeClose=d.beforeclose),i.find("*").add(i).disableSelection(),d.draggable&&a.fn.draggable&&b._makeDraggable(),d.resizable&&a.fn.resizable&&b._makeResizable(),b._createButtons(d.buttons),b._isOpen=!1,a.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy(),a.uiDialog.hide(),a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),a.uiDialog.remove(),a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(b){var c=this,d,e;if(!1!==c._trigger("beforeClose",b)){c.overlay&&c.overlay.destroy(),c.uiDialog.unbind("keypress.ui-dialog"),c._isOpen=!1,c.options.hide?c.uiDialog.hide(c.options.hide,function(){c._trigger("close",b)}):(c.uiDialog.hide(),c._trigger("close",b)),a.ui.dialog.overlay.resize(),c.options.modal&&(d=0,a(".ui-dialog").each(function(){this!==c.uiDialog[0]&&(e=a(this).css("z-index"),isNaN(e)||(d=Math.max(d,e)))}),a.ui.dialog.maxZ=d);return c}},isOpen:function(){return this._isOpen},moveToTop:function(b,c){var d=this,e=d.options,f;if(e.modal&&!b||!e.stack&&!e.modal)return d._trigger("focus",c);e.zIndex>a.ui.dialog.maxZ&&(a.ui.dialog.maxZ=e.zIndex),d.overlay&&(a.ui.dialog.maxZ+=1,d.overlay.$el.css("z-index",a.ui.dialog.overlay.maxZ=a.ui.dialog.maxZ)),f={scrollTop:d.element.scrollTop(),scrollLeft:d.element.scrollLeft()},a.ui.dialog.maxZ+=1,d.uiDialog.css("z-index",a.ui.dialog.maxZ),d.element.attr(f),d._trigger("focus",c);return d},open:function(){if(!this._isOpen){var b=this,c=b.options,d=b.uiDialog;b.overlay=c.modal?new a.ui.dialog.overlay(b):null,b._size(),b._position(c.position),d.show(c.show),b.moveToTop(!0),c.modal&&d.bind("keydown.ui-dialog",function(b){if(b.keyCode===a.ui.keyCode.TAB){var c=a(":tabbable",this),d=c.filter(":first"),e=c.filter(":last");if(b.target===e[0]&&!b.shiftKey){d.focus(1);return!1}if(b.target===d[0]&&b.shiftKey){e.focus(1);return!1}}}),a(b.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus(),b._isOpen=!0,b._trigger("open");return b}},_createButtons:function(b){var c=this,d=!1,e=a("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=a("<div></div>").addClass("ui-dialog-buttonset").appendTo(e);c.uiDialog.find(".ui-dialog-buttonpane").remove(),typeof b=="object"&&b!==null&&a.each(b,function(){return!(d=!0)}),d&&(a.each(b,function(b,d){d=a.isFunction(d)?{click:d,text:b}:d;var e=a('<button type="button"></button>').click(function(){d.click.apply(c.element[0],arguments)}).appendTo(g);a.each(d,function(a,b){a!=="click"&&(a in f?e[a](b):e.attr(a,b))}),a.fn.button&&e.button()}),e.appendTo(c.uiDialog))},_makeDraggable:function(){function f(a){return{position:a.position,offset:a.offset}}var b=this,c=b.options,d=a(document),e;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(d,g){e=c.height==="auto"?"auto":a(this).height(),a(this).height(a(this).height()).addClass("ui-dialog-dragging"),b._trigger("dragStart",d,f(g))},drag:function(a,c){b._trigger("drag",a,f(c))},stop:function(g,h){c.position=[h.position.left-d.scrollLeft(),h.position.top-d.scrollTop()],a(this).removeClass("ui-dialog-dragging").height(e),b._trigger("dragStop",g,f(h)),a.ui.dialog.overlay.resize()}})},_makeResizable:function(c){function h(a){return{originalPosition:a.originalPosition,originalSize:a.originalSize,position:a.position,size:a.size}}c=c===b?this.options.resizable:c;var d=this,e=d.options,f=d.uiDialog.css("position"),g=typeof c=="string"?c:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:g,start:function(b,c){a(this).addClass("ui-dialog-resizing"),d._trigger("resizeStart",b,h(c))},resize:function(a,b){d._trigger("resize",a,h(b))},stop:function(b,c){a(this).removeClass("ui-dialog-resizing"),e.height=a(this).height(),e.width=a(this).width(),d._trigger("resizeStop",b,h(c)),a.ui.dialog.overlay.resize()}}).css("position",f).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(b){var c=[],d=[0,0],e;if(b){if(typeof b=="string"||typeof b=="object"&&"0"in b)c=b.split?b.split(" "):[b[0],b[1]],c.length===1&&(c[1]=c[0]),a.each(["left","top"],function(a,b){+c[a]===c[a]&&(d[a]=c[a],c[a]=b)}),b={my:c.join(" "),at:c.join(" "),offset:d.join(" ")};b=a.extend({},a.ui.dialog.prototype.options.position,b)}else b=a.ui.dialog.prototype.options.position;e=this.uiDialog.is(":visible"),e||this.uiDialog.show(),this.uiDialog.css({top:0,left:0}).position(a.extend({of:window},b)),e||this.uiDialog.hide()},_setOptions:function(b){var c=this,f={},g=!1;a.each(b,function(a,b){c._setOption(a,b),a in d&&(g=!0),a in e&&(f[a]=b)}),g&&this._size(),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",f)},_setOption:function(b,d){var e=this,f=e.uiDialog;switch(b){case"beforeclose":b="beforeClose";break;case"buttons":e._createButtons(d);break;case"closeText":e.uiDialogTitlebarCloseText.text(""+d);break;case"dialogClass":f.removeClass(e.options.dialogClass).addClass(c+d);break;case"disabled":d?f.addClass("ui-dialog-disabled"):f.removeClass("ui-dialog-disabled");break;case"draggable":var g=f.is(":data(draggable)");g&&!d&&f.draggable("destroy"),!g&&d&&e._makeDraggable();break;case"position":e._position(d);break;case"resizable":var h=f.is(":data(resizable)");h&&!d&&f.resizable("destroy"),h&&typeof d=="string"&&f.resizable("option","handles",d),!h&&d!==!1&&e._makeResizable(d);break;case"title":a(".ui-dialog-title",e.uiDialogTitlebar).html(""+(d||" "))}a.Widget.prototype._setOption.apply(e,arguments)},_size:function(){var b=this.options,c,d,e=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0}),b.minWidth>b.width&&(b.width=b.minWidth),c=this.uiDialog.css({height:"auto",width:b.width}).height(),d=Math.max(0,b.minHeight-c);if(b.height==="auto")if(a.support.minHeight)this.element.css({minHeight:d,height:"auto"});else{this.uiDialog.show();var f=this.element.css("height","auto").height();e||this.uiDialog.hide(),this.element.height(Math.max(f,d))}else this.element.height(Math.max(b.height-c,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}}),a.extend(a.ui.dialog,{version:"1.8.18",uuid:0,maxZ:0,getTitleId:function(a){var b=a.attr("id");b||(this.uuid+=1,b=this.uuid);return"ui-dialog-title-"+b},overlay:function(b){this.$el=a.ui.dialog.overlay.create(b)}}),a.extend(a.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:a.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(b){this.instances.length===0&&(setTimeout(function(){a.ui.dialog.overlay.instances.length&&a(document).bind(a.ui.dialog.overlay.events,function(b){if(a(b.target).zIndex()<a.ui.dialog.overlay.maxZ)return!1})},1),a(document).bind("keydown.dialog-overlay",function(c){b.options.closeOnEscape&&!c.isDefaultPrevented()&&c.keyCode&&c.keyCode===a.ui.keyCode.ESCAPE&&(b.close(c),c.preventDefault())}),a(window).bind("resize.dialog-overlay",a.ui.dialog.overlay.resize));var c=(this.oldInstances.pop()||a("<div></div>").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});a.fn.bgiframe&&c.bgiframe(),this.instances.push(c);return c},destroy:function(b){var c=a.inArray(b,this.instances);c!=-1&&this.oldInstances.push(this.instances.splice(c,1)[0]),this.instances.length===0&&a([document,window]).unbind(".dialog-overlay"),b.remove();var d=0;a.each(this.instances,function(){d=Math.max(d,this.css("z-index"))}),this.maxZ=d},height:function(){var b,c;if(a.browser.msie&&a.browser.version<7){b=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),c=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return b<c?a(window).height()+"px":b+"px"}return a(document).height()+"px"},width:function(){var b,c;if(a.browser.msie){b=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth),c=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);return b<c?a(window).width()+"px":b+"px"}return a(document).width()+"px"},resize:function(){var b=a([]);a.each(a.ui.dialog.overlay.instances,function(){b=b.add(this)}),b.css({width:0,height:0}).css({width:a.ui.dialog.overlay.width(),height:a.ui.dialog.overlay.height()})}}),a.extend(a.ui.dialog.overlay.prototype,{destroy:function(){a.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);/* + * jQuery UI Slider 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */(function(a,b){var c=5;a.widget("ui.slider",a.ui.mouse,{widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null},_create:function(){var b=this,d=this.options,e=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),f="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",g=d.values&&d.values.length||1,h=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"+(d.disabled?" ui-slider-disabled ui-disabled":"")),this.range=a([]),d.range&&(d.range===!0&&(d.values||(d.values=[this._valueMin(),this._valueMin()]),d.values.length&&d.values.length!==2&&(d.values=[d.values[0],d.values[0]])),this.range=a("<div></div>").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(d.range==="min"||d.range==="max"?" ui-slider-range-"+d.range:"")));for(var i=e.length;i<g;i+=1)h.push(f);this.handles=e.add(a(h.join("")).appendTo(b.element)),this.handle=this.handles.eq(0),this.handles.add(this.range).filter("a").click(function(a){a.preventDefault()}).hover(function(){d.disabled||a(this).addClass("ui-state-hover")},function(){a(this).removeClass("ui-state-hover")}).focus(function(){d.disabled?a(this).blur():(a(".ui-slider .ui-state-focus").removeClass("ui-state-focus"),a(this).addClass("ui-state-focus"))}).blur(function(){a(this).removeClass("ui-state-focus")}),this.handles.each(function(b){a(this).data("index.ui-slider-handle",b)}),this.handles.keydown(function(d){var e=a(this).data("index.ui-slider-handle"),f,g,h,i;if(!b.options.disabled){switch(d.keyCode){case a.ui.keyCode.HOME:case a.ui.keyCode.END:case a.ui.keyCode.PAGE_UP:case a.ui.keyCode.PAGE_DOWN:case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:d.preventDefault();if(!b._keySliding){b._keySliding=!0,a(this).addClass("ui-state-active"),f=b._start(d,e);if(f===!1)return}}i=b.options.step,b.options.values&&b.options.values.length?g=h=b.values(e):g=h=b.value();switch(d.keyCode){case a.ui.keyCode.HOME:h=b._valueMin();break;case a.ui.keyCode.END:h=b._valueMax();break;case a.ui.keyCode.PAGE_UP:h=b._trimAlignValue(g+(b._valueMax()-b._valueMin())/c);break;case a.ui.keyCode.PAGE_DOWN:h=b._trimAlignValue(g-(b._valueMax()-b._valueMin())/c);break;case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:if(g===b._valueMax())return;h=b._trimAlignValue(g+i);break;case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:if(g===b._valueMin())return;h=b._trimAlignValue(g-i)}b._slide(d,e,h)}}).keyup(function(c){var d=a(this).data("index.ui-slider-handle");b._keySliding&&(b._keySliding=!1,b._stop(c,d),b._change(c,d),a(this).removeClass("ui-state-active"))}),this._refreshValue(),this._animateOff=!1},destroy:function(){this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider"),this._mouseDestroy();return this},_mouseCapture:function(b){var c=this.options,d,e,f,g,h,i,j,k,l;if(c.disabled)return!1;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),d={x:b.pageX,y:b.pageY},e=this._normValueFromMouse(d),f=this._valueMax()-this._valueMin()+1,h=this,this.handles.each(function(b){var c=Math.abs(e-h.values(b));f>c&&(f=c,g=a(this),i=b)}),c.range===!0&&this.values(1)===c.min&&(i+=1,g=a(this.handles[i])),j=this._start(b,i);if(j===!1)return!1;this._mouseSliding=!0,h._handleIndex=i,g.addClass("ui-state-active").focus(),k=g.offset(),l=!a(b.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:b.pageX-k.left-g.width()/2,top:b.pageY-k.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(b,i,e),this._animateOff=!0;return!0},_mouseStart:function(a){return!0},_mouseDrag:function(a){var b={x:a.pageX,y:a.pageY},c=this._normValueFromMouse(b);this._slide(a,this._handleIndex,c);return!1},_mouseStop:function(a){this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(a,this._handleIndex),this._change(a,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1;return!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b,c,d,e,f;this.orientation==="horizontal"?(b=this.elementSize.width,c=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(b=this.elementSize.height,c=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),d=c/b,d>1&&(d=1),d<0&&(d=0),this.orientation==="vertical"&&(d=1-d),e=this._valueMax()-this._valueMin(),f=this._valueMin()+d*e;return this._trimAlignValue(f)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values());return this._trigger("start",a,c)},_slide:function(a,b,c){var d,e,f;this.options.values&&this.options.values.length?(d=this.values(b?0:1),this.options.values.length===2&&this.options.range===!0&&(b===0&&c>d||b===1&&c<d)&&(c=d),c!==this.values(b)&&(e=this.values(),e[b]=c,f=this._trigger("slide",a,{handle:this.handles[b],value:c,values:e}),d=this.values(b?0:1),f!==!1&&this.values(b,c,!0))):c!==this.value()&&(f=this._trigger("slide",a,{handle:this.handles[b],value:c}),f!==!1&&this.value(c))},_stop:function(a,b){var c={handle:this.handles[b],value:this.value()};this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("stop",a,c)},_change:function(a,b){if(!this._keySliding&&!this._mouseSliding){var c={handle:this.handles[b],value:this.value()};this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("change",a,c)}},value:function(a){if(arguments.length)this.options.value=this._trimAlignValue(a),this._refreshValue(),this._change(null,0);else return this._value()},values:function(b,c){var d,e,f;if(arguments.length>1)this.options.values[b]=this._trimAlignValue(c),this._refreshValue(),this._change(null,b);else{if(!arguments.length)return this._values();if(!a.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(b):this.value();d=this.options.values,e=arguments[0];for(f=0;f<d.length;f+=1)d[f]=this._trimAlignValue(e[f]),this._change(null,f);this._refreshValue()}},_setOption:function(b,c){var d,e=0;a.isArray(this.options.values)&&(e=this.options.values.length),a.Widget.prototype._setOption.apply(this,arguments);switch(b){case"disabled":c?(this.handles.filter(".ui-state-focus").blur(),this.handles.removeClass("ui-state-hover"),this.handles.propAttr("disabled",!0),this.element.addClass("ui-disabled")):(this.handles.propAttr("disabled",!1),this.element.removeClass("ui-disabled"));break;case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":this._animateOff=!0,this._refreshValue();for(d=0;d<e;d+=1)this._change(null,d);this._animateOff=!1}},_value:function(){var a=this.options.value;a=this._trimAlignValue(a);return a},_values:function(a){var b,c,d;if(arguments.length){b=this.options.values[a],b=this._trimAlignValue(b);return b}c=this.options.values.slice();for(d=0;d<c.length;d+=1)c[d]=this._trimAlignValue(c[d]);return c},_trimAlignValue:function(a){if(a<=this._valueMin())return this._valueMin();if(a>=this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=(a-this._valueMin())%b,d=a-c;Math.abs(c)*2>=b&&(d+=c>0?b:-b);return parseFloat(d.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var b=this.options.range,c=this.options,d=this,e=this._animateOff?!1:c.animate,f,g={},h,i,j,k;this.options.values&&this.options.values.length?this.handles.each(function(b,i){f=(d.values(b)-d._valueMin())/(d._valueMax()-d._valueMin())*100,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",a(this).stop(1,1)[e?"animate":"css"](g,c.animate),d.options.range===!0&&(d.orientation==="horizontal"?(b===0&&d.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({width:f-h+"%"},{queue:!1,duration:c.animate})):(b===0&&d.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({height:f-h+"%"},{queue:!1,duration:c.animate}))),h=f}):(i=this.value(),j=this._valueMin(),k=this._valueMax(),f=k!==j?(i-j)/(k-j)*100:0,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",this.handle.stop(1,1)[e?"animate":"css"](g,c.animate),b==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},c.animate),b==="max"&&this.orientation==="horizontal"&&this.range[e?"animate":"css"]({width:100-f+"%"},{queue:!1,duration:c.animate}),b==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},c.animate),b==="max"&&this.orientation==="vertical"&&this.range[e?"animate":"css"]({height:100-f+"%"},{queue:!1,duration:c.animate}))}}),a.extend(a.ui.slider,{version:"1.8.18"})})(jQuery);/* + * jQuery UI Tabs 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */(function(a,b){function f(){return++d}function e(){return++c}var c=0,d=0;a.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:!1,cookie:null,collapsible:!1,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"<div></div>",remove:null,select:null,show:null,spinner:"<em>Loading…</em>",tabTemplate:"<li><a href='#{href}'><span>#{label}</span></a></li>"},_create:function(){this._tabify(!0)},_setOption:function(a,b){if(a=="selected"){if(this.options.collapsible&&b==this.options.selected)return;this.select(b)}else this.options[a]=b,this._tabify()},_tabId:function(a){return a.title&&a.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+e()},_sanitizeSelector:function(a){return a.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+f());return a.cookie.apply(null,[b].concat(a.makeArray(arguments)))},_ui:function(a,b){return{tab:a,panel:b,index:this.anchors.index(a)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b=a(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function m(b,c){b.css("display",""),!a.support.opacity&&c.opacity&&b[0].style.removeAttribute("filter")}var d=this,e=this.options,f=/^#.+/;this.list=this.element.find("ol,ul").eq(0),this.lis=a(" > li:has(a[href])",this.list),this.anchors=this.lis.map(function(){return a("a",this)[0]}),this.panels=a([]),this.anchors.each(function(b,c){var g=a(c).attr("href"),h=g.split("#")[0],i;h&&(h===location.toString().split("#")[0]||(i=a("base")[0])&&h===i.href)&&(g=c.hash,c.href=g);if(f.test(g))d.panels=d.panels.add(d.element.find(d._sanitizeSelector(g)));else if(g&&g!=="#"){a.data(c,"href.tabs",g),a.data(c,"load.tabs",g.replace(/#.*$/,""));var j=d._tabId(c);c.href="#"+j;var k=d.element.find("#"+j);k.length||(k=a(e.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(d.panels[b-1]||d.list),k.data("destroy.tabs",!0)),d.panels=d.panels.add(k)}else e.disabled.push(b)}),c?(this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"),this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.lis.addClass("ui-state-default ui-corner-top"),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom"),e.selected===b?(location.hash&&this.anchors.each(function(a,b){if(b.hash==location.hash){e.selected=a;return!1}}),typeof e.selected!="number"&&e.cookie&&(e.selected=parseInt(d._cookie(),10)),typeof e.selected!="number"&&this.lis.filter(".ui-tabs-selected").length&&(e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))),e.selected=e.selected||(this.lis.length?0:-1)):e.selected===null&&(e.selected=-1),e.selected=e.selected>=0&&this.anchors[e.selected]||e.selected<0?e.selected:0,e.disabled=a.unique(e.disabled.concat(a.map(this.lis.filter(".ui-state-disabled"),function(a,b){return d.lis.index(a)}))).sort(),a.inArray(e.selected,e.disabled)!=-1&&e.disabled.splice(a.inArray(e.selected,e.disabled),1),this.panels.addClass("ui-tabs-hide"),this.lis.removeClass("ui-tabs-selected ui-state-active"),e.selected>=0&&this.anchors.length&&(d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash)).removeClass("ui-tabs-hide"),this.lis.eq(e.selected).addClass("ui-tabs-selected ui-state-active"),d.element.queue("tabs",function(){d._trigger("show",null,d._ui(d.anchors[e.selected],d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash))[0]))}),this.load(e.selected)),a(window).bind("unload",function(){d.lis.add(d.anchors).unbind(".tabs"),d.lis=d.anchors=d.panels=null})):e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")),this.element[e.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible"),e.cookie&&this._cookie(e.selected,e.cookie);for(var g=0,h;h=this.lis[g];g++)a(h)[a.inArray(g,e.disabled)!=-1&&!a(h).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");e.cache===!1&&this.anchors.removeData("cache.tabs"),this.lis.add(this.anchors).unbind(".tabs");if(e.event!=="mouseover"){var i=function(a,b){b.is(":not(.ui-state-disabled)")&&b.addClass("ui-state-"+a)},j=function(a,b){b.removeClass("ui-state-"+a)};this.lis.bind("mouseover.tabs",function(){i("hover",a(this))}),this.lis.bind("mouseout.tabs",function(){j("hover",a(this))}),this.anchors.bind("focus.tabs",function(){i("focus",a(this).closest("li"))}),this.anchors.bind("blur.tabs",function(){j("focus",a(this).closest("li"))})}var k,l;e.fx&&(a.isArray(e.fx)?(k=e.fx[0],l=e.fx[1]):k=l=e.fx);var n=l?function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.hide().removeClass("ui-tabs-hide").animate(l,l.duration||"normal",function(){m(c,l),d._trigger("show",null,d._ui(b,c[0]))})}:function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.removeClass("ui-tabs-hide"),d._trigger("show",null,d._ui(b,c[0]))},o=k?function(a,b){b.animate(k,k.duration||"normal",function(){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),m(b,k),d.element.dequeue("tabs")})}:function(a,b,c){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),d.element.dequeue("tabs")};this.anchors.bind(e.event+".tabs",function(){var b=this,c=a(b).closest("li"),f=d.panels.filter(":not(.ui-tabs-hide)"),g=d.element.find(d._sanitizeSelector(b.hash));if(c.hasClass("ui-tabs-selected")&&!e.collapsible||c.hasClass("ui-state-disabled")||c.hasClass("ui-state-processing")||d.panels.filter(":animated").length||d._trigger("select",null,d._ui(this,g[0]))===!1){this.blur();return!1}e.selected=d.anchors.index(this),d.abort();if(e.collapsible){if(c.hasClass("ui-tabs-selected")){e.selected=-1,e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){o(b,f)}).dequeue("tabs"),this.blur();return!1}if(!f.length){e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this)),this.blur();return!1}}e.cookie&&d._cookie(e.selected,e.cookie);if(g.length)f.length&&d.element.queue("tabs",function(){o(b,f)}),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this));else throw"jQuery UI Tabs: Mismatching fragment identifier.";a.browser.msie&&this.blur()}),this.anchors.bind("click.tabs",function(){return!1})},_getIndex:function(a){typeof a=="string"&&(a=this.anchors.index(this.anchors.filter("[href$="+a+"]")));return a},destroy:function(){var b=this.options;this.abort(),this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs"),this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.anchors.each(function(){var b=a.data(this,"href.tabs");b&&(this.href=b);var c=a(this).unbind(".tabs");a.each(["href","load","cache"],function(a,b){c.removeData(b+".tabs")})}),this.lis.unbind(".tabs").add(this.panels).each(function(){a.data(this,"destroy.tabs")?a(this).remove():a(this).removeClass(["ui-state-default","ui-corner-top","ui-tabs-selected","ui-state-active","ui-state-hover","ui-state-focus","ui-state-disabled","ui-tabs-panel","ui-widget-content","ui-corner-bottom","ui-tabs-hide"].join(" "))}),b.cookie&&this._cookie(null,b.cookie);return this},add:function(c,d,e){e===b&&(e=this.anchors.length);var f=this,g=this.options,h=a(g.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,d)),i=c.indexOf("#")?this._tabId(a("a",h)[0]):c.replace("#","");h.addClass("ui-state-default ui-corner-top").data("destroy.tabs",!0);var j=f.element.find("#"+i);j.length||(j=a(g.panelTemplate).attr("id",i).data("destroy.tabs",!0)),j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"),e>=this.lis.length?(h.appendTo(this.list),j.appendTo(this.list[0].parentNode)):(h.insertBefore(this.lis[e]),j.insertBefore(this.panels[e])),g.disabled=a.map(g.disabled,function(a,b){return a>=e?++a:a}),this._tabify(),this.anchors.length==1&&(g.selected=0,h.addClass("ui-tabs-selected ui-state-active"),j.removeClass("ui-tabs-hide"),this.element.queue("tabs",function(){f._trigger("show",null,f._ui(f.anchors[0],f.panels[0]))}),this.load(0)),this._trigger("add",null,this._ui(this.anchors[e],this.panels[e]));return this},remove:function(b){b=this._getIndex(b);var c=this.options,d=this.lis.eq(b).remove(),e=this.panels.eq(b).remove();d.hasClass("ui-tabs-selected")&&this.anchors.length>1&&this.select(b+(b+1<this.anchors.length?1:-1)),c.disabled=a.map(a.grep(c.disabled,function(a,c){return a!=b}),function(a,c){return a>=b?--a:a}),this._tabify(),this._trigger("remove",null,this._ui(d.find("a")[0],e[0]));return this},enable:function(b){b=this._getIndex(b);var c=this.options;if(a.inArray(b,c.disabled)!=-1){this.lis.eq(b).removeClass("ui-state-disabled"),c.disabled=a.grep(c.disabled,function(a,c){return a!=b}),this._trigger("enable",null,this._ui(this.anchors[b],this.panels[b]));return this}},disable:function(a){a=this._getIndex(a);var b=this,c=this.options;a!=c.selected&&(this.lis.eq(a).addClass("ui-state-disabled"),c.disabled.push(a),c.disabled.sort(),this._trigger("disable",null,this._ui(this.anchors[a],this.panels[a])));return this},select:function(a){a=this._getIndex(a);if(a==-1)if(this.options.collapsible&&this.options.selected!=-1)a=this.options.selected;else return this;this.anchors.eq(a).trigger(this.options.event+".tabs");return this},load:function(b){b=this._getIndex(b);var c=this,d=this.options,e=this.anchors.eq(b)[0],f=a.data(e,"load.tabs");this.abort();if(!f||this.element.queue("tabs").length!==0&&a.data(e,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(b).addClass("ui-state-processing");if(d.spinner){var g=a("span",e);g.data("label.tabs",g.html()).html(d.spinner)}this.xhr=a.ajax(a.extend({},d.ajaxOptions,{url:f,success:function(f,g){c.element.find(c._sanitizeSelector(e.hash)).html(f),c._cleanup(),d.cache&&a.data(e,"cache.tabs",!0),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.success(f,g)}catch(h){}},error:function(a,f,g){c._cleanup(),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.error(a,f,b,e)}catch(g){}}})),c.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]),this.panels.stop(!1,!0),this.element.queue("tabs",this.element.queue("tabs").splice(-2,2)),this.xhr&&(this.xhr.abort(),delete this.xhr),this._cleanup();return this},url:function(a,b){this.anchors.eq(a).removeData("cache.tabs").data("load.tabs",b);return this},length:function(){return this.anchors.length}}),a.extend(a.ui.tabs,{version:"1.8.18"}),a.extend(a.ui.tabs.prototype,{rotation:null,rotate:function(a,b){var c=this,d=this.options,e=c._rotate||(c._rotate=function(b){clearTimeout(c.rotation),c.rotation=setTimeout(function(){var a=d.selected;c.select(++a<c.anchors.length?a:0)},a),b&&b.stopPropagation()}),f=c._unrotate||(c._unrotate=b?function(a){t=d.selected,e()}:function(a){a.clientX&&c.rotate(null)});a?(this.element.bind("tabsshow",e),this.anchors.bind(d.event+".tabs",f),e()):(clearTimeout(c.rotation),this.element.unbind("tabsshow",e),this.anchors.unbind(d.event+".tabs",f),delete this._rotate,delete this._unrotate);return this}})})(jQuery);/* + * jQuery UI Datepicker 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Datepicker + * + * Depends: + * jquery.ui.core.js + */(function($,undefined){function isArray(a){return a&&($.browser.safari&&typeof a=="object"&&a.length||a.constructor&&a.constructor.toString().match(/\Array\(\)/))}function extendRemove(a,b){$.extend(a,b);for(var c in b)if(b[c]==null||b[c]==undefined)a[c]=b[c];return a}function bindHover(a){var b="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return a.bind("mouseout",function(a){var c=$(a.target).closest(b);!c.length||c.removeClass("ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover")}).bind("mouseover",function(c){var d=$(c.target).closest(b);!$.datepicker._isDisabledDatepicker(instActive.inline?a.parent()[0]:instActive.input[0])&&!!d.length&&(d.parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),d.addClass("ui-state-hover"),d.hasClass("ui-datepicker-prev")&&d.addClass("ui-datepicker-prev-hover"),d.hasClass("ui-datepicker-next")&&d.addClass("ui-datepicker-next-hover"))})}function Datepicker(){this.debug=!1,this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},$.extend(this._defaults,this.regional[""]),this.dpDiv=bindHover($('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}$.extend($.ui,{datepicker:{version:"1.8.18"}});var PROP_NAME="datepicker",dpuuid=(new Date).getTime(),instActive;$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){extendRemove(this._defaults,a||{});return this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase(),inline=nodeName=="div"||nodeName=="span";target.id||(this.uuid+=1,target.id="dp"+this.uuid);var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{}),nodeName=="input"?this._connectDatepicker(target,inst):inline&&this._inlineDatepicker(target,inst)},_newInst:function(a,b){var c=a[0].id.replace(/([^A-Za-z0-9_-])/g,"\\\\$1");return{id:c,input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:b?bindHover($('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')):this.dpDiv}},_connectDatepicker:function(a,b){var c=$(a);b.append=$([]),b.trigger=$([]);c.hasClass(this.markerClassName)||(this._attachments(c,b),c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(a,c,d){b.settings[c]=d}).bind("getData.datepicker",function(a,c){return this._get(b,c)}),this._autoSize(b),$.data(a,PROP_NAME,b),b.settings.disabled&&this._disableDatepicker(a))},_attachments:function(a,b){var c=this._get(b,"appendText"),d=this._get(b,"isRTL");b.append&&b.append.remove(),c&&(b.append=$('<span class="'+this._appendClass+'">'+c+"</span>"),a[d?"before":"after"](b.append)),a.unbind("focus",this._showDatepicker),b.trigger&&b.trigger.remove();var e=this._get(b,"showOn");(e=="focus"||e=="both")&&a.focus(this._showDatepicker);if(e=="button"||e=="both"){var f=this._get(b,"buttonText"),g=this._get(b,"buttonImage");b.trigger=$(this._get(b,"buttonImageOnly")?$("<img/>").addClass(this._triggerClass).attr({src:g,alt:f,title:f}):$('<button type="button"></button>').addClass(this._triggerClass).html(g==""?f:$("<img/>").attr({src:g,alt:f,title:f}))),a[d?"before":"after"](b.trigger),b.trigger.click(function(){$.datepicker._datepickerShowing&&$.datepicker._lastInput==a[0]?$.datepicker._hideDatepicker():$.datepicker._datepickerShowing&&$.datepicker._lastInput!=a[0]?($.datepicker._hideDatepicker(),$.datepicker._showDatepicker(a[0])):$.datepicker._showDatepicker(a[0]);return!1})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var d=function(a){var b=0,c=0;for(var d=0;d<a.length;d++)a[d].length>b&&(b=a[d].length,c=d);return c};b.setMonth(d(this._get(a,c.match(/MM/)?"monthNames":"monthNamesShort"))),b.setDate(d(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=$(a);c.hasClass(this.markerClassName)||(c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(a,c,d){b.settings[c]=d}).bind("getData.datepicker",function(a,c){return this._get(b,c)}),$.data(a,PROP_NAME,b),this._setDate(b,this._getDefaultDate(b),!0),this._updateDatepicker(b),this._updateAlternate(b),b.settings.disabled&&this._disableDatepicker(a),b.dpDiv.css("display","block"))},_dialogDatepicker:function(a,b,c,d,e){var f=this._dialogInst;if(!f){this.uuid+=1;var g="dp"+this.uuid;this._dialogInput=$('<input type="text" id="'+g+'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>'),this._dialogInput.keydown(this._doKeyDown),$("body").append(this._dialogInput),f=this._dialogInst=this._newInst(this._dialogInput,!1),f.settings={},$.data(this._dialogInput[0],PROP_NAME,f)}extendRemove(f.settings,d||{}),b=b&&b.constructor==Date?this._formatDate(f,b):b,this._dialogInput.val(b),this._pos=e?e.length?e:[e.pageX,e.pageY]:null;if(!this._pos){var h=document.documentElement.clientWidth,i=document.documentElement.clientHeight,j=document.documentElement.scrollLeft||document.body.scrollLeft,k=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[h/2-100+j,i/2-150+k]}this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),f.settings.onSelect=c,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),$.blockUI&&$.blockUI(this.dpDiv),$.data(this._dialogInput[0],PROP_NAME,f);return this},_destroyDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!!b.hasClass(this.markerClassName)){var d=a.nodeName.toLowerCase();$.removeData(a,PROP_NAME),d=="input"?(c.append.remove(),c.trigger.remove(),b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):(d=="div"||d=="span")&&b.removeClass(this.markerClassName).empty()}},_enableDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!!b.hasClass(this.markerClassName)){var d=a.nodeName.toLowerCase();if(d=="input")a.disabled=!1,c.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""});else if(d=="div"||d=="span"){var e=b.children("."+this._inlineClass);e.children().removeClass("ui-state-disabled"),e.find("select.ui-datepicker-month, select.ui-datepicker-year").removeAttr("disabled")}this._disabledInputs=$.map(this._disabledInputs,function(b){return b==a?null:b})}},_disableDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!!b.hasClass(this.markerClassName)){var d=a.nodeName.toLowerCase();if(d=="input")a.disabled=!0,c.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"});else if(d=="div"||d=="span"){var e=b.children("."+this._inlineClass);e.children().addClass("ui-state-disabled"),e.find("select.ui-datepicker-month, select.ui-datepicker-year").attr("disabled","disabled")}this._disabledInputs=$.map(this._disabledInputs,function(b){return b==a?null:b}),this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return!1;for(var b=0;b<this._disabledInputs.length;b++)if(this._disabledInputs[b]==a)return!0;return!1},_getInst:function(a){try{return $.data(a,PROP_NAME)}catch(b){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(a,b,c){var d=this._getInst(a);if(arguments.length==2&&typeof b=="string")return b=="defaults"?$.extend({},$.datepicker._defaults):d?b=="all"?$.extend({},d.settings):this._get(d,b):null;var e=b||{};typeof b=="string"&&(e={},e[b]=c);if(d){this._curInst==d&&this._hideDatepicker();var f=this._getDateDatepicker(a,!0),g=this._getMinMaxDate(d,"min"),h=this._getMinMaxDate(d,"max");extendRemove(d.settings,e),g!==null&&e.dateFormat!==undefined&&e.minDate===undefined&&(d.settings.minDate=this._formatDate(d,g)),h!==null&&e.dateFormat!==undefined&&e.maxDate===undefined&&(d.settings.maxDate=this._formatDate(d,h)),this._attachments($(a),d),this._autoSize(d),this._setDate(d,f),this._updateAlternate(d),this._updateDatepicker(d)}},_changeDatepicker:function(a,b,c){this._optionDatepicker(a,b,c)},_refreshDatepicker:function(a){var b=this._getInst(a);b&&this._updateDatepicker(b)},_setDateDatepicker:function(a,b){var c=this._getInst(a);c&&(this._setDate(c,b),this._updateDatepicker(c),this._updateAlternate(c))},_getDateDatepicker:function(a,b){var c=this._getInst(a);c&&!c.inline&&this._setDateFromField(c,b);return c?this._getDate(c):null},_doKeyDown:function(a){var b=$.datepicker._getInst(a.target),c=!0,d=b.dpDiv.is(".ui-datepicker-rtl");b._keyEvent=!0;if($.datepicker._datepickerShowing)switch(a.keyCode){case 9:$.datepicker._hideDatepicker(),c=!1;break;case 13:var e=$("td."+$.datepicker._dayOverClass+":not(."+$.datepicker._currentClass+")",b.dpDiv);e[0]&&$.datepicker._selectDay(a.target,b.selectedMonth,b.selectedYear,e[0]);var f=$.datepicker._get(b,"onSelect");if(f){var g=$.datepicker._formatDate(b);f.apply(b.input?b.input[0]:null,[g,b])}else $.datepicker._hideDatepicker();return!1;case 27:$.datepicker._hideDatepicker();break;case 33:$.datepicker._adjustDate(a.target,a.ctrlKey?-$.datepicker._get(b,"stepBigMonths"):-$.datepicker._get(b,"stepMonths"),"M");break;case 34:$.datepicker._adjustDate(a.target,a.ctrlKey?+$.datepicker._get(b,"stepBigMonths"):+$.datepicker._get(b,"stepMonths"),"M");break;case 35:(a.ctrlKey||a.metaKey)&&$.datepicker._clearDate(a.target),c=a.ctrlKey||a.metaKey;break;case 36:(a.ctrlKey||a.metaKey)&&$.datepicker._gotoToday(a.target),c=a.ctrlKey||a.metaKey;break;case 37:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,d?1:-1,"D"),c=a.ctrlKey||a.metaKey,a.originalEvent.altKey&&$.datepicker._adjustDate(a.target,a.ctrlKey?-$.datepicker._get(b,"stepBigMonths"):-$.datepicker._get(b,"stepMonths"),"M");break;case 38:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,-7,"D"),c=a.ctrlKey||a.metaKey;break;case 39:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,d?-1:1,"D"),c=a.ctrlKey||a.metaKey,a.originalEvent.altKey&&$.datepicker._adjustDate(a.target,a.ctrlKey?+$.datepicker._get(b,"stepBigMonths"):+$.datepicker._get(b,"stepMonths"),"M");break;case 40:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,7,"D"),c=a.ctrlKey||a.metaKey;break;default:c=!1}else a.keyCode==36&&a.ctrlKey?$.datepicker._showDatepicker(this):c=!1;c&&(a.preventDefault(),a.stopPropagation())},_doKeyPress:function(a){var b=$.datepicker._getInst(a.target);if($.datepicker._get(b,"constrainInput")){var c=$.datepicker._possibleChars($.datepicker._get(b,"dateFormat")),d=String.fromCharCode(a.charCode==undefined?a.keyCode:a.charCode);return a.ctrlKey||a.metaKey||d<" "||!c||c.indexOf(d)>-1}},_doKeyUp:function(a){var b=$.datepicker._getInst(a.target);if(b.input.val()!=b.lastVal)try{var c=$.datepicker.parseDate($.datepicker._get(b,"dateFormat"),b.input?b.input.val():null,$.datepicker._getFormatConfig(b));c&&($.datepicker._setDateFromField(b),$.datepicker._updateAlternate(b),$.datepicker._updateDatepicker(b))}catch(a){$.datepicker.log(a)}return!0},_showDatepicker:function(a){a=a.target||a,a.nodeName.toLowerCase()!="input"&&(a=$("input",a.parentNode)[0]);if(!$.datepicker._isDisabledDatepicker(a)&&$.datepicker._lastInput!=a){var b=$.datepicker._getInst(a);$.datepicker._curInst&&$.datepicker._curInst!=b&&($.datepicker._curInst.dpDiv.stop(!0,!0),b&&$.datepicker._datepickerShowing&&$.datepicker._hideDatepicker($.datepicker._curInst.input[0]));var c=$.datepicker._get(b,"beforeShow"),d=c?c.apply(a,[a,b]):{};if(d===!1)return;extendRemove(b.settings,d),b.lastVal=null,$.datepicker._lastInput=a,$.datepicker._setDateFromField(b),$.datepicker._inDialog&&(a.value=""),$.datepicker._pos||($.datepicker._pos=$.datepicker._findPos(a),$.datepicker._pos[1]+=a.offsetHeight);var e=!1;$(a).parents().each(function(){e|=$(this).css("position")=="fixed";return!e}),e&&$.browser.opera&&($.datepicker._pos[0]-=document.documentElement.scrollLeft,$.datepicker._pos[1]-=document.documentElement.scrollTop);var f={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null,b.dpDiv.empty(),b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),$.datepicker._updateDatepicker(b),f=$.datepicker._checkOffset(b,f,e),b.dpDiv.css({position:$.datepicker._inDialog&&$.blockUI?"static":e?"fixed":"absolute",display:"none",left:f.left+"px",top:f.top+"px"});if(!b.inline){var g=$.datepicker._get(b,"showAnim"),h=$.datepicker._get(b,"duration"),i=function(){var a=b.dpDiv.find("iframe.ui-datepicker-cover");if(!!a.length){var c=$.datepicker._getBorders(b.dpDiv);a.css({left:-c[0],top:-c[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})}};b.dpDiv.zIndex($(a).zIndex()+1),$.datepicker._datepickerShowing=!0,$.effects&&$.effects[g]?b.dpDiv.show(g,$.datepicker._get(b,"showOptions"),h,i):b.dpDiv[g||"show"](g?h:null,i),(!g||!h)&&i(),b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus(),$.datepicker._curInst=b}}},_updateDatepicker:function(a){var b=this;b.maxRows=4;var c=$.datepicker._getBorders(a.dpDiv);instActive=a,a.dpDiv.empty().append(this._generateHTML(a));var d=a.dpDiv.find("iframe.ui-datepicker-cover");!d.length||d.css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}),a.dpDiv.find("."+this._dayOverClass+" a").mouseover();var e=this._getNumberOfMonths(a),f=e[1],g=17;a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),f>1&&a.dpDiv.addClass("ui-datepicker-multi-"+f).css("width",g*f+"em"),a.dpDiv[(e[0]!=1||e[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi"),a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),a==$.datepicker._curInst&&$.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input[0]!=document.activeElement&&a.input.focus();if(a.yearshtml){var h=a.yearshtml;setTimeout(function(){h===a.yearshtml&&a.yearshtml&&a.dpDiv.find("select.ui-datepicker-year:first").replaceWith(a.yearshtml),h=a.yearshtml=null},0)}},_getBorders:function(a){var b=function(a){return{thin:1,medium:2,thick:3}[a]||a};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var d=a.dpDiv.outerWidth(),e=a.dpDiv.outerHeight(),f=a.input?a.input.outerWidth():0,g=a.input?a.input.outerHeight():0,h=document.documentElement.clientWidth+$(document).scrollLeft(),i=document.documentElement.clientHeight+$(document).scrollTop();b.left-=this._get(a,"isRTL")?d-f:0,b.left-=c&&b.left==a.input.offset().left?$(document).scrollLeft():0,b.top-=c&&b.top==a.input.offset().top+g?$(document).scrollTop():0,b.left-=Math.min(b.left,b.left+d>h&&h>d?Math.abs(b.left+d-h):0),b.top-=Math.min(b.top,b.top+e>i&&i>e?Math.abs(e+g):0);return b},_findPos:function(a){var b=this._getInst(a),c=this._get(b,"isRTL");while(a&&(a.type=="hidden"||a.nodeType!=1||$.expr.filters.hidden(a)))a=a[c?"previousSibling":"nextSibling"];var d=$(a).offset();return[d.left,d.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=$.data(a,PROP_NAME))&&this._datepickerShowing){var c=this._get(b,"showAnim"),d=this._get(b,"duration"),e=this,f=function(){$.datepicker._tidyDialog(b),e._curInst=null};$.effects&&$.effects[c]?b.dpDiv.hide(c,$.datepicker._get(b,"showOptions"),d,f):b.dpDiv[c=="slideDown"?"slideUp":c=="fadeIn"?"fadeOut":"hide"](c?d:null,f),c||f(),this._datepickerShowing=!1;var g=this._get(b,"onClose");g&&g.apply(b.input?b.input[0]:null,[b.input?b.input.val():"",b]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),$.blockUI&&($.unblockUI(),$("body").append(this.dpDiv))),this._inDialog=!1}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(!!$.datepicker._curInst){var b=$(a.target),c=$.datepicker._getInst(b[0]);(b[0].id!=$.datepicker._mainDivId&&b.parents("#"+$.datepicker._mainDivId).length==0&&!b.hasClass($.datepicker.markerClassName)&&!b.closest("."+$.datepicker._triggerClass).length&&$.datepicker._datepickerShowing&&(!$.datepicker._inDialog||!$.blockUI)||b.hasClass($.datepicker.markerClassName)&&$.datepicker._curInst!=c)&&$.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){var d=$(a),e=this._getInst(d[0]);this._isDisabledDatepicker(d[0])||(this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c),this._updateDatepicker(e))},_gotoToday:function(a){var b=$(a),c=this._getInst(b[0]);if(this._get(c,"gotoCurrent")&&c.currentDay)c.selectedDay=c.currentDay,c.drawMonth=c.selectedMonth=c.currentMonth,c.drawYear=c.selectedYear=c.currentYear;else{var d=new Date;c.selectedDay=d.getDate(),c.drawMonth=c.selectedMonth=d.getMonth(),c.drawYear=c.selectedYear=d.getFullYear()}this._notifyChange(c),this._adjustDate(b)},_selectMonthYear:function(a,b,c){var d=$(a),e=this._getInst(d[0]);e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10),this._notifyChange(e),this._adjustDate(d)},_selectDay:function(a,b,c,d){var e=$(a);if(!$(d).hasClass(this._unselectableClass)&&!this._isDisabledDatepicker(e[0])){var f=this._getInst(e[0]);f.selectedDay=f.currentDay=$("a",d).html(),f.selectedMonth=f.currentMonth=b,f.selectedYear=f.currentYear=c,this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){var b=$(a),c=this._getInst(b[0]);this._selectDate(b,"")},_selectDate:function(a,b){var c=$(a),d=this._getInst(c[0]);b=b!=null?b:this._formatDate(d),d.input&&d.input.val(b),this._updateAlternate(d);var e=this._get(d,"onSelect");e?e.apply(d.input?d.input[0]:null,[b,d]):d.input&&d.input.trigger("change"),d.inline?this._updateDatepicker(d):(this._hideDatepicker(),this._lastInput=d.input[0],typeof d.input[0]!="object"&&d.input.focus(),this._lastInput=null)},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a,"altFormat")||this._get(a,"dateFormat"),d=this._getDate(a),e=this.formatDate(c,d,this._getFormatConfig(a));$(b).each(function(){$(this).val(e)})}},noWeekends:function(a){var b=a.getDay();return[b>0&&b<6,""]},iso8601Week:function(a){var b=new Date(a.getTime());b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();b.setMonth(0),b.setDate(1);return Math.floor(Math.round((c-b)/864e5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b=="")return null;var d=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff;d=typeof d!="string"?d:(new Date).getFullYear()%100+parseInt(d,10);var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?c.dayNames:null)||this._defaults.dayNames,g=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,h=(c?c.monthNames:null)||this._defaults.monthNames,i=-1,j=-1,k=-1,l=-1,m=!1,n=function(b){var c=s+1<a.length&&a.charAt(s+1)==b;c&&s++;return c},o=function(a){var c=n(a),d=a=="@"?14:a=="!"?20:a=="y"&&c?4:a=="o"?3:2,e=new RegExp("^\\d{1,"+d+"}"),f=b.substring(r).match(e);if(!f)throw"Missing number at position "+r;r+=f[0].length;return parseInt(f[0],10)},p=function(a,c,d){var e=$.map(n(a)?d:c,function(a,b){return[[b,a]]}).sort(function(a,b){return-(a[1].length-b[1].length)}),f=-1;$.each(e,function(a,c){var d=c[1];if(b.substr(r,d.length).toLowerCase()==d.toLowerCase()){f=c[0],r+=d.length;return!1}});if(f!=-1)return f+1;throw"Unknown name at position "+r},q=function(){if(b.charAt(r)!=a.charAt(s))throw"Unexpected literal at position "+r;r++},r=0;for(var s=0;s<a.length;s++)if(m)a.charAt(s)=="'"&&!n("'")?m=!1:q();else switch(a.charAt(s)){case"d":k=o("d");break;case"D":p("D",e,f);break;case"o":l=o("o");break;case"m":j=o("m");break;case"M":j=p("M",g,h);break;case"y":i=o("y");break;case"@":var t=new Date(o("@"));i=t.getFullYear(),j=t.getMonth()+1,k=t.getDate();break;case"!":var t=new Date((o("!")-this._ticksTo1970)/1e4);i=t.getFullYear(),j=t.getMonth()+1,k=t.getDate();break;case"'":n("'")?q():m=!0;break;default:q()}if(r<b.length)throw"Extra/unparsed characters found in date: "+b.substring(r);i==-1?i=(new Date).getFullYear():i<100&&(i+=(new Date).getFullYear()-(new Date).getFullYear()%100+(i<=d?0:-100));if(l>-1){j=1,k=l;for(;;){var u=this._getDaysInMonth(i,j-1);if(k<=u)break;j++,k-=u}}var t=this._daylightSavingAdjust(new Date(i,j-1,k));if(t.getFullYear()!=i||t.getMonth()+1!=j||t.getDate()!=k)throw"Invalid date";return t},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1e7,formatDate:function(a,b,c){if(!b)return"";var d=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,e=(c?c.dayNames:null)||this._defaults.dayNames,f=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,h=function(b){var c=m+1<a.length&&a.charAt(m+1)==b;c&&m++;return c},i=function(a,b,c){var d=""+b;if(h(a))while(d.length<c)d="0"+d;return d},j=function(a,b,c,d){return h(a)?d[b]:c[b]},k="",l=!1;if(b)for(var m=0;m<a.length;m++)if(l)a.charAt(m)=="'"&&!h("'")?l=!1:k+=a.charAt(m);else switch(a.charAt(m)){case"d":k+=i("d",b.getDate(),2);break;case"D":k+=j("D",b.getDay(),d,e);break;case"o":k+=i("o",Math.round(((new Date(b.getFullYear(),b.getMonth(),b.getDate())).getTime()-(new Date(b.getFullYear(),0,0)).getTime())/864e5),3);break;case"m":k+=i("m",b.getMonth()+1,2);break;case"M":k+=j("M",b.getMonth(),f,g);break;case"y":k+=h("y")?b.getFullYear():(b.getYear()%100<10?"0":"")+b.getYear()%100;break;case"@":k+=b.getTime();break;case"!":k+=b.getTime()*1e4+this._ticksTo1970;break;case"'":h("'")?k+="'":l=!0;break;default:k+=a.charAt(m)}return k},_possibleChars:function(a){var b="",c=!1,d=function(b){var c=e+1<a.length&&a.charAt(e+1)==b;c&&e++;return c};for(var e=0;e<a.length;e++)if(c)a.charAt(e)=="'"&&!d("'")?c=!1:b+=a.charAt(e);else switch(a.charAt(e)){case"d":case"m":case"y":case"@":b+="0123456789";break;case"D":case"M":return null;case"'":d("'")?b+="'":c=!0;break;default:b+=a.charAt(e)}return b},_get:function(a,b){return a.settings[b]!==undefined?a.settings[b]:this._defaults[b]},_setDateFromField:function(a,b){if(a.input.val()!=a.lastVal){var c=this._get(a,"dateFormat"),d=a.lastVal=a.input?a.input.val():null,e,f;e=f=this._getDefaultDate(a);var g=this._getFormatConfig(a);try{e=this.parseDate(c,d,g)||f}catch(h){this.log(h),d=b?"":d}a.selectedDay=e.getDate(),a.drawMonth=a.selectedMonth=e.getMonth(),a.drawYear=a.selectedYear=e.getFullYear(),a.currentDay=d?e.getDate():0,a.currentMonth=d?e.getMonth():0,a.currentYear=d?e.getFullYear():0,this._adjustInstDate(a)}},_getDefaultDate:function(a){return this._restrictMinMax(a,this._determineDate(a,this._get(a,"defaultDate"),new Date))},_determineDate:function(a,b,c){var d=function(a){var b=new Date;b.setDate(b.getDate()+a);return b},e=function(b){try{return $.datepicker.parseDate($.datepicker._get(a,"dateFormat"),b,$.datepicker._getFormatConfig(a))}catch(c){}var d=(b.toLowerCase().match(/^c/)?$.datepicker._getDate(a):null)||new Date,e=d.getFullYear(),f=d.getMonth(),g=d.getDate(),h=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,i=h.exec(b);while(i){switch(i[2]||"d"){case"d":case"D":g+=parseInt(i[1],10);break;case"w":case"W":g+=parseInt(i[1],10)*7;break;case"m":case"M":f+=parseInt(i[1],10),g=Math.min(g,$.datepicker._getDaysInMonth(e,f));break;case"y":case"Y":e+=parseInt(i[1],10),g=Math.min(g,$.datepicker._getDaysInMonth(e,f))}i=h.exec(b)}return new Date(e,f,g)},f=b==null||b===""?c:typeof b=="string"?e(b):typeof b=="number"?isNaN(b)?c:d(b):new Date(b.getTime());f=f&&f.toString()=="Invalid Date"?c:f,f&&(f.setHours(0),f.setMinutes(0),f.setSeconds(0),f.setMilliseconds(0));return this._daylightSavingAdjust(f)},_daylightSavingAdjust:function(a){if(!a)return null;a.setHours(a.getHours()>12?a.getHours()+2:0);return a},_setDate:function(a,b,c){var d=!b,e=a.selectedMonth,f=a.selectedYear,g=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=g.getDate(),a.drawMonth=a.selectedMonth=a.currentMonth=g.getMonth(),a.drawYear=a.selectedYear=a.currentYear=g.getFullYear(),(e!=a.selectedMonth||f!=a.selectedYear)&&!c&&this._notifyChange(a),this._adjustInstDate(a),a.input&&a.input.val(d?"":this._formatDate(a))},_getDate:function(a){var b=!a.currentYear||a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return b},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),d=this._get(a,"showButtonPanel"),e=this._get(a,"hideIfNoPrevNext"),f=this._get(a,"navigationAsDateFormat"),g=this._getNumberOfMonths(a),h=this._get(a,"showCurrentAtPos"),i=this._get(a,"stepMonths"),j=g[0]!=1||g[1]!=1,k=this._daylightSavingAdjust(a.currentDay?new Date(a.currentYear,a.currentMonth,a.currentDay):new Date(9999,9,9)),l=this._getMinMaxDate(a,"min"),m=this._getMinMaxDate(a,"max"),n=a.drawMonth-h,o=a.drawYear;n<0&&(n+=12,o--);if(m){var p=this._daylightSavingAdjust(new Date(m.getFullYear(),m.getMonth()-g[0]*g[1]+1,m.getDate()));p=l&&p<l?l:p;while(this._daylightSavingAdjust(new Date(o,n,1))>p)n--,n<0&&(n=11,o--)}a.drawMonth=n,a.drawYear=o;var q=this._get(a,"prevText");q=f?this.formatDate(q,this._daylightSavingAdjust(new Date(o,n-i,1)),this._getFormatConfig(a)):q;var r=this._canAdjustMonth(a,-1,o,n)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_'+dpuuid+".datepicker._adjustDate('#"+a.id+"', -"+i+", 'M');\""+' title="'+q+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+q+"</span></a>":e?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+q+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+q+"</span></a>",s=this._get(a,"nextText");s=f?this.formatDate(s,this._daylightSavingAdjust(new Date(o,n+i,1)),this._getFormatConfig(a)):s;var t=this._canAdjustMonth(a,1,o,n)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_'+dpuuid+".datepicker._adjustDate('#"+a.id+"', +"+i+", 'M');\""+' title="'+s+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+s+"</span></a>":e?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+s+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+s+"</span></a>",u=this._get(a,"currentText"),v=this._get(a,"gotoCurrent")&&a.currentDay?k:b;u=f?this.formatDate(u,v,this._getFormatConfig(a)):u;var w=a.inline?"":'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_'+dpuuid+'.datepicker._hideDatepicker();">'+this._get(a,"closeText")+"</button>",x=d?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(c?w:"")+(this._isInRange(a,v)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_'+dpuuid+".datepicker._gotoToday('#"+a.id+"');\""+">"+u+"</button>":"")+(c?"":w)+"</div>":"",y=parseInt(this._get(a,"firstDay"),10);y=isNaN(y)?0:y;var z=this._get(a,"showWeek"),A=this._get(a,"dayNames"),B=this._get(a,"dayNamesShort"),C=this._get(a,"dayNamesMin"),D=this._get(a,"monthNames"),E=this._get(a,"monthNamesShort"),F=this._get(a,"beforeShowDay"),G=this._get(a,"showOtherMonths"),H=this._get(a,"selectOtherMonths"),I=this._get(a,"calculateWeek")||this.iso8601Week,J=this._getDefaultDate(a),K="";for(var L=0;L<g[0];L++){var M="";this.maxRows=4;for(var N=0;N<g[1];N++){var O=this._daylightSavingAdjust(new Date(o,n,a.selectedDay)),P=" ui-corner-all",Q="";if(j){Q+='<div class="ui-datepicker-group';if(g[1]>1)switch(N){case 0:Q+=" ui-datepicker-group-first",P=" ui-corner-"+(c?"right":"left");break;case g[1]-1:Q+=" ui-datepicker-group-last",P=" ui-corner-"+(c?"left":"right");break;default:Q+=" ui-datepicker-group-middle",P=""}Q+='">'}Q+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+P+'">'+(/all|left/.test(P)&&L==0?c?t:r:"")+(/all|right/.test(P)&&L==0?c?r:t:"")+this._generateMonthYearHeader(a,n,o,l,m,L>0||N>0,D,E)+'</div><table class="ui-datepicker-calendar"><thead>'+"<tr>";var R=z?'<th class="ui-datepicker-week-col">'+this._get(a,"weekHeader")+"</th>":"";for(var S=0;S<7;S++){var T=(S+y)%7;R+="<th"+((S+y+6)%7>=5?' class="ui-datepicker-week-end"':"")+">"+'<span title="'+A[T]+'">'+C[T]+"</span></th>"}Q+=R+"</tr></thead><tbody>";var U=this._getDaysInMonth(o,n);o==a.selectedYear&&n==a.selectedMonth&&(a.selectedDay=Math.min(a.selectedDay,U));var V=(this._getFirstDayOfMonth(o,n)-y+7)%7,W=Math.ceil((V+U)/7),X=j?this.maxRows>W?this.maxRows:W:W;this.maxRows=X;var Y=this._daylightSavingAdjust(new Date(o,n,1-V));for(var Z=0;Z<X;Z++){Q+="<tr>";var _=z?'<td class="ui-datepicker-week-col">'+this._get(a,"calculateWeek")(Y)+"</td>":"";for(var S=0;S<7;S++){var ba=F?F.apply(a.input?a.input[0]:null,[Y]):[!0,""],bb=Y.getMonth()!=n,bc=bb&&!H||!ba[0]||l&&Y<l||m&&Y>m;_+='<td class="'+((S+y+6)%7>=5?" ui-datepicker-week-end":"")+(bb?" ui-datepicker-other-month":"")+(Y.getTime()==O.getTime()&&n==a.selectedMonth&&a._keyEvent||J.getTime()==Y.getTime()&&J.getTime()==O.getTime()?" "+this._dayOverClass:"")+(bc?" "+this._unselectableClass+" ui-state-disabled":"")+(bb&&!G?"":" "+ba[1]+(Y.getTime()==k.getTime()?" "+this._currentClass:"")+(Y.getTime()==b.getTime()?" ui-datepicker-today":""))+'"'+((!bb||G)&&ba[2]?' title="'+ba[2]+'"':"")+(bc?"":' onclick="DP_jQuery_'+dpuuid+".datepicker._selectDay('#"+a.id+"',"+Y.getMonth()+","+Y.getFullYear()+', this);return false;"')+">"+(bb&&!G?" ":bc?'<span class="ui-state-default">'+Y.getDate()+"</span>":'<a class="ui-state-default'+(Y.getTime()==b.getTime()?" ui-state-highlight":"")+(Y.getTime()==k.getTime()?" ui-state-active":"")+(bb?" ui-priority-secondary":"")+'" href="#">'+Y.getDate()+"</a>")+"</td>",Y.setDate(Y.getDate()+1),Y=this._daylightSavingAdjust(Y)}Q+=_+"</tr>"}n++,n>11&&(n=0,o++),Q+="</tbody></table>"+(j?"</div>"+(g[0]>0&&N==g[1]-1?'<div class="ui-datepicker-row-break"></div>':""):""),M+=Q}K+=M}K+=x+($.browser.msie&&parseInt($.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':""), +a._keyEvent=!1;return K},_generateMonthYearHeader:function(a,b,c,d,e,f,g,h){var i=this._get(a,"changeMonth"),j=this._get(a,"changeYear"),k=this._get(a,"showMonthAfterYear"),l='<div class="ui-datepicker-title">',m="";if(f||!i)m+='<span class="ui-datepicker-month">'+g[b]+"</span>";else{var n=d&&d.getFullYear()==c,o=e&&e.getFullYear()==c;m+='<select class="ui-datepicker-month" onchange="DP_jQuery_'+dpuuid+".datepicker._selectMonthYear('#"+a.id+"', this, 'M');\" "+">";for(var p=0;p<12;p++)(!n||p>=d.getMonth())&&(!o||p<=e.getMonth())&&(m+='<option value="'+p+'"'+(p==b?' selected="selected"':"")+">"+h[p]+"</option>");m+="</select>"}k||(l+=m+(f||!i||!j?" ":""));if(!a.yearshtml){a.yearshtml="";if(f||!j)l+='<span class="ui-datepicker-year">'+c+"</span>";else{var q=this._get(a,"yearRange").split(":"),r=(new Date).getFullYear(),s=function(a){var b=a.match(/c[+-].*/)?c+parseInt(a.substring(1),10):a.match(/[+-].*/)?r+parseInt(a,10):parseInt(a,10);return isNaN(b)?r:b},t=s(q[0]),u=Math.max(t,s(q[1]||""));t=d?Math.max(t,d.getFullYear()):t,u=e?Math.min(u,e.getFullYear()):u,a.yearshtml+='<select class="ui-datepicker-year" onchange="DP_jQuery_'+dpuuid+".datepicker._selectMonthYear('#"+a.id+"', this, 'Y');\" "+">";for(;t<=u;t++)a.yearshtml+='<option value="'+t+'"'+(t==c?' selected="selected"':"")+">"+t+"</option>";a.yearshtml+="</select>",l+=a.yearshtml,a.yearshtml=null}}l+=this._get(a,"yearSuffix"),k&&(l+=(f||!i||!j?" ":"")+m),l+="</div>";return l},_adjustInstDate:function(a,b,c){var d=a.drawYear+(c=="Y"?b:0),e=a.drawMonth+(c=="M"?b:0),f=Math.min(a.selectedDay,this._getDaysInMonth(d,e))+(c=="D"?b:0),g=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(d,e,f)));a.selectedDay=g.getDate(),a.drawMonth=a.selectedMonth=g.getMonth(),a.drawYear=a.selectedYear=g.getFullYear(),(c=="M"||c=="Y")&&this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max"),e=c&&b<c?c:b;e=d&&e>d?d:e;return e},_notifyChange:function(a){var b=this._get(a,"onChangeMonthYear");b&&b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){var b=this._get(a,"numberOfMonths");return b==null?[1,1]:typeof b=="number"?[1,b]:b},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-this._daylightSavingAdjust(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,d){var e=this._getNumberOfMonths(a),f=this._daylightSavingAdjust(new Date(c,d+(b<0?b:e[0]*e[1]),1));b<0&&f.setDate(this._getDaysInMonth(f.getFullYear(),f.getMonth()));return this._isInRange(a,f)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!d||b.getTime()<=d.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,d){b||(a.currentDay=a.selectedDay,a.currentMonth=a.selectedMonth,a.currentYear=a.selectedYear);var e=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(d,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),e,this._getFormatConfig(a))}}),$.fn.datepicker=function(a){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv),$.datepicker.initialized=!0);var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return $.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return $.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b));return this.each(function(){typeof a=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this].concat(b)):$.datepicker._attachDatepicker(this,a)})},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.8.18",window["DP_jQuery_"+dpuuid]=$})(jQuery);/* + * jQuery UI Progressbar 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */(function(a,b){a.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()}),this.valueDiv=a("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove(),a.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===b)return this._value();this._setOption("value",a);return this},_setOption:function(b,c){b==="value"&&(this.options.value=c,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),a.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;typeof a!="number"&&(a=0);return Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var a=this.value(),b=this._percentage();this.oldValue!==a&&(this.oldValue=a,this._trigger("change")),this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(b.toFixed(0)+"%"),this.element.attr("aria-valuenow",a)}}),a.extend(a.ui.progressbar,{version:"1.8.18"})})(jQuery);/* + * jQuery UI Effects 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/ + */jQuery.effects||function(a,b){function l(b){if(!b||typeof b=="number"||a.fx.speeds[b])return!0;if(typeof b=="string"&&!a.effects[b])return!0;return!1}function k(b,c,d,e){typeof b=="object"&&(e=c,d=null,c=b,b=c.effect),a.isFunction(c)&&(e=c,d=null,c={});if(typeof c=="number"||a.fx.speeds[c])e=d,d=c,c={};a.isFunction(d)&&(e=d,d=null),c=c||{},d=d||c.duration,d=a.fx.off?0:typeof d=="number"?d:d in a.fx.speeds?a.fx.speeds[d]:a.fx.speeds._default,e=e||c.complete;return[b,c,d,e]}function j(a,b){var c={_:0},d;for(d in b)a[d]!=b[d]&&(c[d]=b[d]);return c}function i(b){var c,d;for(c in b)d=b[c],(d==null||a.isFunction(d)||c in g||/scrollbar/.test(c)||!/color/i.test(c)&&isNaN(parseFloat(d)))&&delete b[c];return b}function h(){var a=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,b={},c,d;if(a&&a.length&&a[0]&&a[a[0]]){var e=a.length;while(e--)c=a[e],typeof a[c]=="string"&&(d=c.replace(/\-(\w)/g,function(a,b){return b.toUpperCase()}),b[d]=a[c])}else for(c in a)typeof a[c]=="string"&&(b[c]=a[c]);return b}function d(b,d){var e;do{e=a.curCSS(b,d);if(e!=""&&e!="transparent"||a.nodeName(b,"body"))break;d="backgroundColor"}while(b=b.parentNode);return c(e)}function c(b){var c;if(b&&b.constructor==Array&&b.length==3)return b;if(c=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b))return[parseInt(c[1],10),parseInt(c[2],10),parseInt(c[3],10)];if(c=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b))return[parseFloat(c[1])*2.55,parseFloat(c[2])*2.55,parseFloat(c[3])*2.55];if(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b))return[parseInt(c[1],16),parseInt(c[2],16),parseInt(c[3],16)];if(c=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b))return[parseInt(c[1]+c[1],16),parseInt(c[2]+c[2],16),parseInt(c[3]+c[3],16)];if(c=/rgba\(0, 0, 0, 0\)/.exec(b))return e.transparent;return e[a.trim(b).toLowerCase()]}a.effects={},a.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","borderColor","color","outlineColor"],function(b,e){a.fx.step[e]=function(a){a.colorInit||(a.start=d(a.elem,e),a.end=c(a.end),a.colorInit=!0),a.elem.style[e]="rgb("+Math.max(Math.min(parseInt(a.pos*(a.end[0]-a.start[0])+a.start[0],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[1]-a.start[1])+a.start[1],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[2]-a.start[2])+a.start[2],10),255),0)+")"}});var e={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},f=["add","remove","toggle"],g={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};a.effects.animateClass=function(b,c,d,e){a.isFunction(d)&&(e=d,d=null);return this.queue(function(){var g=a(this),k=g.attr("style")||" ",l=i(h.call(this)),m,n=g.attr("class");a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),m=i(h.call(this)),g.attr("class",n),g.animate(j(l,m),{queue:!1,duration:c,easing:d,complete:function(){a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),typeof g.attr("style")=="object"?(g.attr("style").cssText="",g.attr("style").cssText=k):g.attr("style",k),e&&e.apply(this,arguments),a.dequeue(this)}})})},a.fn.extend({_addClass:a.fn.addClass,addClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{add:b},c,d,e]):this._addClass(b)},_removeClass:a.fn.removeClass,removeClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{remove:b},c,d,e]):this._removeClass(b)},_toggleClass:a.fn.toggleClass,toggleClass:function(c,d,e,f,g){return typeof d=="boolean"||d===b?e?a.effects.animateClass.apply(this,[d?{add:c}:{remove:c},e,f,g]):this._toggleClass(c,d):a.effects.animateClass.apply(this,[{toggle:c},d,e,f])},switchClass:function(b,c,d,e,f){return a.effects.animateClass.apply(this,[{add:c,remove:b},d,e,f])}}),a.extend(a.effects,{version:"1.8.18",save:function(a,b){for(var c=0;c<b.length;c++)b[c]!==null&&a.data("ec.storage."+b[c],a[0].style[b[c]])},restore:function(a,b){for(var c=0;c<b.length;c++)b[c]!==null&&a.css(b[c],a.data("ec.storage."+b[c]))},setMode:function(a,b){b=="toggle"&&(b=a.is(":hidden")?"show":"hide");return b},getBaseline:function(a,b){var c,d;switch(a[0]){case"top":c=0;break;case"middle":c=.5;break;case"bottom":c=1;break;default:c=a[0]/b.height}switch(a[1]){case"left":d=0;break;case"center":d=.5;break;case"right":d=1;break;default:d=a[1]/b.width}return{x:d,y:c}},createWrapper:function(b){if(b.parent().is(".ui-effects-wrapper"))return b.parent();var c={width:b.outerWidth(!0),height:b.outerHeight(!0),"float":b.css("float")},d=a("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e=document.activeElement;b.wrap(d),(b[0]===e||a.contains(b[0],e))&&a(e).focus(),d=b.parent(),b.css("position")=="static"?(d.css({position:"relative"}),b.css({position:"relative"})):(a.extend(c,{position:b.css("position"),zIndex:b.css("z-index")}),a.each(["top","left","bottom","right"],function(a,d){c[d]=b.css(d),isNaN(parseInt(c[d],10))&&(c[d]="auto")}),b.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"}));return d.css(c).show()},removeWrapper:function(b){var c,d=document.activeElement;if(b.parent().is(".ui-effects-wrapper")){c=b.parent().replaceWith(b),(b[0]===d||a.contains(b[0],d))&&a(d).focus();return c}return b},setTransition:function(b,c,d,e){e=e||{},a.each(c,function(a,c){unit=b.cssUnit(c),unit[0]>0&&(e[c]=unit[0]*d+unit[1])});return e}}),a.fn.extend({effect:function(b,c,d,e){var f=k.apply(this,arguments),g={options:f[1],duration:f[2],callback:f[3]},h=g.options.mode,i=a.effects[b];if(a.fx.off||!i)return h?this[h](g.duration,g.callback):this.each(function(){g.callback&&g.callback.call(this)});return i.call(this,g)},_show:a.fn.show,show:function(a){if(l(a))return this._show.apply(this,arguments);var b=k.apply(this,arguments);b[1].mode="show";return this.effect.apply(this,b)},_hide:a.fn.hide,hide:function(a){if(l(a))return this._hide.apply(this,arguments);var b=k.apply(this,arguments);b[1].mode="hide";return this.effect.apply(this,b)},__toggle:a.fn.toggle,toggle:function(b){if(l(b)||typeof b=="boolean"||a.isFunction(b))return this.__toggle.apply(this,arguments);var c=k.apply(this,arguments);c[1].mode="toggle";return this.effect.apply(this,c)},cssUnit:function(b){var c=this.css(b),d=[];a.each(["em","px","%","pt"],function(a,b){c.indexOf(b)>0&&(d=[parseFloat(c),b])});return d}}),a.easing.jswing=a.easing.swing,a.extend(a.easing,{def:"easeOutQuad",swing:function(b,c,d,e,f){return a.easing[a.easing.def](b,c,d,e,f)},easeInQuad:function(a,b,c,d,e){return d*(b/=e)*b+c},easeOutQuad:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c},easeInOutQuad:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b+c;return-d/2*(--b*(b-2)-1)+c},easeInCubic:function(a,b,c,d,e){return d*(b/=e)*b*b+c},easeOutCubic:function(a,b,c,d,e){return d*((b=b/e-1)*b*b+1)+c},easeInOutCubic:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b*b+c;return d/2*((b-=2)*b*b+2)+c},easeInQuart:function(a,b,c,d,e){return d*(b/=e)*b*b*b+c},easeOutQuart:function(a,b,c,d,e){return-d*((b=b/e-1)*b*b*b-1)+c},easeInOutQuart:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b*b*b+c;return-d/2*((b-=2)*b*b*b-2)+c},easeInQuint:function(a,b,c,d,e){return d*(b/=e)*b*b*b*b+c},easeOutQuint:function(a,b,c,d,e){return d*((b=b/e-1)*b*b*b*b+1)+c},easeInOutQuint:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b*b*b*b+c;return d/2*((b-=2)*b*b*b*b+2)+c},easeInSine:function(a,b,c,d,e){return-d*Math.cos(b/e*(Math.PI/2))+d+c},easeOutSine:function(a,b,c,d,e){return d*Math.sin(b/e*(Math.PI/2))+c},easeInOutSine:function(a,b,c,d,e){return-d/2*(Math.cos(Math.PI*b/e)-1)+c},easeInExpo:function(a,b,c,d,e){return b==0?c:d*Math.pow(2,10*(b/e-1))+c},easeOutExpo:function(a,b,c,d,e){return b==e?c+d:d*(-Math.pow(2,-10*b/e)+1)+c},easeInOutExpo:function(a,b,c,d,e){if(b==0)return c;if(b==e)return c+d;if((b/=e/2)<1)return d/2*Math.pow(2,10*(b-1))+c;return d/2*(-Math.pow(2,-10*--b)+2)+c},easeInCirc:function(a,b,c,d,e){return-d*(Math.sqrt(1-(b/=e)*b)-1)+c},easeOutCirc:function(a,b,c,d,e){return d*Math.sqrt(1-(b=b/e-1)*b)+c},easeInOutCirc:function(a,b,c,d,e){if((b/=e/2)<1)return-d/2*(Math.sqrt(1-b*b)-1)+c;return d/2*(Math.sqrt(1-(b-=2)*b)+1)+c},easeInElastic:function(a,b,c,d,e){var f=1.70158,g=0,h=d;if(b==0)return c;if((b/=e)==1)return c+d;g||(g=e*.3);if(h<Math.abs(d)){h=d;var f=g/4}else var f=g/(2*Math.PI)*Math.asin(d/h);return-(h*Math.pow(2,10*(b-=1))*Math.sin((b*e-f)*2*Math.PI/g))+c},easeOutElastic:function(a,b,c,d,e){var f=1.70158,g=0,h=d;if(b==0)return c;if((b/=e)==1)return c+d;g||(g=e*.3);if(h<Math.abs(d)){h=d;var f=g/4}else var f=g/(2*Math.PI)*Math.asin(d/h);return h*Math.pow(2,-10*b)*Math.sin((b*e-f)*2*Math.PI/g)+d+c},easeInOutElastic:function(a,b,c,d,e){var f=1.70158,g=0,h=d;if(b==0)return c;if((b/=e/2)==2)return c+d;g||(g=e*.3*1.5);if(h<Math.abs(d)){h=d;var f=g/4}else var f=g/(2*Math.PI)*Math.asin(d/h);if(b<1)return-0.5*h*Math.pow(2,10*(b-=1))*Math.sin((b*e-f)*2*Math.PI/g)+c;return h*Math.pow(2,-10*(b-=1))*Math.sin((b*e-f)*2*Math.PI/g)*.5+d+c},easeInBack:function(a,c,d,e,f,g){g==b&&(g=1.70158);return e*(c/=f)*c*((g+1)*c-g)+d},easeOutBack:function(a,c,d,e,f,g){g==b&&(g=1.70158);return e*((c=c/f-1)*c*((g+1)*c+g)+1)+d},easeInOutBack:function(a,c,d,e,f,g){g==b&&(g=1.70158);if((c/=f/2)<1)return e/2*c*c*(((g*=1.525)+1)*c-g)+d;return e/2*((c-=2)*c*(((g*=1.525)+1)*c+g)+2)+d},easeInBounce:function(b,c,d,e,f){return e-a.easing.easeOutBounce(b,f-c,0,e,f)+d},easeOutBounce:function(a,b,c,d,e){return(b/=e)<1/2.75?d*7.5625*b*b+c:b<2/2.75?d*(7.5625*(b-=1.5/2.75)*b+.75)+c:b<2.5/2.75?d*(7.5625*(b-=2.25/2.75)*b+.9375)+c:d*(7.5625*(b-=2.625/2.75)*b+.984375)+c},easeInOutBounce:function(b,c,d,e,f){if(c<f/2)return a.easing.easeInBounce(b,c*2,0,e,f)*.5+d;return a.easing.easeOutBounce(b,c*2-f,0,e,f)*.5+e*.5+d}})}(jQuery);/* + * jQuery UI Effects Blind 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Blind + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.blind=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"vertical";a.effects.save(c,d),c.show();var g=a.effects.createWrapper(c).css({overflow:"hidden"}),h=f=="vertical"?"height":"width",i=f=="vertical"?g.height():g.width();e=="show"&&g.css(h,0);var j={};j[h]=e=="show"?i:0,g.animate(j,b.duration,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);/* + * jQuery UI Effects Bounce 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Bounce + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.bounce=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"effect"),f=b.options.direction||"up",g=b.options.distance||20,h=b.options.times||5,i=b.duration||250;/show|hide/.test(e)&&d.push("opacity"),a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var j=f=="up"||f=="down"?"top":"left",k=f=="up"||f=="left"?"pos":"neg",g=b.options.distance||(j=="top"?c.outerHeight({margin:!0})/3:c.outerWidth({margin:!0})/3);e=="show"&&c.css("opacity",0).css(j,k=="pos"?-g:g),e=="hide"&&(g=g/(h*2)),e!="hide"&&h--;if(e=="show"){var l={opacity:1};l[j]=(k=="pos"?"+=":"-=")+g,c.animate(l,i/2,b.options.easing),g=g/2,h--}for(var m=0;m<h;m++){var n={},p={};n[j]=(k=="pos"?"-=":"+=")+g,p[j]=(k=="pos"?"+=":"-=")+g,c.animate(n,i/2,b.options.easing).animate(p,i/2,b.options.easing),g=e=="hide"?g*2:g/2}if(e=="hide"){var l={opacity:0};l[j]=(k=="pos"?"-=":"+=")+g,c.animate(l,i/2,b.options.easing,function(){c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments)})}else{var n={},p={};n[j]=(k=="pos"?"-=":"+=")+g,p[j]=(k=="pos"?"+=":"-=")+g,c.animate(n,i/2,b.options.easing).animate(p,i/2,b.options.easing,function(){a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments)})}c.queue("fx",function(){c.dequeue()}),c.dequeue()})}})(jQuery);/* + * jQuery UI Effects Clip 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Clip + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.clip=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right","height","width"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"vertical";a.effects.save(c,d),c.show();var g=a.effects.createWrapper(c).css({overflow:"hidden"}),h=c[0].tagName=="IMG"?g:c,i={size:f=="vertical"?"height":"width",position:f=="vertical"?"top":"left"},j=f=="vertical"?h.height():h.width();e=="show"&&(h.css(i.size,0),h.css(i.position,j/2));var k={};k[i.size]=e=="show"?j:0,k[i.position]=e=="show"?0:j/2,h.animate(k,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()}})})}})(jQuery);/* + * jQuery UI Effects Drop 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Drop + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.drop=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right","opacity"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"left";a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var g=f=="up"||f=="down"?"top":"left",h=f=="up"||f=="left"?"pos":"neg",i=b.options.distance||(g=="top"?c.outerHeight({margin:!0})/2:c.outerWidth({margin:!0})/2);e=="show"&&c.css("opacity",0).css(g,h=="pos"?-i:i);var j={opacity:e=="show"?1:0};j[g]=(e=="show"?h=="pos"?"+=":"-=":h=="pos"?"-=":"+=")+i,c.animate(j,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/* + * jQuery UI Effects Explode 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Explode + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.explode=function(b){return this.queue(function(){var c=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3,d=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3;b.options.mode=b.options.mode=="toggle"?a(this).is(":visible")?"hide":"show":b.options.mode;var e=a(this).show().css("visibility","hidden"),f=e.offset();f.top-=parseInt(e.css("marginTop"),10)||0,f.left-=parseInt(e.css("marginLeft"),10)||0;var g=e.outerWidth(!0),h=e.outerHeight(!0);for(var i=0;i<c;i++)for(var j=0;j<d;j++)e.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-j*(g/d),top:-i*(h/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:g/d,height:h/c,left:f.left+j*(g/d)+(b.options.mode=="show"?(j-Math.floor(d/2))*(g/d):0),top:f.top+i*(h/c)+(b.options.mode=="show"?(i-Math.floor(c/2))*(h/c):0),opacity:b.options.mode=="show"?0:1}).animate({left:f.left+j*(g/d)+(b.options.mode=="show"?0:(j-Math.floor(d/2))*(g/d)),top:f.top+i*(h/c)+(b.options.mode=="show"?0:(i-Math.floor(c/2))*(h/c)),opacity:b.options.mode=="show"?1:0},b.duration||500);setTimeout(function(){b.options.mode=="show"?e.css({visibility:"visible"}):e.css({visibility:"visible"}).hide(),b.callback&&b.callback.apply(e[0]),e.dequeue(),a("div.ui-effects-explode").remove()},b.duration||500)})}})(jQuery);/* + * jQuery UI Effects Fade 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fade + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.fade=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"hide");c.animate({opacity:d},{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/* + * jQuery UI Effects Fold 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fold + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.fold=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.size||15,g=!!b.options.horizFirst,h=b.duration?b.duration/2:a.fx.speeds._default/2;a.effects.save(c,d),c.show();var i=a.effects.createWrapper(c).css({overflow:"hidden"}),j=e=="show"!=g,k=j?["width","height"]:["height","width"],l=j?[i.width(),i.height()]:[i.height(),i.width()],m=/([0-9]+)%/.exec(f);m&&(f=parseInt(m[1],10)/100*l[e=="hide"?0:1]),e=="show"&&i.css(g?{height:0,width:f}:{height:f,width:0});var n={},p={};n[k[0]]=e=="show"?l[0]:f,p[k[1]]=e=="show"?l[1]:0,i.animate(n,h,b.options.easing).animate(p,h,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);/* + * jQuery UI Effects Highlight 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Highlight + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.highlight=function(b){return this.queue(function(){var c=a(this),d=["backgroundImage","backgroundColor","opacity"],e=a.effects.setMode(c,b.options.mode||"show"),f={backgroundColor:c.css("backgroundColor")};e=="hide"&&(f.opacity=0),a.effects.save(c,d),c.show().css({backgroundImage:"none",backgroundColor:b.options.color||"#ffff99"}).animate(f,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),e=="show"&&!a.support.opacity&&this.style.removeAttribute("filter"),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/* + * jQuery UI Effects Pulsate 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Pulsate + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.pulsate=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"show");times=(b.options.times||5)*2-1,duration=b.duration?b.duration/2:a.fx.speeds._default/2,isVisible=c.is(":visible"),animateTo=0,isVisible||(c.css("opacity",0).show(),animateTo=1),(d=="hide"&&isVisible||d=="show"&&!isVisible)&×--;for(var e=0;e<times;e++)c.animate({opacity:animateTo},duration,b.options.easing),animateTo=(animateTo+1)%2;c.animate({opacity:animateTo},duration,b.options.easing,function(){animateTo==0&&c.hide(),b.callback&&b.callback.apply(this,arguments)}),c.queue("fx",function(){c.dequeue()}).dequeue()})}})(jQuery);/* + * jQuery UI Effects Scale 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Scale + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.puff=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"hide"),e=parseInt(b.options.percent,10)||150,f=e/100,g={height:c.height(),width:c.width()};a.extend(b.options,{fade:!0,mode:d,percent:d=="hide"?e:100,from:d=="hide"?g:{height:g.height*f,width:g.width*f}}),c.effect("scale",b.options,b.duration,b.callback),c.dequeue()})},a.effects.scale=function(b){return this.queue(function(){var c=a(this),d=a.extend(!0,{},b.options),e=a.effects.setMode(c,b.options.mode||"effect"),f=parseInt(b.options.percent,10)||(parseInt(b.options.percent,10)==0?0:e=="hide"?0:100),g=b.options.direction||"both",h=b.options.origin;e!="effect"&&(d.origin=h||["middle","center"],d.restore=!0);var i={height:c.height(),width:c.width()};c.from=b.options.from||(e=="show"?{height:0,width:0}:i);var j={y:g!="horizontal"?f/100:1,x:g!="vertical"?f/100:1};c.to={height:i.height*j.y,width:i.width*j.x},b.options.fade&&(e=="show"&&(c.from.opacity=0,c.to.opacity=1),e=="hide"&&(c.from.opacity=1,c.to.opacity=0)),d.from=c.from,d.to=c.to,d.mode=e,c.effect("size",d,b.duration,b.callback),c.dequeue()})},a.effects.size=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right","width","height","overflow","opacity"],e=["position","top","bottom","left","right","overflow","opacity"],f=["width","height","overflow"],g=["fontSize"],h=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],i=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],j=a.effects.setMode(c,b.options.mode||"effect"),k=b.options.restore||!1,l=b.options.scale||"both",m=b.options.origin,n={height:c.height(),width:c.width()};c.from=b.options.from||n,c.to=b.options.to||n;if(m){var p=a.effects.getBaseline(m,n);c.from.top=(n.height-c.from.height)*p.y,c.from.left=(n.width-c.from.width)*p.x,c.to.top=(n.height-c.to.height)*p.y,c.to.left=(n.width-c.to.width)*p.x}var q={from:{y:c.from.height/n.height,x:c.from.width/n.width},to:{y:c.to.height/n.height,x:c.to.width/n.width}};if(l=="box"||l=="both")q.from.y!=q.to.y&&(d=d.concat(h),c.from=a.effects.setTransition(c,h,q.from.y,c.from),c.to=a.effects.setTransition(c,h,q.to.y,c.to)),q.from.x!=q.to.x&&(d=d.concat(i),c.from=a.effects.setTransition(c,i,q.from.x,c.from),c.to=a.effects.setTransition(c,i,q.to.x,c.to));(l=="content"||l=="both")&&q.from.y!=q.to.y&&(d=d.concat(g),c.from=a.effects.setTransition(c,g,q.from.y,c.from),c.to=a.effects.setTransition(c,g,q.to.y,c.to)),a.effects.save(c,k?d:e),c.show(),a.effects.createWrapper(c),c.css("overflow","hidden").css(c.from);if(l=="content"||l=="both")h=h.concat(["marginTop","marginBottom"]).concat(g),i=i.concat(["marginLeft","marginRight"]),f=d.concat(h).concat(i),c.find("*[width]").each(function(){child=a(this),k&&a.effects.save(child,f);var c={height:child.height(),width:child.width()};child.from={height:c.height*q.from.y,width:c.width*q.from.x},child.to={height:c.height*q.to.y,width:c.width*q.to.x},q.from.y!=q.to.y&&(child.from=a.effects.setTransition(child,h,q.from.y,child.from),child.to=a.effects.setTransition(child,h,q.to.y,child.to)),q.from.x!=q.to.x&&(child.from=a.effects.setTransition(child,i,q.from.x,child.from),child.to=a.effects.setTransition(child,i,q.to.x,child.to)),child.css(child.from),child.animate(child.to,b.duration,b.options.easing,function(){k&&a.effects.restore(child,f)})});c.animate(c.to,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){c.to.opacity===0&&c.css("opacity",c.from.opacity),j=="hide"&&c.hide(),a.effects.restore(c,k?d:e),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/* + * jQuery UI Effects Shake 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Shake + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.shake=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"effect"),f=b.options.direction||"left",g=b.options.distance||20,h=b.options.times||3,i=b.duration||b.options.duration||140;a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var j=f=="up"||f=="down"?"top":"left",k=f=="up"||f=="left"?"pos":"neg",l={},m={},n={};l[j]=(k=="pos"?"-=":"+=")+g,m[j]=(k=="pos"?"+=":"-=")+g*2,n[j]=(k=="pos"?"-=":"+=")+g*2,c.animate(l,i,b.options.easing);for(var p=1;p<h;p++)c.animate(m,i,b.options.easing).animate(n,i,b.options.easing);c.animate(m,i,b.options.easing).animate(l,i/2,b.options.easing,function(){a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments)}),c.queue("fx",function(){c.dequeue()}),c.dequeue()})}})(jQuery);/* + * jQuery UI Effects Slide 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Slide + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.slide=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"show"),f=b.options.direction||"left";a.effects.save(c,d),c.show(),a.effects.createWrapper(c).css({overflow:"hidden"});var g=f=="up"||f=="down"?"top":"left",h=f=="up"||f=="left"?"pos":"neg",i=b.options.distance||(g=="top"?c.outerHeight({margin:!0}):c.outerWidth({margin:!0}));e=="show"&&c.css(g,h=="pos"?isNaN(i)?"-"+i:-i:i);var j={};j[g]=(e=="show"?h=="pos"?"+=":"-=":h=="pos"?"-=":"+=")+i,c.animate(j,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/* + * jQuery UI Effects Transfer 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Transfer + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.transfer=function(b){return this.queue(function(){var c=a(this),d=a(b.options.to),e=d.offset(),f={top:e.top,left:e.left,height:d.innerHeight(),width:d.innerWidth()},g=c.offset(),h=a('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(b.options.className).css({top:g.top,left:g.left,height:c.innerHeight(),width:c.innerWidth(),position:"absolute"}).animate(f,b.duration,b.options.easing,function(){h.remove(),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/pngfix.js b/subsonic-main/src/main/webapp/script/pngfix.js new file mode 100644 index 00000000..87d4b1cd --- /dev/null +++ b/subsonic-main/src/main/webapp/script/pngfix.js @@ -0,0 +1,39 @@ +/* + +Correctly handle PNG transparency in Win IE 5.5 & 6. +http://homepage.ntlworld.com/bobosola. Updated 18-Jan-2006. + +Use in <HEAD> with DEFER keyword wrapped in conditional comments: +<!--[if lt IE 7]> +<script defer type="text/javascript" src="pngfix.js"></script> +<![endif]--> + +*/ + +var arVersion = navigator.appVersion.split("MSIE") +var version = parseFloat(arVersion[1]) + +if ((version >= 5.5) && (document.body.filters)) +{ + for(var i=0; i<document.images.length; i++) + { + var img = document.images[i] + var imgName = img.src.toUpperCase() + if (imgName.substring(imgName.length-3, imgName.length) == "PNG") + { + var imgID = (img.id) ? "id='" + img.id + "' " : "" + var imgClass = (img.className) ? "class='" + img.className + "' " : "" + var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' " + var imgStyle = "display:inline-block;" + img.style.cssText + if (img.align == "left") imgStyle = "float:left;" + imgStyle + if (img.align == "right") imgStyle = "float:right;" + imgStyle + if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle + var strNewHTML = "<span " + imgID + imgClass + imgTitle + + " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";" + + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader" + + "(src=\'" + img.src + "\', sizingMethod='image');\"></span>" + img.outerHTML = strNewHTML + i = i-1 + } + } +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/prototype.js b/subsonic-main/src/main/webapp/script/prototype.js new file mode 100644 index 00000000..dfe8ab4e --- /dev/null +++ b/subsonic-main/src/main/webapp/script/prototype.js @@ -0,0 +1,4320 @@ +/* Prototype JavaScript framework, version 1.6.0.3 + * (c) 2005-2008 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * + *--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.6.0.3', + + Browser: { + IE: !!(window.attachEvent && + navigator.userAgent.indexOf('Opera') === -1), + Opera: navigator.userAgent.indexOf('Opera') > -1, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && + navigator.userAgent.indexOf('KHTML') === -1, + MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + SelectorsAPI: !!document.querySelector, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + document.createElement('div')['__proto__'] && + document.createElement('div')['__proto__'] !== + document.createElement('form')['__proto__'] + }, + + ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>', + JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +}; + +if (Prototype.Browser.MobileSafari) + Prototype.BrowserFeatures.SpecificElementExtensions = false; + + +/* Based on Alex Arnell's inheritance implementation. */ +var Class = { + create: function() { + var parent = null, properties = $A(arguments); + if (Object.isFunction(properties[0])) + parent = properties.shift(); + + function klass() { + this.initialize.apply(this, arguments); + } + + Object.extend(klass, Class.Methods); + klass.superclass = parent; + klass.subclasses = []; + + if (parent) { + var subclass = function() { }; + subclass.prototype = parent.prototype; + klass.prototype = new subclass; + parent.subclasses.push(klass); + } + + for (var i = 0; i < properties.length; i++) + klass.addMethods(properties[i]); + + if (!klass.prototype.initialize) + klass.prototype.initialize = Prototype.emptyFunction; + + klass.prototype.constructor = klass; + + return klass; + } +}; + +Class.Methods = { + addMethods: function(source) { + var ancestor = this.superclass && this.superclass.prototype; + var properties = Object.keys(source); + + if (!Object.keys({ toString: true }).length) + properties.push("toString", "valueOf"); + + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i], value = source[property]; + if (ancestor && Object.isFunction(value) && + value.argumentNames().first() == "$super") { + var method = value; + value = (function(m) { + return function() { return ancestor[m].apply(this, arguments) }; + })(property).wrap(method); + + value.valueOf = method.valueOf.bind(method); + value.toString = method.toString.bind(method); + } + this.prototype[property] = value; + } + + return this; + } +}; + +var Abstract = { }; + +Object.extend = function(destination, source) { + for (var property in source) + destination[property] = source[property]; + return destination; +}; + +Object.extend(Object, { + inspect: function(object) { + try { + if (Object.isUndefined(object)) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : String(object); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch (type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (Object.isElement(object)) return; + + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (!Object.isUndefined(value)) + results.push(property.toJSON() + ': ' + value); + } + + return '{' + results.join(', ') + '}'; + }, + + toQueryString: function(object) { + return $H(object).toQueryString(); + }, + + toHTML: function(object) { + return object && object.toHTML ? object.toHTML() : String.interpret(object); + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({ }, object); + }, + + isElement: function(object) { + return !!(object && object.nodeType == 1); + }, + + isArray: function(object) { + return object != null && typeof object == "object" && + 'splice' in object && 'join' in object; + }, + + isHash: function(object) { + return object instanceof Hash; + }, + + isFunction: function(object) { + return typeof object == "function"; + }, + + isString: function(object) { + return typeof object == "string"; + }, + + isNumber: function(object) { + return typeof object == "number"; + }, + + isUndefined: function(object) { + return typeof object == "undefined"; + } +}); + +Object.extend(Function.prototype, { + argumentNames: function() { + var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1] + .replace(/\s+/g, '').split(','); + return names.length == 1 && !names[0] ? [] : names; + }, + + bind: function() { + if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } + }, + + bindAsEventListener: function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } + }, + + curry: function() { + if (!arguments.length) return this; + var __method = this, args = $A(arguments); + return function() { + return __method.apply(this, args.concat($A(arguments))); + } + }, + + delay: function() { + var __method = this, args = $A(arguments), timeout = args.shift() * 1000; + return window.setTimeout(function() { + return __method.apply(__method, args); + }, timeout); + }, + + defer: function() { + var args = [0.01].concat($A(arguments)); + return this.delay.apply(this, args); + }, + + wrap: function(wrapper) { + var __method = this; + return function() { + return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); + } + }, + + methodize: function() { + if (this._methodized) return this._methodized; + var __method = this; + return this._methodized = function() { + return __method.apply(null, [this].concat($A(arguments))); + }; + } +}); + +Date.prototype.toJSON = function() { + return '"' + this.getUTCFullYear() + '-' + + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + + this.getUTCDate().toPaddedString(2) + 'T' + + this.getUTCHours().toPaddedString(2) + ':' + + this.getUTCMinutes().toPaddedString(2) + ':' + + this.getUTCSeconds().toPaddedString(2) + 'Z"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) { } + } + + return returnValue; + } +}; + +RegExp.prototype.match = RegExp.prototype.test; + +RegExp.escape = function(str) { + return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); +}; + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create({ + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + execute: function() { + this.callback(this); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.execute(); + } finally { + this.currentlyExecuting = false; + } + } + } +}); +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = Object.isUndefined(count) ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return String(this); + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = Object.isUndefined(truncation) ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : String(this); + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = new Element('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return { }; + + return match[1].split(separator || '&').inject({ }, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + return count < 1 ? '' : new Array(count + 1).join(this); + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + isJSON: function() { + var str = this; + if (str.blank()) return false; + str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); + return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || json.isJSON()) return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + }, + + interpolate: function(object, pattern) { + return new Template(this, pattern).evaluate(object); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + }, + unescapeHTML: function() { + return this.stripTags().replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (Object.isFunction(replacement)) return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +}; + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text); + +var Template = Class.create({ + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + if (Object.isFunction(object.toTemplateReplacements)) + object = object.toTemplateReplacements(); + + return this.template.gsub(this.pattern, function(match) { + if (object == null) return ''; + + var before = match[1] || ''; + if (before == '\\') return match[2]; + + var ctx = object, expr = match[3]; + var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; + match = pattern.exec(expr); + if (match == null) return before; + + while (match != null) { + var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; + ctx = ctx[comp]; + if (null == ctx || '' == match[3]) break; + expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); + match = pattern.exec(expr); + } + + return before + String.interpret(ctx); + }); + } +}); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; + +var $break = { }; + +var Enumerable = { + each: function(iterator, context) { + var index = 0; + try { + this._each(function(value) { + iterator.call(context, value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator, context) { + var index = -number, slices = [], array = this.toArray(); + if (number < 1) return array; + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.collect(iterator, context); + }, + + all: function(iterator, context) { + iterator = iterator || Prototype.K; + var result = true; + this.each(function(value, index) { + result = result && !!iterator.call(context, value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator, context) { + iterator = iterator || Prototype.K; + var result = false; + this.each(function(value, index) { + if (result = !!iterator.call(context, value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + this.each(function(value, index) { + results.push(iterator.call(context, value, index)); + }); + return results; + }, + + detect: function(iterator, context) { + var result; + this.each(function(value, index) { + if (iterator.call(context, value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator, context) { + var results = []; + this.each(function(value, index) { + if (iterator.call(context, value, index)) + results.push(value); + }); + return results; + }, + + grep: function(filter, iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + + if (Object.isString(filter)) + filter = new RegExp(filter); + + this.each(function(value, index) { + if (filter.match(value)) + results.push(iterator.call(context, value, index)); + }); + return results; + }, + + include: function(object) { + if (Object.isFunction(this.indexOf)) + if (this.indexOf(object) != -1) return true; + + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = Object.isUndefined(fillWith) ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator, context) { + this.each(function(value, index) { + memo = iterator.call(context, memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator, context) { + iterator = iterator || Prototype.K; + var trues = [], falses = []; + this.each(function(value, index) { + (iterator.call(context, value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator, context) { + var results = []; + this.each(function(value, index) { + if (!iterator.call(context, value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator, context) { + return this.map(function(value, index) { + return { + value: value, + criteria: iterator.call(context, value, index) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (Object.isFunction(args.last())) + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#<Enumerable:' + this.toArray().inspect() + '>'; + } +}; + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + filter: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray, + every: Enumerable.all, + some: Enumerable.any +}); +function $A(iterable) { + if (!iterable) return []; + if (iterable.toArray) return iterable.toArray(); + var length = iterable.length || 0, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; +} + +if (Prototype.Browser.WebKit) { + $A = function(iterable) { + if (!iterable) return []; + // In Safari, only use the `toArray` method if it's not a NodeList. + // A NodeList is a function, has an function `item` property, and a numeric + // `length` property. Adapted from Google Doctype. + if (!(typeof iterable === 'function' && typeof iterable.length === + 'number' && typeof iterable.item === 'function') && iterable.toArray) + return iterable.toArray(); + var length = iterable.length || 0, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; + }; +} + +Array.from = $A; + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(Object.isArray(value) ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + intersect: function(array) { + return this.uniq().findAll(function(item) { + return array.detect(function(value) { return item === value }); + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (!Object.isUndefined(value)) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +// use native browser JS 1.6 implementation if available +if (Object.isFunction(Array.prototype.forEach)) + Array.prototype._each = Array.prototype.forEach; + +if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; +}; + +if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; +}; + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + if (!Object.isString(string)) return []; + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (Object.isArray(arguments[i])) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + }; +} +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator, context) { + $R(0, this, true).each(iterator, context); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +$w('abs round ceil floor').each(function(method){ + Number.prototype[method] = Math[method].methodize(); +}); +function $H(object) { + return new Hash(object); +}; + +var Hash = Class.create(Enumerable, (function() { + + function toQueryPair(key, value) { + if (Object.isUndefined(value)) return key; + return key + '=' + encodeURIComponent(String.interpret(value)); + } + + return { + initialize: function(object) { + this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); + }, + + _each: function(iterator) { + for (var key in this._object) { + var value = this._object[key], pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + set: function(key, value) { + return this._object[key] = value; + }, + + get: function(key) { + // simulating poorly supported hasOwnProperty + if (this._object[key] !== Object.prototype[key]) + return this._object[key]; + }, + + unset: function(key) { + var value = this._object[key]; + delete this._object[key]; + return value; + }, + + toObject: function() { + return Object.clone(this._object); + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + index: function(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + }, + + merge: function(object) { + return this.clone().update(object); + }, + + update: function(object) { + return new Hash(object).inject(this, function(result, pair) { + result.set(pair.key, pair.value); + return result; + }); + }, + + toQueryString: function() { + return this.inject([], function(results, pair) { + var key = encodeURIComponent(pair.key), values = pair.value; + + if (values && typeof values == 'object') { + if (Object.isArray(values)) + return results.concat(values.map(toQueryPair.curry(key))); + } else results.push(toQueryPair(key, values)); + return results; + }).join('&'); + }, + + inspect: function() { + return '#<Hash:{' + this.map(function(pair) { + return pair.map(Object.inspect).join(': '); + }).join(', ') + '}>'; + }, + + toJSON: function() { + return Object.toJSON(this.toObject()); + }, + + clone: function() { + return new Hash(this); + } + } +})()); + +Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; +Hash.from = $H; +var ObjectRange = Class.create(Enumerable, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +}; + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +}; + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (Object.isFunction(responder[callback])) { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) { } + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { Ajax.activeRequestCount++ }, + onComplete: function() { Ajax.activeRequestCount-- } +}); + +Ajax.Base = Class.create({ + initialize: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '', + evalJSON: true, + evalJS: true + }; + Object.extend(this.options, options || { }); + + this.options.method = this.options.method.toLowerCase(); + + if (Object.isString(this.options.parameters)) + this.options.parameters = this.options.parameters.toQueryParams(); + else if (Object.isHash(this.options.parameters)) + this.options.parameters = this.options.parameters.toObject(); + } +}); + +Ajax.Request = Class.create(Ajax.Base, { + _complete: false, + + initialize: function($super, url, options) { + $super(options); + this.transport = Ajax.getTransport(); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Object.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + var response = new Ajax.Response(this); + if (this.options.onCreate) this.options.onCreate(response); + Ajax.Responders.dispatch('onCreate', this, response); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (Object.isFunction(extras.push)) + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + var status = this.getStatus(); + return !status || (status >= 200 && status < 300); + }, + + getStatus: function() { + try { + return this.transport.status || 0; + } catch (e) { return 0 } + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + response.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + var contentType = response.getHeader('Content-type'); + if (this.options.evalJS == 'force' + || (this.options.evalJS && this.isSameOrigin() && contentType + && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); + Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + isSameOrigin: function() { + var m = this.url.match(/^\s*https?:\/\/[^\/]*/); + return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ + protocol: location.protocol, + domain: document.domain, + port: location.port ? ':' + location.port : '' + })); + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name) || null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Response = Class.create({ + initialize: function(request){ + this.request = request; + var transport = this.transport = request.transport, + readyState = this.readyState = transport.readyState; + + if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { + this.status = this.getStatus(); + this.statusText = this.getStatusText(); + this.responseText = String.interpret(transport.responseText); + this.headerJSON = this._getHeaderJSON(); + } + + if(readyState == 4) { + var xml = transport.responseXML; + this.responseXML = Object.isUndefined(xml) ? null : xml; + this.responseJSON = this._getResponseJSON(); + } + }, + + status: 0, + statusText: '', + + getStatus: Ajax.Request.prototype.getStatus, + + getStatusText: function() { + try { + return this.transport.statusText || ''; + } catch (e) { return '' } + }, + + getHeader: Ajax.Request.prototype.getHeader, + + getAllHeaders: function() { + try { + return this.getAllResponseHeaders(); + } catch (e) { return null } + }, + + getResponseHeader: function(name) { + return this.transport.getResponseHeader(name); + }, + + getAllResponseHeaders: function() { + return this.transport.getAllResponseHeaders(); + }, + + _getHeaderJSON: function() { + var json = this.getHeader('X-JSON'); + if (!json) return null; + json = decodeURIComponent(escape(json)); + try { + return json.evalJSON(this.request.options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + }, + + _getResponseJSON: function() { + var options = this.request.options; + if (!options.evalJSON || (options.evalJSON != 'force' && + !(this.getHeader('Content-type') || '').include('application/json')) || + this.responseText.blank()) + return null; + try { + return this.responseText.evalJSON(options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + } +}); + +Ajax.Updater = Class.create(Ajax.Request, { + initialize: function($super, container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + }; + + options = Object.clone(options); + var onComplete = options.onComplete; + options.onComplete = (function(response, json) { + this.updateContent(response.responseText); + if (Object.isFunction(onComplete)) onComplete(response, json); + }).bind(this); + + $super(url, options); + }, + + updateContent: function(responseText) { + var receiver = this.container[this.success() ? 'success' : 'failure'], + options = this.options; + + if (!options.evalScripts) responseText = responseText.stripScripts(); + + if (receiver = $(receiver)) { + if (options.insertion) { + if (Object.isString(options.insertion)) { + var insertion = { }; insertion[options.insertion] = responseText; + receiver.insert(insertion); + } + else options.insertion(receiver, responseText); + } + else receiver.update(responseText); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { + initialize: function($super, container, url, options) { + $super(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = { }; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(response) { + if (this.options.decay) { + this.decay = (response.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = response.responseText; + } + this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (Object.isString(element)) + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(Element.extend(query.snapshotItem(i))); + return results; + }; +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Node) var Node = { }; + +if (!Node.ELEMENT_NODE) { + // DOM level 2 ECMAScript Language Binding + Object.extend(Node, { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + ENTITY_REFERENCE_NODE: 5, + ENTITY_NODE: 6, + PROCESSING_INSTRUCTION_NODE: 7, + COMMENT_NODE: 8, + DOCUMENT_NODE: 9, + DOCUMENT_TYPE_NODE: 10, + DOCUMENT_FRAGMENT_NODE: 11, + NOTATION_NODE: 12 + }); +} + +(function() { + var element = this.Element; + this.Element = function(tagName, attributes) { + attributes = attributes || { }; + tagName = tagName.toLowerCase(); + var cache = Element.cache; + if (Prototype.Browser.IE && attributes.name) { + tagName = '<' + tagName + ' name="' + attributes.name + '">'; + delete attributes.name; + return Element.writeAttribute(document.createElement(tagName), attributes); + } + if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); + return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); + }; + Object.extend(this.Element, element || { }); + if (element) this.Element.prototype = element.prototype; +}).call(window); + +Element.cache = { }; + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + hide: function(element) { + element = $(element); + element.style.display = 'none'; + return element; + }, + + show: function(element) { + element = $(element); + element.style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: function(element, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) return element.update().insert(content); + content = Object.toHTML(content); + element.innerHTML = content.stripScripts(); + content.evalScripts.bind(content).defer(); + return element; + }, + + replace: function(element, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + else if (!Object.isElement(content)) { + content = Object.toHTML(content); + var range = element.ownerDocument.createRange(); + range.selectNode(element); + content.evalScripts.bind(content).defer(); + content = range.createContextualFragment(content.stripScripts()); + } + element.parentNode.replaceChild(content, element); + return element; + }, + + insert: function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = {bottom:insertions}; + + var content, insert, tagName, childNodes; + + for (var position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + insert = Element._insertionTranslations[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + insert(element, content); + continue; + } + + content = Object.toHTML(content); + + tagName = ((position == 'before' || position == 'after') + ? element.parentNode : element).tagName.toUpperCase(); + + childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + + if (position == 'top' || position == 'after') childNodes.reverse(); + childNodes.each(insert.curry(element)); + + content.evalScripts.bind(content).defer(); + } + + return element; + }, + + wrap: function(element, wrapper, attributes) { + element = $(element); + if (Object.isElement(wrapper)) + $(wrapper).writeAttribute(attributes || { }); + else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); + else wrapper = new Element('div', wrapper); + if (element.parentNode) + element.parentNode.replaceChild(wrapper, element); + wrapper.appendChild(element); + return wrapper; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $(element).select("*"); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return element.previousSiblings().reverse().concat(element.nextSiblings()); + }, + + match: function(element, selector) { + if (Object.isString(selector)) + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = element.ancestors(); + return Object.isNumber(expression) ? ancestors[expression] : + Selector.findElement(ancestors, expression, index); + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + return Object.isNumber(expression) ? element.descendants()[expression] : + Element.select(element, expression)[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = element.previousSiblings(); + return Object.isNumber(expression) ? previousSiblings[expression] : + Selector.findElement(previousSiblings, expression, index); + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = element.nextSiblings(); + return Object.isNumber(expression) ? nextSiblings[expression] : + Selector.findElement(nextSiblings, expression, index); + }, + + select: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + adjacent: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element.parentNode, args).without(element); + }, + + identify: function(element) { + element = $(element); + var id = element.readAttribute('id'), self = arguments.callee; + if (id) return id; + do { id = 'anonymous_element_' + self.counter++ } while ($(id)); + element.writeAttribute('id', id); + return id; + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + var t = Element._attributeTranslations.read; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + if (name.include(':')) { + return (!element.attributes || !element.attributes[name]) ? null : + element.attributes[name].value; + } + } + return element.getAttribute(name); + }, + + writeAttribute: function(element, name, value) { + element = $(element); + var attributes = { }, t = Element._attributeTranslations.write; + + if (typeof name == 'object') attributes = name; + else attributes[name] = Object.isUndefined(value) ? true : value; + + for (var attr in attributes) { + name = t.names[attr] || attr; + value = attributes[attr]; + if (t.values[attr]) name = t.values[attr](element, value); + if (value === false || value === null) + element.removeAttribute(name); + else if (value === true) + element.setAttribute(name, name); + else element.setAttribute(name, value); + } + return element; + }, + + getHeight: function(element) { + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + return (elementClassName.length > 0 && (elementClassName == className || + new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + if (!element.hasClassName(className)) + element.className += (element.className ? ' ' : '') + className; + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + element.className = element.className.replace( + new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + return element[element.hasClassName(className) ? + 'removeClassName' : 'addClassName'](className); + }, + + // removes whitespace-only text node children + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + + if (element.compareDocumentPosition) + return (element.compareDocumentPosition(ancestor) & 8) === 8; + + if (ancestor.contains) + return ancestor.contains(element) && ancestor !== element; + + while (element = element.parentNode) + if (element == ancestor) return true; + + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = element.cumulativeOffset(); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + style = style == 'float' ? 'cssFloat' : style.camelize(); + var value = element.style[style]; + if (!value || value == 'auto') { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } + if (style == 'opacity') return value ? parseFloat(value) : 1.0; + return value == 'auto' ? null : value; + }, + + getOpacity: function(element) { + return $(element).getStyle('opacity'); + }, + + setStyle: function(element, styles) { + element = $(element); + var elementStyle = element.style, match; + if (Object.isString(styles)) { + element.style.cssText += ';' + styles; + return styles.include('opacity') ? + element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; + } + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]); + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : + property] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = element.getStyle('display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + // All *Width and *Height properties give 0 on elements with display none, + // so enable the element temporarily + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + els.position = 'absolute'; + els.display = 'block'; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = originalDisplay; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + // Opera returns the offset relative to the positioning context, when an + // element is position relative but top and left have not been defined + if (Prototype.Browser.Opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = Element.getStyle(element, 'overflow') || 'auto'; + if (element._overflow !== 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if (element.tagName.toUpperCase() == 'BODY') break; + var p = Element.getStyle(element, 'position'); + if (p !== 'static') break; + } + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + absolutize: function(element) { + element = $(element); + if (element.getStyle('position') == 'absolute') return element; + // Position.prepare(); // To be done manually by Scripty when it needs it. + + var offsets = element.positionedOffset(); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + return element; + }, + + relativize: function(element) { + element = $(element); + if (element.getStyle('position') == 'relative') return element; + // Position.prepare(); // To be done manually by Scripty when it needs it. + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + return element; + }, + + cumulativeScrollOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + getOffsetParent: function(element) { + if (element.offsetParent) return $(element.offsetParent); + if (element == document.body) return $(element); + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return $(element); + + return $(document.body); + }, + + viewportOffset: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body && + Element.getStyle(element, 'position') == 'absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return Element._returnOffset(valueL, valueT); + }, + + clonePosition: function(element, source) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || { }); + + // find page position of source + source = $(source); + var p = source.viewportOffset(); + + // find coordinate system to use + element = $(element); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(element, 'position') == 'absolute') { + parent = element.getOffsetParent(); + delta = parent.viewportOffset(); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if (options.setWidth) element.style.width = source.offsetWidth + 'px'; + if (options.setHeight) element.style.height = source.offsetHeight + 'px'; + return element; + } +}; + +Element.Methods.identify.counter = 1; + +Object.extend(Element.Methods, { + getElementsBySelector: Element.Methods.select, + childElements: Element.Methods.immediateDescendants +}); + +Element._attributeTranslations = { + write: { + names: { + className: 'class', + htmlFor: 'for' + }, + values: { } + } +}; + +if (Prototype.Browser.Opera) { + Element.Methods.getStyle = Element.Methods.getStyle.wrap( + function(proceed, element, style) { + switch (style) { + case 'left': case 'top': case 'right': case 'bottom': + if (proceed(element, 'position') === 'static') return null; + case 'height': case 'width': + // returns '0px' for hidden elements; we want it to return null + if (!Element.visible(element)) return null; + + // returns the border-box dimensions rather than the content-box + // dimensions, so we subtract padding and borders from the value + var dim = parseInt(proceed(element, style), 10); + + if (dim !== element['offset' + style.capitalize()]) + return dim + 'px'; + + var properties; + if (style === 'height') { + properties = ['border-top-width', 'padding-top', + 'padding-bottom', 'border-bottom-width']; + } + else { + properties = ['border-left-width', 'padding-left', + 'padding-right', 'border-right-width']; + } + return properties.inject(dim, function(memo, property) { + var val = proceed(element, property); + return val === null ? memo : memo - parseInt(val, 10); + }) + 'px'; + default: return proceed(element, style); + } + } + ); + + Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( + function(proceed, element, attribute) { + if (attribute === 'title') return element.title; + return proceed(element, attribute); + } + ); +} + +else if (Prototype.Browser.IE) { + // IE doesn't report offsets correctly for static elements, so we change them + // to "relative" to get the values, then change them back. + Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( + function(proceed, element) { + element = $(element); + // IE throws an error if element is not in document + try { element.offsetParent } + catch(e) { return $(document.body) } + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + + $w('positionedOffset viewportOffset').each(function(method) { + Element.Methods[method] = Element.Methods[method].wrap( + function(proceed, element) { + element = $(element); + try { element.offsetParent } + catch(e) { return Element._returnOffset(0,0) } + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + // Trigger hasLayout on the offset parent so that IE6 reports + // accurate offsetTop and offsetLeft values for position: fixed. + var offsetParent = element.getOffsetParent(); + if (offsetParent && offsetParent.getStyle('position') === 'fixed') + offsetParent.setStyle({ zoom: 1 }); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + }); + + Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( + function(proceed, element) { + try { element.offsetParent } + catch(e) { return Element._returnOffset(0,0) } + return proceed(element); + } + ); + + Element.Methods.getStyle = function(element, style) { + element = $(element); + style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); + var value = element.style[style]; + if (!value && element.currentStyle) value = element.currentStyle[style]; + + if (style == 'opacity') { + if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if (value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + + if (value == 'auto') { + if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) + return element['offset' + style.capitalize()] + 'px'; + return null; + } + return value; + }; + + Element.Methods.setOpacity = function(element, value) { + function stripAlpha(filter){ + return filter.replace(/alpha\([^\)]*\)/gi,''); + } + element = $(element); + var currentStyle = element.currentStyle; + if ((currentStyle && !currentStyle.hasLayout) || + (!currentStyle && element.style.zoom == 'normal')) + element.style.zoom = 1; + + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + (filter = stripAlpha(filter)) ? + style.filter = filter : style.removeAttribute('filter'); + return element; + } else if (value < 0.00001) value = 0; + style.filter = stripAlpha(filter) + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + Element._attributeTranslations = { + read: { + names: { + 'class': 'className', + 'for': 'htmlFor' + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _getAttrNode: function(element, attribute) { + var node = element.getAttributeNode(attribute); + return node ? node.value : ""; + }, + _getEv: function(element, attribute) { + attribute = element.getAttribute(attribute); + return attribute ? attribute.toString().slice(23, -2) : null; + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + return element.title; + } + } + } + }; + + Element._attributeTranslations.write = { + names: Object.extend({ + cellpadding: 'cellPadding', + cellspacing: 'cellSpacing' + }, Element._attributeTranslations.read.names), + values: { + checked: function(element, value) { + element.checked = !!value; + }, + + style: function(element, value) { + element.style.cssText = value ? value : ''; + } + } + }; + + Element._attributeTranslations.has = {}; + + $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + + 'encType maxLength readOnly longDesc frameBorder').each(function(attr) { + Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; + Element._attributeTranslations.has[attr.toLowerCase()] = attr; + }); + + (function(v) { + Object.extend(v, { + href: v._getAttr, + src: v._getAttr, + type: v._getAttr, + action: v._getAttrNode, + disabled: v._flag, + checked: v._flag, + readonly: v._flag, + multiple: v._flag, + onload: v._getEv, + onunload: v._getEv, + onclick: v._getEv, + ondblclick: v._getEv, + onmousedown: v._getEv, + onmouseup: v._getEv, + onmouseover: v._getEv, + onmousemove: v._getEv, + onmouseout: v._getEv, + onfocus: v._getEv, + onblur: v._getEv, + onkeypress: v._getEv, + onkeydown: v._getEv, + onkeyup: v._getEv, + onsubmit: v._getEv, + onreset: v._getEv, + onselect: v._getEv, + onchange: v._getEv + }); + })(Element._attributeTranslations.read.values); +} + +else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +else if (Prototype.Browser.WebKit) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + + if (value == 1) + if(element.tagName.toUpperCase() == 'IMG' && element.width) { + element.width++; element.width--; + } else try { + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch (e) { } + + return element; + }; + + // Safari returns margins on body which is incorrect if the child is absolutely + // positioned. For performance reasons, redefine Element#cumulativeOffset for + // KHTML/WebKit only. + Element.Methods.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return Element._returnOffset(valueL, valueT); + }; +} + +if (Prototype.Browser.IE || Prototype.Browser.Opera) { + // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements + Element.Methods.update = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) return element.update().insert(content); + + content = Object.toHTML(content); + var tagName = element.tagName.toUpperCase(); + + if (tagName in Element._insertionTranslations.tags) { + $A(element.childNodes).each(function(node) { element.removeChild(node) }); + Element._getContentFromAnonymousElement(tagName, content.stripScripts()) + .each(function(node) { element.appendChild(node) }); + } + else element.innerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +if ('outerHTML' in document.createElement('div')) { + Element.Methods.replace = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + element.parentNode.replaceChild(content, element); + return element; + } + + content = Object.toHTML(content); + var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); + + if (Element._insertionTranslations.tags[tagName]) { + var nextSibling = element.next(); + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + parent.removeChild(element); + if (nextSibling) + fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); + else + fragments.each(function(node) { parent.appendChild(node) }); + } + else element.outerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +Element._returnOffset = function(l, t) { + var result = [l, t]; + result.left = l; + result.top = t; + return result; +}; + +Element._getContentFromAnonymousElement = function(tagName, html) { + var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; + if (t) { + div.innerHTML = t[0] + html + t[1]; + t[2].times(function() { div = div.firstChild }); + } else div.innerHTML = html; + return $A(div.childNodes); +}; + +Element._insertionTranslations = { + before: function(element, node) { + element.parentNode.insertBefore(node, element); + }, + top: function(element, node) { + element.insertBefore(node, element.firstChild); + }, + bottom: function(element, node) { + element.appendChild(node); + }, + after: function(element, node) { + element.parentNode.insertBefore(node, element.nextSibling); + }, + tags: { + TABLE: ['<table>', '</table>', 1], + TBODY: ['<table><tbody>', '</tbody></table>', 2], + TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3], + TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4], + SELECT: ['<select>', '</select>', 1] + } +}; + +(function() { + Object.extend(this.tags, { + THEAD: this.tags.TBODY, + TFOOT: this.tags.TBODY, + TH: this.tags.TD + }); +}).call(Element._insertionTranslations); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + attribute = Element._attributeTranslations.has[attribute] || attribute; + var node = $(element).getAttributeNode(attribute); + return !!(node && node.specified); + } +}; + +Element.Methods.ByTag = { }; + +Object.extend(Element, Element.Methods); + +if (!Prototype.BrowserFeatures.ElementExtensions && + document.createElement('div')['__proto__']) { + window.HTMLElement = { }; + window.HTMLElement.prototype = document.createElement('div')['__proto__']; + Prototype.BrowserFeatures.ElementExtensions = true; +} + +Element.extend = (function() { + if (Prototype.BrowserFeatures.SpecificElementExtensions) + return Prototype.K; + + var Methods = { }, ByTag = Element.Methods.ByTag; + + var extend = Object.extend(function(element) { + if (!element || element._extendedByPrototype || + element.nodeType != 1 || element == window) return element; + + var methods = Object.clone(Methods), + tagName = element.tagName.toUpperCase(), property, value; + + // extend methods for specific tags + if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); + + for (property in methods) { + value = methods[property]; + if (Object.isFunction(value) && !(property in element)) + element[property] = value.methodize(); + } + + element._extendedByPrototype = Prototype.emptyFunction; + return element; + + }, { + refresh: function() { + // extend methods for all tags (Safari doesn't need this) + if (!Prototype.BrowserFeatures.ElementExtensions) { + Object.extend(Methods, Element.Methods); + Object.extend(Methods, Element.Methods.Simulated); + } + } + }); + + extend.refresh(); + return extend; +})(); + +Element.hasAttribute = function(element, attribute) { + if (element.hasAttribute) return element.hasAttribute(attribute); + return Element.Methods.Simulated.hasAttribute(element, attribute); +}; + +Element.addMethods = function(methods) { + var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + + if (!methods) { + Object.extend(Form, Form.Methods); + Object.extend(Form.Element, Form.Element.Methods); + Object.extend(Element.Methods.ByTag, { + "FORM": Object.clone(Form.Methods), + "INPUT": Object.clone(Form.Element.Methods), + "SELECT": Object.clone(Form.Element.Methods), + "TEXTAREA": Object.clone(Form.Element.Methods) + }); + } + + if (arguments.length == 2) { + var tagName = methods; + methods = arguments[1]; + } + + if (!tagName) Object.extend(Element.Methods, methods || { }); + else { + if (Object.isArray(tagName)) tagName.each(extend); + else extend(tagName); + } + + function extend(tagName) { + tagName = tagName.toUpperCase(); + if (!Element.Methods.ByTag[tagName]) + Element.Methods.ByTag[tagName] = { }; + Object.extend(Element.Methods.ByTag[tagName], methods); + } + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + for (var property in methods) { + var value = methods[property]; + if (!Object.isFunction(value)) continue; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = value.methodize(); + } + } + + function findDOMClass(tagName) { + var klass; + var trans = { + "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", + "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", + "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", + "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", + "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": + "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": + "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": + "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": + "FrameSet", "IFRAME": "IFrame" + }; + if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName.capitalize() + 'Element'; + if (window[klass]) return window[klass]; + + window[klass] = { }; + window[klass].prototype = document.createElement(tagName)['__proto__']; + return window[klass]; + } + + if (F.ElementExtensions) { + copy(Element.Methods, HTMLElement.prototype); + copy(Element.Methods.Simulated, HTMLElement.prototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (Object.isUndefined(klass)) continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; + + if (Element.extend.refresh) Element.extend.refresh(); + Element.cache = { }; +}; + +document.viewport = { + getDimensions: function() { + var dimensions = { }, B = Prototype.Browser; + $w('width height').each(function(d) { + var D = d.capitalize(); + if (B.WebKit && !document.evaluate) { + // Safari <3.0 needs self.innerWidth/Height + dimensions[d] = self['inner' + D]; + } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) { + // Opera <9.5 needs document.body.clientWidth/Height + dimensions[d] = document.body['client' + D] + } else { + dimensions[d] = document.documentElement['client' + D]; + } + }); + return dimensions; + }, + + getWidth: function() { + return this.getDimensions().width; + }, + + getHeight: function() { + return this.getDimensions().height; + }, + + getScrollOffsets: function() { + return Element._returnOffset( + window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); + } +}; +/* Portions of the Selector class are derived from Jack Slocum's DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create({ + initialize: function(expression) { + this.expression = expression.strip(); + + if (this.shouldUseSelectorsAPI()) { + this.mode = 'selectorsAPI'; + } else if (this.shouldUseXPath()) { + this.mode = 'xpath'; + this.compileXPathMatcher(); + } else { + this.mode = "normal"; + this.compileMatcher(); + } + + }, + + shouldUseXPath: function() { + if (!Prototype.BrowserFeatures.XPath) return false; + + var e = this.expression; + + // Safari 3 chokes on :*-of-type and :empty + if (Prototype.Browser.WebKit && + (e.include("-of-type") || e.include(":empty"))) + return false; + + // XPath can't do namespaced attributes, nor can it read + // the "checked" property from DOM nodes + if ((/(\[[\w-]*?:|:checked)/).test(e)) + return false; + + return true; + }, + + shouldUseSelectorsAPI: function() { + if (!Prototype.BrowserFeatures.SelectorsAPI) return false; + + if (!Selector._div) Selector._div = new Element('div'); + + // Make sure the browser treats the selector as valid. Test on an + // isolated element to minimize cost of this check. + try { + Selector._div.querySelector(this.expression); + } catch(e) { + return false; + } + + return true; + }, + + compileMatcher: function() { + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; + return; + } + + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + var e = this.expression, results; + + switch (this.mode) { + case 'selectorsAPI': + // querySelectorAll queries document-wide, then filters to descendants + // of the context element. That's not what we want. + // Add an explicit context to the selector if necessary. + if (root !== document) { + var oldId = root.id, id = $(root).identify(); + e = "#" + id + " " + e; + } + + results = $A(root.querySelectorAll(e)).map(Element.extend); + root.id = oldId; + + return results; + case 'xpath': + return document._getElementsByXPath(this.xpath, root); + default: + return this.matcher(root); + } + }, + + match: function(element) { + this.tokens = []; + + var e = this.expression, ps = Selector.patterns, as = Selector.assertions; + var le, p, m; + + while (e && le !== e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + // use the Selector.assertions methods unless the selector + // is too complex. + if (as[i]) { + this.tokens.push([i, Object.clone(m)]); + e = e.replace(m[0], ''); + } else { + // reluctantly do a document-wide search + // and look for a match in the array + return this.findElements(document).include(element); + } + } + } + } + + var match = true, name, matches; + for (var i = 0, token; token = this.tokens[i]; i++) { + name = token[0], matches = token[1]; + if (!Selector.assertions[name](element, matches)) { + match = false; break; + } + } + + return match; + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#<Selector:" + this.expression.inspect() + ">"; + } +}); + +Object.extend(Selector, { + _cache: { }, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: function(m) { + m[1] = m[1].toLowerCase(); + return new Template("[@#{1}]").evaluate(m); + }, + attr: function(m) { + m[1] = m[1].toLowerCase(); + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (Object.isFunction(h)) return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0)]", + 'checked': "[@checked]", + 'disabled': "[(@disabled) and (@type!='hidden')]", + 'enabled': "[not(@disabled) and (@type!='hidden')]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: +/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/, + attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + // for Selector.match and Element#match + assertions: { + tagName: function(element, matches) { + return matches[1].toUpperCase() == element.tagName.toUpperCase(); + }, + + className: function(element, matches) { + return Element.hasClassName(element, matches[1]); + }, + + id: function(element, matches) { + return element.id === matches[1]; + }, + + attrPresence: function(element, matches) { + return Element.hasAttribute(element, matches[1]); + }, + + attr: function(element, matches) { + var nodeValue = Element.readAttribute(element, matches[1]); + return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); + } + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + var _true = Prototype.emptyFunction; + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = _true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._countedByPrototype = Prototype.emptyFunction; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + var node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._countedByPrototype) { + n._countedByPrototype = Prototype.emptyFunction; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + var uTagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() === uTagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!targetNode) return []; + if (!nodes && root == document) return [targetNode]; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._countedByPrototype) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || node.firstChild) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._countedByPrototype) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled && (!node.type || node.type !== 'hidden')) + results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, + '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, + '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + + '-').include('-' + (v || "").toUpperCase() + '-'); } + }, + + split: function(expression) { + var expressions = []; + expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + return expressions; + }, + + matchElements: function(elements, expression) { + var matches = $$(expression), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._countedByPrototype) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (Object.isNumber(expression)) { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + expressions = Selector.split(expressions.join(',')); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +if (Prototype.Browser.IE) { + Object.extend(Selector.handlers, { + // IE returns comment nodes on getElementsByTagName("*"). + // Filter them out. + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + if (node.tagName !== "!") a.push(node); + return a; + }, + + // IE improperly serializes _countedByPrototype in (inner|outer)HTML. + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node.removeAttribute('_countedByPrototype'); + return nodes; + } + }); +} + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, options) { + if (typeof options != 'object') options = { hash: !!options }; + else if (Object.isUndefined(options.hash)) options.hash = true; + var key, value, submitted = false, submit = options.submit; + + var data = elements.inject({ }, function(result, element) { + if (!element.disabled && element.name) { + key = element.name; value = $(element).getValue(); + if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && + submit !== false && (!submit || key == submit) && (submitted = true)))) { + if (key in result) { + // a key is already present; construct an array of values + if (!Object.isArray(result[key])) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return options.hash ? data : Object.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, options) { + return Form.serializeElements(Form.getElements(form), options); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + var elements = $(form).getElements().findAll(function(element) { + return 'hidden' != element.type && !element.disabled; + }); + var firstByIndex = elements.findAll(function(element) { + return element.hasAttribute('tabIndex') && element.tabIndex >= 0; + }).sortBy(function(element) { return element.tabIndex }).first(); + + return firstByIndex ? firstByIndex : elements.find(function(element) { + return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || { }); + + var params = options.parameters, action = form.readAttribute('action') || ''; + if (action.blank()) action = window.location.href; + options.parameters = form.serialize(true); + + if (params) { + if (Object.isString(params)) params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(action, options); + } +}; + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +}; + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = { }; + pair[element.name] = value; + return Object.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + setValue: function(element, value) { + element = $(element); + var method = element.tagName.toLowerCase(); + Form.Element.Serializers[method](element, value); + return element; + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !['button', 'reset', 'submit'].include(element.type))) + element.select(); + } catch (e) { } + return element; + }, + + disable: function(element) { + element = $(element); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +}; + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element, value) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element, value); + default: + return Form.Element.Serializers.textarea(element, value); + } + }, + + inputSelector: function(element, value) { + if (Object.isUndefined(value)) return element.checked ? element.value : null; + else element.checked = !!value; + }, + + textarea: function(element, value) { + if (Object.isUndefined(value)) return element.value; + else element.value = value; + }, + + select: function(element, value) { + if (Object.isUndefined(value)) + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + else { + var opt, currentValue, single = !Object.isArray(value); + for (var i = 0, length = element.length; i < length; i++) { + opt = element.options[i]; + currentValue = this.optionValue(opt); + if (single) { + if (currentValue == value) { + opt.selected = true; + return; + } + } + else opt.selected = value.include(currentValue); + } + } + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +}; + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = Class.create(PeriodicalExecuter, { + initialize: function($super, element, frequency, callback) { + $super(callback, frequency); + this.element = $(element); + this.lastValue = this.getValue(); + }, + + execute: function() { + var value = this.getValue(); + if (Object.isString(this.lastValue) && Object.isString(value) ? + this.lastValue != value : String(this.lastValue) != String(value)) { + this.callback(this.element, value); + this.lastValue = value; + } + } +}); + +Form.Element.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = Class.create({ + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback, this); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +}); + +Form.Element.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) var Event = { }; + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + KEY_INSERT: 45, + + cache: { }, + + relatedTarget: function(event) { + var element; + switch(event.type) { + case 'mouseover': element = event.fromElement; break; + case 'mouseout': element = event.toElement; break; + default: return null; + } + return Element.extend(element); + } +}); + +Event.Methods = (function() { + var isButton; + + if (Prototype.Browser.IE) { + var buttonMap = { 0: 1, 1: 4, 2: 2 }; + isButton = function(event, code) { + return event.button == buttonMap[code]; + }; + + } else if (Prototype.Browser.WebKit) { + isButton = function(event, code) { + switch (code) { + case 0: return event.which == 1 && !event.metaKey; + case 1: return event.which == 1 && event.metaKey; + default: return false; + } + }; + + } else { + isButton = function(event, code) { + return event.which ? (event.which === code + 1) : (event.button === code); + }; + } + + return { + isLeftClick: function(event) { return isButton(event, 0) }, + isMiddleClick: function(event) { return isButton(event, 1) }, + isRightClick: function(event) { return isButton(event, 2) }, + + element: function(event) { + event = Event.extend(event); + + var node = event.target, + type = event.type, + currentTarget = event.currentTarget; + + if (currentTarget && currentTarget.tagName) { + // Firefox screws up the "click" event when moving between radio buttons + // via arrow keys. It also screws up the "load" and "error" events on images, + // reporting the document as the target instead of the original image. + if (type === 'load' || type === 'error' || + (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' + && currentTarget.type === 'radio')) + node = currentTarget; + } + if (node.nodeType == Node.TEXT_NODE) node = node.parentNode; + return Element.extend(node); + }, + + findElement: function(event, expression) { + var element = Event.element(event); + if (!expression) return element; + var elements = [element].concat(element.ancestors()); + return Selector.findElement(elements, expression, 0); + }, + + pointer: function(event) { + var docElement = document.documentElement, + body = document.body || { scrollLeft: 0, scrollTop: 0 }; + return { + x: event.pageX || (event.clientX + + (docElement.scrollLeft || body.scrollLeft) - + (docElement.clientLeft || 0)), + y: event.pageY || (event.clientY + + (docElement.scrollTop || body.scrollTop) - + (docElement.clientTop || 0)) + }; + }, + + pointerX: function(event) { return Event.pointer(event).x }, + pointerY: function(event) { return Event.pointer(event).y }, + + stop: function(event) { + Event.extend(event); + event.preventDefault(); + event.stopPropagation(); + event.stopped = true; + } + }; +})(); + +Event.extend = (function() { + var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { + m[name] = Event.Methods[name].methodize(); + return m; + }); + + if (Prototype.Browser.IE) { + Object.extend(methods, { + stopPropagation: function() { this.cancelBubble = true }, + preventDefault: function() { this.returnValue = false }, + inspect: function() { return "[object Event]" } + }); + + return function(event) { + if (!event) return false; + if (event._extendedByPrototype) return event; + + event._extendedByPrototype = Prototype.emptyFunction; + var pointer = Event.pointer(event); + Object.extend(event, { + target: event.srcElement, + relatedTarget: Event.relatedTarget(event), + pageX: pointer.x, + pageY: pointer.y + }); + return Object.extend(event, methods); + }; + + } else { + Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__']; + Object.extend(Event.prototype, methods); + return Prototype.K; + } +})(); + +Object.extend(Event, (function() { + var cache = Event.cache; + + function getEventID(element) { + if (element._prototypeEventID) return element._prototypeEventID[0]; + arguments.callee.id = arguments.callee.id || 1; + return element._prototypeEventID = [++arguments.callee.id]; + } + + function getDOMEventName(eventName) { + if (eventName && eventName.include(':')) return "dataavailable"; + return eventName; + } + + function getCacheForID(id) { + return cache[id] = cache[id] || { }; + } + + function getWrappersForEventName(id, eventName) { + var c = getCacheForID(id); + return c[eventName] = c[eventName] || []; + } + + function createWrapper(element, eventName, handler) { + var id = getEventID(element); + var c = getWrappersForEventName(id, eventName); + if (c.pluck("handler").include(handler)) return false; + + var wrapper = function(event) { + if (!Event || !Event.extend || + (event.eventName && event.eventName != eventName)) + return false; + + Event.extend(event); + handler.call(element, event); + }; + + wrapper.handler = handler; + c.push(wrapper); + return wrapper; + } + + function findWrapper(id, eventName, handler) { + var c = getWrappersForEventName(id, eventName); + return c.find(function(wrapper) { return wrapper.handler == handler }); + } + + function destroyWrapper(id, eventName, handler) { + var c = getCacheForID(id); + if (!c[eventName]) return false; + c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); + } + + function destroyCache() { + for (var id in cache) + for (var eventName in cache[id]) + cache[id][eventName] = null; + } + + + // Internet Explorer needs to remove event handlers on page unload + // in order to avoid memory leaks. + if (window.attachEvent) { + window.attachEvent("onunload", destroyCache); + } + + // Safari has a dummy event handler on page unload so that it won't + // use its bfcache. Safari <= 3.1 has an issue with restoring the "document" + // object when page is returned to via the back button using its bfcache. + if (Prototype.Browser.WebKit) { + window.addEventListener('unload', Prototype.emptyFunction, false); + } + + return { + observe: function(element, eventName, handler) { + element = $(element); + var name = getDOMEventName(eventName); + + var wrapper = createWrapper(element, eventName, handler); + if (!wrapper) return element; + + if (element.addEventListener) { + element.addEventListener(name, wrapper, false); + } else { + element.attachEvent("on" + name, wrapper); + } + + return element; + }, + + stopObserving: function(element, eventName, handler) { + element = $(element); + var id = getEventID(element), name = getDOMEventName(eventName); + + if (!handler && eventName) { + getWrappersForEventName(id, eventName).each(function(wrapper) { + element.stopObserving(eventName, wrapper.handler); + }); + return element; + + } else if (!eventName) { + Object.keys(getCacheForID(id)).each(function(eventName) { + element.stopObserving(eventName); + }); + return element; + } + + var wrapper = findWrapper(id, eventName, handler); + if (!wrapper) return element; + + if (element.removeEventListener) { + element.removeEventListener(name, wrapper, false); + } else { + element.detachEvent("on" + name, wrapper); + } + + destroyWrapper(id, eventName, handler); + + return element; + }, + + fire: function(element, eventName, memo) { + element = $(element); + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + var event; + if (document.createEvent) { + event = document.createEvent("HTMLEvents"); + event.initEvent("dataavailable", true, true); + } else { + event = document.createEventObject(); + event.eventType = "ondataavailable"; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) { + element.dispatchEvent(event); + } else { + element.fireEvent(event.eventType, event); + } + + return Event.extend(event); + } + }; +})()); + +Object.extend(Event, Event.Methods); + +Element.addMethods({ + fire: Event.fire, + observe: Event.observe, + stopObserving: Event.stopObserving +}); + +Object.extend(document, { + fire: Element.Methods.fire.methodize(), + observe: Element.Methods.observe.methodize(), + stopObserving: Element.Methods.stopObserving.methodize(), + loaded: false +}); + +(function() { + /* Support for the DOMContentLoaded event is based on work by Dan Webb, + Matthias Miller, Dean Edwards and John Resig. */ + + var timer; + + function fireContentLoadedEvent() { + if (document.loaded) return; + if (timer) window.clearInterval(timer); + document.fire("dom:loaded"); + document.loaded = true; + } + + if (document.addEventListener) { + if (Prototype.Browser.WebKit) { + timer = window.setInterval(function() { + if (/loaded|complete/.test(document.readyState)) + fireContentLoadedEvent(); + }, 0); + + Event.observe(window, "load", fireContentLoadedEvent); + + } else { + document.addEventListener("DOMContentLoaded", + fireContentLoadedEvent, false); + } + + } else { + document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>"); + $("__onDOMContentLoaded").onreadystatechange = function() { + if (this.readyState == "complete") { + this.onreadystatechange = null; + fireContentLoadedEvent(); + } + }; + } +})(); +/*------------------------------- DEPRECATED -------------------------------*/ + +Hash.toQueryString = Object.toQueryString; + +var Toggle = { display: Element.toggle }; + +Element.Methods.childOf = Element.Methods.descendantOf; + +var Insertion = { + Before: function(element, content) { + return Element.insert(element, {before:content}); + }, + + Top: function(element, content) { + return Element.insert(element, {top:content}); + }, + + Bottom: function(element, content) { + return Element.insert(element, {bottom:content}); + }, + + After: function(element, content) { + return Element.insert(element, {after:content}); + } +}; + +var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +// This should be moved to script.aculo.us; notice the deprecated methods +// further below, that map to the newer Element methods. +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = Element.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = Element.cumulativeScrollOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = Element.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + // Deprecation layer -- use newer Element methods now (1.5.2). + + cumulativeOffset: Element.Methods.cumulativeOffset, + + positionedOffset: Element.Methods.positionedOffset, + + absolutize: function(element) { + Position.prepare(); + return Element.absolutize(element); + }, + + relativize: function(element) { + Position.prepare(); + return Element.relativize(element); + }, + + realOffset: Element.Methods.cumulativeScrollOffset, + + offsetParent: Element.Methods.getOffsetParent, + + page: Element.Methods.viewportOffset, + + clone: function(source, target, options) { + options = options || { }; + return Element.clonePosition(target, source, options); + } +}; + +/*--------------------------------------------------------------------------*/ + +if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ + function iter(name) { + return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; + } + + instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? + function(element, className) { + className = className.toString().strip(); + var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); + return cond ? document._getElementsByXPath('.//*' + cond, element) : []; + } : function(element, className) { + className = className.toString().strip(); + var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); + if (!classNames && !className) return elements; + + var nodes = $(element).getElementsByTagName('*'); + className = ' ' + className + ' '; + + for (var i = 0, child, cn; child = nodes[i]; i++) { + if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || + (classNames && classNames.all(function(name) { + return !name.toString().blank() && cn.include(' ' + name + ' '); + })))) + elements.push(Element.extend(child)); + } + return elements; + }; + + return function(className, parentElement) { + return $(parentElement || document.body).getElementsByClassName(className); + }; +}(Element.Methods); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, + + toString: function() { + return $A(this).join(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); + +/*--------------------------------------------------------------------------*/ + +Element.addMethods();
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/scripts.js b/subsonic-main/src/main/webapp/script/scripts.js new file mode 100644 index 00000000..959ed7a6 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/scripts.js @@ -0,0 +1,21 @@ +function noop() { +} + +function popup(mylink, windowname) { + return popupSize(mylink, windowname, 400, 200); +} + +function popupSize(mylink, windowname, width, height) { + var href; + if (typeof(mylink) == "string") { + href = mylink; + } else { + href = mylink.href; + } + + var w = window.open(href, windowname, "width=" + width + ",height=" + height + ",scrollbars=yes,resizable=yes"); + w.focus(); + w.moveTo(300, 200); + return false; +} + diff --git a/subsonic-main/src/main/webapp/script/smooth-scroll.js b/subsonic-main/src/main/webapp/script/smooth-scroll.js new file mode 100644 index 00000000..9199732b --- /dev/null +++ b/subsonic-main/src/main/webapp/script/smooth-scroll.js @@ -0,0 +1,102 @@ +/*-------------------------------------------------------------------------- + * Smooth Scroller Script, version 1.0.1 + * (c) 2007 Dezinerfolio Inc. <midart@gmail.com> + * + * For details, please check the website : http://dezinerfolio.com/ + * +/*--------------------------------------------------------------------------*/ + +Scroller = { + // control the speed of the scroller. + // dont change it here directly, please use Scroller.speed=50; + speed:10, + + // returns the Y position of the div + gy: function (d) { + gy = d.offsetTop + if (d.offsetParent) while (d = d.offsetParent) gy += d.offsetTop + return gy + }, + + // returns the current scroll position + scrollTop: function (){ + body=document.body + d=document.documentElement + if (body && body.scrollTop) return body.scrollTop + if (d && d.scrollTop) return d.scrollTop + if (window.pageYOffset) return window.pageYOffset + return 0 + }, + + // attach an event for an element + // (element, type, function) + add: function(event, body, d) { + if (event.addEventListener) return event.addEventListener(body, d,false) + if (event.attachEvent) return event.attachEvent('on'+body, d) + }, + + // kill an event of an element + end: function(e){ + if (window.event) { + window.event.cancelBubble = true + window.event.returnValue = false + return; + } + if (e.preventDefault && e.stopPropagation) { + e.preventDefault() + e.stopPropagation() + } + }, + + // move the scroll bar to the particular div. + scroll: function(d){ + i = window.innerHeight || document.documentElement.clientHeight; + h=document.body.scrollHeight; + a = Scroller.scrollTop() + if(d>a) + if(h-d>i) + a+=Math.ceil((d-a)/Scroller.speed) + else + a+=Math.ceil((d-a-(h-d))/Scroller.speed) + else + a = a+(d-a)/Scroller.speed; + window.scrollTo(0,a) + if(a==d || Scroller.offsetTop==a)clearInterval(Scroller.interval) + Scroller.offsetTop=a + }, + // initializer that adds the renderer to the onload function of the window + init: function(){ + Scroller.add(window,'load', Scroller.render) + }, + + // this method extracts all the anchors and validates then as # and attaches the events. + render: function(){ + a = document.getElementsByTagName('a'); + Scroller.end(this); + window.onscroll + for (i=0;i<a.length;i++) { + l = a[i]; + if(l.href && l.href.indexOf('#') != -1 && ((l.pathname==location.pathname) || ('/'+l.pathname==location.pathname)) ){ + Scroller.add(l,'click',Scroller.end) + l.onclick = function(){ + Scroller.end(this); + l=this.hash.substr(1); + a = document.getElementsByTagName('a'); + for (i=0;i<a.length;i++) { + if(a[i].name == l){ + clearInterval(Scroller.interval); + Scroller.interval=setInterval('Scroller.scroll('+Scroller.gy(a[i])+')',10); + } + } + } + } + } + } +} +// invoke the initializer of the scroller +Scroller.init(); + + +/*------------------------------------------------------------ + * END OF CODE +/*-----------------------------------------------------------*/
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/swfobject.js b/subsonic-main/src/main/webapp/script/swfobject.js new file mode 100644 index 00000000..8eafe9dd --- /dev/null +++ b/subsonic-main/src/main/webapp/script/swfobject.js @@ -0,0 +1,4 @@ +/* SWFObject v2.2 <http://code.google.com/p/swfobject/> + is released under the MIT License <http://www.opensource.org/licenses/mit-license.php> +*/ +var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}();
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/tip_balloon.js b/subsonic-main/src/main/webapp/script/tip_balloon.js new file mode 100644 index 00000000..dc9d2e44 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/tip_balloon.js @@ -0,0 +1,221 @@ +/* +tip_balloon.js v. 1.81 + +The latest version is available at +http://www.walterzorn.com +or http://www.devira.com +or http://www.walterzorn.de + +Initial author: Walter Zorn +Last modified: 2.2.2009 + +Extension for the tooltip library wz_tooltip.js. +Implements balloon tooltips. +*/ + +// Make sure that the core file wz_tooltip.js is included first +if(typeof config == "undefined") + alert("Error:\nThe core tooltip script file 'wz_tooltip.js' must be included first, before the plugin files!"); + +// Here we define new global configuration variable(s) (as members of the +// predefined "config." class). +// From each of these config variables, wz_tooltip.js will automatically derive +// a command which can be passed to Tip() or TagToTip() in order to customize +// tooltips individually. These command names are just the config variable +// name(s) translated to uppercase, +// e.g. from config. Balloon a command BALLOON will automatically be +// created. + +//=================== GLOBAL TOOLTIP CONFIGURATION =========================// +config. Balloon = false // true or false - set to true if you want this to be the default behaviour +config. BalloonImgPath = "script/tip_balloon/" // Path to images (border, corners, stem), in quotes. Path must be relative to your HTML file. +// Sizes of balloon images +config. BalloonEdgeSize = 6 // Integer - sidelength of quadratic corner images +config. BalloonStemWidth = 15 // Integer +config. BalloonStemHeight = 19 // Integer +config. BalloonStemOffset = -7 // Integer - horizontal offset of left stem edge from mouse (recommended: -stemwidth/2 to center the stem above the mouse) +config. BalloonImgExt = "gif";// File name extension of default balloon images, e.g. "gif" or "png" +//======= END OF TOOLTIP CONFIG, DO NOT CHANGE ANYTHING BELOW ==============// + + +// Create a new tt_Extension object (make sure that the name of that object, +// here balloon, is unique amongst the extensions available for wz_tooltips.js): +var balloon = new tt_Extension(); + +// Implement extension eventhandlers on which our extension should react + +balloon.OnLoadConfig = function() +{ + if(tt_aV[BALLOON]) + { + // Turn off native style properties which are not appropriate + balloon.padding = Math.max(tt_aV[PADDING] - tt_aV[BALLOONEDGESIZE], 0); + balloon.width = tt_aV[WIDTH]; + //if(tt_bBoxOld) + // balloon.width += (balloon.padding << 1); + tt_aV[BORDERWIDTH] = 0; + tt_aV[WIDTH] = 0; + tt_aV[PADDING] = 0; + tt_aV[BGCOLOR] = ""; + tt_aV[BGIMG] = ""; + tt_aV[SHADOW] = false; + // Append slash to img path if missing + if(tt_aV[BALLOONIMGPATH].charAt(tt_aV[BALLOONIMGPATH].length - 1) != '/') + tt_aV[BALLOONIMGPATH] += "/"; + return true; + } + return false; +}; +balloon.OnCreateContentString = function() +{ + if(!tt_aV[BALLOON]) + return false; + + var aImg, sImgZ, sCssCrn, sVaT, sVaB, sCss0; + + // Cache balloon images in advance: + // Either use the pre-cached default images... + if(tt_aV[BALLOONIMGPATH] == config.BalloonImgPath) + aImg = balloon.aDefImg; + // ...or load images from different directory + else + aImg = Balloon_CacheImgs(tt_aV[BALLOONIMGPATH], tt_aV[BALLOONIMGEXT]); + sCss0 = 'padding:0;margin:0;border:0;line-height:0;overflow:hidden;'; + sCssCrn = ' style="position:relative;width:' + tt_aV[BALLOONEDGESIZE] + 'px;' + sCss0 + 'overflow:hidden;'; + sVaT = 'vertical-align:top;" valign="top"'; + sVaB = 'vertical-align:bottom;" valign="bottom"'; + sImgZ = '" style="' + sCss0 + '" />'; + + tt_sContent = '<table border="0" cellpadding="0" cellspacing="0" style="width:auto;padding:0;margin:0;left:0;top:0;"><tr>' + // Left-top corner + + '<td' + sCssCrn + sVaB + '>' + + '<img src="' + aImg[1].src + '" width="' + tt_aV[BALLOONEDGESIZE] + '" height="' + tt_aV[BALLOONEDGESIZE] + sImgZ + + '</td>' + // Top border + + '<td valign="bottom" style="position:relative;' + sCss0 + '">' + + '<img id="bALlOOnT" style="position:relative;top:1px;z-index:1;display:none;' + sCss0 + '" src="' + aImg[9].src + '" width="' + tt_aV[BALLOONSTEMWIDTH] + '" height="' + tt_aV[BALLOONSTEMHEIGHT] + '" />' + + '<div style="position:relative;z-index:0;top:0;' + sCss0 + 'width:auto;height:' + tt_aV[BALLOONEDGESIZE] + 'px;background-image:url(' + aImg[2].src + ');">' + + '</div>' + + '</td>' + // Right-top corner + + '<td' + sCssCrn + sVaB + '>' + + '<img src="' + aImg[3].src + '" width="' + tt_aV[BALLOONEDGESIZE] + '" height="' + tt_aV[BALLOONEDGESIZE] + sImgZ + + '</td>' + + '</tr><tr>' + // Left border (background-repeat fix courtesy Dirk Schnitzler) + + '<td style="position:relative;background-repeat:repeat;' + sCss0 + 'width:' + tt_aV[BALLOONEDGESIZE] + 'px;background-image:url(' + aImg[8].src + ');">' + // Redundant image for bugous old Geckos which won't auto-expand TD height to 100% + + '<img width="' + tt_aV[BALLOONEDGESIZE] + '" height="100%" src="' + aImg[8].src + sImgZ + + '</td>' + // Content + + '<td id="bALlO0nBdY" style="position:relative;line-height:normal;background-repeat:repeat;' + + ';background-image:url(' + aImg[0].src + ')' + + ';color:' + tt_aV[FONTCOLOR] + + ';font-family:' + tt_aV[FONTFACE] + + ';font-size:' + tt_aV[FONTSIZE] + + ';font-weight:' + tt_aV[FONTWEIGHT] + + ';text-align:' + tt_aV[TEXTALIGN] + + ';padding:' + balloon.padding + 'px' + + ';width:' + ((balloon.width > 0) ? (balloon.width + 'px') : 'auto') + + ';">' + tt_sContent + '</td>' + // Right border + + '<td style="position:relative;background-repeat:repeat;' + sCss0 + 'width:' + tt_aV[BALLOONEDGESIZE] + 'px;background-image:url(' + aImg[4].src + ');">' + // Image redundancy for bugous old Geckos that won't auto-expand TD height to 100% + + '<img width="' + tt_aV[BALLOONEDGESIZE] + '" height="100%" src="' + aImg[4].src + sImgZ + + '</td>' + + '</tr><tr>' + // Left-bottom corner + + '<td' + sCssCrn + sVaT + '>' + + '<img src="' + aImg[7].src + '" width="' + tt_aV[BALLOONEDGESIZE] + '" height="' + tt_aV[BALLOONEDGESIZE] + sImgZ + + '</td>' + // Bottom border + + '<td valign="top" style="position:relative;' + sCss0 + '">' + + '<div style="position:relative;left:0;top:0;' + sCss0 + 'width:auto;height:' + tt_aV[BALLOONEDGESIZE] + 'px;background-image:url(' + aImg[6].src + ');"></div>' + + '<img id="bALlOOnB" style="position:relative;top:-1px;left:2px;z-index:1;display:none;' + sCss0 + '" src="' + aImg[10].src + '" width="' + tt_aV[BALLOONSTEMWIDTH] + '" height="' + tt_aV[BALLOONSTEMHEIGHT] + '" />' + + '</td>' + // Right-bottom corner + + '<td' + sCssCrn + sVaT + '>' + + '<img src="' + aImg[5].src + '" width="' + tt_aV[BALLOONEDGESIZE] + '" height="' + tt_aV[BALLOONEDGESIZE] + sImgZ + + '</td>' + + '</tr></table>';//alert(tt_sContent); + return true; +}; +balloon.OnSubDivsCreated = function() +{ + if(tt_aV[BALLOON]) + { + var bdy = tt_GetElt("bALlO0nBdY"); + + // Insert a TagToTip() HTML element into the central body TD + if (tt_t2t && !tt_aV[COPYCONTENT] && bdy) + tt_MovDomNode(tt_t2t, tt_GetDad(tt_t2t), bdy); + balloon.iStem = tt_aV[ABOVE] * 1; + balloon.aStem = [tt_GetElt("bALlOOnT"), tt_GetElt("bALlOOnB")]; + balloon.aStem[balloon.iStem].style.display = "inline"; + if (balloon.width < -1) + Balloon_MaxW(bdy); + return true; + } + return false; +}; +// Display the stem appropriately +balloon.OnMoveAfter = function() +{ + if(tt_aV[BALLOON]) + { + var iStem = (tt_aV[ABOVE] != tt_bJmpVert) * 1; + + // Tooltip position vertically flipped? + if(iStem != balloon.iStem) + { + // Display opposite stem + balloon.aStem[balloon.iStem].style.display = "none"; + balloon.aStem[iStem].style.display = "inline"; + balloon.iStem = iStem; + } + + balloon.aStem[iStem].style.left = Balloon_CalcStemX() + "px"; + return true; + } + return false; +}; +function Balloon_CalcStemX() +{ + var x = tt_musX - tt_x + tt_aV[BALLOONSTEMOFFSET] - tt_aV[BALLOONEDGESIZE]; + return Math.max(Math.min(x, tt_w - tt_aV[BALLOONSTEMWIDTH] - (tt_aV[BALLOONEDGESIZE] << 1) - 2), 2); +} +function Balloon_CacheImgs(sPath, sExt) +{ + var asImg = ["background", "lt", "t", "rt", "r", "rb", "b", "lb", "l", "stemt", "stemb"], + n = asImg.length, + aImg = new Array(n), + img; + + while(n) + {--n; + img = aImg[n] = new Image(); + img.src = sPath + asImg[n] + "." + sExt; + } + return aImg; +} +function Balloon_MaxW(bdy) +{ + if (bdy) + { + var iAdd = tt_bBoxOld ? (balloon.padding << 1) : 0, w = tt_GetDivW(bdy); + if (w > -balloon.width + iAdd) + bdy.style.width = (-balloon.width + iAdd) + "px"; + } +} +// This mechanism pre-caches the default images specified by +// congif.BalloonImgPath, so, whenever a balloon tip using these default images +// is created, no further server connection is necessary. +function Balloon_PreCacheDefImgs() +{ + // Append slash to img path if missing + if(config.BalloonImgPath.charAt(config.BalloonImgPath.length - 1) != '/') + config.BalloonImgPath += "/"; + // Preload default images into array + balloon.aDefImg = Balloon_CacheImgs(config.BalloonImgPath, config.BalloonImgExt); +} +Balloon_PreCacheDefImgs(); diff --git a/subsonic-main/src/main/webapp/script/tip_balloon/b.gif b/subsonic-main/src/main/webapp/script/tip_balloon/b.gif Binary files differnew file mode 100644 index 00000000..ff0c04b2 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/tip_balloon/b.gif diff --git a/subsonic-main/src/main/webapp/script/tip_balloon/background.gif b/subsonic-main/src/main/webapp/script/tip_balloon/background.gif Binary files differnew file mode 100644 index 00000000..cb61e7ff --- /dev/null +++ b/subsonic-main/src/main/webapp/script/tip_balloon/background.gif diff --git a/subsonic-main/src/main/webapp/script/tip_balloon/l.gif b/subsonic-main/src/main/webapp/script/tip_balloon/l.gif Binary files differnew file mode 100644 index 00000000..14a68d93 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/tip_balloon/l.gif diff --git a/subsonic-main/src/main/webapp/script/tip_balloon/lb.gif b/subsonic-main/src/main/webapp/script/tip_balloon/lb.gif Binary files differnew file mode 100644 index 00000000..713c3739 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/tip_balloon/lb.gif diff --git a/subsonic-main/src/main/webapp/script/tip_balloon/lt.gif b/subsonic-main/src/main/webapp/script/tip_balloon/lt.gif Binary files differnew file mode 100644 index 00000000..93c71f46 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/tip_balloon/lt.gif diff --git a/subsonic-main/src/main/webapp/script/tip_balloon/r.gif b/subsonic-main/src/main/webapp/script/tip_balloon/r.gif Binary files differnew file mode 100644 index 00000000..be041ff9 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/tip_balloon/r.gif diff --git a/subsonic-main/src/main/webapp/script/tip_balloon/rb.gif b/subsonic-main/src/main/webapp/script/tip_balloon/rb.gif Binary files differnew file mode 100644 index 00000000..70b6834e --- /dev/null +++ b/subsonic-main/src/main/webapp/script/tip_balloon/rb.gif diff --git a/subsonic-main/src/main/webapp/script/tip_balloon/rt.gif b/subsonic-main/src/main/webapp/script/tip_balloon/rt.gif Binary files differnew file mode 100644 index 00000000..2752a0cc --- /dev/null +++ b/subsonic-main/src/main/webapp/script/tip_balloon/rt.gif diff --git a/subsonic-main/src/main/webapp/script/tip_balloon/stemb.gif b/subsonic-main/src/main/webapp/script/tip_balloon/stemb.gif Binary files differnew file mode 100644 index 00000000..92f2ad51 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/tip_balloon/stemb.gif diff --git a/subsonic-main/src/main/webapp/script/tip_balloon/stemt.gif b/subsonic-main/src/main/webapp/script/tip_balloon/stemt.gif Binary files differnew file mode 100644 index 00000000..d259a4ae --- /dev/null +++ b/subsonic-main/src/main/webapp/script/tip_balloon/stemt.gif diff --git a/subsonic-main/src/main/webapp/script/tip_balloon/t.gif b/subsonic-main/src/main/webapp/script/tip_balloon/t.gif Binary files differnew file mode 100644 index 00000000..6fec86f8 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/tip_balloon/t.gif diff --git a/subsonic-main/src/main/webapp/script/webfx/boxsizing.htc b/subsonic-main/src/main/webapp/script/webfx/boxsizing.htc new file mode 100644 index 00000000..fbeaa56c --- /dev/null +++ b/subsonic-main/src/main/webapp/script/webfx/boxsizing.htc @@ -0,0 +1,157 @@ +<component lightWeight="true">
+<attach event="onpropertychange" onevent="checkPropertyChange()" />
+<attach event="ondetach" onevent="restore()" />
+<script>
+//<![CDATA[
+
+var doc = element.document;
+
+function init() {
+ updateBorderBoxWidth();
+ updateBorderBoxHeight();
+}
+
+function restore() {
+ element.runtimeStyle.width = "";
+ element.runtimeStyle.height = "";
+}
+
+/* border width getters */
+function getBorderWidth(sSide) {
+ if (element.currentStyle["border" + sSide + "Style"] == "none")
+ return 0;
+ var n = parseInt(element.currentStyle["border" + sSide + "Width"]);
+ return n || 0;
+}
+
+function getBorderLeftWidth() { return getBorderWidth("Left"); }
+function getBorderRightWidth() { return getBorderWidth("Right"); }
+function getBorderTopWidth() { return getBorderWidth("Top"); }
+function getBorderBottomWidth() { return getBorderWidth("Bottom"); }
+/* end border width getters */
+
+/* padding getters */
+function getPadding(sSide) {
+ var n = parseInt(element.currentStyle["padding" + sSide]);
+ return n || 0;
+}
+
+function getPaddingLeft() { return getPadding("Left"); }
+function getPaddingRight() { return getPadding("Right"); }
+function getPaddingTop() { return getPadding("Top"); }
+function getPaddingBottom() { return getPadding("Bottom"); }
+/* end padding getters */
+
+function getBoxSizing() {
+ var s = element.style;
+ var cs = element.currentStyle
+
+ if (typeof s.boxSizing != "undefined" && s.boxSizing != "")
+ return s.boxSizing;
+ if (typeof s["box-sizing"] != "undefined" && s["box-sizing"] != "")
+ return s["box-sizing"];
+ if (typeof cs.boxSizing != "undefined" && cs.boxSizing != "")
+ return cs.boxSizing;
+ if (typeof cs["box-sizing"] != "undefined" && cs["box-sizing"] != "")
+ return cs["box-sizing"];
+ return getDocumentBoxSizing();
+}
+
+function getDocumentBoxSizing() {
+ if (doc.compatMode == null || doc.compatMode == "BackCompat")
+ return "border-box";
+ return "content-box"
+}
+
+/* width and height setters */
+function setBorderBoxWidth(n) {
+ element.runtimeStyle.width = Math.max(0, n - getBorderLeftWidth() -
+ getPaddingLeft() - getPaddingRight() - getBorderRightWidth()) + "px";
+}
+
+function setBorderBoxHeight(n) {
+ element.runtimeStyle.height = Math.max(0, n - getBorderTopWidth() -
+ getPaddingTop() - getPaddingBottom() - getBorderBottomWidth()) + "px";
+}
+
+function setContentBoxWidth(n) {
+ element.runtimeStyle.width = Math.max(0, n + getBorderLeftWidth() +
+ getPaddingLeft() + getPaddingRight() + getBorderRightWidth()) + "px";
+}
+
+function setContentBoxHeight(n) {
+ element.runtimeStyle.height = Math.max(0, n + getBorderTopWidth() +
+ getPaddingTop() + getPaddingBottom() + getBorderBottomWidth()) + "px";
+}
+/* end width and height setters */
+
+function updateBorderBoxWidth() {
+ element.runtimeStyle.width = "";
+ if (getDocumentBoxSizing() == getBoxSizing())
+ return;
+ var csw = element.currentStyle.width;
+ if (csw != "auto" && csw.indexOf("px") != -1) {
+ if (getBoxSizing() == "border-box")
+ setBorderBoxWidth(parseInt(csw));
+ else
+ setContentBoxWidth(parseInt(csw));
+ }
+}
+
+function updateBorderBoxHeight() {
+ element.runtimeStyle.height = "";
+ if (getDocumentBoxSizing() == getBoxSizing())
+ return;
+ var csh = element.currentStyle.height;
+ if (csh != "auto" && csh.indexOf("px") != -1) {
+ if (getBoxSizing() == "border-box")
+ setBorderBoxHeight(parseInt(csh));
+ else
+ setContentBoxHeight(parseInt(csh));
+ }
+}
+
+function checkPropertyChange() {
+ var pn = event.propertyName;
+ var undef;
+
+ if (pn == "style.boxSizing" && element.style.boxSizing == "") {
+ element.style.removeAttribute("boxSizing");
+ element.runtimeStyle.boxSizing = undef;
+ }
+
+
+ switch (pn) {
+ case "style.width":
+ case "style.borderLeftWidth":
+ case "style.borderLeftStyle":
+ case "style.borderRightWidth":
+ case "style.borderRightStyle":
+ case "style.paddingLeft":
+ case "style.paddingRight":
+ updateBorderBoxWidth();
+ break;
+
+ case "style.height":
+ case "style.borderTopWidth":
+ case "style.borderTopStyle":
+ case "style.borderBottomWidth":
+ case "style.borderBottomStyle":
+ case "style.paddingTop":
+ case "style.paddingBottom":
+ updateBorderBoxHeight();
+ break;
+
+ case "className":
+ case "style.boxSizing":
+ updateBorderBoxWidth();
+ updateBorderBoxHeight();
+ break;
+ }
+}
+
+init();
+
+//]]>
+</script>
+</component>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/webfx/handle.horizontal.hover.png b/subsonic-main/src/main/webapp/script/webfx/handle.horizontal.hover.png Binary files differnew file mode 100644 index 00000000..d2fd059d --- /dev/null +++ b/subsonic-main/src/main/webapp/script/webfx/handle.horizontal.hover.png diff --git a/subsonic-main/src/main/webapp/script/webfx/handle.horizontal.png b/subsonic-main/src/main/webapp/script/webfx/handle.horizontal.png Binary files differnew file mode 100644 index 00000000..b3af6bbf --- /dev/null +++ b/subsonic-main/src/main/webapp/script/webfx/handle.horizontal.png diff --git a/subsonic-main/src/main/webapp/script/webfx/handle.vertical.hover.png b/subsonic-main/src/main/webapp/script/webfx/handle.vertical.hover.png Binary files differnew file mode 100644 index 00000000..379cdc29 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/webfx/handle.vertical.hover.png diff --git a/subsonic-main/src/main/webapp/script/webfx/handle.vertical.png b/subsonic-main/src/main/webapp/script/webfx/handle.vertical.png Binary files differnew file mode 100644 index 00000000..537135e8 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/webfx/handle.vertical.png diff --git a/subsonic-main/src/main/webapp/script/webfx/luna.css b/subsonic-main/src/main/webapp/script/webfx/luna.css new file mode 100644 index 00000000..b01107cb --- /dev/null +++ b/subsonic-main/src/main/webapp/script/webfx/luna.css @@ -0,0 +1,75 @@ +.dynamic-slider-control { + position: relative; + /*background-color: ThreeDFace;*/ + -moz-user-focus: normal; + -moz-user-select: none; + cursor: default; +} + +.horizontal { + width: 200px; + height: 27px; +} + +.vertical { + width: 29px; + height: 200px; +} + +.dynamic-slider-control input { + display: none; +} + +.dynamic-slider-control .handle { + position: absolute; + font-size: 1px; + overflow: hidden; + -moz-user-select: none; + cursor: default; +} + +.dynamic-slider-control.horizontal .handle { + width: 11px; + height: 21px; + background-image: url("handle.horizontal.png"); +} + +.dynamic-slider-control.horizontal .handle div {} +.dynamic-slider-control.horizontal .handle.hover { + background-image: url("handle.horizontal.hover.png"); +} + +.dynamic-slider-control.vertical .handle { + width: 25px; + height: 13px; + background-image: url("handle.vertical.png"); +} + +.dynamic-slider-control.vertical .handle.hover { + background-image: url("handle.vertical.hover.png"); +} + +.dynamic-slider-control .line { + position: absolute; + font-size: 0.01mm; + overflow: hidden; + border: 1px solid; + border-color: ThreeDShadow ThreeDHighlight + ThreeDHighlight ThreeDShadow; + -moz-border-radius: 50%; + + behavior: url("boxsizing.htc"); /* ie path bug */ + box-sizing: content-box; + -moz-box-sizing: content-box; +} +.dynamic-slider-control.vertical .line { + width: 2px; +} + +.dynamic-slider-control.horizontal .line { + height: 2px; +} + +.dynamic-slider-control .line div { + display: none; +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/webfx/range.js b/subsonic-main/src/main/webapp/script/webfx/range.js new file mode 100644 index 00000000..53c8f34e --- /dev/null +++ b/subsonic-main/src/main/webapp/script/webfx/range.js @@ -0,0 +1,132 @@ +/*----------------------------------------------------------------------------\ +| Range Class | +|-----------------------------------------------------------------------------| +| Created by Erik Arvidsson | +| (http://webfx.eae.net/contact.html#erik) | +| For WebFX (http://webfx.eae.net/) | +|-----------------------------------------------------------------------------| +| Used to model the data used when working with sliders, scrollbars and | +| progress bars. Based on the ideas of the javax.swing.BoundedRangeModel | +| interface defined by Sun for Java; http://java.sun.com/products/jfc/ | +| swingdoc-api-1.0.3/com/sun/java/swing/BoundedRangeModel.html | +|-----------------------------------------------------------------------------| +| Copyright (c) 2002, 2005, 2006 Erik Arvidsson | +|-----------------------------------------------------------------------------| +| Licensed under the Apache License, Version 2.0 (the "License"); you may not | +| use this file except in compliance with the License. You may obtain a copy | +| of the License at http://www.apache.org/licenses/LICENSE-2.0 | +| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | +| WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | +| License for the specific language governing permissions and limitations | +| under the License. | +|-----------------------------------------------------------------------------| +| 2002-10-14 | Original version released | +| 2005-10-27 | Use Math.round instead of Math.floor | +| 2006-05-28 | Changed license to Apache Software License 2.0. | +|-----------------------------------------------------------------------------| +| Created 2002-10-14 | All changes are in the log above. | Updated 2006-05-28 | +\----------------------------------------------------------------------------*/ + + +function Range() { + this._value = 0; + this._minimum = 0; + this._maximum = 100; + this._extent = 0; + + this._isChanging = false; +} + +Range.prototype.setValue = function (value) { + value = Math.round(parseFloat(value)); + if (isNaN(value)) return; + if (this._value != value) { + if (value + this._extent > this._maximum) + this._value = this._maximum - this._extent; + else if (value < this._minimum) + this._value = this._minimum; + else + this._value = value; + if (!this._isChanging && typeof this.onchange == "function") + this.onchange(); + } +}; + +Range.prototype.getValue = function () { + return this._value; +}; + +Range.prototype.setExtent = function (extent) { + if (this._extent != extent) { + if (extent < 0) + this._extent = 0; + else if (this._value + extent > this._maximum) + this._extent = this._maximum - this._value; + else + this._extent = extent; + if (!this._isChanging && typeof this.onchange == "function") + this.onchange(); + } +}; + +Range.prototype.getExtent = function () { + return this._extent; +}; + +Range.prototype.setMinimum = function (minimum) { + if (this._minimum != minimum) { + var oldIsChanging = this._isChanging; + this._isChanging = true; + + this._minimum = minimum; + + if (minimum > this._value) + this.setValue(minimum); + if (minimum > this._maximum) { + this._extent = 0; + this.setMaximum(minimum); + this.setValue(minimum) + } + if (minimum + this._extent > this._maximum) + this._extent = this._maximum - this._minimum; + + this._isChanging = oldIsChanging; + if (!this._isChanging && typeof this.onchange == "function") + this.onchange(); + } +}; + +Range.prototype.getMinimum = function () { + return this._minimum; +}; + +Range.prototype.setMaximum = function (maximum) { + if (this._maximum != maximum) { + var oldIsChanging = this._isChanging; + this._isChanging = true; + + this._maximum = maximum; + + if (maximum < this._value) + this.setValue(maximum - this._extent); + if (maximum < this._minimum) { + this._extent = 0; + this.setMinimum(maximum); + this.setValue(this._maximum); + } + if (maximum < this._minimum + this._extent) + this._extent = this._maximum - this._minimum; + if (maximum < this._value + this._extent) + this._extent = this._maximum - this._value; + + this._isChanging = oldIsChanging; + if (!this._isChanging && typeof this.onchange == "function") + this.onchange(); + } +}; + +Range.prototype.getMaximum = function () { + return this._maximum; +}; diff --git a/subsonic-main/src/main/webapp/script/webfx/slider.js b/subsonic-main/src/main/webapp/script/webfx/slider.js new file mode 100644 index 00000000..ddc6d756 --- /dev/null +++ b/subsonic-main/src/main/webapp/script/webfx/slider.js @@ -0,0 +1,489 @@ +/*----------------------------------------------------------------------------\ +| Slider 1.02 | +|-----------------------------------------------------------------------------| +| Created by Erik Arvidsson | +| (http://webfx.eae.net/contact.html#erik) | +| For WebFX (http://webfx.eae.net/) | +|-----------------------------------------------------------------------------| +| A slider control that degrades to an input control for non supported | +| browsers. | +|-----------------------------------------------------------------------------| +| Copyright (c) 2002, 2003, 2006 Erik Arvidsson | +|-----------------------------------------------------------------------------| +| Licensed under the Apache License, Version 2.0 (the "License"); you may not | +| use this file except in compliance with the License. You may obtain a copy | +| of the License at http://www.apache.org/licenses/LICENSE-2.0 | +| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | +| WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | +| License for the specific language governing permissions and limitations | +| under the License. | +|-----------------------------------------------------------------------------| +| Dependencies: timer.js - an OO abstraction of timers | +| range.js - provides the data model for the slider | +| winclassic.css or any other css file describing the look | +|-----------------------------------------------------------------------------| +| 2002-10-14 | Original version released | +| 2003-03-27 | Added a test in the constructor for missing oElement arg | +| 2003-11-27 | Only use mousewheel when focused | +| 2006-05-28 | Changed license to Apache Software License 2.0. | +|-----------------------------------------------------------------------------| +| Created 2002-10-14 | All changes are in the log above. | Updated 2006-05-28 | +\----------------------------------------------------------------------------*/ + +Slider.isSupported = typeof document.createElement != "undefined" && + typeof document.documentElement != "undefined" && + typeof document.documentElement.offsetWidth == "number"; + + +function Slider(oElement, oInput, sOrientation) { + if (!oElement) return; + this._orientation = sOrientation || "horizontal"; + this._range = new Range(); + this._range.setExtent(0); + this._blockIncrement = 10; + this._unitIncrement = 1; + this._timer = new Timer(100); + + + if (Slider.isSupported && oElement) { + + this.document = oElement.ownerDocument || oElement.document; + + this.element = oElement; + this.element.slider = this; + this.element.unselectable = "on"; + + // add class name tag to class name + this.element.className = this._orientation + " " + this.classNameTag + " " + this.element.className; + + // create line + this.line = this.document.createElement("DIV"); + this.line.className = "line"; + this.line.unselectable = "on"; + this.line.appendChild(this.document.createElement("DIV")); + this.element.appendChild(this.line); + + // create handle + this.handle = this.document.createElement("DIV"); + this.handle.className = "handle"; + this.handle.unselectable = "on"; + this.handle.appendChild(this.document.createElement("DIV")); + this.handle.firstChild.appendChild( + this.document.createTextNode(String.fromCharCode(160))); + this.element.appendChild(this.handle); + } + + this.input = oInput; + + // events + var oThis = this; + this._range.onchange = function () { + oThis.recalculate(); + if (typeof oThis.onchange == "function") + oThis.onchange(); + }; + + if (Slider.isSupported && oElement) { + this.element.onfocus = Slider.eventHandlers.onfocus; + this.element.onblur = Slider.eventHandlers.onblur; + this.element.onmousedown = Slider.eventHandlers.onmousedown; + this.element.onmouseover = Slider.eventHandlers.onmouseover; + this.element.onmouseout = Slider.eventHandlers.onmouseout; + this.element.onkeydown = Slider.eventHandlers.onkeydown; + this.element.onkeypress = Slider.eventHandlers.onkeypress; + this.element.onmousewheel = Slider.eventHandlers.onmousewheel; + this.handle.onselectstart = + this.element.onselectstart = function () { return false; }; + + this._timer.ontimer = function () { + oThis.ontimer(); + }; + + // extra recalculate for ie + window.setTimeout(function() { + oThis.recalculate(); + }, 1); + } + else { + this.input.onchange = function (e) { + oThis.setValue(oThis.input.value); + }; + } +} + +Slider.eventHandlers = { + + // helpers to make events a bit easier + getEvent: function (e, el) { + if (!e) { + if (el) + e = el.document.parentWindow.event; + else + e = window.event; + } + if (!e.srcElement) { + var el = e.target; + while (el != null && el.nodeType != 1) + el = el.parentNode; + e.srcElement = el; + } + if (typeof e.offsetX == "undefined") { + e.offsetX = e.layerX; + e.offsetY = e.layerY; + } + + return e; + }, + + getDocument: function (e) { + if (e.target) + return e.target.ownerDocument; + return e.srcElement.document; + }, + + getSlider: function (e) { + var el = e.target || e.srcElement; + while (el != null && el.slider == null) { + el = el.parentNode; + } + if (el) + return el.slider; + return null; + }, + + getLine: function (e) { + var el = e.target || e.srcElement; + while (el != null && el.className != "line") { + el = el.parentNode; + } + return el; + }, + + getHandle: function (e) { + var el = e.target || e.srcElement; + var re = /handle/; + while (el != null && !re.test(el.className)) { + el = el.parentNode; + } + return el; + }, + // end helpers + + onfocus: function (e) { + var s = this.slider; + s._focused = true; + s.handle.className = "handle hover"; + }, + + onblur: function (e) { + var s = this.slider + s._focused = false; + s.handle.className = "handle"; + }, + + onmouseover: function (e) { + e = Slider.eventHandlers.getEvent(e, this); + var s = this.slider; + if (e.srcElement == s.handle) + s.handle.className = "handle hover"; + }, + + onmouseout: function (e) { + e = Slider.eventHandlers.getEvent(e, this); + var s = this.slider; + if (e.srcElement == s.handle && !s._focused) + s.handle.className = "handle"; + }, + + onmousedown: function (e) { + e = Slider.eventHandlers.getEvent(e, this); + var s = this.slider; + if (s.element.focus) + s.element.focus(); + + Slider._currentInstance = s; + var doc = s.document; + + if (doc.addEventListener) { + doc.addEventListener("mousemove", Slider.eventHandlers.onmousemove, true); + doc.addEventListener("mouseup", Slider.eventHandlers.onmouseup, true); + } + else if (doc.attachEvent) { + doc.attachEvent("onmousemove", Slider.eventHandlers.onmousemove); + doc.attachEvent("onmouseup", Slider.eventHandlers.onmouseup); + doc.attachEvent("onlosecapture", Slider.eventHandlers.onmouseup); + s.element.setCapture(); + } + + if (Slider.eventHandlers.getHandle(e)) { // start drag + Slider._sliderDragData = { + screenX: e.screenX, + screenY: e.screenY, + dx: e.screenX - s.handle.offsetLeft, + dy: e.screenY - s.handle.offsetTop, + startValue: s.getValue(), + slider: s + }; + } + else { + var lineEl = Slider.eventHandlers.getLine(e); + s._mouseX = e.offsetX + (lineEl ? s.line.offsetLeft : 0); + s._mouseY = e.offsetY + (lineEl ? s.line.offsetTop : 0); + s._increasing = null; + s.ontimer(); + } + }, + + onmousemove: function (e) { + e = Slider.eventHandlers.getEvent(e, this); + + if (Slider._sliderDragData) { // drag + var s = Slider._sliderDragData.slider; + + var boundSize = s.getMaximum() - s.getMinimum(); + var size, pos, reset; + + if (s._orientation == "horizontal") { + size = s.element.offsetWidth - s.handle.offsetWidth; + pos = e.screenX - Slider._sliderDragData.dx; + reset = Math.abs(e.screenY - Slider._sliderDragData.screenY) > 100; + } + else { + size = s.element.offsetHeight - s.handle.offsetHeight; + pos = s.element.offsetHeight - s.handle.offsetHeight - + (e.screenY - Slider._sliderDragData.dy); + reset = Math.abs(e.screenX - Slider._sliderDragData.screenX) > 100; + } + s.setValue(reset ? Slider._sliderDragData.startValue : + s.getMinimum() + boundSize * pos / size); + return false; + } + else { + var s = Slider._currentInstance; + if (s != null) { + var lineEl = Slider.eventHandlers.getLine(e); + s._mouseX = e.offsetX + (lineEl ? s.line.offsetLeft : 0); + s._mouseY = e.offsetY + (lineEl ? s.line.offsetTop : 0); + } + } + + }, + + onmouseup: function (e) { + e = Slider.eventHandlers.getEvent(e, this); + var s = Slider._currentInstance; + var doc = s.document; + if (doc.removeEventListener) { + doc.removeEventListener("mousemove", Slider.eventHandlers.onmousemove, true); + doc.removeEventListener("mouseup", Slider.eventHandlers.onmouseup, true); + } + else if (doc.detachEvent) { + doc.detachEvent("onmousemove", Slider.eventHandlers.onmousemove); + doc.detachEvent("onmouseup", Slider.eventHandlers.onmouseup); + doc.detachEvent("onlosecapture", Slider.eventHandlers.onmouseup); + s.element.releaseCapture(); + } + + if (Slider._sliderDragData) { // end drag + Slider._sliderDragData = null; + } + else { + s._timer.stop(); + s._increasing = null; + } + Slider._currentInstance = null; + }, + + onkeydown: function (e) { + e = Slider.eventHandlers.getEvent(e, this); + //var s = Slider.eventHandlers.getSlider(e); + var s = this.slider; + var kc = e.keyCode; + switch (kc) { + case 33: // page up + s.setValue(s.getValue() + s.getBlockIncrement()); + break; + case 34: // page down + s.setValue(s.getValue() - s.getBlockIncrement()); + break; + case 35: // end + s.setValue(s.getOrientation() == "horizontal" ? + s.getMaximum() : + s.getMinimum()); + break; + case 36: // home + s.setValue(s.getOrientation() == "horizontal" ? + s.getMinimum() : + s.getMaximum()); + break; + case 38: // up + case 39: // right + s.setValue(s.getValue() + s.getUnitIncrement()); + break; + + case 37: // left + case 40: // down + s.setValue(s.getValue() - s.getUnitIncrement()); + break; + } + + if (kc >= 33 && kc <= 40) { + return false; + } + }, + + onkeypress: function (e) { + e = Slider.eventHandlers.getEvent(e, this); + var kc = e.keyCode; + if (kc >= 33 && kc <= 40) { + return false; + } + }, + + onmousewheel: function (e) { + e = Slider.eventHandlers.getEvent(e, this); + var s = this.slider; + if (s._focused) { + s.setValue(s.getValue() + e.wheelDelta / 120 * s.getUnitIncrement()); + // windows inverts this on horizontal sliders. That does not + // make sense to me + return false; + } + } +}; + + + +Slider.prototype.classNameTag = "dynamic-slider-control"; + +Slider.prototype.setValue = function (v) { + this._range.setValue(v); + this.input.value = this.getValue(); +}; + +Slider.prototype.getValue = function () { + return this._range.getValue(); +}; + +Slider.prototype.setMinimum = function (v) { + this._range.setMinimum(v); + this.input.value = this.getValue(); +}; + +Slider.prototype.getMinimum = function () { + return this._range.getMinimum(); +}; + +Slider.prototype.setMaximum = function (v) { + this._range.setMaximum(v); + this.input.value = this.getValue(); +}; + +Slider.prototype.getMaximum = function () { + return this._range.getMaximum(); +}; + +Slider.prototype.setUnitIncrement = function (v) { + this._unitIncrement = v; +}; + +Slider.prototype.getUnitIncrement = function () { + return this._unitIncrement; +}; + +Slider.prototype.setBlockIncrement = function (v) { + this._blockIncrement = v; +}; + +Slider.prototype.getBlockIncrement = function () { + return this._blockIncrement; +}; + +Slider.prototype.getOrientation = function () { + return this._orientation; +}; + +Slider.prototype.setOrientation = function (sOrientation) { + if (sOrientation != this._orientation) { + if (Slider.isSupported && this.element) { + // add class name tag to class name + this.element.className = this.element.className.replace(this._orientation, + sOrientation); + } + this._orientation = sOrientation; + this.recalculate(); + + } +}; + +Slider.prototype.recalculate = function() { + if (!Slider.isSupported || !this.element) return; + + var w = this.element.offsetWidth; + var h = this.element.offsetHeight; + var hw = this.handle.offsetWidth; + var hh = this.handle.offsetHeight; + var lw = this.line.offsetWidth; + var lh = this.line.offsetHeight; + + // this assumes a border-box layout + + if (this._orientation == "horizontal") { + this.handle.style.left = (w - hw) * (this.getValue() - this.getMinimum()) / + (this.getMaximum() - this.getMinimum()) + "px"; + this.handle.style.top = (h - hh) / 2 + "px"; + + this.line.style.top = (h - lh) / 2 + "px"; + this.line.style.left = hw / 2 + "px"; + //this.line.style.right = hw / 2 + "px"; + this.line.style.width = Math.max(0, w - hw - 2)+ "px"; + this.line.firstChild.style.width = Math.max(0, w - hw - 4)+ "px"; + } + else { + this.handle.style.left = (w - hw) / 2 + "px"; + this.handle.style.top = h - hh - (h - hh) * (this.getValue() - this.getMinimum()) / + (this.getMaximum() - this.getMinimum()) + "px"; + + this.line.style.left = (w - lw) / 2 + "px"; + this.line.style.top = hh / 2 + "px"; + this.line.style.height = Math.max(0, h - hh - 2) + "px"; //hard coded border width + //this.line.style.bottom = hh / 2 + "px"; + this.line.firstChild.style.height = Math.max(0, h - hh - 4) + "px"; //hard coded border width + } +}; + +Slider.prototype.ontimer = function () { + var hw = this.handle.offsetWidth; + var hh = this.handle.offsetHeight; + var hl = this.handle.offsetLeft; + var ht = this.handle.offsetTop; + + if (this._orientation == "horizontal") { + if (this._mouseX > hl + hw && + (this._increasing == null || this._increasing)) { + this.setValue(this.getValue() + this.getBlockIncrement()); + this._increasing = true; + } + else if (this._mouseX < hl && + (this._increasing == null || !this._increasing)) { + this.setValue(this.getValue() - this.getBlockIncrement()); + this._increasing = false; + } + } + else { + if (this._mouseY > ht + hh && + (this._increasing == null || !this._increasing)) { + this.setValue(this.getValue() - this.getBlockIncrement()); + this._increasing = false; + } + else if (this._mouseY < ht && + (this._increasing == null || this._increasing)) { + this.setValue(this.getValue() + this.getBlockIncrement()); + this._increasing = true; + } + } + + this._timer.start(); +};
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/webfx/timer.js b/subsonic-main/src/main/webapp/script/webfx/timer.js new file mode 100644 index 00000000..0c1e897f --- /dev/null +++ b/subsonic-main/src/main/webapp/script/webfx/timer.js @@ -0,0 +1,62 @@ +/*----------------------------------------------------------------------------\ +| Timer Class | +|-----------------------------------------------------------------------------| +| Created by Erik Arvidsson | +| (http://webfx.eae.net/contact.html#erik) | +| For WebFX (http://webfx.eae.net/) | +|-----------------------------------------------------------------------------| +| Object Oriented Encapsulation of setTimeout fires ontimer when the timer | +| is triggered. Does not work in IE 5.00 | +|-----------------------------------------------------------------------------| +| Copyright (c) 2002, 2006 Erik Arvidsson | +|-----------------------------------------------------------------------------| +| Licensed under the Apache License, Version 2.0 (the "License"); you may not | +| use this file except in compliance with the License. You may obtain a copy | +| of the License at http://www.apache.org/licenses/LICENSE-2.0 | +| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | +| WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | +| License for the specific language governing permissions and limitations | +| under the License. | +|-----------------------------------------------------------------------------| +| 2002-10-14 | Original version released | +| 2006-05-28 | Changed license to Apache Software License 2.0. | +|-----------------------------------------------------------------------------| +| Created 2002-10-14 | All changes are in the log above. | Updated 2006-05-28 | +\----------------------------------------------------------------------------*/ + +function Timer(nPauseTime) { + this._pauseTime = typeof nPauseTime == "undefined" ? 1000 : nPauseTime; + this._timer = null; + this._isStarted = false; +} + +Timer.prototype.start = function () { + if (this.isStarted()) + this.stop(); + var oThis = this; + this._timer = window.setTimeout(function () { + if (typeof oThis.ontimer == "function") + oThis.ontimer(); + }, this._pauseTime); + this._isStarted = false; +}; + +Timer.prototype.stop = function () { + if (this._timer != null) + window.clearTimeout(this._timer); + this._isStarted = false; +}; + +Timer.prototype.isStarted = function () { + return this._isStarted; +}; + +Timer.prototype.getPauseTime = function () { + return this._pauseTime; +}; + +Timer.prototype.setPauseTime = function (nPauseTime) { + this._pauseTime = nPauseTime; +};
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/script/wz_tooltip.js b/subsonic-main/src/main/webapp/script/wz_tooltip.js new file mode 100644 index 00000000..01f55f2d --- /dev/null +++ b/subsonic-main/src/main/webapp/script/wz_tooltip.js @@ -0,0 +1,1301 @@ +/* This notice must be untouched at all times. +Copyright (c) 2002-2008 Walter Zorn. All rights reserved. + +wz_tooltip.js v. 5.31 + +The latest version is available at +http://www.walterzorn.com +or http://www.devira.com +or http://www.walterzorn.de + +Created 1.12.2002 by Walter Zorn (Web: http://www.walterzorn.com ) +Last modified: 7.11.2008 + +Easy-to-use cross-browser tooltips. +Just include the script at the beginning of the <body> section, and invoke +Tip('Tooltip text') to show and UnTip() to hide the tooltip, from the desired +HTML eventhandlers. Example: +<a onmouseover="Tip('Some text')" onmouseout="UnTip()" href="index.htm">My home page</a> +No container DIV required. +By default, width and height of tooltips are automatically adapted to content. +Is even capable of dynamically converting arbitrary HTML elements to tooltips +by calling TagToTip('ID_of_HTML_element_to_be_converted') instead of Tip(), +which means you can put important, search-engine-relevant stuff into tooltips. +Appearance & behaviour of tooltips can be individually configured +via commands passed to Tip() or TagToTip(). + +Tab Width: 4 +LICENSE: LGPL + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License (LGPL) as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +For more details on the GNU Lesser General Public License, +see http://www.gnu.org/copyleft/lesser.html +*/ + +var config = new Object(); + + +//=================== GLOBAL TOOLTIP CONFIGURATION =========================// +var tt_Debug = true // false or true - recommended: false once you release your page to the public +var tt_Enabled = true // Allows to (temporarily) suppress tooltips, e.g. by providing the user with a button that sets this global variable to false +var TagsToTip = true // false or true - if true, HTML elements to be converted to tooltips via TagToTip() are automatically hidden; + // if false, you should hide those HTML elements yourself + +// For each of the following config variables there exists a command, which is +// just the variablename in uppercase, to be passed to Tip() or TagToTip() to +// configure tooltips individually. Individual commands override global +// configuration. Order of commands is arbitrary. +// Example: onmouseover="Tip('Tooltip text', LEFT, true, BGCOLOR, '#FF9900', FADEIN, 400)" + +config. Above = false // false or true - tooltip above mousepointer +config. BgColor = '#E2E7FF' // Background colour (HTML colour value, in quotes) +config. BgImg = '' // Path to background image, none if empty string '' +config. BorderColor = '#003099' +config. BorderStyle = 'solid' // Any permitted CSS value, but I recommend 'solid', 'dotted' or 'dashed' +config. BorderWidth = 1 +config. CenterMouse = false // false or true - center the tip horizontally below (or above) the mousepointer +config. ClickClose = false // false or true - close tooltip if the user clicks somewhere +config. ClickSticky = false // false or true - make tooltip sticky if user left-clicks on the hovered element while the tooltip is active +config. CloseBtn = false // false or true - closebutton in titlebar +config. CloseBtnColors = ['#990000', '#FFFFFF', '#DD3333', '#FFFFFF'] // [Background, text, hovered background, hovered text] - use empty strings '' to inherit title colours +config. CloseBtnText = ' X ' // Close button text (may also be an image tag) +config. CopyContent = true // When converting a HTML element to a tooltip, copy only the element's content, rather than converting the element by its own +config. Delay = 400 // Time span in ms until tooltip shows up +config. Duration = 0 // Time span in ms after which the tooltip disappears; 0 for infinite duration, < 0 for delay in ms _after_ the onmouseout until the tooltip disappears +config. Exclusive = false // false or true - no other tooltip can appear until the current one has actively been closed +config. FadeIn = 100 // Fade-in duration in ms, e.g. 400; 0 for no animation +config. FadeOut = 100 +config. FadeInterval = 30 // Duration of each fade step in ms (recommended: 30) - shorter is smoother but causes more CPU-load +config. Fix = null // Fixated position, two modes. Mode 1: x- an y-coordinates in brackets, e.g. [210, 480]. Mode 2: Show tooltip at a position related to an HTML element: [ID of HTML element, x-offset, y-offset from HTML element], e.g. ['SomeID', 10, 30]. Value null (default) for no fixated positioning. +config. FollowMouse = true // false or true - tooltip follows the mouse +config. FontColor = '#000044' +config. FontFace = 'Verdana,Geneva,sans-serif' +config. FontSize = '8pt' // E.g. '9pt' or '12px' - unit is mandatory +config. FontWeight = 'normal' // 'normal' or 'bold'; +config. Height = 0 // Tooltip height; 0 for automatic adaption to tooltip content, < 0 (e.g. -100) for a maximum for automatic adaption +config. JumpHorz = false // false or true - jump horizontally to other side of mouse if tooltip would extend past clientarea boundary +config. JumpVert = true // false or true - jump vertically " +config. Left = false // false or true - tooltip on the left of the mouse +config. OffsetX = 14 // Horizontal offset of left-top corner from mousepointer +config. OffsetY = 8 // Vertical offset +config. Opacity = 100 // Integer between 0 and 100 - opacity of tooltip in percent +config. Padding = 3 // Spacing between border and content +config. Shadow = false // false or true +config. ShadowColor = '#C0C0C0' +config. ShadowWidth = 5 +config. Sticky = false // false or true - fixate tip, ie. don't follow the mouse and don't hide on mouseout +config. TextAlign = 'left' // 'left', 'right' or 'justify' +config. Title = '' // Default title text applied to all tips (no default title: empty string '') +config. TitleAlign = 'left' // 'left' or 'right' - text alignment inside the title bar +config. TitleBgColor = '' // If empty string '', BorderColor will be used +config. TitleFontColor = '#FFFFFF' // Color of title text - if '', BgColor (of tooltip body) will be used +config. TitleFontFace = '' // If '' use FontFace (boldified) +config. TitleFontSize = '' // If '' use FontSize +config. TitlePadding = 2 +config. Width = 0 // Tooltip width; 0 for automatic adaption to tooltip content; < -1 (e.g. -240) for a maximum width for that automatic adaption; + // -1: tooltip width confined to the width required for the titlebar +//======= END OF TOOLTIP CONFIG, DO NOT CHANGE ANYTHING BELOW ==============// + + + + +//===================== PUBLIC =============================================// +function Tip() +{ + tt_Tip(arguments, null); +} +function TagToTip() +{ + var t2t = tt_GetElt(arguments[0]); + if(t2t) + tt_Tip(arguments, t2t); +} +function UnTip() +{ + tt_OpReHref(); + if(tt_aV[DURATION] < 0 && (tt_iState & 0x2)) + tt_tDurt.Timer("tt_HideInit()", -tt_aV[DURATION], true); + else if(!(tt_aV[STICKY] && (tt_iState & 0x2))) + tt_HideInit(); +} + +//================== PUBLIC PLUGIN API =====================================// +// Extension eventhandlers currently supported: +// OnLoadConfig, OnCreateContentString, OnSubDivsCreated, OnShow, OnMoveBefore, +// OnMoveAfter, OnHideInit, OnHide, OnKill + +var tt_aElt = new Array(10), // Container DIV, outer title & body DIVs, inner title & body TDs, closebutton SPAN, shadow DIVs, and IFRAME to cover windowed elements in IE +tt_aV = new Array(), // Caches and enumerates config data for currently active tooltip +tt_sContent, // Inner tooltip text or HTML +tt_t2t, tt_t2tDad, // Tag converted to tip, and its DOM parent element +tt_musX, tt_musY, +tt_over, +tt_x, tt_y, tt_w, tt_h; // Position, width and height of currently displayed tooltip + +function tt_Extension() +{ + tt_ExtCmdEnum(); + tt_aExt[tt_aExt.length] = this; + return this; +} +function tt_SetTipPos(x, y) +{ + var css = tt_aElt[0].style; + + tt_x = x; + tt_y = y; + css.left = x + "px"; + css.top = y + "px"; + if(tt_ie56) + { + var ifrm = tt_aElt[tt_aElt.length - 1]; + if(ifrm) + { + ifrm.style.left = css.left; + ifrm.style.top = css.top; + } + } +} +function tt_HideInit() +{ + if(tt_iState) + { + tt_ExtCallFncs(0, "HideInit"); + tt_iState &= ~(0x4 | 0x8); + if(tt_flagOpa && tt_aV[FADEOUT]) + { + tt_tFade.EndTimer(); + if(tt_opa) + { + var n = Math.round(tt_aV[FADEOUT] / (tt_aV[FADEINTERVAL] * (tt_aV[OPACITY] / tt_opa))); + tt_Fade(tt_opa, tt_opa, 0, n); + return; + } + } + tt_tHide.Timer("tt_Hide();", 1, false); + } +} +function tt_Hide() +{ + if(tt_db && tt_iState) + { + tt_OpReHref(); + if(tt_iState & 0x2) + { + tt_aElt[0].style.visibility = "hidden"; + tt_ExtCallFncs(0, "Hide"); + } + tt_tShow.EndTimer(); + tt_tHide.EndTimer(); + tt_tDurt.EndTimer(); + tt_tFade.EndTimer(); + if(!tt_op && !tt_ie) + { + tt_tWaitMov.EndTimer(); + tt_bWait = false; + } + if(tt_aV[CLICKCLOSE] || tt_aV[CLICKSTICKY]) + tt_RemEvtFnc(document, "mouseup", tt_OnLClick); + tt_ExtCallFncs(0, "Kill"); + // In case of a TagToTip tip, hide converted DOM node and + // re-insert it into DOM + if(tt_t2t && !tt_aV[COPYCONTENT]) + tt_UnEl2Tip(); + tt_iState = 0; + tt_over = null; + tt_ResetMainDiv(); + if(tt_aElt[tt_aElt.length - 1]) + tt_aElt[tt_aElt.length - 1].style.display = "none"; + } +} +function tt_GetElt(id) +{ + return(document.getElementById ? document.getElementById(id) + : document.all ? document.all[id] + : null); +} +function tt_GetDivW(el) +{ + return(el ? (el.offsetWidth || el.style.pixelWidth || 0) : 0); +} +function tt_GetDivH(el) +{ + return(el ? (el.offsetHeight || el.style.pixelHeight || 0) : 0); +} +function tt_GetScrollX() +{ + return(window.pageXOffset || (tt_db ? (tt_db.scrollLeft || 0) : 0)); +} +function tt_GetScrollY() +{ + return(window.pageYOffset || (tt_db ? (tt_db.scrollTop || 0) : 0)); +} +function tt_GetClientW() +{ + return tt_GetWndCliSiz("Width"); +} +function tt_GetClientH() +{ + return tt_GetWndCliSiz("Height"); +} +function tt_GetEvtX(e) +{ + return (e ? ((typeof(e.pageX) != tt_u) ? e.pageX : (e.clientX + tt_GetScrollX())) : 0); +} +function tt_GetEvtY(e) +{ + return (e ? ((typeof(e.pageY) != tt_u) ? e.pageY : (e.clientY + tt_GetScrollY())) : 0); +} +function tt_AddEvtFnc(el, sEvt, PFnc) +{ + if(el) + { + if(el.addEventListener) + el.addEventListener(sEvt, PFnc, false); + else + el.attachEvent("on" + sEvt, PFnc); + } +} +function tt_RemEvtFnc(el, sEvt, PFnc) +{ + if(el) + { + if(el.removeEventListener) + el.removeEventListener(sEvt, PFnc, false); + else + el.detachEvent("on" + sEvt, PFnc); + } +} +function tt_GetDad(el) +{ + return(el.parentNode || el.parentElement || el.offsetParent); +} +function tt_MovDomNode(el, dadFrom, dadTo) +{ + if(dadFrom) + dadFrom.removeChild(el); + if(dadTo) + dadTo.appendChild(el); +} + +//====================== PRIVATE ===========================================// +var tt_aExt = new Array(), // Array of extension objects + +tt_db, tt_op, tt_ie, tt_ie56, tt_bBoxOld, // Browser flags +tt_body, +tt_ovr_, // HTML element the mouse is currently over +tt_flagOpa, // Opacity support: 1=IE, 2=Khtml, 3=KHTML, 4=Moz, 5=W3C +tt_maxPosX, tt_maxPosY, +tt_iState = 0, // Tooltip active |= 1, shown |= 2, move with mouse |= 4, exclusive |= 8 +tt_opa, // Currently applied opacity +tt_bJmpVert, tt_bJmpHorz,// Tip temporarily on other side of mouse +tt_elDeHref, // The tag from which we've removed the href attribute +// Timer +tt_tShow = new Number(0), tt_tHide = new Number(0), tt_tDurt = new Number(0), +tt_tFade = new Number(0), tt_tWaitMov = new Number(0), +tt_bWait = false, +tt_u = "undefined"; + + +function tt_Init() +{ + tt_MkCmdEnum(); + // Send old browsers instantly to hell + if(!tt_Browser() || !tt_MkMainDiv()) + return; + tt_IsW3cBox(); + tt_OpaSupport(); + tt_AddEvtFnc(document, "mousemove", tt_Move); + // In Debug mode we search for TagToTip() calls in order to notify + // the user if they've forgotten to set the TagsToTip config flag + if(TagsToTip || tt_Debug) + tt_SetOnloadFnc(); + // Ensure the tip be hidden when the page unloads + tt_AddEvtFnc(window, "unload", tt_Hide); +} +// Creates command names by translating config variable names to upper case +function tt_MkCmdEnum() +{ + var n = 0; + for(var i in config) + eval("window." + i.toString().toUpperCase() + " = " + n++); + tt_aV.length = n; +} +function tt_Browser() +{ + var n, nv, n6, w3c; + + n = navigator.userAgent.toLowerCase(), + nv = navigator.appVersion; + tt_op = (document.defaultView && typeof(eval("w" + "indow" + "." + "o" + "p" + "er" + "a")) != tt_u); + tt_ie = n.indexOf("msie") != -1 && document.all && !tt_op; + if(tt_ie) + { + var ieOld = (!document.compatMode || document.compatMode == "BackCompat"); + tt_db = !ieOld ? document.documentElement : (document.body || null); + if(tt_db) + tt_ie56 = parseFloat(nv.substring(nv.indexOf("MSIE") + 5)) >= 5.5 + && typeof document.body.style.maxHeight == tt_u; + } + else + { + tt_db = document.documentElement || document.body || + (document.getElementsByTagName ? document.getElementsByTagName("body")[0] + : null); + if(!tt_op) + { + n6 = document.defaultView && typeof document.defaultView.getComputedStyle != tt_u; + w3c = !n6 && document.getElementById; + } + } + tt_body = (document.getElementsByTagName ? document.getElementsByTagName("body")[0] + : (document.body || null)); + if(tt_ie || n6 || tt_op || w3c) + { + if(tt_body && tt_db) + { + if(document.attachEvent || document.addEventListener) + return true; + } + else + tt_Err("wz_tooltip.js must be included INSIDE the body section," + + " immediately after the opening <body> tag.", false); + } + tt_db = null; + return false; +} +function tt_MkMainDiv() +{ + // Create the tooltip DIV + if(tt_body.insertAdjacentHTML) + tt_body.insertAdjacentHTML("afterBegin", tt_MkMainDivHtm()); + else if(typeof tt_body.innerHTML != tt_u && document.createElement && tt_body.appendChild) + tt_body.appendChild(tt_MkMainDivDom()); + if(window.tt_GetMainDivRefs /* FireFox Alzheimer */ && tt_GetMainDivRefs()) + return true; + tt_db = null; + return false; +} +function tt_MkMainDivHtm() +{ + return( + '<div id="WzTtDiV"></div>' + + (tt_ie56 ? ('<iframe id="WzTtIfRm" src="javascript:false" scrolling="no" frameborder="0" style="filter:Alpha(opacity=0);position:absolute;top:0px;left:0px;display:none;"></iframe>') + : '') + ); +} +function tt_MkMainDivDom() +{ + var el = document.createElement("div"); + if(el) + el.id = "WzTtDiV"; + return el; +} +function tt_GetMainDivRefs() +{ + tt_aElt[0] = tt_GetElt("WzTtDiV"); + if(tt_ie56 && tt_aElt[0]) + { + tt_aElt[tt_aElt.length - 1] = tt_GetElt("WzTtIfRm"); + if(!tt_aElt[tt_aElt.length - 1]) + tt_aElt[0] = null; + } + if(tt_aElt[0]) + { + var css = tt_aElt[0].style; + + css.visibility = "hidden"; + css.position = "absolute"; + css.overflow = "hidden"; + return true; + } + return false; +} +function tt_ResetMainDiv() +{ + tt_SetTipPos(0, 0); + tt_aElt[0].innerHTML = ""; + tt_aElt[0].style.width = "0px"; + tt_h = 0; +} +function tt_IsW3cBox() +{ + var css = tt_aElt[0].style; + + css.padding = "10px"; + css.width = "40px"; + tt_bBoxOld = (tt_GetDivW(tt_aElt[0]) == 40); + css.padding = "0px"; + tt_ResetMainDiv(); +} +function tt_OpaSupport() +{ + var css = tt_body.style; + + tt_flagOpa = (typeof(css.KhtmlOpacity) != tt_u) ? 2 + : (typeof(css.KHTMLOpacity) != tt_u) ? 3 + : (typeof(css.MozOpacity) != tt_u) ? 4 + : (typeof(css.opacity) != tt_u) ? 5 + : (typeof(css.filter) != tt_u) ? 1 + : 0; +} +// Ported from http://dean.edwards.name/weblog/2006/06/again/ +// (Dean Edwards et al.) +function tt_SetOnloadFnc() +{ + tt_AddEvtFnc(document, "DOMContentLoaded", tt_HideSrcTags); + tt_AddEvtFnc(window, "load", tt_HideSrcTags); + if(tt_body.attachEvent) + tt_body.attachEvent("onreadystatechange", + function() { + if(tt_body.readyState == "complete") + tt_HideSrcTags(); + } ); + if(/WebKit|KHTML/i.test(navigator.userAgent)) + { + var t = setInterval(function() { + if(/loaded|complete/.test(document.readyState)) + { + clearInterval(t); + tt_HideSrcTags(); + } + }, 10); + } +} +function tt_HideSrcTags() +{ + if(!window.tt_HideSrcTags || window.tt_HideSrcTags.done) + return; + window.tt_HideSrcTags.done = true; + if(!tt_HideSrcTagsRecurs(tt_body)) + tt_Err("There are HTML elements to be converted to tooltips.\nIf you" + + " want these HTML elements to be automatically hidden, you" + + " must edit wz_tooltip.js, and set TagsToTip in the global" + + " tooltip configuration to true.", true); +} +function tt_HideSrcTagsRecurs(dad) +{ + var ovr, asT2t; + // Walk the DOM tree for tags that have an onmouseover or onclick attribute + // containing a TagToTip('...') call. + // (.childNodes first since .children is bugous in Safari) + var a = dad.childNodes || dad.children || null; + + for(var i = a ? a.length : 0; i;) + {--i; + if(!tt_HideSrcTagsRecurs(a[i])) + return false; + ovr = a[i].getAttribute ? (a[i].getAttribute("onmouseover") || a[i].getAttribute("onclick")) + : (typeof a[i].onmouseover == "function") ? (a[i].onmouseover || a[i].onclick) + : null; + if(ovr) + { + asT2t = ovr.toString().match(/TagToTip\s*\(\s*'[^'.]+'\s*[\),]/); + if(asT2t && asT2t.length) + { + if(!tt_HideSrcTag(asT2t[0])) + return false; + } + } + } + return true; +} +function tt_HideSrcTag(sT2t) +{ + var id, el; + + // The ID passed to the found TagToTip() call identifies an HTML element + // to be converted to a tooltip, so hide that element + id = sT2t.replace(/.+'([^'.]+)'.+/, "$1"); + el = tt_GetElt(id); + if(el) + { + if(tt_Debug && !TagsToTip) + return false; + else + el.style.display = "none"; + } + else + tt_Err("Invalid ID\n'" + id + "'\npassed to TagToTip()." + + " There exists no HTML element with that ID.", true); + return true; +} +function tt_Tip(arg, t2t) +{ + if(!tt_db || (tt_iState & 0x8)) + return; + if(tt_iState) + tt_Hide(); + if(!tt_Enabled) + return; + tt_t2t = t2t; + if(!tt_ReadCmds(arg)) + return; + tt_iState = 0x1 | 0x4; + tt_AdaptConfig1(); + tt_MkTipContent(arg); + tt_MkTipSubDivs(); + tt_FormatTip(); + tt_bJmpVert = false; + tt_bJmpHorz = false; + tt_maxPosX = tt_GetClientW() + tt_GetScrollX() - tt_w - 1; + tt_maxPosY = tt_GetClientH() + tt_GetScrollY() - tt_h - 1; + tt_AdaptConfig2(); + // Ensure the tip be shown and positioned before the first onmousemove + tt_OverInit(); + tt_ShowInit(); + tt_Move(); +} +function tt_ReadCmds(a) +{ + var i; + + // First load the global config values, to initialize also values + // for which no command is passed + i = 0; + for(var j in config) + tt_aV[i++] = config[j]; + // Then replace each cached config value for which a command is + // passed (ensure the # of command args plus value args be even) + if(a.length & 1) + { + for(i = a.length - 1; i > 0; i -= 2) + tt_aV[a[i - 1]] = a[i]; + return true; + } + tt_Err("Incorrect call of Tip() or TagToTip().\n" + + "Each command must be followed by a value.", true); + return false; +} +function tt_AdaptConfig1() +{ + tt_ExtCallFncs(0, "LoadConfig"); + // Inherit unspecified title formattings from body + if(!tt_aV[TITLEBGCOLOR].length) + tt_aV[TITLEBGCOLOR] = tt_aV[BORDERCOLOR]; + if(!tt_aV[TITLEFONTCOLOR].length) + tt_aV[TITLEFONTCOLOR] = tt_aV[BGCOLOR]; + if(!tt_aV[TITLEFONTFACE].length) + tt_aV[TITLEFONTFACE] = tt_aV[FONTFACE]; + if(!tt_aV[TITLEFONTSIZE].length) + tt_aV[TITLEFONTSIZE] = tt_aV[FONTSIZE]; + if(tt_aV[CLOSEBTN]) + { + // Use title colours for non-specified closebutton colours + if(!tt_aV[CLOSEBTNCOLORS]) + tt_aV[CLOSEBTNCOLORS] = new Array("", "", "", ""); + for(var i = 4; i;) + {--i; + if(!tt_aV[CLOSEBTNCOLORS][i].length) + tt_aV[CLOSEBTNCOLORS][i] = (i & 1) ? tt_aV[TITLEFONTCOLOR] : tt_aV[TITLEBGCOLOR]; + } + // Enforce titlebar be shown + if(!tt_aV[TITLE].length) + tt_aV[TITLE] = " "; + } + // Circumvents broken display of images and fade-in flicker in Geckos < 1.8 + if(tt_aV[OPACITY] == 100 && typeof tt_aElt[0].style.MozOpacity != tt_u && !Array.every) + tt_aV[OPACITY] = 99; + // Smartly shorten the delay for fade-in tooltips + if(tt_aV[FADEIN] && tt_flagOpa && tt_aV[DELAY] > 100) + tt_aV[DELAY] = Math.max(tt_aV[DELAY] - tt_aV[FADEIN], 100); +} +function tt_AdaptConfig2() +{ + if(tt_aV[CENTERMOUSE]) + { + tt_aV[OFFSETX] -= ((tt_w - (tt_aV[SHADOW] ? tt_aV[SHADOWWIDTH] : 0)) >> 1); + tt_aV[JUMPHORZ] = false; + } +} +// Expose content globally so extensions can modify it +function tt_MkTipContent(a) +{ + if(tt_t2t) + { + if(tt_aV[COPYCONTENT]) + tt_sContent = tt_t2t.innerHTML; + else + tt_sContent = ""; + } + else + tt_sContent = a[0]; + tt_ExtCallFncs(0, "CreateContentString"); +} +function tt_MkTipSubDivs() +{ + var sCss = 'position:relative;margin:0px;padding:0px;border-width:0px;left:0px;top:0px;line-height:normal;width:auto;', + sTbTrTd = ' cellspacing="0" cellpadding="0" border="0" style="' + sCss + '"><tbody style="' + sCss + '"><tr><td '; + + tt_aElt[0].style.width = tt_GetClientW() + "px"; + tt_aElt[0].innerHTML = + ('' + + (tt_aV[TITLE].length ? + ('<div id="WzTiTl" style="position:relative;z-index:1;">' + + '<table id="WzTiTlTb"' + sTbTrTd + 'id="WzTiTlI" style="' + sCss + '">' + + tt_aV[TITLE] + + '</td>' + + (tt_aV[CLOSEBTN] ? + ('<td align="right" style="' + sCss + + 'text-align:right;">' + + '<span id="WzClOsE" style="position:relative;left:2px;padding-left:2px;padding-right:2px;' + + 'cursor:' + (tt_ie ? 'hand' : 'pointer') + + ';" onmouseover="tt_OnCloseBtnOver(1)" onmouseout="tt_OnCloseBtnOver(0)" onclick="tt_HideInit()">' + + tt_aV[CLOSEBTNTEXT] + + '</span></td>') + : '') + + '</tr></tbody></table></div>') + : '') + + '<div id="WzBoDy" style="position:relative;z-index:0;">' + + '<table' + sTbTrTd + 'id="WzBoDyI" style="' + sCss + '">' + + tt_sContent + + '</td></tr></tbody></table></div>' + + (tt_aV[SHADOW] + ? ('<div id="WzTtShDwR" style="position:absolute;overflow:hidden;"></div>' + + '<div id="WzTtShDwB" style="position:relative;overflow:hidden;"></div>') + : '') + ); + tt_GetSubDivRefs(); + // Convert DOM node to tip + if(tt_t2t && !tt_aV[COPYCONTENT]) + tt_El2Tip(); + tt_ExtCallFncs(0, "SubDivsCreated"); +} +function tt_GetSubDivRefs() +{ + var aId = new Array("WzTiTl", "WzTiTlTb", "WzTiTlI", "WzClOsE", "WzBoDy", "WzBoDyI", "WzTtShDwB", "WzTtShDwR"); + + for(var i = aId.length; i; --i) + tt_aElt[i] = tt_GetElt(aId[i - 1]); +} +function tt_FormatTip() +{ + var css, w, h, pad = tt_aV[PADDING], padT, wBrd = tt_aV[BORDERWIDTH], + iOffY, iOffSh, iAdd = (pad + wBrd) << 1; + + //--------- Title DIV ---------- + if(tt_aV[TITLE].length) + { + padT = tt_aV[TITLEPADDING]; + css = tt_aElt[1].style; + css.background = tt_aV[TITLEBGCOLOR]; + css.paddingTop = css.paddingBottom = padT + "px"; + css.paddingLeft = css.paddingRight = (padT + 2) + "px"; + css = tt_aElt[3].style; + css.color = tt_aV[TITLEFONTCOLOR]; + if(tt_aV[WIDTH] == -1) + css.whiteSpace = "nowrap"; + css.fontFamily = tt_aV[TITLEFONTFACE]; + css.fontSize = tt_aV[TITLEFONTSIZE]; + css.fontWeight = "bold"; + css.textAlign = tt_aV[TITLEALIGN]; + // Close button DIV + if(tt_aElt[4]) + { + css = tt_aElt[4].style; + css.background = tt_aV[CLOSEBTNCOLORS][0]; + css.color = tt_aV[CLOSEBTNCOLORS][1]; + css.fontFamily = tt_aV[TITLEFONTFACE]; + css.fontSize = tt_aV[TITLEFONTSIZE]; + css.fontWeight = "bold"; + } + if(tt_aV[WIDTH] > 0) + tt_w = tt_aV[WIDTH]; + else + { + tt_w = tt_GetDivW(tt_aElt[3]) + tt_GetDivW(tt_aElt[4]); + // Some spacing between title DIV and closebutton + if(tt_aElt[4]) + tt_w += pad; + // Restrict auto width to max width + if(tt_aV[WIDTH] < -1 && tt_w > -tt_aV[WIDTH]) + tt_w = -tt_aV[WIDTH]; + } + // Ensure the top border of the body DIV be covered by the title DIV + iOffY = -wBrd; + } + else + { + tt_w = 0; + iOffY = 0; + } + + //-------- Body DIV ------------ + css = tt_aElt[5].style; + css.top = iOffY + "px"; + if(wBrd) + { + css.borderColor = tt_aV[BORDERCOLOR]; + css.borderStyle = tt_aV[BORDERSTYLE]; + css.borderWidth = wBrd + "px"; + } + if(tt_aV[BGCOLOR].length) + css.background = tt_aV[BGCOLOR]; + if(tt_aV[BGIMG].length) + css.backgroundImage = "url(" + tt_aV[BGIMG] + ")"; + css.padding = pad + "px"; + css.textAlign = tt_aV[TEXTALIGN]; + if(tt_aV[HEIGHT]) + { + css.overflow = "auto"; + if(tt_aV[HEIGHT] > 0) + css.height = (tt_aV[HEIGHT] + iAdd) + "px"; + else + tt_h = iAdd - tt_aV[HEIGHT]; + } + // TD inside body DIV + css = tt_aElt[6].style; + css.color = tt_aV[FONTCOLOR]; + css.fontFamily = tt_aV[FONTFACE]; + css.fontSize = tt_aV[FONTSIZE]; + css.fontWeight = tt_aV[FONTWEIGHT]; + css.textAlign = tt_aV[TEXTALIGN]; + if(tt_aV[WIDTH] > 0) + w = tt_aV[WIDTH]; + // Width like title (if existent) + else if(tt_aV[WIDTH] == -1 && tt_w) + w = tt_w; + else + { + // Measure width of the body's inner TD, as some browsers would expand + // the container and outer body DIV to 100% + w = tt_GetDivW(tt_aElt[6]); + // Restrict auto width to max width + if(tt_aV[WIDTH] < -1 && w > -tt_aV[WIDTH]) + w = -tt_aV[WIDTH]; + } + if(w > tt_w) + tt_w = w; + tt_w += iAdd; + + //--------- Shadow DIVs ------------ + if(tt_aV[SHADOW]) + { + tt_w += tt_aV[SHADOWWIDTH]; + iOffSh = Math.floor((tt_aV[SHADOWWIDTH] * 4) / 3); + // Bottom shadow + css = tt_aElt[7].style; + css.top = iOffY + "px"; + css.left = iOffSh + "px"; + css.width = (tt_w - iOffSh - tt_aV[SHADOWWIDTH]) + "px"; + css.height = tt_aV[SHADOWWIDTH] + "px"; + css.background = tt_aV[SHADOWCOLOR]; + // Right shadow + css = tt_aElt[8].style; + css.top = iOffSh + "px"; + css.left = (tt_w - tt_aV[SHADOWWIDTH]) + "px"; + css.width = tt_aV[SHADOWWIDTH] + "px"; + css.background = tt_aV[SHADOWCOLOR]; + } + else + iOffSh = 0; + + //-------- Container DIV ------- + tt_SetTipOpa(tt_aV[FADEIN] ? 0 : tt_aV[OPACITY]); + tt_FixSize(iOffY, iOffSh); +} +// Fixate the size so it can't dynamically change while the tooltip is moving. +function tt_FixSize(iOffY, iOffSh) +{ + var wIn, wOut, h, add, pad = tt_aV[PADDING], wBrd = tt_aV[BORDERWIDTH], i; + + tt_aElt[0].style.width = tt_w + "px"; + tt_aElt[0].style.pixelWidth = tt_w; + wOut = tt_w - ((tt_aV[SHADOW]) ? tt_aV[SHADOWWIDTH] : 0); + // Body + wIn = wOut; + if(!tt_bBoxOld) + wIn -= (pad + wBrd) << 1; + tt_aElt[5].style.width = wIn + "px"; + // Title + if(tt_aElt[1]) + { + wIn = wOut - ((tt_aV[TITLEPADDING] + 2) << 1); + if(!tt_bBoxOld) + wOut = wIn; + tt_aElt[1].style.width = wOut + "px"; + tt_aElt[2].style.width = wIn + "px"; + } + // Max height specified + if(tt_h) + { + h = tt_GetDivH(tt_aElt[5]); + if(h > tt_h) + { + if(!tt_bBoxOld) + tt_h -= (pad + wBrd) << 1; + tt_aElt[5].style.height = tt_h + "px"; + } + } + tt_h = tt_GetDivH(tt_aElt[0]) + iOffY; + // Right shadow + if(tt_aElt[8]) + tt_aElt[8].style.height = (tt_h - iOffSh) + "px"; + i = tt_aElt.length - 1; + if(tt_aElt[i]) + { + tt_aElt[i].style.width = tt_w + "px"; + tt_aElt[i].style.height = tt_h + "px"; + } +} +function tt_DeAlt(el) +{ + var aKid; + + if(el) + { + if(el.alt) + el.alt = ""; + if(el.title) + el.title = ""; + aKid = el.childNodes || el.children || null; + if(aKid) + { + for(var i = aKid.length; i;) + tt_DeAlt(aKid[--i]); + } + } +} +// This hack removes the native tooltips over links in Opera +function tt_OpDeHref(el) +{ + if(!tt_op) + return; + if(tt_elDeHref) + tt_OpReHref(); + while(el) + { + if(el.hasAttribute && el.hasAttribute("href")) + { + el.t_href = el.getAttribute("href"); + el.t_stats = window.status; + el.removeAttribute("href"); + el.style.cursor = "hand"; + tt_AddEvtFnc(el, "mousedown", tt_OpReHref); + window.status = el.t_href; + tt_elDeHref = el; + break; + } + el = tt_GetDad(el); + } +} +function tt_OpReHref() +{ + if(tt_elDeHref) + { + tt_elDeHref.setAttribute("href", tt_elDeHref.t_href); + tt_RemEvtFnc(tt_elDeHref, "mousedown", tt_OpReHref); + window.status = tt_elDeHref.t_stats; + tt_elDeHref = null; + } +} +function tt_El2Tip() +{ + var css = tt_t2t.style; + + // Store previous positioning + tt_t2t.t_cp = css.position; + tt_t2t.t_cl = css.left; + tt_t2t.t_ct = css.top; + tt_t2t.t_cd = css.display; + // Store the tag's parent element so we can restore that DOM branch + // when the tooltip is being hidden + tt_t2tDad = tt_GetDad(tt_t2t); + tt_MovDomNode(tt_t2t, tt_t2tDad, tt_aElt[6]); + css.display = "block"; + css.position = "static"; + css.left = css.top = css.marginLeft = css.marginTop = "0px"; +} +function tt_UnEl2Tip() +{ + // Restore positioning and display + var css = tt_t2t.style; + + css.display = tt_t2t.t_cd; + tt_MovDomNode(tt_t2t, tt_GetDad(tt_t2t), tt_t2tDad); + css.position = tt_t2t.t_cp; + css.left = tt_t2t.t_cl; + css.top = tt_t2t.t_ct; + tt_t2tDad = null; +} +function tt_OverInit() +{ + if(window.event) + tt_over = window.event.target || window.event.srcElement; + else + tt_over = tt_ovr_; + tt_DeAlt(tt_over); + tt_OpDeHref(tt_over); +} +function tt_ShowInit() +{ + tt_tShow.Timer("tt_Show()", tt_aV[DELAY], true); + if(tt_aV[CLICKCLOSE] || tt_aV[CLICKSTICKY]) + tt_AddEvtFnc(document, "mouseup", tt_OnLClick); +} +function tt_Show() +{ + var css = tt_aElt[0].style; + + // Override the z-index of the topmost wz_dragdrop.js D&D item + css.zIndex = Math.max((window.dd && dd.z) ? (dd.z + 2) : 0, 1010); + if(tt_aV[STICKY] || !tt_aV[FOLLOWMOUSE]) + tt_iState &= ~0x4; + if(tt_aV[EXCLUSIVE]) + tt_iState |= 0x8; + if(tt_aV[DURATION] > 0) + tt_tDurt.Timer("tt_HideInit()", tt_aV[DURATION], true); + tt_ExtCallFncs(0, "Show") + css.visibility = "visible"; + tt_iState |= 0x2; + if(tt_aV[FADEIN]) + tt_Fade(0, 0, tt_aV[OPACITY], Math.round(tt_aV[FADEIN] / tt_aV[FADEINTERVAL])); + tt_ShowIfrm(); +} +function tt_ShowIfrm() +{ + if(tt_ie56) + { + var ifrm = tt_aElt[tt_aElt.length - 1]; + if(ifrm) + { + var css = ifrm.style; + css.zIndex = tt_aElt[0].style.zIndex - 1; + css.display = "block"; + } + } +} +function tt_Move(e) +{ + if(e) + tt_ovr_ = e.target || e.srcElement; + e = e || window.event; + if(e) + { + tt_musX = tt_GetEvtX(e); + tt_musY = tt_GetEvtY(e); + } + if(tt_iState & 0x4) + { + // Prevent jam of mousemove events + if(!tt_op && !tt_ie) + { + if(tt_bWait) + return; + tt_bWait = true; + tt_tWaitMov.Timer("tt_bWait = false;", 1, true); + } + if(tt_aV[FIX]) + { + tt_iState &= ~0x4; + tt_PosFix(); + } + else if(!tt_ExtCallFncs(e, "MoveBefore")) + tt_SetTipPos(tt_Pos(0), tt_Pos(1)); + tt_ExtCallFncs([tt_musX, tt_musY], "MoveAfter") + } +} +function tt_Pos(iDim) +{ + var iX, bJmpMod, cmdAlt, cmdOff, cx, iMax, iScrl, iMus, bJmp; + + // Map values according to dimension to calculate + if(iDim) + { + bJmpMod = tt_aV[JUMPVERT]; + cmdAlt = ABOVE; + cmdOff = OFFSETY; + cx = tt_h; + iMax = tt_maxPosY; + iScrl = tt_GetScrollY(); + iMus = tt_musY; + bJmp = tt_bJmpVert; + } + else + { + bJmpMod = tt_aV[JUMPHORZ]; + cmdAlt = LEFT; + cmdOff = OFFSETX; + cx = tt_w; + iMax = tt_maxPosX; + iScrl = tt_GetScrollX(); + iMus = tt_musX; + bJmp = tt_bJmpHorz; + } + if(bJmpMod) + { + if(tt_aV[cmdAlt] && (!bJmp || tt_CalcPosAlt(iDim) >= iScrl + 16)) + iX = tt_PosAlt(iDim); + else if(!tt_aV[cmdAlt] && bJmp && tt_CalcPosDef(iDim) > iMax - 16) + iX = tt_PosAlt(iDim); + else + iX = tt_PosDef(iDim); + } + else + { + iX = iMus; + if(tt_aV[cmdAlt]) + iX -= cx + tt_aV[cmdOff] - (tt_aV[SHADOW] ? tt_aV[SHADOWWIDTH] : 0); + else + iX += tt_aV[cmdOff]; + } + // Prevent tip from extending past clientarea boundary + if(iX > iMax) + iX = bJmpMod ? tt_PosAlt(iDim) : iMax; + // In case of insufficient space on both sides, ensure the left/upper part + // of the tip be visible + if(iX < iScrl) + iX = bJmpMod ? tt_PosDef(iDim) : iScrl; + return iX; +} +function tt_PosDef(iDim) +{ + if(iDim) + tt_bJmpVert = tt_aV[ABOVE]; + else + tt_bJmpHorz = tt_aV[LEFT]; + return tt_CalcPosDef(iDim); +} +function tt_PosAlt(iDim) +{ + if(iDim) + tt_bJmpVert = !tt_aV[ABOVE]; + else + tt_bJmpHorz = !tt_aV[LEFT]; + return tt_CalcPosAlt(iDim); +} +function tt_CalcPosDef(iDim) +{ + return iDim ? (tt_musY + tt_aV[OFFSETY]) : (tt_musX + tt_aV[OFFSETX]); +} +function tt_CalcPosAlt(iDim) +{ + var cmdOff = iDim ? OFFSETY : OFFSETX; + var dx = tt_aV[cmdOff] - (tt_aV[SHADOW] ? tt_aV[SHADOWWIDTH] : 0); + if(tt_aV[cmdOff] > 0 && dx <= 0) + dx = 1; + return((iDim ? (tt_musY - tt_h) : (tt_musX - tt_w)) - dx); +} +function tt_PosFix() +{ + var iX, iY; + + if(typeof(tt_aV[FIX][0]) == "number") + { + iX = tt_aV[FIX][0]; + iY = tt_aV[FIX][1]; + } + else + { + if(typeof(tt_aV[FIX][0]) == "string") + el = tt_GetElt(tt_aV[FIX][0]); + // First slot in array is direct reference to HTML element + else + el = tt_aV[FIX][0]; + iX = tt_aV[FIX][1]; + iY = tt_aV[FIX][2]; + // By default, vert pos is related to bottom edge of HTML element + if(!tt_aV[ABOVE] && el) + iY += tt_GetDivH(el); + for(; el; el = el.offsetParent) + { + iX += el.offsetLeft || 0; + iY += el.offsetTop || 0; + } + } + // For a fixed tip positioned above the mouse, use the bottom edge as anchor + // (recommended by Christophe Rebeschini, 31.1.2008) + if(tt_aV[ABOVE]) + iY -= tt_h; + tt_SetTipPos(iX, iY); +} +function tt_Fade(a, now, z, n) +{ + if(n) + { + now += Math.round((z - now) / n); + if((z > a) ? (now >= z) : (now <= z)) + now = z; + else + tt_tFade.Timer( + "tt_Fade(" + + a + "," + now + "," + z + "," + (n - 1) + + ")", + tt_aV[FADEINTERVAL], + true + ); + } + now ? tt_SetTipOpa(now) : tt_Hide(); +} +function tt_SetTipOpa(opa) +{ + // To circumvent the opacity nesting flaws of IE, we set the opacity + // for each sub-DIV separately, rather than for the container DIV. + tt_SetOpa(tt_aElt[5], opa); + if(tt_aElt[1]) + tt_SetOpa(tt_aElt[1], opa); + if(tt_aV[SHADOW]) + { + opa = Math.round(opa * 0.8); + tt_SetOpa(tt_aElt[7], opa); + tt_SetOpa(tt_aElt[8], opa); + } +} +function tt_OnCloseBtnOver(iOver) +{ + var css = tt_aElt[4].style; + + iOver <<= 1; + css.background = tt_aV[CLOSEBTNCOLORS][iOver]; + css.color = tt_aV[CLOSEBTNCOLORS][iOver + 1]; +} +function tt_OnLClick(e) +{ + // Ignore right-clicks + e = e || window.event; + if(!((e.button && e.button & 2) || (e.which && e.which == 3))) + { + if(tt_aV[CLICKSTICKY] && (tt_iState & 0x4)) + { + tt_aV[STICKY] = true; + tt_iState &= ~0x4; + } + else if(tt_aV[CLICKCLOSE]) + tt_HideInit(); + } +} +function tt_Int(x) +{ + var y; + + return(isNaN(y = parseInt(x)) ? 0 : y); +} +Number.prototype.Timer = function(s, iT, bUrge) +{ + if(!this.value || bUrge) + this.value = window.setTimeout(s, iT); +} +Number.prototype.EndTimer = function() +{ + if(this.value) + { + window.clearTimeout(this.value); + this.value = 0; + } +} +function tt_GetWndCliSiz(s) +{ + var db, y = window["inner" + s], sC = "client" + s, sN = "number"; + if(typeof y == sN) + { + var y2; + return( + // Gecko or Opera with scrollbar + // ... quirks mode + ((db = document.body) && typeof(y2 = db[sC]) == sN && y2 && y2 <= y) ? y2 + // ... strict mode + : ((db = document.documentElement) && typeof(y2 = db[sC]) == sN && y2 && y2 <= y) ? y2 + // No scrollbar, or clientarea size == 0, or other browser (KHTML etc.) + : y + ); + } + // IE + return( + // document.documentElement.client+s functional, returns > 0 + ((db = document.documentElement) && (y = db[sC])) ? y + // ... not functional, in which case document.body.client+s + // is the clientarea size, fortunately + : document.body[sC] + ); +} +function tt_SetOpa(el, opa) +{ + var css = el.style; + + tt_opa = opa; + if(tt_flagOpa == 1) + { + if(opa < 100) + { + // Hacks for bugs of IE: + // 1.) Once a CSS filter has been applied, fonts are no longer + // anti-aliased, so we store the previous 'non-filter' to be + // able to restore it + if(typeof(el.filtNo) == tt_u) + el.filtNo = css.filter; + // 2.) A DIV cannot be made visible in a single step if an + // opacity < 100 has been applied while the DIV was hidden + var bVis = css.visibility != "hidden"; + // 3.) In IE6, applying an opacity < 100 has no effect if the + // element has no layout (position, size, zoom, ...) + css.zoom = "100%"; + if(!bVis) + css.visibility = "visible"; + css.filter = "alpha(opacity=" + opa + ")"; + if(!bVis) + css.visibility = "hidden"; + } + else if(typeof(el.filtNo) != tt_u) + // Restore 'non-filter' + css.filter = el.filtNo; + } + else + { + opa /= 100.0; + switch(tt_flagOpa) + { + case 2: + css.KhtmlOpacity = opa; break; + case 3: + css.KHTMLOpacity = opa; break; + case 4: + css.MozOpacity = opa; break; + case 5: + css.opacity = opa; break; + } + } +} +function tt_Err(sErr, bIfDebug) +{ + if(tt_Debug || !bIfDebug) + alert("Tooltip Script Error Message:\n\n" + sErr); +} + +//============ EXTENSION (PLUGIN) MANAGER ===============// +function tt_ExtCmdEnum() +{ + var s; + + // Add new command(s) to the commands enum + for(var i in config) + { + s = "window." + i.toString().toUpperCase(); + if(eval("typeof(" + s + ") == tt_u")) + { + eval(s + " = " + tt_aV.length); + tt_aV[tt_aV.length] = null; + } + } +} +function tt_ExtCallFncs(arg, sFnc) +{ + var b = false; + for(var i = tt_aExt.length; i;) + {--i; + var fnc = tt_aExt[i]["On" + sFnc]; + // Call the method the extension has defined for this event + if(fnc && fnc(arg)) + b = true; + } + return b; +} + +tt_Init(); diff --git a/subsonic-main/src/main/webapp/style/barents.css b/subsonic-main/src/main/webapp/style/barents.css new file mode 100644 index 00000000..75fd3323 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/barents.css @@ -0,0 +1,30 @@ +/* + * CSS styleshet for the "Barents Sea" theme. + * + * Author: Sindre Mehus + */ + +@import "hd.css"; + +body { + margin:0.75em; + font-size: 9pt; +} + +.detail, .albumComment, .log { + font-size: 8pt; +} + +/* Font 1 */ +body, h2, form, label, table, a { + font-family: verdana, arial, sans-serif; +} + +/* Font 2 */ +h1, h1 a, input, select { + font-family: arial, sans-serif; +} + +h1, h2, th { + font-weight:bold; +} diff --git a/subsonic-main/src/main/webapp/style/black.css b/subsonic-main/src/main/webapp/style/black.css new file mode 100644 index 00000000..a28d8d93 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/black.css @@ -0,0 +1,17 @@ +/* + * CSS styleshet for the "Back In Black" theme. + * + * Author: Sindre Mehus + */ + +@import "midnight.css"; + +/* The primary background color. */ +.bgcolor1 { + background-color: #333333 +} + +/* The secondary background color. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: black +} diff --git a/subsonic-main/src/main/webapp/style/buuftheme.css b/subsonic-main/src/main/webapp/style/buuftheme.css new file mode 100644 index 00000000..5f84f239 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/buuftheme.css @@ -0,0 +1,120 @@ +/* + * CSS styleshet for the "Cool and Clean" theme. + * + * Author: Dan Eriksen (dan.o.eriksen[at]gmail.com) + * + * Icons used are released under Creative Commons. + * Heading icons are part of the Albook icon pack created by Laurent Baumann (http://lbaumann.com/) + * Main theme icon part of itunes icon pack created by Michael Flarup (http://pixelresort.com) + * + * + * Edited for BUUF Theme by Fractal Systems + * BUUF artwork: Based on icons by Paul Davey aka Mattahan. All rights reserved. + */ + +@import "default.css"; + +/* The primary background colour, light gray. Images used to force background on left frame headings and playlist. */ +.bgcolor1 { + background-image:url( "../icons/buuftheme/list_heading.png" ); + background-repeat:repeat; + background-color: #3C2D22; +} + +/* The secondary background colour, light blue, primary theme colour. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #4C4039; +} + +/* Background for selected headers. */ +.headerSelected { + background-image:url( "../icons/buuftheme/home_hover.png" ); + background-repeat:repeat; + color: #333333; +} + + +/* Foreground colour used for h1, h2, b, tr, details and albumcomments. */ +h1, h2, b, tr, .detail, .albumComment { + color: #ffAE00; +} + +/* Table sizing */ +table { + font-size: 100%; + line-height: 130%; + padding: 0; + border: 0; + margin: 0 0 0 0; +} + +/* Main frame image & colour */ +.mainframe { + background-image:url( "../icons/buuftheme/background_main.png" ); + background-repeat:no-repeat; + background-attachment:fixed; + background-color: #4C4039; + background-position:right; +} + +/* Right frame background. */ +.rightframe { + background-color: #4C4039; + background-image:none; +} + +/* Back image */ +.back { + background-image:url( "../icons/buuftheme/back.png" ); +} + +/* Forward image */ +.forward { + background-image:url( "../icons/buuftheme/forward.png" ); +} + +/* Link colour */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #ffAE00; +} + +/* Link hover colour */ +a:hover, a:hover * { + text-decoration: none; + color: #169F30; +} + +/* Colour for warning messages. */ +.warning { + color: #AA1F15; +} + +/* The primary foreground colour. */ +body { + background-color: #D1D9E1; + scrollbar-arrow-color: #636363; + scrollbar-track-color: #D1D9E1; +} + +/* The album comments. */ +.albumComment { + width: 50em; + font-size: 8pt; + line-height: 1.4em; + padding-top: 0.25em; +} + +/* The log. */ +.log { + font-weight: bold; + white-space: nowrap; + font-size: 8pt; + line-height: 1em; +} + +/* The help, status & web payer settings tables. */ +.ruleTableHeader, .ruleTableCell { + margin: 5px; + padding: 5px; +} + diff --git a/subsonic-main/src/main/webapp/style/coolandclean.css b/subsonic-main/src/main/webapp/style/coolandclean.css new file mode 100644 index 00000000..0786b15b --- /dev/null +++ b/subsonic-main/src/main/webapp/style/coolandclean.css @@ -0,0 +1,116 @@ +/* + * CSS styleshet for the "Cool and Clean" theme. + * + * Author: Dan Eriksen (dan.o.eriksen[at]gmail.com) + * + * Icons used are released under Creative Commons. + * Heading icons are part of the Albook icon pack created by Laurent Baumann (http://lbaumann.com/) + * Main theme icon part of itunes icon pack created by Michael Flarup (http://pixelresort.com) + */ + +@import "default.css"; + +/* The primary background colour, light gray. Images used to force background on left frame headings and playlist. */ +.bgcolor1 { + background-image:url( "../icons/coolandclean/list_heading.png" ); + background-repeat:repeat; + background-color: #F7F7F7; +} + +/* The secondary background colour, light blue, primary theme colour. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #D1D9E1; +} + +/* Background for selected headers. */ +.headerSelected { + background-image:url( "../icons/coolandclean/home_hover.png" ); + background-repeat:repeat; + color: #333333; +} + + +/* Foreground colour used for h1, h2, b, tr, details and albumcomments. */ +h1, h2, b, tr, .detail, .albumComment { + color: #333333; +} + +/* Table sizing */ +table { + font-size: 100%; + line-height: 130%; + padding: 0; + border: 0; + margin: 0 0 0 0; +} + +/* Main frame image & colour */ +.mainframe { + background-image:url( "../icons/coolandclean/background_main.png" ); + background-repeat:no-repeat; + background-attachment:fixed; + background-color: #D1D9E1; + background-position:right; +} + +/* Right frame background. */ +.rightframe { + background-color: #D1D9E1; + background-image:none; +} + +/* Back image */ +.back { + background-image:url( "../icons/coolandclean/back.png" ); +} + +/* Forward image */ +.forward { + background-image:url( "../icons/coolandclean/forward.png" ); +} + +/* Link colour */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #656569; +} + +/* Link hover colour */ +a:hover, a:hover * { + text-decoration: none; + color: #333333; +} + +/* Colour for warning messages. */ +.warning { + color: #AA1F15; +} + +/* The primary foreground colour. */ +body { + background-color: #D1D9E1; + scrollbar-arrow-color: #636363; + scrollbar-track-color: #D1D9E1; +} + +/* The album comments. */ +.albumComment { + width: 50em; + font-size: 8pt; + line-height: 1.4em; + padding-top: 0.25em; +} + +/* The log. */ +.log { + font-weight: bold; + white-space: nowrap; + font-size: 8pt; + line-height: 1em; +} + +/* The help, status & web payer settings tables. */ +.ruleTableHeader, .ruleTableCell { + margin: 5px; + padding: 5px; +} + diff --git a/subsonic-main/src/main/webapp/style/default.css b/subsonic-main/src/main/webapp/style/default.css new file mode 100644 index 00000000..50182327 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/default.css @@ -0,0 +1,245 @@ +/* + * CSS styleshet for default theme. + * + * Note that attributes that are typically changed by theme authors are + * placed at the top. + * + * Author: Sindre Mehus + */ + +/* The primary background color (light blue). */ +.bgcolor1 { + background-color: #EFEFEF; +} + +/* The secondary background color (darker blue). */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #DEE3E7 +} + +/* Put stuff here if you need to customize any of the frames. */ +.mainframe { +} +.topframe { +} +.leftframe { +} +.rightframe { +} +.playlistframe { +} + +/* Background color for selected header. */ +.headerSelected { + background-color: lightyellow; +} + +/* Background color for form controls (use default). */ +input, select { +} + +/* Hover color for form controls (use default). */ +input:hover, select:hover { +} + +/* The primary foreground color (black). */ +body { + color: black; +} + +/* The secondary foreground color used for h1, details etc (gray). */ +h1, .detail, .albumComment { + color: #696969; +} + +/* Foreground color used for h2, bold and tr. */ +h2, b, tr { + color: #333333; +} + +/* Link color */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #006699 +} + +/* Link hover color */ +a:hover, a:hover * { + text-decoration: underline; + color: #DD6900 +} + +/* Color for warning messages. */ +.warning { + color: red; +} + +/* Simple dark border. */ +.border1, .ruleTableHeader, .ruleTableCell, .headerSelected, .log { + border: 1px solid black; +} + +/* Scrollbar colors (supported on IE and Opera) */ +body { + scrollbar-face-color: #DEE3E7; + scrollbar-highlight-color: #FFFFFF; + scrollbar-shadow-color: #DEE3E7; + scrollbar-3dlight-color: #D1D7DC; + scrollbar-arrow-color: #006699; + scrollbar-track-color: #EFEFEF; + scrollbar-darkshadow-color: #98AAB1; +} + +/* Font 1 */ +body, h2, form, label, table, a { + font-family: verdana, arial, sans-serif; +} + +/* Font 2 */ +h1, h1 a, .logo { + font-family: arial, sans-serif; +} + +/*************************************************************************************** + * The rest of the CSS is typically not changed in other themes (but not necessarily so). + ***************************************************************************************/ + +body { + padding:0; + border:0; + margin:0.75em; + font-size: 9pt; + line-height: 1.5em; +} + +p { + padding:0; + border:0; + margin:0 0 1em 0; +} + +.dense { + white-space: nowrap; + margin: 0; + line-height: 1.3em +} + +h1 { + white-space: nowrap; + font-size: 140%; + padding: 0 0 0.2em 0; + border: 0; + margin: 0; +} + +h2 { + white-space: nowrap; + font-size: 100%; + margin: 1em 0 0.2em 0; +} + +form { + font-size: 100%; + line-height: 140%; + padding: 0; + border: 0; + margin: 0; +} + +input, select, textarea { + font-size: 9pt; +} + +label { + font-size: 100%; + line-height: 140%; +} + +table { + font-size: 100%; + line-height: 140%; + padding: 0; + border: 0; + margin: 0 0 0.4em 0; +} + +/* Table with some white space above it.*/ +table.indent { + margin: 1em 0 0.4em 0; +} + +a { + font-size: 100%; + text-decoration: none +} + +img { + border-style: none; + border: 0; + margin: 0; + padding: 0; + vertical-align: middle; +} + +.headerSelected { + padding: 0.25em; +} + +.detail { + white-space: nowrap; + font-size: 8pt; + line-height: 1.25em; +} + +.warning { + white-space: nowrap; +} + +.logo { + white-space: nowrap; + font-size: 16pt; +} + +.back, .forward { + background-position:center left; + background-repeat:no-repeat; + padding-left: 16px; + line-height: 16px; +} + +.back { + background-image:url("../icons/back.gif"); +} + +.forward { + background-image:url("../icons/forward.gif"); +} + +.albumComment { + width: 50em; + font-size: 8pt; + line-height: 1.4em; + padding-top: 0.25em; +} + +.log { + white-space: nowrap; + font-size: 8pt; + line-height: 1em; +} + +.checkbox { +} + +/* Table with simple lines between the cells. */ +.ruleTable { + border-collapse: collapse; +} + +.ruleTableHeader, .ruleTableCell { + margin: 5px; + padding: 5px; +} + +.ruleTableHeader { + font-weight: bold; +} diff --git a/subsonic-main/src/main/webapp/style/denim.css b/subsonic-main/src/main/webapp/style/denim.css new file mode 100644 index 00000000..b273a559 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/denim.css @@ -0,0 +1,90 @@ +/* + * CSS styleshet for the "Denim" theme. + * + * Author: Thomas Bruce Dyrud (thomasbrucedyrud[at]gmail.com) + * + */ + +@import "default.css"; + +/* The primary background colour. */ +.bgcolor1 { + background-color: #456993; +} + +/* The secondary background colour, light blue, primary theme colour. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #456993; + color: #EFE9D9; +} + +/* Background colour for selected header, log etc. */ +.headerSelected { + color: #EFE9D9; + background-color: #456993; + border: 1px solid #EFE9D9; +} + + +/* The secondary foreground colour used for h1, details etc. */ +h1, .detail, .albumComment { + color: #EFE9D9; +} + +/* Foreground colour used for h2, bold and tr. */ +h2, b, tr { + color: #EFE9D9; +} + +/* Table sizing */ +table { + margin: 0 0 0 0; +} + +/* Main frame image & colour */ +.mainframe { + background-color: #456993; + background-position:right; +} + + +/* Back image */ +.back { + background-image:url( "../icons/denim/back.png" ); +} + +/* Forward image */ +.forward { + background-image:url( "../icons/denim/forward.png" ); +} + + +/* Link colour */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #B6BEC2; +} + +/* Link hover colour */ +a:hover, a:hover * { + text-decoration: underline; + color: #B6BEC2; +} + +/* Colour for warning messages. */ +.warning { + color: #990099; +} + +/* The primary foreground colour. */ +body { + color: #EFE9D9; + background-color: #DDDDDD; +} + +html { + background-color: transparent; +} + +label, p { + color: #CCC; +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/style/groove.css b/subsonic-main/src/main/webapp/style/groove.css new file mode 100644 index 00000000..88ae3e2d --- /dev/null +++ b/subsonic-main/src/main/webapp/style/groove.css @@ -0,0 +1,102 @@ +/* + * CSS styleshet for the "Groove" theme. + * + * Author: Thomas Bruce Dyrud (thomasbrucedyrud[at]gmail.com) + * + * Moified version of the "Cool and Clean" and "Monochrome Black" themes. + * (Cool and Clean created by: Dan Eriksen - dan.o.eriksen[at]gmail.com ) + * (Monochrome Black created by: David D - ddavis1[at]gmail.com ) + * + * + * Icons used are released under Creative Commons. + * Heading icons: (http://toffeenut.deviantart.com/art/Black-Neon-Agua-iPhone-Theme-85452072) + * Main theme icon part of itunes icon pack created by Michael Flarup (http://pixelresort.com) + */ + +@import "default.css"; + +/* The primary background colour. */ +.bgcolor1 { + background-color: #222; +} + +/* The secondary background colour, light blue, primary theme colour. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #222; + color: #FFFFFF; + +} + +/* Background colour for selected header, log etc. */ +.headerSelected { + color: #FFFFFF; + background-color: #222; + border: 1px solid #eee; +} + + +/* The secondary foreground colour used for h1, details etc. */ +h1, .detail, .albumComment { + color: #FFFFFF; +} + +/* Foreground colour used for h2, bold and tr. */ +h2, b, tr { + color: #FFFFFF; +} + +/* Table sizing */ +table { + margin: 0 0 0 0; +} + +/* Main frame image & colour */ +.mainframe { + background-image:url( "../icons/groove/background_main.png" ); + background-repeat:no-repeat; + background-attachment:fixed; + background-color: #222; + background-position:right; +} + + +/* Back image */ +.back { + background-image:url( "../icons/groove/back.png" ); +} + +/* Forward image */ +.forward { + background-image:url( "../icons/groove/forward.png" ); +} + + +/* Link colour */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #FFFFFF; +} + +/* Link hover colour */ +a:hover, a:hover * { + text-decoration: underline; + color: #FFFFFF; +} + +/* Colour for warning messages. */ +.warning { + color: #990099; +} + +/* The primary foreground colour. */ +body { + color: #FFFFFF; + background-color: #DDDDDD; +} + +html { + background-color: transparent; +} + +label, p { + color: #CCC; +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/style/groove_simple.css b/subsonic-main/src/main/webapp/style/groove_simple.css new file mode 100644 index 00000000..83b3ac98 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/groove_simple.css @@ -0,0 +1,32 @@ +/* + * CSS styleshet for the "Groove (Simple)" theme. + * + * Author: Thomas Bruce Dyrud (thomasbrucedyrud[at]gmail.com) + * + * Moified version of the "Cool and Clean" and "Monochrome Black" themes. + * (Cool and Clean created by: Dan Eriksen - dan.o.eriksen[at]gmail.com ) + * (Monochrome Black created by: David D - ddavis1[at]gmail.com ) + * + * + * Icons used are released under Creative Commons. + * Heading icons: (http://toffeenut.deviantart.com/art/Black-Neon-Agua-iPhone-Theme-85452072) + * Main theme icon part of itunes icon pack created by Michael Flarup (http://pixelresort.com) + */ + +@import "groove.css"; + +/* Main frame image */ +.mainframe { + background-image:url( "../icons/groove_simple/background_main_blank.png" ); +} + + +/* Back image */ +.back { + background-image:url( "../icons/groove/back.png" ); +} + +/* Forward image */ +.forward { + background-image:url( "../icons/groove/forward.png" ); +} diff --git a/subsonic-main/src/main/webapp/style/hd.css b/subsonic-main/src/main/webapp/style/hd.css new file mode 100644 index 00000000..3a5c3f7d --- /dev/null +++ b/subsonic-main/src/main/webapp/style/hd.css @@ -0,0 +1,93 @@ +/* + * CSS styleshet for the "HD-1080" theme. + * + * Author: Sindre Mehus + */ + +@import "midnight.css"; + +/* The primary background color. */ +.bgcolor1 { + background-color: #000843; +} + +/* The secondary background color. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #00042E +} + +/* Put stuff here if you need to customize the body of the main frame. */ +.mainframe { + background-image:url('../icons/hd/background.png'); + background-repeat:no-repeat; + background-attachment:fixed; + background-color: #00042E +} + +/* Background color for selected header, log etc. */ +.headerSelected { + background-color: #CFD1D6; +} + +/* The primary foreground color. */ +body { + color: #CFD1D6; +} + +/* The secondary foreground color used for h1, details etc. */ +h1, .detail, .albumComment { + color: #CFD1D6; +} + +/* Foreground color used for h2, bold and tr. */ +h2, b, tr { + color: #CFD1D6; +} + +/* Link color */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #97D9FF +} + +/* Link hover color */ +a:hover, a:hover * { + color: orange; +} + +/* Scrollbar colors (supported on IE and Opera) */ +body { + scrollbar-face-color: #00042E; + scrollbar-highlight-color: #000843; + scrollbar-shadow-color: #00042E; + scrollbar-3dlight-color: #00042E; + scrollbar-arrow-color: #000843; + scrollbar-track-color: #000843; + scrollbar-darkshadow-color: #000843; +} + +/* Font 1 */ +body, h2, form, input, select, label, table, a, h1, h1 a, .logo { + font-family: calibri, arial, sans-serif; +} + +body { + margin:1.5em; + font-size: 14pt; +} + +h1, h2, th { + font-weight:normal; +} + +input, select { + font-size: 100%; +} + +.detail { + font-size: 12pt; +} + +.albumComment, .log { + font-size: 12pt; +} + diff --git a/subsonic-main/src/main/webapp/style/hd1080.css b/subsonic-main/src/main/webapp/style/hd1080.css new file mode 100644 index 00000000..b11e7f1e --- /dev/null +++ b/subsonic-main/src/main/webapp/style/hd1080.css @@ -0,0 +1,17 @@ +/* + * CSS styleshet for the "HD-1080" theme. + * + * Author: Sindre Mehus + */ + +@import "hd.css"; + +body { + margin:1.5em; + font-size: 14pt; +} + +.detail, .albumComment, .log { + font-size: 12pt; +} + diff --git a/subsonic-main/src/main/webapp/style/hd720.css b/subsonic-main/src/main/webapp/style/hd720.css new file mode 100644 index 00000000..0edb8ee4 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/hd720.css @@ -0,0 +1,16 @@ +/* + * CSS styleshet for the "HD-720" theme. + * + * Author: Sindre Mehus + */ + +@import "hd.css"; + +body { + margin:0.5em; + font-size: 11pt; +} + +.detail, .albumComment, .log { + font-size: 9pt; +} diff --git a/subsonic-main/src/main/webapp/style/hd768.css b/subsonic-main/src/main/webapp/style/hd768.css new file mode 100644 index 00000000..c7b7b25a --- /dev/null +++ b/subsonic-main/src/main/webapp/style/hd768.css @@ -0,0 +1,16 @@ +/* + * CSS styleshet for the "HD-768" theme. + * + * Author: Sindre Mehus + */ + +@import "hd.css"; + +body { + margin:0.5em; + font-size: 12pt; +} + +.detail, .albumComment, .log { + font-size: 10pt; +} diff --git a/subsonic-main/src/main/webapp/style/hicon.css b/subsonic-main/src/main/webapp/style/hicon.css new file mode 100644 index 00000000..ea13f95c --- /dev/null +++ b/subsonic-main/src/main/webapp/style/hicon.css @@ -0,0 +1,85 @@ +/* + * CSS styleshet for the "High Contast" theme. + * + * Author: Jeebs (Fisher Evans) + */ + +@import "default.css"; + +table { + color: #5c5c5c; +} + +/* The primary background color. */ +.bgcolor1 { + background-color: white; +} + +/* The secondary background color. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: white; +} + +body.bgcolor2 { + border-bottom: 1px solid #5c5c5c; +} + +/* Background color for selected header, log etc. */ +.headerSelected { + color: #5c5c5c; + background-color: white; +} + +/* The primary foreground color. */ +body { + color: #5c5c5c; +} + +/* The secondary foreground color used for h1, details etc. */ +h1, .detail, .albumComment { + color: #5c5c5c; +} + +/* Foreground color used for h2, bold and tr. */ +h2, b, tr { + color: #5c5c5c; +} + +/* Link color */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: black +} + +/* Link hover color */ +a:hover, a:hover * { + text-decoration: underline; + color: #5c5c5c; +} + +/* Color for warning messages. */ +.warning { + color: red; +} + +/* Simple border. */ +.border1, .ruleTableHeader, .ruleTableCell, .headerSelected, .log { + border: 1px solid #5c5c5c; +} + +/* Scrollbar colors (supported on IE and Opera) */ +body { + scrollbar-face-color: white; + scrollbar-highlight-color: #5c5c5c; + scrollbar-shadow-color: white; + scrollbar-3dlight-color: white; + scrollbar-arrow-color: #5c5c5c; + scrollbar-track-color: #5c5c5c; + scrollbar-darkshadow-color: #5c5c5c; +} + +.back { + background-image:url("../icons/midnight/back.png");background-position: 0px 3px; background-repeat:no-repeat; padding-left: 16px; line-height: 16px; +} +.forward { + background-image:url("../icons/midnight/forward.png");background-position: 0px 3px; background-repeat:no-repeat; padding-left: 16px; line-height: 16px; +} diff --git a/subsonic-main/src/main/webapp/style/hiconi.css b/subsonic-main/src/main/webapp/style/hiconi.css new file mode 100644 index 00000000..81e8ed01 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/hiconi.css @@ -0,0 +1,85 @@ +/* + * CSS styleshet for the "High Contast (Inverted)" theme. + * + * Author: Jeebs (Fisher Evans) + */ + +@import "default.css"; + +table { + color: #a3a3a3; +} + +/* The primary background color. */ +.bgcolor1 { + background-color: black; +} + +/* The secondary background color. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: black; +} + +body.bgcolor2 { + border-bottom: 1px solid #a3a3a3; +} + +/* Background color for selected header, log etc. */ +.headerSelected { + color: #a3a3a3; + background-color: black; +} + +/* The primary foreground color. */ +body { + color: #a3a3a3; +} + +/* The secondary foreground color used for h1, details etc. */ +h1, .detail, .albumComment { + color: #a3a3a3; +} + +/* Foreground color used for h2, bold and tr. */ +h2, b, tr { + color: #a3a3a3; +} + +/* Link color */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: white +} + +/* Link hover color */ +a:hover, a:hover * { + text-decoration: underline; + color: #a3a3a3; +} + +/* Color for warning messages. */ +.warning { + color: red; +} + +/* Simple border. */ +.border1, .ruleTableHeader, .ruleTableCell, .headerSelected, .log { + border: 1px solid #a3a3a3; +} + +/* Scrollbar colors (supported on IE and Opera) */ +body { + scrollbar-face-color: black; + scrollbar-highlight-color: #a3a3a3; + scrollbar-shadow-color: black; + scrollbar-3dlight-color: black; + scrollbar-arrow-color: #a3a3a3; + scrollbar-track-color: #a3a3a3; + scrollbar-darkshadow-color: #a3a3a3; +} + +.back { + background-image:url("../icons/midnight/back.png");background-position: 0px 3px; background-repeat:no-repeat; padding-left: 16px; line-height: 16px; +} +.forward { + background-image:url("../icons/midnight/forward.png");background-position: 0px 3px; background-repeat:no-repeat; padding-left: 16px; line-height: 16px; +} diff --git a/subsonic-main/src/main/webapp/style/hitech.css b/subsonic-main/src/main/webapp/style/hitech.css new file mode 100644 index 00000000..a5fc6b3e --- /dev/null +++ b/subsonic-main/src/main/webapp/style/hitech.css @@ -0,0 +1,96 @@ +/* + * CSS styleshet for the "High Tech" theme. + * + * Author: Jeebs (Fisher Evans) + */ + +@import "default.css"; + +table { + color: #d2f1d5; +} + +/* The primary background color. */ +.bgcolor1 { + background-color: #090a09; +} + +/* The secondary background color. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #090a09; +} + +body.bgcolor2 { + border-bottom: 1px solid #272727; +} + +.bgcolor2 { + background-image:url(../icons/hitech/bg.jpg); +} + +/* Background color for selected header, log etc. */ +.headerSelected { + color: #d2f1d5; + background-color: #090a09; +} + +/* The primary foreground color. */ +body { + color: #d2f1d5; +} + +/* The secondary foreground color used for h1, details etc. */ +h1, .detail, .albumComment { + color: #d2f1d5; +} + +/* Foreground color used for h2, bold and tr. */ +h2, b, tr { + color: #d2f1d5; +} + +/* Link color */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #00d61b +} + +/* Link hover color */ +a:hover, a:hover * { + text-decoration: underline; + color: #ffffff; +} + +/* Color for warning messages. */ +.warning { + color: white; +} + +/* Simple border. */ +.border1, .ruleTableHeader, .ruleTableCell, .headerSelected, .log { + border: 1px solid #272727; +} + +/* Scrollbar colors (supported on IE and Opera) */ +body { + scrollbar-face-color: #253126; + scrollbar-highlight-color: #00c52c; + scrollbar-shadow-color: #253126; + scrollbar-3dlight-color: #253126; + scrollbar-arrow-color: #00c52c; + scrollbar-track-color: #00c52c; + scrollbar-darkshadow-color: #00c52c; +} + +.back { + background-image:url("../icons/midnight/back.png");background-position: 0px 3px; background-repeat:no-repeat; padding-left: 16px; line-height: 16px; +} +.forward { + background-image:url("../icons/midnight/forward.png");background-position: 0px 3px; background-repeat:no-repeat; padding-left: 16px; line-height: 16px; +} + +.mainframe { + background-image:url( "../icons/hitech/bg2.jpg" ); + background-repeat:no-repeat; + background-attachment:fixed; + background-position:bottom right; +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/style/lowerleftfade.png b/subsonic-main/src/main/webapp/style/lowerleftfade.png Binary files differnew file mode 100644 index 00000000..cc0665b4 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/lowerleftfade.png diff --git a/subsonic-main/src/main/webapp/style/midnight.css b/subsonic-main/src/main/webapp/style/midnight.css new file mode 100644 index 00000000..b6519bb8 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/midnight.css @@ -0,0 +1,77 @@ +/* + * CSS styleshet for the "2 Minutes To Midnight" theme. + * + * Author: Sindre Mehus + */ + +@import "default.css"; + +/* The primary background color. */ +.bgcolor1 { + background-color: #656569; +} + +/* The secondary background color. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #4D4C52 +} + +/* Background color for selected header, log etc. */ +.headerSelected { + color: black; + background-color: #DDDDDD; +} + +/* The primary foreground color. */ +body { + color: #DDDDDD; +} + +/* The secondary foreground color used for h1, details etc. */ +h1, .detail, .albumComment { + color: #DDDDDD; +} + +/* Foreground color used for h2, bold and tr. */ +h2, b, tr { + color: #DDDDDD; +} + +/* Link color */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #BAD9F2 +} + +/* Link hover color */ +a:hover, a:hover * { + text-decoration: underline; + color: orange; +} + +/* Color for warning messages. */ +.warning { + color: orange; +} + +/* Simple border. */ +.border1, .ruleTableHeader, .ruleTableCell, .headerSelected, .log { + border: 1px solid white; +} + +/* Scrollbar colors (supported on IE and Opera) */ +body { + scrollbar-face-color: #4D4C52; + scrollbar-highlight-color: #656569; + scrollbar-shadow-color: #4D4C52; + scrollbar-3dlight-color: #4D4C52; + scrollbar-arrow-color: #656569; + scrollbar-track-color: #656569; + scrollbar-darkshadow-color: #656569; +} + +.back { + background-image:url("../icons/midnight/back.png");background-position: 0px 3px; background-repeat:no-repeat; padding-left: 16px; line-height: 16px; +} +.forward { + background-image:url("../icons/midnight/forward.png");background-position: 0px 3px; background-repeat:no-repeat; padding-left: 16px; line-height: 16px; +} diff --git a/subsonic-main/src/main/webapp/style/midnightfun.css b/subsonic-main/src/main/webapp/style/midnightfun.css new file mode 100644 index 00000000..07f69420 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/midnightfun.css @@ -0,0 +1,158 @@ +/* + * CSS styleshet for the http://www.midnightfun.co.uk "MidnightFun" theme. + * + * Author: Don Pearson + */ + +@import "default.css"; + +/* The primary background colour. */ +.bgcolor1 { + background-image:url('../icons/midnightfun/midnightfun_text_back.jpg'); + background-repeat:repeat; + background-color: #AAAAAA; +} + +/* The secondary background colour. */ +.bgcolor2, .ruleTableHeader, .log { + background-image:url('../icons/midnightfun/midnightfun_background.gif'); + background-repeat:repeat; + background-attachment:fixed; + background-color: #C0C0C0; +} + +/* Background colour for selected header, log etc. */ +.headerSelected { + background-image:url('../icons/midnightfun/midnightfun_home_hover.jpg'); + background-repeat:repeat; + color: #000000; + background-color: #C0C0C0; +} + + +/* The secondary foreground colour used for h1, details etc. */ +h1, .detail, .albumComment { + color: #333333; +} + +/* Foreground colour used for h2, bold and tr. */ +h2, b, tr { + color: #000000; +} + +/* Table sizing */ +table { + margin: 0 0 0 0; +} + +/* Main frame image & colour */ +.mainframe, .rightframe { + background-image:url('../icons/midnightfun/midnightfun_background.gif'); + background-repeat:repeat; + background-attachment:fixed; + background-color: #C0C0C0; +} + +/* Back image */ +.back { + background-image:url("../icons/midnightfun/midnightfun_back.png"); +} + +/* Forward image */ +.forward { + background-image:url("../icons/midnightfun/midnightfun_forward.png"); +} + +/* Link colour */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #656569; +} + +/* Link hover colour */ +a:hover, a:hover * { + text-decoration: underline; + color: #000000; +} + +/* Colour for warning messages. */ +.warning { + color: #990099; +} + +/* Background colour for form controls. */ +input, select { + background-image:url('../icons/midnightfun/midnightfun_form_controls.jpg'); + background-repeat:repeat; + color: #FFFFFF; + background-color: #AAAAAA; +} + +/* Hover colour for form controls. */ +input:hover, select:hover { + background-image:url('../icons/midnightfun/midnightfun_form_controls_hover.jpg'); + background-repeat:repeat; + color: #000000; + background-color: #C0C0C0; +} + +/* Background colour for option controls. */ +option { + font-weight: bold; + background-color: #666666; + color: #FFFFFF; +} + +/* Background colour for option comments. */ +textarea { + background-image:url('../icons/midnightfun/midnightfun_form_controls.jpg'); + background-repeat:repeat; + background-color: #AAAAAA; + color: #FFFFFF; +} + +/* The primary foreground colour. */ +body { + background-color: #C0C0C0; + scrollbar-face-color: #CCCCCC; + scrollbar-highlight-color: #FFFFFF; + scrollbar-shadow-color: #CCCCCC; + scrollbar-3dlight-color: #D1D7DC; + scrollbar-arrow-color: #000000; + scrollbar-track-color: #C0C0C0; + scrollbar-darkshadow-color: #98AAB1; +} + +/* The album comments. */ +.albumComment { + width: 50em; + font-size: 8pt; + line-height: 1.4em; + padding-top: 0.25em; + color: #000000; +} + +/* The log. */ +.log { + font-weight: bold; + white-space: nowrap; + font-size: 8pt; + line-height: 1em; + background-image:url('../icons/midnightfun/midnightfun_table.jpg'); + background-repeat:repeat; + color: #000000; + background-color: #C0C0C0; +} + +/* The help, status & web payer settings tables. */ +.ruleTableHeader, .ruleTableCell { + margin: 5px; + padding: 5px; + background-image:url('../icons/midnightfun/midnightfun_table.jpg'); + background-repeat:repeat; + background-attachment:fixed; + color: #FFFFFF; + background-color: #C0C0C0; +} + + +/* MidnightFun http://www.midnightfun.co.uk */ diff --git a/subsonic-main/src/main/webapp/style/monochrome.css b/subsonic-main/src/main/webapp/style/monochrome.css new file mode 100644 index 00000000..ce1bf47d --- /dev/null +++ b/subsonic-main/src/main/webapp/style/monochrome.css @@ -0,0 +1,111 @@ +/* + * CSS styleshet for monochrome style + * + * Author: David D ddavis1@gmail.com + */ + +@import "default.css"; + +/* highlights to contrast with bgcolor2. */ +.bgcolor1 { + background-color: #EEE; +} + +/* The primary background colour, light blue, primary theme colour. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #CCC; +} + +/* Background colour for selected header, log etc. */ +.headerSelected { + color: #000000; + background-color: #AAAAAA; +} + + +/* The secondary foreground colour used for h1, details etc. */ +h1, .detail, .albumComment { + color: #000000; +} + +/* Foreground colour used for h2, bold and tr. */ +h2, b, tr { + color: #000000; +} + +/* Table sizing */ +table { + margin: 0 0 0 0; +} + +/* Main frame image & colour */ +.mainframe, .rightframe { + background-color: #EEE; +} + +/* Link colour */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #000000; +} + +/* Link hover colour */ +a:hover, a:hover * { + text-decoration: underline; + color: #FFFFFF; +} + +/* Colour for warning messages. */ +.warning { + color: #990099; +} + +/* Background colour for form controls. */ +input, select { + color: #333; + background-color: #EEE; +} + +/* Hover colour for form controls. */ +input:hover, select:hover { + color: #000000; + background-color: #FFF; +} + +/* Background colour for option controls. */ +option { + font-weight: bold; + background-color: #666666; + color: #FFFFFF; +} + +/* The primary foreground colour. */ +body { + background-color: #EEEEEE; +} + +/* The album comments. */ +.albumComment { + width: 50em; + font-size: 8pt; + line-height: 1.4em; + padding-top: 0.25em; + color: #000000; +} + +/* The log. */ +.log { + font-weight: bold; + white-space: nowrap; + font-size: 8pt; + line-height: 1em; + color: #000000; + background-color: #C0C0C0; +} + +/* The help, status & web payer settings tables. */ +.ruleTableHeader, .ruleTableCell { + margin: 5px; + padding: 5px; + color: #FFFFFF; + background-color: #C0C0C0; +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/style/monochrome_black.css b/subsonic-main/src/main/webapp/style/monochrome_black.css new file mode 100644 index 00000000..0a9f42d3 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/monochrome_black.css @@ -0,0 +1,115 @@ +/* + * CSS styleshet for monochrome style + * + * Author: David D ddavis1@gmail.com + */ + +@import "default.css"; + +/* The primary background colour. */ +.bgcolor1 { + background-color: #222; +} + +/* The secondary background colour, light blue, primary theme colour. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #000000; +} + +/* Background colour for selected header, log etc. */ +.headerSelected { + color: #FFFFFF; + background-color: #333333; +} + + +/* The secondary foreground colour used for h1, details etc. */ +h1, .detail, .albumComment { + color: #FFFFFF; +} + +/* Foreground colour used for h2, bold and tr. */ +h2, b, tr { + color: #FFFFFF; +} + +/* Table sizing */ +table { + margin: 0 0 0 0; +} + +/* Main frame image & colour */ +.mainframe, .rightframe { + background-color: #222; +} + +/* Link colour */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #FFFFFF; +} + +/* Link hover colour */ +a:hover, a:hover * { + text-decoration: underline; + color: #FFFFFF; +} + +/* Colour for warning messages. */ +.warning { + color: #990099; +} + +/* Background colour for form controls. */ +input, select { + color: #000; + background-color: #EEE; +} + +/* Hover colour for form controls. */ +input:hover, select:hover { + color: #000000; + background-color: #FFF; +} + +/* Background colour for option controls. */ +option { + font-weight: bold; + background-color: #666666; + color: #FFFFFF; +} + +/* The primary foreground colour. */ +body { + background-color: #DDDDDD; +} + +/* The album comments. */ +.albumComment { + width: 50em; + font-size: 8pt; + line-height: 1.4em; + padding-top: 0.25em; + color: #000000; +} + +/* The log. */ +.log { + font-weight: bold; + white-space: nowrap; + font-size: 8pt; + line-height: 1em; + color: #000000; + background-color: #C0C0C0; +} + +/* The help, status & web payer settings tables. */ +.ruleTableHeader, .ruleTableCell { + margin: 5px; + padding: 5px; + color: #FFFFFF; + background-color: #C0C0C0; +} + +label, p { + color: #CCC; +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/style/pinkpanther.css b/subsonic-main/src/main/webapp/style/pinkpanther.css new file mode 100644 index 00000000..f72494d7 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/pinkpanther.css @@ -0,0 +1,91 @@ +/* + * CSS styleshet for the "PinkPanther" theme. + * + * Author: Thomas Bruce Dyrud (thomasbrucedyrud[at]gmail.com) + * + */ + +@import "default.css"; + +/* The primary background colour. */ +.bgcolor1 { + background-color: #402c31; +} + +/* The secondary background colour, light blue, primary theme colour. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #402c31; + color: #EFE9D9; +} + +/* Background colour for selected header, log etc. */ +.headerSelected { + color: #EFE9D9; + background-color: #402c31; + border: 1px solid #EFE9D9; +} + + +/* The secondary foreground colour used for h1, details etc. */ +h1, .detail, .albumComment { + color: #EFE9D9; +} + +/* Foreground colour used for h2, bold and tr. */ +h2, b, tr { + color: #EFE9D9; +} + +/* Table sizing */ +table { + margin: 0 0 0 0; +} + +/* Main frame image & colour */ +.mainframe { + background-color: #402c31; + background-position:right; +} + + +/* Back image */ +.back { + background-image:url( "../icons/pinkpanther/back.png" ); +} + +/* Forward image */ +.forward { + background-image:url( "../icons/pinkpanther/forward.png" ); +} + + +/* Link colour */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #11bdcb; +} + +/* Link hover colour */ +a:hover, a:hover * { + text-decoration: underline; + color: #11bdcb; +} + +/* Colour for warning messages. */ +.warning { + color: #990099; +} + + +/* The primary foreground colour. */ +body { + color: #EFE9D9; + background-color: #DDDDDD; +} + +html { + background-color: transparent; +} + +label, p { + color: #CCC; +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/style/ripserver.css b/subsonic-main/src/main/webapp/style/ripserver.css new file mode 100644 index 00000000..9959fabe --- /dev/null +++ b/subsonic-main/src/main/webapp/style/ripserver.css @@ -0,0 +1,44 @@ +/* + * CSS styleshet for the "Ripserver" theme. + * + * Author: Ralph Hill + */ + +@import "default.css"; + +/* The primary background color (light blue). */ +.bgcolor1 { + background-color: #FFFFFF; +} + +/* The secondary background color (darker blue). */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #EBEFF9 +} + +.mainframe { + background-image:url('../icons/ripserver/background.png'); + background-repeat:no-repeat; + background-attachment:fixed; + background-color: #FFFFFF +} + +/* Link color */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #0076B6 +} + +/* Link hover color */ +a:hover, a:hover * { + color: orange +} + +body { + scrollbar-face-color: #DEE3E7; + scrollbar-highlight-color: #FFFFFF; + scrollbar-shadow-color: #DEE3E7; + scrollbar-3dlight-color: #D1D7DC; + scrollbar-arrow-color: #006699; + scrollbar-track-color: #EFEFEF; + scrollbar-darkshadow-color: #98AAB1; +} diff --git a/subsonic-main/src/main/webapp/style/sandstorm.css b/subsonic-main/src/main/webapp/style/sandstorm.css new file mode 100644 index 00000000..89556bc9 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/sandstorm.css @@ -0,0 +1,39 @@ +/* + * CSS styleshet for the "Sandstorm" theme. + * + * Author: Sindre Mehus + */ + +@import "default.css"; + +/* The primary background color. */ +.bgcolor1 { + background-color: #F5F5D0 +} + +/* The secondary background color. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #CCCC99 +} + +/* Link color */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #057368 +} + +/* Link hover color */ +a:hover, a:hover * { + text-decoration: underline; + color: #DD6900 +} + +/* Scrollbar colors (supported on IE and Opera) */ +body { + scrollbar-face-color: #CCCC99; + scrollbar-highlight-color: #F5F5D0; + scrollbar-shadow-color: #CCCC99; + scrollbar-3dlight-color: #CCCC99; + scrollbar-arrow-color: #F5F5D0; + scrollbar-track-color: #F5F5D0; + scrollbar-darkshadow-color: #F5F5D0; +} diff --git a/subsonic-main/src/main/webapp/style/shadow.css b/subsonic-main/src/main/webapp/style/shadow.css new file mode 100644 index 00000000..144a34bc --- /dev/null +++ b/subsonic-main/src/main/webapp/style/shadow.css @@ -0,0 +1,107 @@ +/* + From http://www.positioniseverything.net/articles/dropshadows.html +*/ + +html>body .outerpair1 { + background: url( upperrightfade.png ) right top no-repeat; +} + +/* .outerpair1 must be given a width contraint, via either a width, +or by floating or absolute positioning. In this demo these are +applied from the second class name on the .outerpair1 DIV's. +This box also has one of the corner .png's. */ + +html>body .outerpair2 { + background: url( lowerleftfade.png ) left bottom no-repeat; + padding-top: 8px; + padding-left: 8px; +} + +/* .outerpair2 has padding equal to the shadow +thickness, and also has one of the corner .png's */ + +html>body .shadowbox { + background: url( shadow.png ) bottom right; +} + +/* .shadowbox holds the main shadow .png */ + +html>body .innerbox { + position: relative; + left: -8px; + top: -8px; +} + +/* .innerbox is made "relative" and is "pulled" up and to +the left, by a distance equal to the thickness of the shadow. +Because this is a relative-based shift, the box retains its +exact dimensions without change. */ + +.shadowbox img { + border: 0; + vertical-align: bottom; +} + +/* Shadowed images should not be made "block" for eliminating the baseline +space under the images, because this may trigger IE background bugs. +Instead, use "vertical-align: bottom;" for this purpose. */ + +/*XXXXXXXXXXXXXXXXXX Custom width constraints and extra styling XXXXXXXXXXXXXXX*/ + +.floatimage { + float: left; /* Floating causes this box to shrinkwrap around sized content elements. */ + margin: 130px 0 0 450px; + display: inline; /* IE doubled margin bug is defeated via this fixer rule. */ +} + +.flashbox { +/* Absolute positioning also causes the shrinkwrap behavior. */ + position: absolute; + left: 377px; + top: 30px; +} + +.flashbox .innerbox { + background: #eed; + border: 1px solid #ccb; +} + +.absoluteimage { +/* Again, absolute positioning causes shrinkwrapping. */ + position: absolute; + left: 40px; + top: 200px; +} + +.textbox { + position: absolute; /* AP once more... */ + left: 20px; + top: 1.8em; +} + +.textbox .innerbox { + border: 1px solid #ccc; + background: #e8e8e8; + width: 330px; + height: 210px; + overflow: auto; +} + +/* Unlike the other items, the .textbox content is just text without a natural +width, and so shrinkwrapping fails, unless .innerbox is given a specific width. +All shadowed text elements will need a width of some kind to avoid a full-width +shadowed box, unless that is the desired effect. The width may be appied to +div.inner, div.outerpair1, or an external wrapper element. */ + +.linkbox { + position: absolute; /* AP once more... */ + left: 10px; + top: 6px; +} + +.linkbox .innerbox { + display: block; + background: #fff; + border: 1px solid #ccc; + padding: 3px 5px; +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/style/shadow.png b/subsonic-main/src/main/webapp/style/shadow.png Binary files differnew file mode 100644 index 00000000..7862c9bb --- /dev/null +++ b/subsonic-main/src/main/webapp/style/shadow.png diff --git a/subsonic-main/src/main/webapp/style/simplify.css b/subsonic-main/src/main/webapp/style/simplify.css new file mode 100644 index 00000000..d3ac78c1 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/simplify.css @@ -0,0 +1,90 @@ +/* + * CSS styleshet for the "Simplify" theme. + * + * Author: Thomas Bruce Dyrud (thomasbrucedyrud[at]gmail.com) + * + */ + +@import "default.css"; + +/* The primary background colour. */ +.bgcolor1 { + background-color: #1b1b1b; +} + +/* The secondary background colour, light blue, primary theme colour. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #1b1b1b; + color: #FFFFFF; +} + +/* Background colour for selected header, log etc. */ +.headerSelected { + color: #FFFFFF; + background-color: #1b1b1b; + border: 1px solid #FFFFFF; +} + + +/* The secondary foreground colour used for h1, details etc. */ +h1, .detail, .albumComment { + color: #FFFFFF; +} + +/* Foreground colour used for h2, bold and tr. */ +h2, b, tr { + color: #FFFFFF; +} + +/* Table sizing */ +table { + margin: 0 0 0 0; +} + +/* Main frame image & colour */ +.mainframe { + background-color: #1b1b1b; + background-position:right; +} + + +/* Back image */ +.back { + background-image:url( "../icons/simplify/back.png" ); +} + +/* Forward image */ +.forward { + background-image:url( "../icons/simplify/forward.png" ); +} + + +/* Link colour */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #FFFFFF; +} + +/* Link hover colour */ +a:hover, a:hover * { + text-decoration: underline; + color: #FFFFFF; +} + +/* Colour for warning messages. */ +.warning { + color: #e7238b; +} + +/* The primary foreground colour. */ +body { + color: #FFFFFF; + background-color: #DDDDDD; +} + +html { + background-color: transparent; +} + +label, p { + color: #CCC; +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/style/slick.css b/subsonic-main/src/main/webapp/style/slick.css new file mode 100644 index 00000000..1ae02240 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/slick.css @@ -0,0 +1,89 @@ +/* + * CSS styleshet for the "Slick" theme. + * + * Author: Jeebs (Fisher Evans) + */ + +@import "default.css"; + +table { + color: #0e0e0e; +} + +/* The primary background color. */ +.bgcolor1 { + background-color: #0e0e0e; +} + +/* The secondary background color. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #0e0e0e; +} + +body.bgcolor2 { + border-bottom: 1px solid #67778c; +} + +.bgcolor2 { + background-image:url(../icons/slick/top_bg.jpg); +} + +/* Background color for selected header, log etc. */ +.headerSelected { + color: #0e0e0e; + background-color: #8eacc4; +} + +/* The primary foreground color. */ +body { + color: #ccd5dc; +} + +/* The secondary foreground color used for h1, details etc. */ +h1, .detail, .albumComment { + color: #ccd5dc; +} + +/* Foreground color used for h2, bold and tr. */ +h2, b, tr { + color: #ccd5dc; +} + +/* Link color */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #8a9aa7 +} + +/* Link hover color */ +a:hover, a:hover * { + text-decoration: underline; + color: #d2d9df; +} + +/* Color for warning messages. */ +.warning { + color: #ff4800; +} + +/* Simple border. */ +.border1, .ruleTableHeader, .ruleTableCell, .headerSelected, .log { + border: 1px solid #67778c; +} + +/* Scrollbar colors (supported on IE and Opera) */ +body { + scrollbar-face-color: #8eacc4; + scrollbar-highlight-color: #67778c; + scrollbar-shadow-color: #8eacc4; + scrollbar-3dlight-color: #8eacc4; + scrollbar-arrow-color: #67778c; + scrollbar-track-color: #67778c; + scrollbar-darkshadow-color: #67778c; +} + +.back { + background-image:url("../icons/midnight/back.png");background-position: 0px 3px; background-repeat:no-repeat; padding-left: 16px; line-height: 16px; +} +.forward { + background-image:url("../icons/midnight/forward.png");background-position: 0px 3px; background-repeat:no-repeat; padding-left: 16px; line-height: 16px; +} diff --git a/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png Binary files differnew file mode 100644 index 00000000..5b5dab2a --- /dev/null +++ b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png diff --git a/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_flat_75_ffffff_40x100.png Binary files differnew file mode 100644 index 00000000..ac8b229a --- /dev/null +++ b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_flat_75_ffffff_40x100.png diff --git a/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png Binary files differnew file mode 100644 index 00000000..ad3d6346 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png diff --git a/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_65_ffffff_1x400.png Binary files differnew file mode 100644 index 00000000..42ccba26 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_65_ffffff_1x400.png diff --git a/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_75_dadada_1x400.png b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_75_dadada_1x400.png Binary files differnew file mode 100644 index 00000000..5a46b47c --- /dev/null +++ b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_75_dadada_1x400.png diff --git a/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png Binary files differnew file mode 100644 index 00000000..86c2baa6 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png diff --git a/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png Binary files differnew file mode 100644 index 00000000..4443fdc1 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png diff --git a/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png Binary files differnew file mode 100644 index 00000000..7c9fa6c6 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png diff --git a/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_222222_256x240.png b/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_222222_256x240.png Binary files differnew file mode 100644 index 00000000..b273ff11 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_222222_256x240.png diff --git a/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_2e83ff_256x240.png b/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_2e83ff_256x240.png Binary files differnew file mode 100644 index 00000000..09d1cdc8 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_2e83ff_256x240.png diff --git a/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_454545_256x240.png b/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_454545_256x240.png Binary files differnew file mode 100644 index 00000000..59bd45b9 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_454545_256x240.png diff --git a/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_888888_256x240.png b/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_888888_256x240.png Binary files differnew file mode 100644 index 00000000..6d02426c --- /dev/null +++ b/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_888888_256x240.png diff --git a/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_cd0a0a_256x240.png b/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_cd0a0a_256x240.png Binary files differnew file mode 100644 index 00000000..2ab019b7 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/smoothness/images/ui-icons_cd0a0a_256x240.png diff --git a/subsonic-main/src/main/webapp/style/smoothness/jquery-ui-1.8.18.custom.css b/subsonic-main/src/main/webapp/style/smoothness/jquery-ui-1.8.18.custom.css new file mode 100644 index 00000000..4cfb50a4 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/smoothness/jquery-ui-1.8.18.custom.css @@ -0,0 +1,565 @@ +/* + * jQuery UI CSS Framework 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; } +.ui-helper-clearfix:after { clear: both; } +.ui-helper-clearfix { zoom: 1; } +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + + +/* + * jQuery UI CSS Framework 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } +.ui-widget-content a { color: #222222; } +.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } +.ui-widget-header a { color: #222222; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; } +.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* + * jQuery UI Resizable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizable#theming + */ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; } +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* + * jQuery UI Selectable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectable#theming + */ +.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } +/* + * jQuery UI Accordion 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Accordion#theming + */ +/* IE/Win - Fix animation bug - #4615 */ +.ui-accordion { width: 100%; } +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } +.ui-accordion .ui-accordion-li-fix { display: inline; } +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } +.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } +.ui-accordion .ui-accordion-content-active { display: block; } +/* + * jQuery UI Autocomplete 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete#theming + */ +.ui-autocomplete { position: absolute; cursor: default; } + +/* workarounds */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ + +/* + * jQuery UI Menu 1.8.18 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menu#theming + */ +.ui-menu { + list-style:none; + padding: 2px; + margin: 0; + display:block; + float: left; +} +.ui-menu .ui-menu { + margin-top: -3px; +} +.ui-menu .ui-menu-item { + margin:0; + padding: 0; + zoom: 1; + float: left; + clear: left; + width: 100%; +} +.ui-menu .ui-menu-item a { + text-decoration:none; + display:block; + padding:.2em .4em; + line-height:1.5; + zoom:1; +} +.ui-menu .ui-menu-item a.ui-state-hover, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} +/* + * jQuery UI Button 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Button#theming + */ +.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: hidden; *overflow: visible; } /* the overflow property removes extra width in IE */ +.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ +button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ +.ui-button-icons-only { width: 3.4em; } +button.ui-button-icons-only { width: 3.7em; } + +/*button text element */ +.ui-button .ui-button-text { display: block; line-height: 1.4; } +.ui-button-text-only .ui-button-text { padding: .4em 1em; } +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } +.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } +.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } +.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } +/* no icon support for input elements, provide padding by default */ +input.ui-button { padding: .4em 1em; } + +/*button icon element(s) */ +.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } +.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } +.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } +.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } + +/*button sets*/ +.ui-buttonset { margin-right: 7px; } +.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } + +/* workarounds */ +button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ +/* + * jQuery UI Dialog 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } +.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } +.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/* + * jQuery UI Slider 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider#theming + */ +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* + * jQuery UI Tabs 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs#theming + */ +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } +/* + * jQuery UI Datepicker 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Datepicker#theming + */ +.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +}/* + * jQuery UI Progressbar 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar#theming + */ +.ui-progressbar { height:2em; text-align: left; overflow: hidden; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/style/sonic.css b/subsonic-main/src/main/webapp/style/sonic.css new file mode 100644 index 00000000..526ac59d --- /dev/null +++ b/subsonic-main/src/main/webapp/style/sonic.css @@ -0,0 +1,88 @@ +/* + * CSS styleshet for the "Sonic" theme. + * + * Author: Thomas Bruce Dyrud (thomasbrucedyrud[at]gmail.com) + * + */ + +@import "default.css"; + +/* The primary background colour. */ +.bgcolor1 { + background-color: #e7e7e7; +} + +/* The secondary background colour, light blue, primary theme colour. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #e7e7e7; + color: #696969; +} + +/* Background colour for selected header, log etc. */ +.headerSelected { + color: #696969; + background-color: #e7e7e7; + border: 1px solid #696969; +} + + +/* The primary foreground color (black). */ +body { + color: #696969; + background-color: #DDDDDD; +} + +/* The secondary foreground colour used for h1, details etc. */ +h1, .detail, .albumComment { + color: #696969; +} + +/* Foreground colour used for h2, bold and tr. */ +h2, b, tr { + color: #696969; +} + +/* Table sizing */ +table { + margin: 0 0 0 0; +} + +/* Main frame image & colour */ +.mainframe { + background-color: #e7e7e7; +} + +/* Back image */ +.back { + background-image:url( "../icons/sonic/back.png" ); +} + +/* Forward image */ +.forward { + background-image:url( "../icons/sonic/forward.png" ); +} + + +/* Link colour */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #333333; +} + +/* Link hover colour */ +a:hover, a:hover * { + text-decoration: underline; + color: #696969; +} + +/* Colour for warning messages. */ +.warning { + color: #e7238b; +} + +html { + background-color: transparent; +} + +label, p { + color: #696969; +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/style/sonic_blue.css b/subsonic-main/src/main/webapp/style/sonic_blue.css new file mode 100644 index 00000000..7122ad59 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/sonic_blue.css @@ -0,0 +1,77 @@ +/* + * CSS styleshet for the "Sonic Blue" theme. + * + * Author: Thomas Bruce Dyrud (thomasbrucedyrud[at]gmail.com) + * + */ + +@import "sonic.css"; + +/* The primary background colour. */ +.bgcolor1 { + background-color: #456993; +} + +/* The secondary background colour, light blue, primary theme colour. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #456993; + color: #EFE9D9; +} + +/* Background colour for selected header, log etc. */ +.headerSelected { + color: #EFE9D9; + background-color: #456993; + border: 1px solid #EFE9D9; +} + +/* The primary foreground color (black). */ +body { + color: #EFE9D9; + background-color: #DDDDDD; +} + +/* The secondary foreground colour used for h1, details etc. */ +h1, .detail, .albumComment { + color: #EFE9D9; +} + +/* Foreground colour used for h2, bold and tr. */ +h2, b, tr { + color: #EFE9D9; +} + +/* Main frame image & colour */ +.mainframe { + background-color: #456993; +} + +/* Back image */ +.back { + background-image:url( "../icons/sonic_blue/back.png" ); +} + +/* Forward image */ +.forward { + background-image:url( "../icons/sonic_blue/forward.png" ); +} + + +/* Link colour */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #B6BEC2; +} + +/* Link hover colour */ +a:hover, a:hover * { + color: #B6BEC2; +} + +/* Colour for warning messages. */ +.warning { + color: #990099; +} + +label, p { + color: #CCC; +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/style/sonic_white.css b/subsonic-main/src/main/webapp/style/sonic_white.css new file mode 100644 index 00000000..0c28f138 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/sonic_white.css @@ -0,0 +1,78 @@ +/* + * CSS styleshet for the "Sonic White" theme. + * + * Author: Thomas Bruce Dyrud (thomasbrucedyrud[at]gmail.com) + * + */ + +@import "sonic.css"; + +/* The primary background colour. */ +.bgcolor1 { + background-color: #FFFFFF; +} + +/* The secondary background colour, light blue, primary theme colour. */ +.bgcolor2, .ruleTableHeader, .log { + background-color: #FFFFFF; + color: #696969; +} + +/* Background colour for selected header, log etc. */ +.headerSelected { + color: #696969; + background-color: #FFFFFF; + border: 1px solid #696969; +} + + +/* The primary foreground color (black). */ +body { + color: #696969; + background-color: #DDDDDD; +} + +/* The secondary foreground colour used for h1, details etc. */ +h1, .detail, .albumComment { + color: #696969; +} + +/* Foreground colour used for h2, bold and tr. */ +h2, b, tr { + color: #696969; +} + +/* Main frame image & colour */ +.mainframe { + background-color: #FFFFFF; +} + +/* Back image */ +.back { + background-image:url( "../icons/sonic_white/back.png" ); +} + +/* Forward image */ +.forward { + background-image:url( "../icons/sonic_white/forward.png" ); +} + + +/* Link colour */ +a:link, a:active, a:visited, a:link *, a:active *, a:visited * { + color: #333333; +} + +/* Link hover colour */ +a:hover, a:hover * { + color: #696969; +} + +/* Colour for warning messages. */ +.warning { + color: #e7238b; +} + +label, p { + color: #696969; +}
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/style/upperrightfade.png b/subsonic-main/src/main/webapp/style/upperrightfade.png Binary files differnew file mode 100644 index 00000000..cad0f2c7 --- /dev/null +++ b/subsonic-main/src/main/webapp/style/upperrightfade.png diff --git a/subsonic-main/src/main/webapp/xsd/albumList2_example_1.xml b/subsonic-main/src/main/webapp/xsd/albumList2_example_1.xml new file mode 100644 index 00000000..21684156 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/albumList2_example_1.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.8.0">
+ <albumList2>
+ <album id="1768" name="Duets" coverArt="al-1768" songCount="2" created="2002-11-09T15:44:40" duration="514" artist="Nik Kershaw" artistId="829"/>
+ <album id="2277" name="Hot" coverArt="al-2277" songCount="4" created="2004-11-28T00:06:52" duration="1110" artist="Melanie B" artistId="1242"/>
+ <album id="4201" name="Bande A Part" coverArt="al-4201" songCount="14" created="2007-10-29T19:25:05" duration="3061" artist="Nouvelle Vague" artistId="2060"/>
+ <album id="2910" name="Soundtrack From Twin Peaks" coverArt="al-2910" songCount="6" created="2002-11-17T09:58:42" duration="1802" artist="Angelo Badalamenti" artistId="1515"/>
+ <album id="3109" name="Wild One" coverArt="al-3109" songCount="38" created="2001-04-17T00:20:08" duration="9282" artist="Thin Lizzy" artistId="661"/>
+ <album id="1151" name="Perleporten" coverArt="al-1151" songCount="2" created="2002-11-16T22:24:22" duration="494" artist="Magnus Grønneberg" artistId="747"/>
+ <album id="2204" name="Wholesale Meats And Fish" coverArt="al-2204" songCount="24" created="2004-11-27T23:44:31" duration="5362" artist="Letters To Cleo" artistId="1216"/>
+ <album id="114" name="Sounds of the Seventies: AM Nuggets" coverArt="al-114" songCount="2" created="2004-03-09T07:32:46" duration="420" artist="Rubettes" artistId="97"/>
+ <album id="279" name="Waiting for the Day" coverArt="al-279" songCount="2" created="2004-11-27T17:49:19" duration="448" artist="Bachelor Girl" artistId="231"/>
+ <album id="4414" name="For Sale" songCount="14" created="2007-10-30T00:11:58" duration="2046" artist="The Beatles" artistId="509"/>
+ </albumList2>
+</subsonic-response>
+
diff --git a/subsonic-main/src/main/webapp/xsd/albumList_example_1.xml b/subsonic-main/src/main/webapp/xsd/albumList_example_1.xml new file mode 100644 index 00000000..d83482a9 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/albumList_example_1.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.6.0">
+
+ <albumList>
+ <album id="11" parent="1" title="Arrival" artist="ABBA" isDir="true" coverArt="22" userRating="4" averageRating="4.5"/>
+ <album id="12" parent="1" title="Super Trouper" artist="ABBA" isDir="true" coverArt="23" averageRating="4.4"/>
+ </albumList>
+
+</subsonic-response>
+
diff --git a/subsonic-main/src/main/webapp/xsd/album_example_1.xml b/subsonic-main/src/main/webapp/xsd/album_example_1.xml new file mode 100644 index 00000000..c1a8df27 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/album_example_1.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.8.0">
+
+ <album id="11053" name="High Voltage" coverArt="al-11053" songCount="8" created="2004-11-27T20:23:32" duration="2414" artist="AC/DC" artistId="5432">
+ <song id="71463" parent="71381" title="The Jack" album="High Voltage" artist="AC/DC" isDir="false" coverArt="71381" created="2004-11-08T23:36:11" duration="352" bitRate="128" size="5624132" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="ACDC/High voltage/ACDC - The Jack.mp3" albumId="11053" artistId="5432" type="music"/>
+ <song id="71464" parent="71381" title="Tnt" album="High Voltage" artist="AC/DC" isDir="false" coverArt="71381" created="2004-11-08T23:36:11" duration="215" bitRate="128" size="3433798" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="ACDC/High voltage/ACDC - TNT.mp3" albumId="11053" artistId="5432" type="music"/>
+ <song id="71458" parent="71381" title="It's A Long Way To The Top" album="High Voltage" artist="AC/DC" isDir="false" coverArt="71381" created="2004-11-27T20:23:32" duration="315" bitRate="128" year="1976" genre="Rock" size="5037357" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="ACDC/High voltage/ACDC - It's a long way to the top if you wanna rock 'n 'roll.mp3" albumId="11053" artistId="5432" type="music"/>
+ <song id="71461" parent="71381" title="Rock 'n' Roll Singer." album="High Voltage" artist="AC/DC" isDir="false" coverArt="71381" created="2004-11-27T20:23:33" duration="303" bitRate="128" track="2" year="1976" genre="Rock" size="4861680" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="ACDC/High voltage/ACDC - Rock N Roll Singer.mp3" albumId="11053" artistId="5432" type="music"/>
+ <song id="71460" parent="71381" title="Live Wire" album="High Voltage" artist="AC/DC" isDir="false" coverArt="71381" created="2004-11-27T20:23:33" duration="349" bitRate="128" track="4" year="1976" genre="Rock" size="5600206" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="ACDC/High voltage/ACDC - Live Wire.mp3" albumId="11053" artistId="5432" type="music"/>
+ <song id="71456" parent="71381" title="Can I sit next to you girl" album="High Voltage" artist="AC/DC" isDir="false" coverArt="71381" created="2004-11-27T20:23:32" duration="251" bitRate="128" track="6" year="1976" genre="Rock" size="4028276" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="ACDC/High voltage/ACDC - Can I Sit Next To You Girl.mp3" albumId="11053" artistId="5432" type="music"/>
+ <song id="71459" parent="71381" title="Little Lover" album="High Voltage" artist="AC/DC" isDir="false" coverArt="71381" created="2004-11-27T20:23:33" duration="339" bitRate="128" track="7" year="1976" genre="Rock" size="5435119" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="ACDC/High voltage/ACDC - Little Lover.mp3" albumId="11053" artistId="5432" type="music"/>
+ <song id="71462" parent="71381" title="She's Got Balls" album="High Voltage" artist="AC/DC" isDir="false" coverArt="71381" created="2004-11-27T20:23:34" duration="290" bitRate="128" track="8" year="1976" genre="Rock" size="4651866" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="ACDC/High voltage/ACDC - Shes Got Balls.mp3" albumId="11053" artistId="5432" type="music"/>
+ </album>
+
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/artist_example_1.xml b/subsonic-main/src/main/webapp/xsd/artist_example_1.xml new file mode 100644 index 00000000..86fc4e67 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/artist_example_1.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.8.0">
+
+ <artist id="5432" name="AC/DC" coverArt="ar-5432" albumCount="15">
+ <album id="11047" name="Back In Black" coverArt="al-11047" songCount="10" created="2004-11-08T23:33:11" duration="2534" artist="AC/DC" artistId="5432"/>
+ <album id="11048" name="Black Ice" coverArt="al-11048" songCount="15" created="2008-10-30T09:20:52" duration="3332" artist="AC/DC" artistId="5432"/>
+ <album id="11049" name="Blow up your Video" coverArt="al-11049" songCount="10" created="2004-11-27T19:22:45" duration="2578" artist="AC/DC" artistId="5432"/>
+ <album id="11050" name="Flick Of The Switch" coverArt="al-11050" songCount="10" created="2004-11-27T19:22:51" duration="2222" artist="AC/DC" artistId="5432"/>
+ <album id="11051" name="Fly On The Wall" coverArt="al-11051" songCount="10" created="2004-11-27T19:22:57" duration="2405" artist="AC/DC" artistId="5432"/>
+ <album id="11052" name="For Those About To Rock" coverArt="al-11052" songCount="10" created="2004-11-08T23:35:02" duration="2403" artist="AC/DC" artistId="5432"/>
+ <album id="11053" name="High Voltage" coverArt="al-11053" songCount="8" created="2004-11-27T20:23:32" duration="2414" artist="AC/DC" artistId="5432"/>
+ <album id="10489" name="Highway To Hell" coverArt="al-10489" songCount="12" created="2009-06-15T09:41:54" duration="2745" artist="AC/DC" artistId="5432"/>
+ <album id="11054" name="If You Want Blood..." coverArt="al-11054" songCount="1" created="2004-11-27T20:23:32" duration="304" artist="AC/DC" artistId="5432"/>
+ <album id="11056" name="Let There Be Rock" coverArt="al-11056" songCount="8" created="2004-11-27T20:33:40" duration="2449" artist="AC/DC" artistId="5432"/>
+ <album id="11057" name="Live - Special Collector's Edition" coverArt="al-11057" songCount="22" created="2004-11-08T23:37:09" duration="6999" artist="AC/DC" artistId="5432"/>
+ <album id="11058" name="Powerage" coverArt="al-11058" songCount="9" created="2004-11-27T20:33:41" duration="2380" artist="AC/DC" artistId="5432"/>
+ <album id="11059" name="Stiff Upper Lip" coverArt="al-11059" songCount="11" created="2004-11-08T23:41:13" duration="2595" artist="AC/DC" artistId="5432"/>
+ <album id="11060" name="The Razors Edge" coverArt="al-11060" songCount="12" created="2004-11-27T20:33:42" duration="2787" artist="AC/DC" artistId="5432"/>
+ <album id="11061" name="Who Made Who" coverArt="al-11061" songCount="9" created="2004-11-08T23:43:18" duration="2291" artist="AC/DC" artistId="5432"/>
+ </artist>
+
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/artists_example_1.xml b/subsonic-main/src/main/webapp/xsd/artists_example_1.xml new file mode 100644 index 00000000..0c2498b2 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/artists_example_1.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.8.0">
+ <artists>
+ <artist id="5449" name="A-Ha" coverArt="ar-5449" albumCount="4"/>
+ <artist id="5421" name="ABBA" coverArt="ar-5421" albumCount="6"/>
+ <artist id="5432" name="AC/DC" coverArt="ar-5432" albumCount="15"/>
+ <artist id="6633" name="Aaron Neville" coverArt="ar-6633" albumCount="1"/>
+ <artist id="5950" name="Bob Marley" coverArt="ar-5950" albumCount="8"/>
+ <artist id="5957" name="Bruce Dickinson" coverArt="ar-5957" albumCount="2"/>
+</artists>
+
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/chatMessages_example_1.xml b/subsonic-main/src/main/webapp/xsd/chatMessages_example_1.xml new file mode 100644 index 00000000..b633d534 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/chatMessages_example_1.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.2.0">
+
+ <chatMessages>
+ <chatMessage username="sindre" time="1269771845310" message="Sindre was here"/>
+ <chatMessage username="ben" time="1269771842504" message="Ben too"/>
+ </chatMessages>
+
+</subsonic-response>
+
diff --git a/subsonic-main/src/main/webapp/xsd/directory_example_1.xml b/subsonic-main/src/main/webapp/xsd/directory_example_1.xml new file mode 100644 index 00000000..c2ec1582 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/directory_example_1.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.4.0">
+
+ <directory id="1" name="ABBA">
+ <child id="11" parent="1" title="Arrival" artist="ABBA" isDir="true" coverArt="22"/>
+ <child id="12" parent="1" title="Super Trouper" artist="ABBA" isDir="true" coverArt="23"/>
+ </directory>
+
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/directory_example_2.xml b/subsonic-main/src/main/webapp/xsd/directory_example_2.xml new file mode 100644 index 00000000..246e7b51 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/directory_example_2.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.4.0">
+
+ <directory id="11" parent="1" name="Arrival">
+ <child id="111" parent="11" title="Dancing Queen" isDir="false"
+ album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="24"
+ size="8421341" contentType="audio/mpeg" suffix="mp3" duration="146" bitRate="128"
+ path="ABBA/Arrival/Dancing Queen.mp3"/>
+
+ <child id="112" parent="11" title="Money, Money, Money" isDir="false"
+ album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="25"
+ size="4910028" contentType="audio/flac" suffix="flac"
+ transcodedContentType="audio/mpeg" transcodedSuffix="mp3" duration="208" bitRate="128"
+ path="ABBA/Arrival/Money, Money, Money.mp3"/>
+ </directory>
+
+</subsonic-response>
+
diff --git a/subsonic-main/src/main/webapp/xsd/error_example_1.xml b/subsonic-main/src/main/webapp/xsd/error_example_1.xml new file mode 100644 index 00000000..80cafabf --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/error_example_1.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="failed" version="1.1.1">
+
+ <error code="40" message="Wrong username or password."/>
+
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/indexes_example_1.xml b/subsonic-main/src/main/webapp/xsd/indexes_example_1.xml new file mode 100644 index 00000000..5438ad51 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/indexes_example_1.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.1.1">
+
+ <indexes lastModified="237462836472342">
+ <shortcut id="11" name="Audio books"/>
+ <shortcut id="10" name="Podcasts"/>
+ <index name="A">
+ <artist id="1" name="ABBA"/>
+ <artist id="2" name="Alanis Morisette"/>
+ <artist id="3" name="Alphaville"/>
+ </index>
+ <index name="B">
+ <artist name="Bob Dylan" id="4"/>
+ </index>
+
+ <child id="111" parent="11" title="Dancing Queen" isDir="false"
+ album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="24"
+ size="8421341" contentType="audio/mpeg" suffix="mp3" duration="146" bitRate="128"
+ path="ABBA/Arrival/Dancing Queen.mp3"/>
+
+ <child id="112" parent="11" title="Money, Money, Money" isDir="false"
+ album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="25"
+ size="4910028" contentType="audio/flac" suffix="flac"
+ transcodedContentType="audio/mpeg" transcodedSuffix="mp3" duration="208" bitRate="128"
+ path="ABBA/Arrival/Money, Money, Money.mp3"/>
+ </indexes>
+
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/jukeboxPlaylist_example_1.xml b/subsonic-main/src/main/webapp/xsd/jukeboxPlaylist_example_1.xml new file mode 100644 index 00000000..e214a860 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/jukeboxPlaylist_example_1.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.4.0">
+
+ <jukeboxPlaylist currentIndex="0" playing="true" gain="0.67" position="67">
+ <entry id="111" parent="11" title="Dancing Queen" isDir="false"
+ album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="24"
+ duration="345" size="8421341" contentType="audio/mpeg" suffix="mp3"
+ path="ABBA/Arrival/Dancing Queen.mp3"/>
+
+ <entry id="112" parent="11" title="Money, Money, Money" isDir="false"
+ album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="25"
+ duration="240" size="4910028" contentType="audio/flac" suffix="flac"
+ transcodedContentType="audio/mpeg" transcodedSuffix="mp3"
+ path="ABBA/Arrival/Money, Money, Money.mp3"/>
+ </jukeboxPlaylist>
+
+</subsonic-response>
+
diff --git a/subsonic-main/src/main/webapp/xsd/jukeboxStatus_example_1.xml b/subsonic-main/src/main/webapp/xsd/jukeboxStatus_example_1.xml new file mode 100644 index 00000000..a0200494 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/jukeboxStatus_example_1.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.7.0">
+
+ <jukeboxStatus currentIndex="7" playing="true" gain="0.9" position="67"/>
+
+</subsonic-response>
+
diff --git a/subsonic-main/src/main/webapp/xsd/license_example_1.xml b/subsonic-main/src/main/webapp/xsd/license_example_1.xml new file mode 100644 index 00000000..720381ab --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/license_example_1.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.1.1">
+
+ <license valid="true" email="foo@bar.com" key="ABC123DEF" date="2009-09-03T14:46:43"/>
+
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/lyrics_example_1.xml b/subsonic-main/src/main/webapp/xsd/lyrics_example_1.xml new file mode 100644 index 00000000..1a2831cb --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/lyrics_example_1.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.2.0">
+ <lyrics artist="Muse" title="Hysteria">
+It's bugging me
+Grating me
+And twisting me around
+Yeah I'm endlessly
+Caving in
+And turning inside out
+
+Cause I want it now
+I want it now
+Give me your heart and your soul
+And I'm breaking out
+I'm breaking out
+That's when she'll lose control
+
+It's holding me
+Morphing me
+And forcing me to strive
+To be endlessly
+Cold within
+And dreaming I'm alive
+
+Cause I want it now
+I want it now
+Give me your heart and your soul
+I'm not breaking down
+I'm breaking out
+That's when she'll lose control
+
+And I want you now
+I want you now
+I'll feel my heart implode
+And I'm breaking out
+Escaping now
+Feeling my faith erode
+ </lyrics>
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/musicFolders_example_1.xml b/subsonic-main/src/main/webapp/xsd/musicFolders_example_1.xml new file mode 100644 index 00000000..8531045b --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/musicFolders_example_1.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.1.1">
+
+ <musicFolders>
+ <musicFolder id="1" name="Music"/>
+ <musicFolder id="2" name="Movies"/>
+ <musicFolder id="3" name="Incoming"/>
+ </musicFolders>
+
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/nowPlaying_example_1.xml b/subsonic-main/src/main/webapp/xsd/nowPlaying_example_1.xml new file mode 100644 index 00000000..b492fbb7 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/nowPlaying_example_1.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.4.0">
+
+ <nowPlaying>
+ <entry username="sindre" minutesAgo="12" playerId="2"
+ id="111" parent="11" title="Dancing Queen" isDir="false"
+ album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="24"
+ size="8421341" contentType="audio/mpeg" suffix="mp3" path="ABBA/Arrival/Dancing Queen.mp3"/>
+
+ <entry username="bente" minutesAgo="1" playerId="4" playerName="Kitchen" id="112" parent="11" title="Money, Money, Money" isDir="false"
+ album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="25"
+ size="4910028" contentType="audio/flac" suffix="flac" transcodedContentType="audio/mpeg"
+ transcodedSuffix="mp3" path="ABBA/Arrival/Money, Money, Money.mp3"/>
+ </nowPlaying>
+
+</subsonic-response>
+
diff --git a/subsonic-main/src/main/webapp/xsd/ping_example_1.xml b/subsonic-main/src/main/webapp/xsd/ping_example_1.xml new file mode 100644 index 00000000..b475286d --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/ping_example_1.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.1.1">
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/playlist_example_1.xml b/subsonic-main/src/main/webapp/xsd/playlist_example_1.xml new file mode 100644 index 00000000..58966868 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/playlist_example_1.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.8.0">
+ <playlist id="15" name="kokos" comment="fan" owner="admin" public="true" songCount="6" duration="1391"
+ created="2012-04-17T19:53:44">
+ <allowedUser>sindre</allowedUser>
+ <allowedUser>john</allowedUser>
+ <entry id="657" parent="655" title="Making Me Nervous" album="I Don't Know What I'm Doing"
+ artist="Brad Sucks" isDir="false" coverArt="655" created="2008-04-10T07:10:32" duration="159"
+ bitRate="202" track="1" year="2003" size="4060113" suffix="mp3" contentType="audio/mpeg" isVideo="false"
+ path="Brad Sucks/I Don't Know What I'm Doing/01 - Making Me Nervous.mp3" albumId="58"
+ artistId="45" type="music"/>
+ <entry id="823" parent="784" title="Piano escena" album="BSO Sebastian" artist="PeerGynt Lobogris"
+ isDir="false" coverArt="784" created="2009-01-14T22:26:29" duration="129" bitRate="170" track="8"
+ year="2008" genre="Blues" size="2799954" suffix="mp3" contentType="audio/mpeg" isVideo="false"
+ path="PeerGynt Lobogris/BSO Sebastian/08 - Piano escena.mp3" albumId="75" artistId="54" type="music"/>
+ <entry id="748" parent="746" title="Stories from Emona II" album="Between two worlds" artist="Maya Filipič"
+ isDir="false" coverArt="746" created="2008-07-30T22:05:40" duration="335" bitRate="176" track="2"
+ year="2008" genre="Classical" size="7458214" suffix="mp3" contentType="audio/mpeg" isVideo="false"
+ path="Maya Filipic/Between two worlds/02 - Stories from Emona II.mp3" albumId="68" artistId="51"
+ type="music"/>
+ <entry id="848" parent="827" title="Run enemy" album="Eve" artist="Shearer" isDir="false" coverArt="827"
+ created="2009-01-15T22:54:38" duration="331" bitRate="195" track="14" year="2008" genre="Rock"
+ size="8160185" suffix="mp3" contentType="audio/mpeg" isVideo="false"
+ path="Shearer/Eve/14 - Run enemy.mp3" albumId="77" artistId="55" type="music"/>
+ <entry id="884" parent="874" title="Isolation" album="Kosmonaut" artist="Ugress" isDir="false" coverArt="874"
+ created="2009-01-14T21:34:49" duration="320" bitRate="160" track="4" year="2006" genre="Electronic"
+ size="6412176" suffix="mp3" contentType="audio/mpeg" isVideo="false"
+ path="Ugress/Kosmonaut/Ugress-KosmonautEP-04-Isolation.mp3" albumId="81" artistId="57" type="music"/>
+ <entry id="805" parent="783" title="Bajo siete lunas (intro)" album="Broken Dreams" artist="PeerGynt Lobogris"
+ isDir="false" coverArt="783" created="2008-12-19T14:13:58" duration="117" bitRate="225" track="1"
+ year="2008" genre="Blues" size="3363271" suffix="mp3" contentType="audio/mpeg" isVideo="false"
+ path="PeerGynt Lobogris/Broken Dreams/01 - Bajo siete lunas (intro).mp3" albumId="74" artistId="54"
+ type="music"/>
+ </playlist>
+</subsonic-response>
+
diff --git a/subsonic-main/src/main/webapp/xsd/playlists_example_1.xml b/subsonic-main/src/main/webapp/xsd/playlists_example_1.xml new file mode 100644 index 00000000..9b4b60a3 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/playlists_example_1.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.8.0">
+ <playlists>
+ <playlist id="15" name="Some random songs" comment="Just something I tossed together" owner="admin" public="false" songCount="6" duration="1391" created="2012-04-17T19:53:44">
+ <allowedUser>sindre</allowedUser>
+ <allowedUser>john</allowedUser>
+ </playlist>
+ <playlist id="16" name="More random songs" comment="No comment" owner="admin" public="true" songCount="5" duration="1018" created="2012-04-17T19:55:49"/>
+ </playlists>
+</subsonic-response>
+
diff --git a/subsonic-main/src/main/webapp/xsd/podcasts_example_1.xml b/subsonic-main/src/main/webapp/xsd/podcasts_example_1.xml new file mode 100644 index 00000000..23b8d2ae --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/podcasts_example_1.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.6.0">
+
+ <podcasts>
+ <channel id="1"
+ url="http://downloads.bbc.co.uk/podcasts/fivelive/drkarl/rss.xml"
+ title="Dr Karl and the Naked Scientist"
+ description="Dr Chris Smith aka The Naked Scientist with the latest news from the world of science and Dr Karl answers listeners' science questions."
+ status="completed">
+ <episode id="34"
+ streamId="523"
+ title="Scorpions have re-evolved eyes"
+ description="This week Dr Chris fills us in on the UK's largest free science festival, plus all this week's big scientific discoveries."
+ publishDate="2011-02-03T14:46:43"
+ status="completed"
+ parent="11" isDir="false" year="2011" genre="Podcast" coverArt="24"
+ size="78421341" contentType="audio/mpeg" suffix="mp3" duration="3146" bitRate="128"
+ path="Podcast/drkarl/20110203.mp3"/>
+ <episode id="35"
+ streamId="524"
+ title="Scar tissue and snake venom treatment"
+ description="This week Dr Karl tells the gruesome tale of a surgeon who operated on himself."
+ publishDate="2011-09-03T16:47:52"
+ status="completed"
+ parent="11" isDir="false" year="2011" genre="Podcast" coverArt="27"
+ size="45624671" contentType="audio/mpeg" suffix="mp3" duration="3099" bitRate="128"
+ path="Podcast/drkarl/20110903.mp3"/>
+ </channel>
+ <channel id="2"
+ url="http://podkast.nrk.no/program/herreavdelingen.rss"
+ title="NRK P1 - Herreavdelingen"
+ description="Et program der herrene Yan Friis og Finn Bjelke møtes og musikk nytes."
+ status="completed">
+ </channel>
+ <channel id="3"
+ url="http://foo.bar.com/xyz.rss"
+ status="error"
+ errorMessage="Not found."/>
+ </podcasts>
+
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/randomSongs_example_1.xml b/subsonic-main/src/main/webapp/xsd/randomSongs_example_1.xml new file mode 100644 index 00000000..dc3a6a99 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/randomSongs_example_1.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.4.0">
+
+ <randomSongs>
+ <song id="111" parent="11" title="Dancing Queen" isDir="false"
+ album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="24"
+ size="8421341" contentType="audio/mpeg" suffix="mp3" duration="146" bitRate="128"
+ path="ABBA/Arrival/Dancing Queen.mp3"/>
+
+ <song id="112" parent="11" title="Money, Money, Money" isDir="false"
+ album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="25"
+ size="4910028" contentType="audio/flac" suffix="flac"
+ transcodedContentType="audio/mpeg" transcodedSuffix="mp3" duration="208" bitRate="128"
+ path="ABBA/Arrival/Money, Money, Money.mp3"/>
+ </randomSongs>
+
+</subsonic-response>
+
diff --git a/subsonic-main/src/main/webapp/xsd/searchResult2_example_1.xml b/subsonic-main/src/main/webapp/xsd/searchResult2_example_1.xml new file mode 100644 index 00000000..dd7a2c10 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/searchResult2_example_1.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<subsonic-response xmlns="http://subsonic.org/restapi" + status="ok" version="1.4.0"> + + <searchResult2> + <artist id="1" name="ABBA"/> + <album id="11" parent="1" title="Arrival" artist="ABBA" isDir="true" coverArt="22"/> + <album id="12" parent="1" title="Super Trouper" artist="ABBA" isDir="true" coverArt="23"/> + <song id="112" parent="11" title="Money, Money, Money" isDir="false" + album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="25" + size="4910028" contentType="audio/flac" suffix="flac" + transcodedContentType="audio/mpeg" transcodedSuffix="mp3" + path="ABBA/Arrival/Money, Money, Money.mp3"/> + </searchResult2> + +</subsonic-response> + diff --git a/subsonic-main/src/main/webapp/xsd/searchResult3_example_1.xml b/subsonic-main/src/main/webapp/xsd/searchResult3_example_1.xml new file mode 100644 index 00000000..ef1b1df9 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/searchResult3_example_1.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.8.0"> + <searchResult3> + <artist id="5944" name="Black" coverArt="ar-5944" albumCount="2"/> + <artist id="5785" name="Black Sabbath" coverArt="ar-5785" albumCount="22"/> + <artist id="5945" name="Black Debbath" coverArt="ar-5945" albumCount="7"/> + <artist id="6063" name="Mary Black" coverArt="ar-6063" albumCount="1"/> + <artist id="6065" name="Frances Black" coverArt="ar-6065" albumCount="1"/> + <artist id="6131" name="Black Box" coverArt="ar-6131" albumCount="1"/> + <artist id="6973" name="The Black Crowes" coverArt="ar-6973" albumCount="2"/> + <artist id="6974" name="The Black Sorrows" coverArt="ar-6974" albumCount="1"/> + <artist id="6061" name="Eleanor Mcevoy With Mary Black" coverArt="ar-6061" albumCount="1"/> + <album id="11241" name="Black" coverArt="al-11241" songCount="10" created="2004-11-14T13:02:03" duration="2575" artist="Black" artistId="5944"/> + <album id="12768" name="Black" coverArt="al-12768" songCount="1" created="2000-07-31T15:13:50" duration="448" artist="Metallica" artistId="6308"/> + <album id="11242" name="Black Debbath Hyller Kvinnen!" coverArt="al-11242" songCount="11" created="2010-05-25T13:04:41" duration="2778" artist="Black Debbath" artistId="5945"/> + <album id="11047" name="Back In Black" coverArt="al-11047" songCount="10" created="2004-11-08T23:33:11" duration="2534" artist="AC/DC" artistId="5432"/> + <album id="11048" name="Black Ice" coverArt="al-11048" songCount="15" created="2008-10-30T09:20:52" duration="3332" artist="AC/DC" artistId="5432"/> + <album id="11615" name="The Black Parade" coverArt="al-11615" songCount="15" created="2007-06-21T07:52:46" duration="3356" artist="My Chemical Romance" artistId="6159"/> + <album id="12132" name="Black Celebration" coverArt="al-12132" songCount="10" created="2005-01-18T23:19:33" duration="2225" artist="Depeche Mode" artistId="6355"/> + <album id="12544" name="The Black Halo" coverArt="al-12544" songCount="3" created="2010-04-07T13:41:39" duration="668" artist="Kamelot" artistId="5433"/> + <album id="12771" name="The Black Album" coverArt="al-12771" songCount="1" created="1999-10-15T00:00:00" duration="386" artist="Metallica" artistId="6308"/> + <album id="13554" name="Black Angel" coverArt="al-13554" songCount="12" created="2002-11-16T15:37:20" duration="3160" artist="Savage Rose" artistId="6999"/> + <album id="13609" name="The Black Rider" coverArt="al-13609" songCount="20" created="2002-02-22T14:50:34" duration="3327" artist="Tom Waits" artistId="6920"/> + <album id="11243" name="Black Debbaths Beste-Ti År Med Rock Mot Alt Som Er Kult" coverArt="al-11243" songCount="27" created="2009-05-27T14:43:12" duration="6710" artist="Black Debbath" artistId="5945"/> + <album id="11250" name="Black sabbath & Rob Halford live 11-15-92 Costa mesa" coverArt="al-11250" songCount="13" created="2003-07-21T13:52:14" duration="4500" artist="Black Sabbath" artistId="5785"/> + <album id="10490" name="The Black Halo [Bonus Track]" coverArt="al-10490" songCount="42" created="2010-04-07T12:58:16" duration="10305" artist="Kamelot" artistId="5433"/> + <album id="10559" name="Back to Black: 1900-1999" coverArt="al-10559" songCount="1" created="2004-03-09T07:32:42" duration="99" artist="Earth, Wind & Fire, The Emotions" artistId="5489"/> + <album id="11087" name="Back To Black (Deluxe Edition)" coverArt="al-11087" songCount="19" created="2008-06-25T10:01:30" duration="3663" artist="Amy Winehouse" artistId="5870"/> + <album id="11604" name="Black Holes & Revelations" coverArt="al-11604" songCount="12" created="2007-06-21T07:52:44" duration="3025" artist="Muse" artistId="6150"/> + <album id="12993" name="Black Market Music" coverArt="al-12993" songCount="1" created="2003-07-21T14:48:38" duration="233" artist="Placebo" artistId="6313"/> + <album id="13580" name="Black Rose [Remastered]" coverArt="al-13580" songCount="9" created="2009-07-06T08:55:22" duration="2324" artist="Thin Lizzy" artistId="6084"/> + <album id="13904" name="Down Under The Black Light" songCount="1" created="2003-10-07T07:22:26" duration="90" artist="The Molecules" artistId="7202"/> + <song id="77451" parent="77433" title="Black" album="Angry Machines" artist="Dio" isDir="false" coverArt="77433" created="2007-03-15T06:46:06" duration="190" bitRate="192" track="3" year="1996" genre="Hard Rock" size="4575589" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="Dio/Angry Machines/Angry Machines 2.mp3" albumId="12168" artistId="6357" type="music"/> + <song id="84902" parent="84883" title="Black" album="Ten" artist="Pearl Jam" isDir="false" coverArt="84883" created="2001-06-11T22:15:52" duration="344" bitRate="160" year="1992" genre="Rock" size="6882991" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="Pearl Jam/Ten/05 - Black.mp3" albumId="12944" artistId="6745" type="music"/> + <song id="84916" parent="84884" title="Black" album="Unplugged at MTV" artist="Pearl Jam" isDir="false" coverArt="84884" created="1999-07-18T13:40:38" duration="449" bitRate="128" size="7180644" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="Pearl Jam/Unplugged at MTV/4- Pearl Jam Unplugged - Black.mp3" albumId="12945" artistId="6745" type="music"/> + <song id="85038" parent="85036" title="Black" album="Musicforthemorningafter" artist="Pete Yorn" isDir="false" coverArt="85036" created="2004-11-28T00:42:29" duration="250" bitRate="192" track="4" year="2001" genre="Rock/Pop" size="6026430" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="Pete Yorn/Pete Yorn/Pete Yorn - 04 - Black.mp3" albumId="12951" artistId="6747" type="music"/> + <song id="73890" parent="73888" title="Black Sabbath" album="Best Of...CD1" artist="Black Sabbath" isDir="false" coverArt="73888" created="2003-07-21T12:19:32" duration="380" bitRate="160" track="1" genre="Hard Rock" size="8124439" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="Black Sabbath/Best Of Black Sabbath/CD1/01 - Black Sabbath.mp3" albumId="11248" artistId="5785" type="music"/> + <song id="73934" parent="73875" title="Black Moon" album="Headless Cross" artist="Black Sabbath" isDir="false" coverArt="73875" created="2002-09-05T23:00:52" duration="246" bitRate="128" track="7" genre="(255)" size="3949687" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="Black Sabbath/Headless Cross/07 - Black Moon.mp3" albumId="11251" artistId="5785" type="music"/> + <song id="73844" parent="73790" title="Datidas Black Debbath" album="Naar Vi Døde Rocker" artist="Black Debbath" isDir="false" coverArt="73790" created="2010-05-03T09:40:22" duration="192" bitRate="320" track="7" year="2006" genre="Rock" size="7704160" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="Black Debbath/Når vi døde rocker/Black Debbath - Datidas Black Debbath.mp3" albumId="11245" artistId="5945" type="music"/> + <song id="73924" parent="73874" title="Black Sabbath (with Ozzy)" album="Black sabbath & Rob Halford live 11-15-92 Costa mesa" artist="Black Sabbath" isDir="false" coverArt="73874" created="2003-07-21T13:54:14" duration="407" bitRate="128" track="10" genre="Hard Rock" size="6518578" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="Black Sabbath/Black sabbath & Rob Halford live 11-15-92 Costa mesa/10 - Black Sabbath (with Ozzy).mp3" albumId="11250" artistId="5785" type="music"/> + <song id="75272" parent="75055" title="Black Sabbath - Paranoid" album="All Time Greatest Rock Songs (Disc 1)" artist="Black Sabbath" isDir="false" coverArt="75055" created="2002-11-23T19:31:34" duration="169" bitRate="160" track="18" genre="General Rock" size="3379328" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="Compilations/All Time Greatest Rock Songs (CD 1)/18 - Black Sabbath - Paranoid.mp3" albumId="11482" artistId="5785" type="music"/> + <song id="89111" parent="89093" title="Black Moon Creeping" album="The Southern Harmony And Musical Companion" artist="The Black Crowes" isDir="false" coverArt="89093" created="2002-11-03T13:51:24" duration="294" bitRate="160" track="7" size="5891285" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="The Black Crowes/The Southern Harmony And Musical Companion/07 - Black Moon Creeping.mp3" albumId="13473" artistId="6973" type="music"/> + <song id="92435" parent="92347" title="Belle Epoque - Black Is Black" album="Cd4" artist="Summer Hits - Top 100" isDir="false" created="1999-07-18T10:48:14" duration="204" bitRate="160" size="4087948" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="_Various/Summer Hits - Top 100/Cd4/16. Belle Epoque - Black Is Black.mp3" albumId="13948" artistId="7223" type="music"/> + <song id="70221" parent="70211" title="The Black Halo" album="The Black Halo [Bonus Track]" artist="Kamelot" isDir="false" coverArt="70211" created="2010-04-07T12:58:17" duration="223" bitRate="192" track="10" year="2005" genre="Progressive Metal" size="5363128" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="Incoming/Kamelot/08 - The Black Halo - 2005/10 - The Black Halo.mp3" albumId="10490" artistId="5433" type="music"/> + <song id="71056" parent="70678" title="Black Coffee" album="Saints & Sinners" artist="All Saints" isDir="false" coverArt="70678" created="2004-03-09T07:34:28" duration="290" bitRate="192" track="5" year="2000" genre="Rock/Pop" size="6975616" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="Absolute/Absolute music 36/Absolute Music 36 - 12 All Saints - Black Coffee.mp3" albumId="10811" artistId="5692" type="music"/> + <song id="71393" parent="71375" title="Back In Black" album="Back In Black" artist="AC/DC" isDir="false" coverArt="71375" created="2004-11-08T23:33:11" duration="268" bitRate="128" genre="Blues" size="4292608" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="ACDC/Back in black/ACDC - Back In Black.mp3" albumId="11047" artistId="5432" type="music"/> + <song id="71415" parent="71376" title="Black Ice" album="Black Ice" artist="AC/DC" isDir="false" coverArt="71376" created="2008-10-30T10:08:28" duration="205" bitRate="320" track="15" year="2008" genre="Heavy Metal" size="8210893" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="ACDC/Black Ice/15 AC-DC - Black Ice.mp3" albumId="11048" artistId="5432" type="music"/> + <song id="71495" parent="71385" title="Back In Black" album="Live - Special Collector's Edition" artist="AC/DC" isDir="false" coverArt="71385" created="2004-11-08T23:37:09" duration="266" bitRate="128" year="1992" genre="Metal" size="4255615" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="ACDC/Live (CD1)/ac dc - live - special collector edition - disc 1 - 03 - ba.mp3" albumId="11057" artistId="5432" type="music"/> + <song id="71763" parent="71758" title="Back To Black" album="Back To Black (Deluxe Edition)" artist="Amy Winehouse" isDir="false" coverArt="71758" created="2008-06-25T10:12:14" duration="241" bitRate="153" track="5" year="2007" genre="Blues" size="4639525" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="Amy Winehouse/Back To Black/105-amy_winehouse-back_to_black-ukp.mp3" albumId="11087" artistId="5870" type="music"/> + <song id="75149" parent="75052" title="Black Sabbath" album="70" artist="Paranoid" isDir="false" coverArt="75052" created="2004-11-14T13:38:38" duration="169" bitRate="160" track="18" genre="Rock" size="3406066" suffix="wma" contentType="audio/x-ms-wma" isVideo="false" path="Compilations/70/Black Sabbath - Paranoid.wma" albumId="11396" artistId="6010" type="music"/> + <song id="75301" parent="75057" title="Black Betty" album="Born To Be Wild - Vol. 2" artist="Ram Jam" isDir="false" coverArt="75057" created="2006-02-04T20:30:44" duration="239" bitRate="160" track="12" year="1994" genre="Hard Rock" size="4792458" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="Compilations/Born To Be Wild - Vol. 2/12 - Black Betty.mp3" albumId="11510" artistId="6091" type="music"/> + <song id="76048" parent="75100" title="Black Velvet" album="The Good" artist="Alannah Myles" isDir="false" coverArt="75100" created="2002-11-17T15:44:08" duration="289" bitRate="128" genre="Other" size="4628480" suffix="mp3" contentType="audio/mpeg" isVideo="false" path="Compilations/The Good/Alannah Myles - Black Velvet.mp3" albumId="11818" artistId="6286" type="music"/> + </searchResult3> +</subsonic-response> diff --git a/subsonic-main/src/main/webapp/xsd/searchResult_example_1.xml b/subsonic-main/src/main/webapp/xsd/searchResult_example_1.xml new file mode 100644 index 00000000..fb1e9c4a --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/searchResult_example_1.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.4.0">
+
+ <searchResult offset="0" totalHits="2">
+ <match id="111" parent="11" title="Dancing Queen" isDir="false"
+ album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="24"
+ size="8421341" contentType="audio/mpeg" suffix="mp3"
+ path="ABBA/Arrival/Dancing Queen.mp3"/>
+
+ <match id="112" parent="11" title="Money, Money, Money" isDir="false"
+ album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="25"
+ size="4910028" contentType="audio/flac" suffix="flac"
+ transcodedContentType="audio/mpeg" transcodedSuffix="mp3"
+ path="ABBA/Arrival/Money, Money, Money.mp3"/>
+ </searchResult>
+
+</subsonic-response>
+
diff --git a/subsonic-main/src/main/webapp/xsd/shares_example_1.xml b/subsonic-main/src/main/webapp/xsd/shares_example_1.xml new file mode 100644 index 00000000..1fb8732f --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/shares_example_1.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.6.0">
+
+ <shares>
+ <share id="1" url="http://sindre.subsonic.org/share/sKoYn" description="Check this out" username="sindre"
+ created="2011-06-04T12:34:56" lastVisited="2011-06-04T13:14:15" expires="2013-06-04T00:00:00" visitCount="0">
+
+ <entry id="111" parent="11" title="Dancing Queen" isDir="false"
+ album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="24"
+ size="8421341" contentType="audio/mpeg" suffix="mp3" duration="146" bitRate="128"
+ path="ABBA/Arrival/Dancing Queen.mp3"/>
+
+ <entry id="112" parent="11" title="Money, Money, Money" isDir="false"
+ album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="25"
+ size="4910028" contentType="audio/flac" suffix="flac"
+ transcodedContentType="audio/mpeg" transcodedSuffix="mp3" duration="208" bitRate="128"
+ path="ABBA/Arrival/Money, Money, Money.mp3"/>
+ </share>
+ </shares>
+
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/song_example_1.xml b/subsonic-main/src/main/webapp/xsd/song_example_1.xml new file mode 100644 index 00000000..58b8773b --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/song_example_1.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.8.0">
+
+ <song id="48228" parent="48203" title="You Shook Me All Night Long" album="Back In Black" artist="AC/DC"
+ isDir="false" coverArt="48203" created="2004-11-08T23:33:11" duration="210" bitRate="112" size="2945619"
+ suffix="mp3" contentType="audio/mpeg" isVideo="false"
+ path="ACDC/Back in black/ACDC - You Shook Me All Night Long.mp3"/>
+
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/starred2_example_1.xml b/subsonic-main/src/main/webapp/xsd/starred2_example_1.xml new file mode 100644 index 00000000..8c0104dd --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/starred2_example_1.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.8.0">
+ <starred2>
+ <artist id="126" name="Iron Maiden" coverArt="ar-126" albumCount="1" starred="2012-04-05T19:03:31"/>
+ <artist id="133" name="Dimmu Borgir" coverArt="ar-133" albumCount="1" starred="2012-04-05T19:03:17"/>
+ <artist id="141" name="Kvelertak" albumCount="1" starred="2012-04-05T19:03:05"/>
+ <album id="180" name="Collapse Into Now" artist="R.E.M." artistId="144" songCount="12" duration="2459"
+ created="2011-03-23T09:37:55" starred="2012-04-05T19:02:02"/>
+ <album id="178" name="Postcards From A Young Man" artist="Manic Street Preachers" artistId="142"
+ coverArt="al-178" songCount="12" duration="2665" created="2011-02-26T10:47:19"
+ starred="2012-04-05T19:01:03"/>
+ <song id="143588" parent="143586" title="Born Treacherous" album="Abrahadabra" artist="Dimmu Borgir"
+ isDir="false" coverArt="143586" created="2010-09-27T20:52:23" starred="2012-04-02T17:17:01" duration="302"
+ bitRate="320" track="2" year="2010" genre="Scene-core" size="12087601" suffix="mp3"
+ contentType="audio/mpeg" isVideo="false" path="Dimmu Borgir/Abrahadabra/02 - Born Treacherous.mp3"
+ albumId="163" artistId="133" type="music"/>
+ <song id="143600" parent="143386" title="Satellite 15....The Final Frontier"
+ album="The Final Frontier (Mission Edition)" artist="Iron Maiden" isDir="false" coverArt="143386"
+ created="2010-08-16T21:08:01" starred="2012-04-02T14:12:54" duration="521" bitRate="320" track="1"
+ year="2010" genre="Heavy Metal" size="21855635" suffix="mp3" contentType="audio/mpeg" isVideo="false"
+ path="Iron Maiden/2010 The Final Frontier/01 Satellite 15....The Final Frontier.mp3" albumId="156"
+ artistId="126" type="music"/>
+ <song id="143604" parent="143386" title="The Alchemist" album="The Final Frontier (Mission Edition)"
+ artist="Iron Maiden" isDir="false" coverArt="143386" created="2010-08-16T21:07:51"
+ starred="2012-04-02T14:12:52" duration="269" bitRate="320" track="5" year="2010" genre="Heavy Metal"
+ size="11774455" suffix="mp3" contentType="audio/mpeg" isVideo="false"
+ path="Iron Maiden/2010 The Final Frontier/05 The Alchemist.mp3" albumId="156" artistId="126"
+ type="music"/>
+ </starred2>
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/starred_example_1.xml b/subsonic-main/src/main/webapp/xsd/starred_example_1.xml new file mode 100644 index 00000000..916b2a7b --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/starred_example_1.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.8.0">
+ <starred>
+ <artist name="Kvelertak" id="143408"/>
+ <artist name="Dimmu Borgir" id="143402"/>
+ <artist name="Iron Maiden" id="143403"/>
+ <album id="143862" parent="143410" title="Postcards From A Young Man" album="Postcards From A Young Man"
+ artist="Manic Street Preachers" isDir="true" coverArt="143862" created="2011-02-26T10:45:30"
+ starred="2012-04-05T18:40:08"/>
+ <album id="143888" parent="143412" title="Collapse Into Now" album="Collapse Into Now" artist="R.E.M."
+ isDir="true" created="2011-03-23T09:29:13" starred="2012-04-05T18:40:02"/>
+ <song id="143588" parent="143586" title="Born Treacherous" album="Abrahadabra" artist="Dimmu Borgir"
+ isDir="false" coverArt="143586" created="2010-09-27T20:52:23" starred="2012-04-02T17:17:01" duration="302"
+ bitRate="320" track="2" year="2010" genre="Scene-core" size="12087601" suffix="mp3"
+ contentType="audio/mpeg" isVideo="false" path="Dimmu Borgir/Abrahadabra/02 - Born Treacherous.mp3"
+ albumId="163" artistId="133" type="music"/>
+ <song id="143600" parent="143386" title="Satellite 15....The Final Frontier"
+ album="The Final Frontier (Mission Edition)" artist="Iron Maiden" isDir="false" coverArt="143386"
+ created="2010-08-16T21:08:01" starred="2012-04-02T14:12:54" duration="521" bitRate="320" track="1"
+ year="2010" genre="Heavy Metal" size="21855635" suffix="mp3" contentType="audio/mpeg" isVideo="false"
+ path="Iron Maiden/2010 The Final Frontier/01 Satellite 15....The Final Frontier.mp3" albumId="156"
+ artistId="126" type="music"/>
+ <song id="143604" parent="143386" title="The Alchemist" album="The Final Frontier (Mission Edition)"
+ artist="Iron Maiden" isDir="false" coverArt="143386" created="2010-08-16T21:07:51"
+ starred="2012-04-02T14:12:52" duration="269" bitRate="320" track="5" year="2010" genre="Heavy Metal"
+ size="11774455" suffix="mp3" contentType="audio/mpeg" isVideo="false"
+ path="Iron Maiden/2010 The Final Frontier/05 The Alchemist.mp3" albumId="156" artistId="126"
+ type="music"/>
+ </starred>
+</subsonic-response>
diff --git a/subsonic-main/src/main/webapp/xsd/subsonic-rest-api.xsd b/subsonic-main/src/main/webapp/xsd/subsonic-rest-api.xsd new file mode 100644 index 00000000..449b49e8 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/subsonic-rest-api.xsd @@ -0,0 +1,434 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:sub="http://subsonic.org/restapi"
+ targetNamespace="http://subsonic.org/restapi"
+ attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ version="1.8.0">
+
+ <xs:element name="subsonic-response" type="sub:Response"/>
+
+ <xs:complexType name="Response">
+ <xs:choice minOccurs="0" maxOccurs="1">
+ <xs:element name="musicFolders" type="sub:MusicFolders" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="indexes" type="sub:Indexes" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="directory" type="sub:Directory" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="artists" type="sub:ArtistsID3" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="artist" type="sub:ArtistWithAlbumsID3" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="album" type="sub:AlbumWithSongsID3" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="song" type="sub:Child" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="videos" type="sub:Videos" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="nowPlaying" type="sub:NowPlaying" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="searchResult" type="sub:SearchResult" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="searchResult2" type="sub:SearchResult2" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="searchResult3" type="sub:SearchResult3" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="playlists" type="sub:Playlists" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="playlist" type="sub:PlaylistWithSongs" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="jukeboxStatus" type="sub:JukeboxStatus" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="jukeboxPlaylist" type="sub:JukeboxPlaylist" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="license" type="sub:License" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="user" type="sub:User" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="chatMessages" type="sub:ChatMessages" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="albumList" type="sub:AlbumList" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="albumList2" type="sub:AlbumList2" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="randomSongs" type="sub:RandomSongs" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="lyrics" type="sub:Lyrics" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="podcasts" type="sub:Podcasts" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="shares" type="sub:Shares" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="starred" type="sub:Starred" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="starred2" type="sub:Starred2" minOccurs="1" maxOccurs="1"/>
+ <xs:element name="error" type="sub:Error" minOccurs="1" maxOccurs="1"/>
+ </xs:choice>
+ <xs:attribute name="status" type="sub:ResponseStatus" use="required"/>
+ <xs:attribute name="version" type="sub:Version" use="required"/>
+ </xs:complexType>
+
+ <xs:simpleType name="ResponseStatus">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="ok"/>
+ <xs:enumeration value="failed"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="Version">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="\d+\.\d+\.\d+"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="MusicFolders">
+ <xs:sequence>
+ <xs:element name="musicFolder" type="sub:MusicFolder" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="MusicFolder">
+ <xs:attribute name="id" type="xs:int" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="optional"/>
+ </xs:complexType>
+
+ <xs:complexType name="Indexes">
+ <xs:sequence>
+ <xs:element name="shortcut" type="sub:Artist" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="index" type="sub:Index" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="child" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/> <!-- Added in 1.7.0 -->
+ </xs:sequence>
+ <xs:attribute name="lastModified" type="xs:long" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="Index">
+ <xs:sequence>
+ <xs:element name="artist" type="sub:Artist" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="Artist">
+ <xs:attribute name="id" type="xs:string" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="ArtistsID3">
+ <xs:sequence>
+ <xs:element name="artist" type="sub:ArtistID3" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="ArtistID3">
+ <xs:attribute name="id" type="xs:string" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="coverArt" type="xs:string" use="optional"/>
+ <xs:attribute name="albumCount" type="xs:int" use="required"/>
+ <xs:attribute name="starred" type="xs:dateTime" use="optional"/>
+ </xs:complexType>
+
+ <xs:complexType name="ArtistWithAlbumsID3">
+ <xs:complexContent>
+ <xs:extension base="sub:ArtistID3">
+ <xs:sequence>
+ <xs:element name="album" type="sub:AlbumID3" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="AlbumID3">
+ <xs:attribute name="id" type="xs:string" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="artist" type="xs:string" use="optional"/>
+ <xs:attribute name="artistId" type="xs:string" use="optional"/>
+ <xs:attribute name="coverArt" type="xs:string" use="optional"/>
+ <xs:attribute name="songCount" type="xs:int" use="required"/>
+ <xs:attribute name="duration" type="xs:int" use="required"/>
+ <xs:attribute name="created" type="xs:dateTime" use="required"/>
+ <xs:attribute name="starred" type="xs:dateTime" use="optional"/>
+ </xs:complexType>
+
+ <xs:complexType name="AlbumWithSongsID3">
+ <xs:complexContent>
+ <xs:extension base="sub:AlbumID3">
+ <xs:sequence>
+ <xs:element name="song" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="Videos">
+ <xs:sequence>
+ <xs:element name="video" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Directory">
+ <xs:sequence>
+ <xs:element name="child" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:string" use="required"/>
+ <xs:attribute name="parent" type="xs:string" use="optional"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="Child">
+ <xs:attribute name="id" type="xs:string" use="required"/>
+ <xs:attribute name="parent" type="xs:string" use="optional"/>
+ <xs:attribute name="isDir" type="xs:boolean" use="required"/>
+ <xs:attribute name="title" type="xs:string" use="required"/>
+ <xs:attribute name="album" type="xs:string" use="optional"/>
+ <xs:attribute name="artist" type="xs:string" use="optional"/>
+ <xs:attribute name="track" type="xs:int" use="optional"/>
+ <xs:attribute name="year" type="xs:int" use="optional"/>
+ <xs:attribute name="genre" type="xs:string" use="optional"/>
+ <xs:attribute name="coverArt" type="xs:string" use="optional"/>
+ <xs:attribute name="size" type="xs:long" use="optional"/>
+ <xs:attribute name="contentType" type="xs:string" use="optional"/>
+ <xs:attribute name="suffix" type="xs:string" use="optional"/>
+ <xs:attribute name="transcodedContentType" type="xs:string" use="optional"/>
+ <xs:attribute name="transcodedSuffix" type="xs:string" use="optional"/>
+ <xs:attribute name="duration" type="xs:int" use="optional"/>
+ <xs:attribute name="bitRate" type="xs:int" use="optional"/>
+ <xs:attribute name="path" type="xs:string" use="optional"/>
+ <xs:attribute name="isVideo" type="xs:boolean" use="optional"/> <!-- Added in 1.4.1 -->
+ <xs:attribute name="userRating" type="sub:UserRating" use="optional"/> <!-- Added in 1.6.0 -->
+ <xs:attribute name="averageRating" type="sub:AverageRating" use="optional"/> <!-- Added in 1.6.0 -->
+ <xs:attribute name="discNumber" type="xs:int" use="optional"/> <!-- Added in 1.8.0 -->
+ <xs:attribute name="created" type="xs:dateTime" use="optional"/> <!-- Added in 1.8.0 -->
+ <xs:attribute name="starred" type="xs:dateTime" use="optional"/> <!-- Added in 1.8.0 -->
+ <xs:attribute name="albumId" type="xs:string" use="optional"/> <!-- Added in 1.8.0 -->
+ <xs:attribute name="artistId" type="xs:string" use="optional"/> <!-- Added in 1.8.0 -->
+ <xs:attribute name="type" type="sub:MediaType" use="optional"/> <!-- Added in 1.8.0 -->
+ </xs:complexType>
+
+ <xs:simpleType name="MediaType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="music"/>
+ <xs:enumeration value="podcast"/>
+ <xs:enumeration value="audiobook"/>
+ <xs:enumeration value="video"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="UserRating">
+ <xs:restriction base="xs:int">
+ <xs:minInclusive value="1"/>
+ <xs:maxInclusive value="5"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="AverageRating">
+ <xs:restriction base="xs:double">
+ <xs:minInclusive value="1.0"/>
+ <xs:maxInclusive value="5.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="NowPlaying">
+ <xs:sequence>
+ <xs:element name="entry" type="sub:NowPlayingEntry" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="NowPlayingEntry">
+ <xs:complexContent>
+ <xs:extension base="sub:Child">
+ <xs:attribute name="username" type="xs:string" use="required"/>
+ <xs:attribute name="minutesAgo" type="xs:int" use="required"/>
+ <xs:attribute name="playerId" type="xs:int" use="required"/>
+ <xs:attribute name="playerName" type="xs:string" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <!--Deprecated-->
+ <xs:complexType name="SearchResult">
+ <xs:sequence>
+ <xs:element name="match" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="offset" type="xs:int" use="required"/>
+ <xs:attribute name="totalHits" type="xs:int" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="SearchResult2">
+ <xs:sequence>
+ <xs:element name="artist" type="sub:Artist" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="album" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="song" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="SearchResult3">
+ <xs:sequence>
+ <xs:element name="artist" type="sub:ArtistID3" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="album" type="sub:AlbumID3" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="song" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Playlists">
+ <xs:sequence>
+ <xs:element name="playlist" type="sub:Playlist" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Playlist">
+ <xs:sequence>
+ <xs:element name="allowedUser" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> <!--Added in 1.8.0-->
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:string" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ <xs:attribute name="comment" type="xs:string" use="optional"/> <!--Added in 1.8.0-->
+ <xs:attribute name="owner" type="xs:string" use="optional"/> <!--Added in 1.8.0-->
+ <xs:attribute name="public" type="xs:boolean" use="optional"/> <!--Added in 1.8.0-->
+ <xs:attribute name="songCount" type="xs:int" use="required"/> <!--Added in 1.8.0-->
+ <xs:attribute name="duration" type="xs:int" use="required"/> <!--Added in 1.8.0-->
+ <xs:attribute name="created" type="xs:dateTime" use="required"/> <!--Added in 1.8.0-->
+ </xs:complexType>
+
+ <xs:complexType name="PlaylistWithSongs">
+ <xs:complexContent>
+ <xs:extension base="sub:Playlist">
+ <xs:sequence>
+ <xs:element name="entry" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="JukeboxStatus">
+ <xs:attribute name="currentIndex" type="xs:int" use="required"/>
+ <xs:attribute name="playing" type="xs:boolean" use="required"/>
+ <xs:attribute name="gain" type="xs:float" use="required"/>
+ <xs:attribute name="position" type="xs:int" use="optional"/> <!--Added in 1.7.0-->
+ </xs:complexType>
+
+ <xs:complexType name="JukeboxPlaylist">
+ <xs:complexContent>
+ <xs:extension base="sub:JukeboxStatus">
+ <xs:sequence>
+ <xs:element name="entry" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="ChatMessages">
+ <xs:sequence>
+ <xs:element name="chatMessage" type="sub:ChatMessage" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="ChatMessage">
+ <xs:attribute name="username" type="xs:string" use="required"/>
+ <xs:attribute name="time" type="xs:long" use="required"/>
+ <xs:attribute name="message" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="AlbumList">
+ <xs:sequence>
+ <xs:element name="album" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="AlbumList2">
+ <xs:sequence>
+ <xs:element name="album" type="sub:AlbumID3" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="RandomSongs">
+ <xs:sequence>
+ <xs:element name="song" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Lyrics" mixed="true">
+ <xs:attribute name="artist" type="xs:string" use="optional"/>
+ <xs:attribute name="title" type="xs:string" use="optional"/>
+ </xs:complexType>
+
+ <xs:complexType name="Podcasts">
+ <xs:sequence>
+ <xs:element name="channel" type="sub:PodcastChannel" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="PodcastChannel">
+ <xs:sequence>
+ <xs:element name="episode" type="sub:PodcastEpisode" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:string" use="required"/>
+ <xs:attribute name="url" type="xs:string" use="required"/>
+ <xs:attribute name="title" type="xs:string" use="optional"/>
+ <xs:attribute name="description" type="xs:string" use="optional"/>
+ <xs:attribute name="status" type="sub:PodcastStatus" use="required"/>
+ <xs:attribute name="errorMessage" type="xs:string" use="optional"/>
+ </xs:complexType>
+
+ <xs:complexType name="PodcastEpisode">
+ <xs:complexContent>
+ <xs:extension base="sub:Child">
+ <xs:attribute name="streamId" type="xs:string" use="optional"/> <!-- Use this ID for streaming the podcast. -->
+ <xs:attribute name="description" type="xs:string" use="optional"/>
+ <xs:attribute name="status" type="sub:PodcastStatus" use="required"/>
+ <xs:attribute name="publishDate" type="xs:dateTime" use="optional"/>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:simpleType name="PodcastStatus">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="new"/>
+ <xs:enumeration value="downloading"/>
+ <xs:enumeration value="completed"/>
+ <xs:enumeration value="error"/>
+ <xs:enumeration value="deleted"/>
+ <xs:enumeration value="skipped"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="Shares">
+ <xs:sequence>
+ <xs:element name="share" type="sub:Share" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Share">
+ <xs:sequence>
+ <xs:element name="entry" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:string" use="required"/>
+ <xs:attribute name="url" type="xs:string" use="required"/>
+ <xs:attribute name="description" type="xs:string" use="optional"/>
+ <xs:attribute name="username" type="xs:string" use="required"/>
+ <xs:attribute name="created" type="xs:dateTime" use="required"/>
+ <xs:attribute name="expires" type="xs:dateTime" use="optional"/>
+ <xs:attribute name="lastVisited" type="xs:dateTime" use="optional"/>
+ <xs:attribute name="visitCount" type="xs:int" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="Starred">
+ <xs:sequence>
+ <xs:element name="artist" type="sub:Artist" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="album" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="song" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="Starred2">
+ <xs:sequence>
+ <xs:element name="artist" type="sub:ArtistID3" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="album" type="sub:AlbumID3" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="song" type="sub:Child" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="License">
+ <xs:attribute name="valid" type="xs:boolean" use="required"/>
+ <xs:attribute name="email" type="xs:string" use="optional"/>
+ <xs:attribute name="key" type="xs:string" use="optional"/>
+ <xs:attribute name="date" type="xs:dateTime" use="optional"/>
+ </xs:complexType>
+
+ <xs:complexType name="User">
+ <xs:attribute name="username" type="xs:string" use="required"/>
+ <xs:attribute name="email" type="xs:string" use="optional"/> <!-- Added in 1.6.0 -->
+ <xs:attribute name="scrobblingEnabled" type="xs:boolean" use="required"/> <!-- Added in 1.7.0 -->
+ <xs:attribute name="adminRole" type="xs:boolean" use="required"/>
+ <xs:attribute name="settingsRole" type="xs:boolean" use="required"/>
+ <xs:attribute name="downloadRole" type="xs:boolean" use="required"/>
+ <xs:attribute name="uploadRole" type="xs:boolean" use="required"/>
+ <xs:attribute name="playlistRole" type="xs:boolean" use="required"/>
+ <xs:attribute name="coverArtRole" type="xs:boolean" use="required"/>
+ <xs:attribute name="commentRole" type="xs:boolean" use="required"/>
+ <xs:attribute name="podcastRole" type="xs:boolean" use="required"/>
+ <xs:attribute name="streamRole" type="xs:boolean" use="required"/>
+ <xs:attribute name="jukeboxRole" type="xs:boolean" use="required"/>
+ <xs:attribute name="shareRole" type="xs:boolean" use="required"/> <!-- Added in 1.7.0 -->
+ </xs:complexType>
+
+ <xs:complexType name="Error">
+ <xs:attribute name="code" type="xs:int" use="required"/>
+ <xs:attribute name="message" type="xs:string" use="optional"/>
+ </xs:complexType>
+
+</xs:schema>
\ No newline at end of file diff --git a/subsonic-main/src/main/webapp/xsd/user_example_1.xml b/subsonic-main/src/main/webapp/xsd/user_example_1.xml new file mode 100644 index 00000000..9b96db67 --- /dev/null +++ b/subsonic-main/src/main/webapp/xsd/user_example_1.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?>
+
+<subsonic-response xmlns="http://subsonic.org/restapi"
+ status="ok" version="1.7.0">
+
+ <user username="sindre" email="sindre@activeobjects.no" scrobblingEnabled="true" adminRole="false" settingsRole="true" downloadRole="true" uploadRole="false" playlistRole="true"
+ coverArtRole="true" commentRole="true" podcastRole="true" streamRole="true" jukeboxRole="true" shareRole="false"/>
+
+</subsonic-response>
+
|