diff --git a/.gitignore b/.gitignore index 2f820efc4d..f3f48c5963 100644 --- a/.gitignore +++ b/.gitignore @@ -271,6 +271,7 @@ modules/blogging/app/Volo.BloggingTestApp/wwwroot/files/*.* modules/docs/app/VoloDocs.Web/Logs/*.* modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/Logs/*.* templates/module/app/MyCompanyName.MyProjectName.DemoApp/Logs/*.* +templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/Logs/logs.txt templates/mvc/src/MyCompanyName.MyProjectName.Web/Logs/*.* @@ -313,4 +314,4 @@ abp-build-config.json tempkey.jwk # ABP Analyzing files -*.abppkg.analyze.json \ No newline at end of file +*.abppkg.analyze.json diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en-GB.json index 970e04d24e..4ea99af7e1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en-GB.json @@ -197,6 +197,19 @@ "RemoveCache": "Remove Cache", "Language": "Language", "Optional": "Optional", - "CreateArticleLanguageInfo": "The language in which the article is written" + "CreateArticleLanguageInfo": "The language in which the article is written", + "Menu:Quotation": "Quotation", + "Menu:Invoice": "Invoice", + "Menu:PaymentRequests": "Payment Requests", + "Permission:PaymentRequests": "Payment Requests", + "PaymentRequests": "Payment Requests", + "Creator": "Creator", + "ExtraProperties": "Extra Properties", + "Organization": "Organization", + "Waiting": "Waiting", + "Completed": "Completed", + "Failed": "Failed", + "PaymentRequestDeletionWarningMessage": "This payment request will be deleted. Do you confirm that?", + "Payment": "Payment" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index 0cfd2a477a..bbfcb08e18 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -277,6 +277,19 @@ "ThisExtensionIsNotAllowed": "This extension is not allowed.", "TheFileIsTooLarge": "The file is too large!", "ArticleDeletionConfirmationMessage": "Are you sure you want to hard delete this article?", - "ChooseCoverImage": "Choose a cover image..." + "ChooseCoverImage": "Choose a cover image...", + "Menu:Quotation": "Quotation", + "Menu:Invoice": "Invoice", + "Menu:PaymentRequests": "Payment Requests", + "Permission:PaymentRequests": "Payment Requests", + "PaymentRequests": "Payment Requests", + "Creator": "Creator", + "ExtraProperties": "Extra Properties", + "Organization": "Organization", + "Waiting": "Waiting", + "Completed": "Completed", + "Failed": "Failed", + "PaymentRequestDeletionWarningMessage": "This payment request will be deleted. Do you confirm that?", + "Payment": "Payment" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json index c1253db259..19e81c5788 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json @@ -227,6 +227,19 @@ "TheFileIsTooLarge": "Dosya çok büyük.", "ArticleDeletionConfirmationMessage": "Bu makaleyi kalıcı olarak silmek istediğinizden emin misiniz?", "ChooseCoverImage": "Bir kapak resmi seçin...", - "CoverImage": "Kapak Resmi" + "CoverImage": "Kapak Resmi", + "Menu:Quotation": "Fiyatlandırma", + "Menu:Invoice": "Fatura", + "Menu:PaymentRequests": "Ödeme İstekleri", + "Permission:PaymentRequests": "Ödeme İstekleri", + "PaymentRequests": "Ödeme İstekleri", + "Creator": "Oluşturan", + "ExtraProperties": "Ekstra Özellikler", + "Organization": "Organizasyon", + "Waiting": "Bekliyor", + "Completed": "Tamamlandı", + "Failed": "Başarısız Oldu", + "PaymentRequestDeletionWarningMessage": "Bu ödeme isteği silinecek. Bunu onaylıyor musun?", + "Payment": "Ödeme" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en-GB.json index 82ffbf0f4c..442384bd0a 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en-GB.json @@ -32,6 +32,7 @@ "SeeDocuments": "See Documents", "Samples": "Samples", "FreeDDDBook": "Free DDD E-book", - "New": "New" + "New": "New", + "Volo.AbpIo.Domain:020005": "License extend year can not be lower than {MinExtendLicenseYear} year and greater than {MaxExtendLicenseYear} years " } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json index 646c2f9648..b9c8d23563 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json @@ -34,6 +34,7 @@ "Framework": "Framework", "Support": "Support", "FreeDDDBook": "Free DDD E-book", - "New": "New" + "New": "New", + "Volo.AbpIo.Domain:020005": "License extend year can not be lower than {MinExtendLicenseYear} year and greater than {MaxExtendLicenseYear} years " } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hi.json index cd1ec4491d..5096d3cbe7 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hi.json @@ -11,8 +11,8 @@ "Volo.AbpIo.Domain:010011": "व्यक्तिगत लाइसेंस में 1 से अधिक डेवलपर नहीं हो सकते हैं!", "Volo.AbpIo.Domain:010012": "लाइसेंस की अवधि समाप्त होने के एक महीने बाद तक लाइसेंस नहीं बढ़ाया जा सकता है!", "Volo.AbpIo.Domain:020001": "इस NPM पैकेज को नहीं हटाया जा सका क्योंकि \"{NugetPackages}\" नुगेट पैकेज इस पैकेज पर निर्भर हैं।", - "Volo.AbpIo.Domain:020002": "यह NPM पैकेज नहीं हटा सका क्योंकि \"{मॉड्यूल}\" मॉड्यूल इस पैकेज का उपयोग कर रहे हैं।", - "Volo.AbpIo.Domain:020003": "इस NPM पैकेज को नहीं हटाया जा सका क्योंकि \"{मॉड्यूल}\" मॉड्यूल इस पैकेज का उपयोग कर रहे हैं और \"{NugetPackages}\" नुगेट पैकेज इस पैकेज पर निर्भर हैं।", + "Volo.AbpIo.Domain:020002": "यह NPM पैकेज नहीं हटा सका क्योंकि \"{Modules}\" मॉड्यूल इस पैकेज का उपयोग कर रहे हैं।", + "Volo.AbpIo.Domain:020003": "इस NPM पैकेज को नहीं हटाया जा सका क्योंकि \"{Modules}\" मॉड्यूल इस पैकेज का उपयोग कर रहे हैं और \"{NugetPackages}\" नुगेट पैकेज इस पैकेज पर निर्भर हैं।", "Volo.AbpIo.Domain:020004": "इस Nuget पैकेज को हटाया नहीं जा सका क्योंकि \"{Modules}\" मॉड्यूल इस पैकेज का उपयोग कर रहे हैं।", "WantToLearn?": "सीखना चाहते है?", "ReadyToGetStarted?": "आरंभ करने के लिए तैयार हैं?", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json index 2f932f299b..04c114a6c2 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json @@ -28,6 +28,7 @@ "Commercial": "Ticari", "SeeDocuments": "Dokümanlara Göz Atın", "FreeDDDBook": "Ücretsiz DDD Kitabı", - "New": "Yeni" + "New": "Yeni", + "Volo.AbpIo.Domain:020005": "Lisans uzatma yılı {MinExtendLicenseYear} yıldan az {MaxExtendLicenseYear} yıldan fazla olamaz." } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json index 0694811b78..af20ee9ba7 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en-GB.json @@ -100,6 +100,7 @@ "VolosoftSharingInformationMessage": "I would like Volosoft to share my information with select partners so I can receive relevant information about their products and services.", "WeWillSendYouADownloadLink": "We've sent the file to {0}.", "InvalidFormInputs": "Please, type the valid information specified on the form.", - "DDDBookEmailBody": "Thank you.
To download your book, click here." + "DDDBookEmailBody": "Thank you.
To download your book, click here.", + "FreeDDDEBook": "Free DDD E-Book" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index d7f9f3c651..58e4b561d6 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -357,6 +357,7 @@ "VolosoftSharingInformationMessage": "I would like Volosoft to share my information with select partners so I can receive relevant information about their products and services.", "WeWillSendYouADownloadLink": "A link to download the e-book has been sent to {0}.
Check your inbox / junk / spam boxes!", "InvalidFormInputs": "Please, type the valid information specified on the form.", - "DDDBookEmailBody": "Thank you.
To download your book, click here." + "DDDBookEmailBody": "Thank you.
To download your book, click here.", + "FreeDDDEBook": "Free DDD E-Book" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json index b2da832b2a..317ace31b5 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json @@ -151,7 +151,7 @@ "SeeAllModules": "Katso kaikki moduulit", "ABPCLIExplanation": "ABP CLI (Command Line Interface) on komentorivityökalu joidenkin yleisten toimintojen suorittamiseen ABP-pohjaisiin ratkaisuihin.", "ABPSuiteEasilyCURD": "ABP Suite on työkalu, jonka avulla voit helposti luoda CRUD-sivuja", - "WeAreHereToHelp": " Apua olemme täällä", + "WeAreHereToHelp": "Apua olemme täällä", "BrowseOrAskQuestion": "Voit selata ohjeaiheitamme tai etsiä usein kysyttyjä kysymyksiä tai voit esittää meille kysymyksiä yhteydenottolomakkeella .", "SearchQuestionPlaceholder": "Hae usein kysyttyjä kysymyksiä", "WhatIsTheABPCommercial": "Mikä on ABP-kauppa?", @@ -177,7 +177,7 @@ "ChangingLicenseType": "Voinko muuttaa lisenssityyppiäni tulevaisuudessa?", "ChangingLicenseTypeExplanation": "Voit aina lisätä uusia kehittäjiä samaan lisenssityyppiin. Katso myös \"Kuinka monta kehittäjää voi työskennellä ABP Commercialilla?\". Voit myös päivittää korkeampaan lisenssiin maksamalla lasketun hintaeron. Kun päivität korkeampaan lisenssisuunnitelmaan, saat uuden suunnitelman edut, mutta lisenssin päivitys ei muuta lisenssin voimassaolon päättymispäivää.", "LicenseExtendUpgradeDiff": "Mitä eroa on lisenssin laajennuksella ja päivityksellä?", - "LicenseExtendUpgradeDiffExplanation": " Laajentaminen: Laajentamalla / uusimalla käyttöoikeutta saat jatkossakin ensiluokkaista tukea ja saat tärkeitä päivityksiä moduuleille ja teemoille. Lisäksi voit jatkaa uusien projektien luomista. Ja voit silti käyttää ABP Suitea, joka vauhdittaa kehitystäsi.
Päivittäminen: Päivittämällä lisenssisi edistyt korkeampaan lisenssisuunnitelmaan, jonka avulla voit saada lisäetuja . Katso lisenssisuunnitelmien väliset erot lisenssien vertailutaulukosta . Toisaalta, kun päivität, lisenssin vanhentumispäivä ei muutu! Lisenssin päättymispäivän jatkamiseksi sinun on jatkettava käyttöoikeutta.", + "LicenseExtendUpgradeDiffExplanation": " Extension: en prolongeant/renouvelant votre licence, vous continuerez à bénéficier d'une assistance premium et à des mises à jour majeures pour les modules et les thèmes. De plus, vous pourrez continuer à créer de nouveaux projets. Et vous pourrez toujours utiliser ABP Suite, ce qui accélère votre développement.
Mise à niveau: En mettant à jour votre licence, vous passerez à un plan de licence supérieur qui vous permettra d’obtenir des avantages supplémentaires . Consultez le tableau de comparaison des licences pour vérifier les différences entre les plans de licence. En revanche, lors de la mise à niveau, la date d'expiration de votre licence ne changera pas! Pour prolonger la date de fin de votre licence, vous devez prolonger votre licence.", "LicenseRenewalCost": "Mitkä ovat lisenssin uusimiskustannukset vuoden kuluttua?", "LicenseRenewalCostExplanation": "Kaikkien ABP Commercial perpetual -lisenssien uusimis- (laajennus) hinta on {0} lisenssiluettelohinnasta. Tavallisen tiimilisenssin uusimishinta on $ {1}, tavallinen yrityslisenssi on $ {2} ja tavallinen yrityslisenssi on $ {3}. Jos olet jo asiakas, kirjaudu tilillesi ja tarkista käytettävissä oleva uusimishinta.", "HowDoIRenewMyLicense": "Kuinka uusin lisenssin?", @@ -230,7 +230,7 @@ "HowCanIRefundVatExplanation2": "Kirjaudu sisään 2Tarkista -tiliisi.", "HowCanIRefundVatExplanation3": "Etsi sopiva tilaus ja paina \"Hyvitä myöhässä oleva alv\" (kirjoita ALV-tunnuksesi)", "HowCanIGetMyInvoice": "Kuinka saan laskuni?", - "HowCanIGetMyInvoiceExplanation": "Lisenssin ostamiseen on 2 maksuyhdyskäytävää: PayU ja 2Checkout. Jos ostat lisenssin 2Checkout gatewayn kautta, se lähettää PDF-laskun sähköpostiosoitteeseesi, katso 2Tarkista laskutus. Jos ostat PayU-yhdyskäytävän kautta tai pankkisiirrolla, valmistelemme ja lähetämme laskusi. Voit pyytää laskua organisaation hallintasivulta ", + "HowCanIGetMyInvoiceExplanation": "Lisenssin ostamiseen on 2 maksuyhdyskäytävää: PayU ja 2Checkout. Jos ostat lisenssin 2Checkout gatewayn kautta, se lähettää PDF-laskun sähköpostiosoitteeseesi, katso 2Tarkista laskutus. Jos ostat PayU-yhdyskäytävän kautta tai pankkisiirrolla, valmistelemme ja lähetämme laskusi. Voit pyytää laskua organisaation hallintasivulta ", "Forum": "Foorumi", "SupportExplanation": "ABP Commercial -lisenssit tarjoavat ensiluokkaisen foorumituen ABP-kehyksen asiantuntijoista koostuvalle tiimille.", "PrivateTicket": "Yksityinen lippu", @@ -240,7 +240,7 @@ "FastEasy": "Nopea ja helppo", "AbpSuiteExplanation3": "ABP Suiten avulla voit luoda helposti CRUD-sivuja. Sinun tarvitsee vain määritellä entiteetti ja sen ominaisuudet, antaa loput ABP Suiten puolestasi! ABP Suite luo kaikki tarvittavat koodit CRUD-sivullesi muutamassa sekunnissa. Se tukee Angular-, MVC- ja Blazor-käyttöliittymiä.", "RichOptions": "Monipuoliset vaihtoehdot", - "AbpSuiteExplanation4": "ABP Suite tukee useita käyttöliittymävaihtoehtoja, kuten Razor Pages ja Kulma .Se tukee myös useita tietokantoja, kuten MongoDB ja kaikkia EntityFramework Core <: n tukemia tietokantoja. / strong> (MS SQL Server, Oracle, MySql, PostgreSQL ja lisää ).", + "AbpSuiteExplanation4": "ABP Suite supports multiple UI options like Razor Pages and Angular.It also supports multiple databases like MongoDB and all databases supported by EntityFramework Core (MS SQL Server, Oracle, MySql, PostgreSQL and more).", "AbpSuiteExplanation5": "Hyvä asia on, että sinun ei tarvitse huolehtia näistä vaihtoehdoista. ABP Suite ymmärtää projektisi tyypin ja luo koodin projektillesi ja sijoittaa luodun koodin oikeaan paikkaan projektissasi.", "SourceCode": "Lähdekoodi", "AbpSuiteExplanation6": "ABP Suite luo lähdekoodin sinulle! Se ei luo taikuustiedostoja verkkosivun luomiseksi. ABP Suite luo lähdekoodin Entity, Repository, Application Service, Code First Migration, JavaScript / TypeScript ja CSHTML / HTML sekä tarvittavat liitännät. ABP Suite tuottaa koodin myös ohjelmistokehityksen parhaiden käytäntöjen mukaisesti, joten sinun ei tarvitse huolehtia luodun koodin laadusta.", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json index c5f9f1db6c..90d1fcf0c9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json @@ -177,7 +177,7 @@ "ChangingLicenseType": "Puis-je changer mon type de licence à l'avenir?", "ChangingLicenseTypeExplanation": "Vous pouvez toujours ajouter de nouveaux développeurs dans votre même type de licence. Voir aussi \"Combien de développeurs peuvent travailler sur l'ABP Commercial?\". Vous pouvez également passer à une licence supérieure en payant la différence de prix calculée. Lorsque vous passez à un plan de licence supérieur, vous bénéficiez des avantages du nouveau plan, mais la mise à niveau de la licence ne modifie pas la date d'expiration de la licence.", "LicenseExtendUpgradeDiff": "Quelle est la différence entre l'extension de licence et la mise à niveau?", - "LicenseExtendUpgradeDiffExplanation": " Extension: en prolongeant / renouvelant votre licence, vous continuerez à bénéficier d'une assistance premium et à des mises à jour majeures pour les modules et les thèmes. De plus, vous pourrez continuer à créer de nouveaux projets. Et vous pourrez toujours utiliser ABP Suite, ce qui accélère votre développement.
Mise à niveau: En mettant à jour votre licence, vous passerez à un plan de licence supérieur qui vous permettra d’obtenir des avantages supplémentaires . Consultez le tableau de comparaison des licences pour vérifier les différences entre les plans de licence. En revanche, lors de la mise à niveau, la date d'expiration de votre licence ne changera pas! Pour prolonger la date de fin de votre licence, vous devez prolonger votre licence.", + "LicenseExtendUpgradeDiffExplanation": " Extension: en prolongeant/renouvelant votre licence, vous continuerez à bénéficier d'une assistance premium et à des mises à jour majeures pour les modules et les thèmes. De plus, vous pourrez continuer à créer de nouveaux projets. Et vous pourrez toujours utiliser ABP Suite, ce qui accélère votre développement.
Mise à niveau: En mettant à jour votre licence, vous passerez à un plan de licence supérieur qui vous permettra d’obtenir des avantages supplémentaires . Consultez le tableau de comparaison des licences pour vérifier les différences entre les plans de licence. En revanche, lors de la mise à niveau, la date d'expiration de votre licence ne changera pas! Pour prolonger la date de fin de votre licence, vous devez prolonger votre licence.", "LicenseRenewalCost": "Quel est le coût du renouvellement de la licence après 1 an?", "LicenseRenewalCostExplanation": "Le taux de renouvellement (extension) de toutes les licences perpétuelles ABP Commercial correspond à {0} du prix catalogue de la licence. Le prix de renouvellement de la licence d'équipe standard est de {1} $, la licence professionnelle standard de {2} $ et la licence d'entreprise standard de {3} $. Si vous êtes déjà client, connectez-vous à votre compte pour consulter les tarifs de renouvellement disponibles.", "HowDoIRenewMyLicense": "Comment renouveler ma licence?", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json index 54216f7719..dd7e117541 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json @@ -42,7 +42,7 @@ "NotOrganizationMember": "आप किसी संगठन के सदस्य नहीं हैं।", "UnsubscribeLicenseExpirationEmailSuccessTitle": "सफलतापूर्वक सदस्यता समाप्त कर दी गई", "UnsubscribeLicenseExpirationEmailSuccessMessage": "अब आपको लाइसेंस समाप्ति तिथि अनुस्मारक ईमेल प्राप्त नहीं होंगे।", - "IndexPageHeroSection": " एक पूर्ण वेब विकास मंच अंतर्निहित ढांचा ", + "IndexPageHeroSection": "एक पूर्ण वेब डेवलपमेंट प्लेटफॉर्मबिल्ट-ऑन Framework", "AbpCommercialShortDescription": "एबीपी कमर्शियल प्री-बिल्ट एप्लिकेशन मॉड्यूल, रैपिड एप्लिकेशन डेवलपमेंट टूलिंग, पेशेवर यूआई थीम, प्रीमियम सपोर्ट आदि प्रदान करता है।", "LiveDemo": "लाइव डेमो", "GetLicence": "एक लाइसेंस प्राप्त करें", @@ -135,7 +135,7 @@ "GoHome": "घर जाओ", "CreateLiveDemo": "लाइव डेमो बनाएँ", "RegisterToTheNewsletter": "ABP.IO के बारे में जानकारी प्राप्त करने के लिए न्यूज़लेटर के लिए रजिस्टर करें, जिसमें नई रिलीज़ आदि शामिल हैं।", - "EnterYourEmailOrLogin": "अपने मौजूदा खाते का उपयोग करके अपना डेमो बनाने के लिए अपना ई-मेल पता दर्ज करें या अपना प्रदर्शन लॉगिन करें।", + "EnterYourEmailOrLogin": "अपना डेमो बनाने के लिए अपना ई-मेल पता दर्ज करें या अपने मौजूदा खाते का उपयोग करके लॉगिन करें।", "ApplicationTemplate": "एप्लिकेशन टेम्पलेट", "ApplicationTemplateExplanation": "एप्लिकेशन स्टार्टअप टेम्पलेट का उपयोग एक नया वेब एप्लिकेशन बनाने के लिए किया जाता है।", "EfCoreProvider": "इकाई ढाँचा (SQL सर्वर, MySQL, PostgreSQL, Oracle और अन्य का समर्थन करता है)", @@ -152,50 +152,50 @@ "ABPCLIExplanation": "ABP CLI (कमांड लाइन इंटरफेस) ABP आधारित समाधानों के लिए कुछ सामान्य ऑपरेशन करने के लिए एक कमांड लाइन टूल है।", "ABPSuiteEasilyCURD": "एबीपी सूट एक उपकरण है जो आपको आसानी से CRUD पेज बनाने की अनुमति देता है", "WeAreHereToHelp": "हम यहाँ हैं मदद ", - "BrowseOrAskQuestion": "आप हमारे सहायता विषयों को ब्राउज़ कर सकते हैं या अक्सर पूछे जाने वाले प्रश्नों में खोज कर सकते हैं, या आप संपर्क फ़ॉर्म का उपयोग करके हमसे एक प्रश्न पूछ सकते हैं।", + "BrowseOrAskQuestion": "आप हमारे सहायता विषयों को ब्राउज़ कर सकते हैं या अक्सर पूछे जाने वाले प्रश्नों में खोज कर सकते हैं, या आप संपर्क फ़ॉर्म का उपयोग करके हमसे एक प्रश्न पूछ सकते हैं।", "SearchQuestionPlaceholder": "अक्सर पूछे जाने वाले प्रश्नों में खोजें", "WhatIsTheABPCommercial": "ABP कमर्शियल क्या है?", "WhatAreDifferencesThanAbpFramework": "ओपन सोर्स ABP फ्रेमवर्क और ABP कमर्शियल के बीच क्या अंतर हैं?", - "ABPCommercialExplanation": "एबीपी कमर्शियल, खुले स्रोत के शीर्ष पर बनाए गए प्रीमियम मॉड्यूल, टूल, थीम और सेवाओं का एक सेट है जो ABP फ्रेमवर्क है। एबीपी कमर्शियल को एबीपी फ्रेमवर्क के पीछे उसी टीम द्वारा विकसित और समर्थित किया जा रहा है।", - "WhatAreDifferencesThanABPFrameworkExplanation": "

ABP फ्रेमवर्क ASP.NET Core के लिए एक मॉड्यूलर, थीमेबल, माइक्रो-सर्विस संगत एप्लिकेशन डेवलपमेंट फ्रेमवर्क है। यह आपको हर नई परियोजना के लिए खुद को दोहराने के बजाय अपने खुद के व्यवसाय कोड पर ध्यान केंद्रित करने के लिए एक पूर्ण वास्तुकला और एक मजबूत बुनियादी ढांचा प्रदान करता है। यह सॉफ्टवेयर विकास सर्वोत्तम प्रथाओं और लोकप्रिय उपकरणों पर आधारित है जिन्हें आप पहले से जानते हैं।

एबीपी फ्रेमवर्क पूरी तरह से मुक्त, खुला स्रोत और समुदाय-संचालित है। यह एक मुफ्त थीम और कुछ पूर्व-निर्मित मॉड्यूल (जैसे पहचान प्रबंधन और किरायेदार प्रबंधन) प्रदान करता है। ", - "VisitTheFrameworkVSCommercialDocument": "अधिक जानकारी के लिए, निम्न लिंक पर जाएं {1} ", + "ABPCommercialExplanation": "एबीपी कमर्शियल ओपन सोर्स ABP फ्रेमवर्क के शीर्ष पर निर्मित प्रीमियम मॉड्यूल, टूल, थीम और सेवाओं का एक सेट है। एबीपी कमर्शियल को एबीपी ढांचे के पीछे उसी टीम द्वारा विकसित और समर्थित किया जा रहा है।", + "WhatAreDifferencesThanABPFrameworkExplanation": "

ABP फ्रेमवर्क ASP.NET कोर के लिए एक मॉड्यूलर, थीम योग्य, माइक्रो-सर्विस संगत एप्लिकेशन डेवलपमेंट फ्रेमवर्क है। यह आपको हर नई परियोजना के लिए खुद को दोहराने के बजाय अपने स्वयं के व्यवसाय कोड पर ध्यान केंद्रित करने के लिए एक पूर्ण वास्तुकला और एक मजबूत बुनियादी ढांचा प्रदान करता है। यह सॉफ्टवेयर विकास सर्वोत्तम प्रथाओं और लोकप्रिय टूल पर आधारित है जिन्हें आप पहले से जानते हैं।

एबीपी ढांचा पूरी तरह से मुक्त, खुला स्रोत और समुदाय संचालित है। यह एक मुफ्त थीम और कुछ पूर्व-निर्मित मॉड्यूल (जैसे पहचान प्रबंधन और किरायेदार प्रबंधन) भी प्रदान करता है।

", + "VisitTheFrameworkVSCommercialDocument": "अधिक जानकारी के लिए, निम्न लिंक पर जाएँ {1} ", "ABPCommercialFollowingBenefits": "एबीपी वाणिज्यिक एबीपी ढांचे के शीर्ष पर निम्नलिखित लाभ जोड़ता है;", "Professional": "पेशेवर", "UIThemes": "यूआई थीम", - "EnterpriseModules": "एंटरप्राइज रेडी, फीचर से भरपूर, पहले से निर्मित एप्लिकेशन मॉड्यूल (जैसे पहचान सर्वर प्रबंधन, सास प्रबंधन, भाषा प्रबंधन)", - "ToolingToSupport": "अपनी विकास उत्पादकता का समर्थन करने का टूल", - "PremiumSupportLink": "प्रीमियम समर्थन ", + "EnterpriseModules": "एंटरप्राइज़ तैयार, सुविधा संपन्न, पूर्व-निर्मित एप्लिकेशन मॉड्यूल (उदा. पहचान सर्वर प्रबंधन, SaaS प्रबंधन, भाषा प्रबंधन)", + "ToolingToSupport": "आपकी विकास उत्पादकता का समर्थन करने के लिए टूलिंग (उदा. ABP Suite)", + "PremiumSupportLink": "प्रीमियम समर्थन", "WhatDoIDownloadABPCommercial": "जब मैं एबीपी कमर्शियल खरीदता हूं तो क्या डाउनलोड करता हूं?", - "CreateUnlimitedSolutions": "एक बार जब आप एक एबीपी कमर्शियल लाइसेंस खरीदते हैं, तो आप असीमित समाधान बना पाएंगे, जैसे कि Get Started दस्तावेज़ में वर्णित है।", + "CreateUnlimitedSolutions": "एक बार जब आप एबीपी वाणिज्यिक लाइसेंस खरीद लेते हैं, तो आप असीमित समाधान बनाने में सक्षम होंगे जैसा कि आरंभ करना दस्तावेज़ में वर्णित है।", "ABPCommercialSolutionExplanation": "जब आप एक नया एप्लिकेशन बनाते हैं, तो आपको अपनी प्राथमिकताओं के आधार पर एक विज़ुअल स्टूडियो समाधान (एक स्टार्टअप टेम्प्लेट) मिलता है। डाउनलोड किए गए समाधान में आपके लिए पहले से इंस्टॉल और कॉन्फ़िगर किए गए वाणिज्यिक मॉड्यूल और थीम हैं। यदि आप चाहें तो आप पहले से स्थापित मॉड्यूल को हटा सकते हैं या किसी अन्य मॉड्यूल को जोड़ सकते हैं। सभी मॉड्यूल और थीम डिफ़ॉल्ट रूप से एक NuGet / NPM पैकेज का उपयोग किया जाता है।", - "StartDevelopWithTutorials": "डाउनलोड किया गया समाधान अच्छी तरह से वास्तुकला और दस्तावेज है। आप अपने स्वयं के व्यवसाय कोड को इस आधार पर विकसित करना शुरू कर सकते हैं कि वह ट्यूटोरियल्स का अनुसरण कर सकता है", - "TryTheCommercialDemo": "ABP कमर्शियल स्टार्टअप टेम्प्लेट का उपयोग करके बनाए गए एक नमूना अनुप्रयोग को देखने के लिए आप डेमो का प्रयास कर सकते हैं।", + "StartDevelopWithTutorials": "डाउनलोड किया गया समाधान अच्छी तरह से संरचित और प्रलेखित है। आप ट्यूटोरियल . का अनुसरण करके इसके आधार पर अपना खुद का व्यवसाय कोड विकसित करना शुरू कर सकते हैं", + "TryTheCommercialDemo": "ABP कमर्शियल स्टार्टअप टेम्प्लेट का उपयोग करके बनाए गए एक नमूना एप्लिकेशन को देखने के लिए आप डेमो आज़मा सकते हैं।", "HowManyProducts": "ABP वाणिज्यिक का उपयोग करके मैं कितने विभिन्न उत्पाद / समाधान बना सकता हूं?", "HowManyProductsExplanation": "ABP प्रोजेक्ट बनाने की कोई सीमा नहीं है। आप जितने चाहें उतने प्रोजेक्ट बना सकते हैं, उन्हें विकसित कर सकते हैं और उन्हें विभिन्न सर्वरों पर अपलोड कर सकते हैं।", "HowManyDevelopers": "एबीपी कमर्शियल पर कितने डेवलपर काम कर सकते हैं?", - "HowManyDevelopersExplanation": "एबीपी वाणिज्यिक लाइसेंस प्रति डेवलपर हैं। विभिन्न लाइसेंस प्रकारों में अलग-अलग डेवलपर सीमाएँ होती हैं। हालाँकि, जब भी आपको आवश्यकता हो, आप किसी भी प्रकार के लाइसेंस में अधिक डेवलपर्स जोड़ सकते हैं। लाइसेंस प्रकार, डेवलपर सीमा और अतिरिक्त डेवलपर लागतों के लिए कीमतें पृष्ठ देखें।", + "HowManyDevelopersExplanation": "एबीपी वाणिज्यिक लाइसेंस प्रति डेवलपर हैं। विभिन्न लाइसेंस प्रकारों की अलग-अलग डेवलपर सीमाएँ होती हैं। हालांकि, जब भी आपको आवश्यकता हो, आप किसी भी प्रकार के लाइसेंस में अधिक डेवलपर जोड़ सकते हैं। लाइसेंस प्रकारों, डेवलपर सीमाओं और अतिरिक्त डेवलपर लागतों के लिए कीमतें पृष्ठ देखें।", "ChangingLicenseType": "क्या मैं भविष्य में अपना लाइसेंस प्रकार बदल सकता हूं?", "ChangingLicenseTypeExplanation": "आप अपने समान लाइसेंस प्रकार में हमेशा नए डेवलपर्स को जोड़ सकते हैं। यह भी देखें \"एबीपी कमर्शियल पर कितने डेवलपर काम कर सकते हैं?\"। आप गणना मूल्य अंतर का भुगतान करके एक उच्च लाइसेंस के लिए भी अपग्रेड कर सकते हैं। जब आप उच्च लाइसेंस योजना में अपग्रेड करते हैं, तो आपको नई योजना का लाभ मिलता है, लेकिन लाइसेंस अपग्रेड लाइसेंस की समाप्ति की तारीख को नहीं बदलता है।", "LicenseExtendUpgradeDiff": "लाइसेंस विस्तार और उन्नयन के बीच क्या अंतर है?", "LicenseExtendUpgradeDiffExplanation": " विस्तार: अपने लाइसेंस का विस्तार / नवीनीकरण करके, आप प्रीमियम समर्थन प्राप्त करना और मॉड्यूल और थीम के लिए प्रमुख अपडेट प्राप्त करना जारी रखेंगे। इसके अलावा, आप नई परियोजनाओं को जारी रखने में सक्षम होंगे। और आप अभी भी एबीपी सूट का उपयोग कर पाएंगे जो आपके विकास को गति देता है।
उन्नयन: अपने लाइसेंस को अपग्रेड करके, आप एक उच्च लाइसेंस योजना को बढ़ावा देंगे जिससे आप अतिरिक्त लाभ प्राप्त कर सकेंगे। । लाइसेंस योजनाओं के बीच अंतर की जांच करने के लिए लाइसेंस तुलना तालिका देखें। दूसरी ओर, जब आप अपग्रेड करते हैं, तो आपकी लाइसेंस की समाप्ति तिथि नहीं बदलेगी! > अपनी लाइसेंस की अंतिम तिथि बढ़ाने के लिए, आपको अपने लाइसेंस का विस्तार करना होगा।", "LicenseRenewalCost": "1 वर्ष के बाद लाइसेंस नवीनीकरण लागत क्या है?", - "LicenseRenewalCostExplanation": "सभी एबीपी वाणिज्यिक स्थायी लाइसेंसों का नवीकरण (विस्तार) दर लाइसेंस सूची मूल्य का {0} है। मानक टीम लाइसेंस का नवीनीकरण मूल्य $ {1} है, मानक व्यवसाय लाइसेंस $ {2} है और मानक एंटरप्राइज़ लाइसेंस $ {3} है। यदि आप पहले से ही ग्राहक हैं, तो उपलब्ध नवीनीकरण मूल्य निर्धारण की समीक्षा करने के लिए अपने खाते में लॉग इन करें ।", + "LicenseRenewalCostExplanation": "सभी एबीपी वाणिज्यिक स्थायी लाइसेंसों की नवीनीकरण (विस्तार) दर लाइसेंस सूची मूल्य का {0} है। मानक टीम लाइसेंस का नवीनीकरण मूल्य ${1} है, मानक व्यवसाय लाइसेंस ${2} है और मानक एंटरप्राइज़ लाइसेंस ${3} है। यदि आप पहले से ही ग्राहक हैं, तो उपलब्ध नवीनीकरण मूल्य-निर्धारण की समीक्षा के लिए अपने खाते में लॉग इन करें।", "HowDoIRenewMyLicense": "मैं अपने लाइसेंस का नवीनीकरण कैसे करूँ?", - "HowDoIRenewMyLicenseExplanation": "आप अपने लाइसेंस को संगठन प्रबंधन पृष्ठ पर नेविगेट करके नवीनीकृत कर सकते हैं। हमारी रियायती अर्ली रिन्यूअल दरों का लाभ उठाने के लिए, सुनिश्चित करें कि आप अपने लाइसेंस की समय सीमा समाप्त होने से पहले नवीनीकरण करें। हालाँकि, जब आपका प्रारंभिक नवीनीकरण अवसर बंद हो जाता है, तो यह जानने की चिंता न करें। आपकी सदस्यता समाप्त होने से पहले आपको 2 अनुस्मारक ई-मेल प्राप्त होंगे। हम उन्हें 30 दिन, समाप्ति से 7 दिन पहले भेज देंगे।", + "HowDoIRenewMyLicenseExplanation": "आप संगठन प्रबंधन पृष्ठ पर नेविगेट करके अपने लाइसेंस का नवीनीकरण कर सकते हैं। हमारी रियायती प्रारंभिक नवीनीकरण दरों का लाभ उठाने के लिए, अपने लाइसेंस की समय सीमा समाप्त होने से पहले नवीनीकरण करना सुनिश्चित करें। हालाँकि, यह जानने की चिंता न करें कि आपका प्रारंभिक नवीनीकरण अवसर कब बंद होगा। आपकी सदस्यता समाप्त होने से पहले आपको 2 अनुस्मारक ई-मेल प्राप्त होंगे। हम उन्हें समाप्ति से ७ दिन पहले, ३० दिनों में भेजेंगे।", "IsSourceCodeIncluded": "क्या मेरे लाइसेंस में वाणिज्यिक मॉड्यूल और थीम का स्रोत कोड शामिल है?", "IsSourceCodeIncludedExplanation1": "आपके द्वारा खरीदे गए लाइसेंस प्रकार पर निर्भर करता है:", "IsSourceCodeIncludedExplanation2": " टीम : आपका समाधान मॉड्यूल और थीम को NuGet और NPM पैकेज के रूप में उपयोग करता है। इसमें उनका स्रोत कोड शामिल नहीं है। इस तरह, जब भी कोई नया संस्करण उपलब्ध हो, आप इन मॉड्यूल और थीम को आसानी से अपग्रेड कर सकते हैं। हालाँकि, आप मॉड्यूल और थीम के स्रोत कोड प्राप्त नहीं कर सकते।", "IsSourceCodeIncludedExplanation3": " व्यवसाय / उद्यम : टीम लाइसेंस के अतिरिक्त, आप किसी भी मॉड्यूल या थीम की आवश्यकता के स्रोत कोड को डाउनलोड करने में सक्षम हैं। तुम भी एक विशेष मॉड्यूल के लिए NuGet / NPM पैकेज संदर्भ निकाल सकते हैं और इसे पूरी तरह से बदलने के लिए अपने समाधान के लिए अपने स्रोत कोड को सीधे जोड़ सकते हैं।", - "IsSourceCodeIncludedExplanation4": "

एक मॉड्यूल के स्रोत कोड को आपके समाधान में शामिल करना आपको उस मॉड्यूल को अनुकूलित करने की अधिकतम स्वतंत्रता देता है। हालाँकि, तब नया संस्करण जारी होने पर मॉड्यूल को स्वचालित रूप से अपग्रेड करना संभव नहीं होगा।

किसी भी लाइसेंस में ABP सुइट स्रोत कोड शामिल नहीं है, जो एक बाहरी उपकरण है जो आपके लिए कोड बनाता है और सहायता करता है आपके विकास के लिए।

लाइसेंस प्रकारों के अन्य अंतरों के लिए मूल्य निर्धारण पृष्ठ देखें। ", + "IsSourceCodeIncludedExplanation4": "

अपने समाधान में मॉड्यूल के स्रोत कोड को शामिल करने से आपको उस मॉड्यूल को अनुकूलित करने की अधिकतम स्वतंत्रता मिलती है। हालांकि, नया संस्करण जारी होने पर मॉड्यूल को स्वचालित रूप से अपग्रेड करना संभव नहीं होगा।

किसी भी लाइसेंस में एबीपी सूट स्रोत कोड शामिल नहीं है, जो एक बाहरी उपकरण है जो आपके लिए कोड उत्पन्न करता है और सहायता करता है। आपके विकास के लिए।

लाइसेंस प्रकारों के बीच अन्य अंतरों के लिए मूल्य निर्धारण पृष्ठ देखें।

", "ChangingDevelopers": "क्या मैं भविष्य में अपने संगठन के पंजीकृत डेवलपर्स को बदल सकता हूं?", "ChangingDevelopersExplanation": "अपने लाइसेंस में नए डेवलपर्स को जोड़ने के अलावा, आप मौजूदा डेवलपर्स को भी बदल सकते हैं (आप एक डेवलपर को हटा सकते हैं और एक ही सीट पर एक नया जोड़ सकते हैं) बिना किसी अतिरिक्त लागत के।", "WhatHappensWhenLicenseEnds": "मेरे लाइसेंस की अवधि समाप्त होने पर क्या होता है?", - "WhatHappensWhenLicenseEndsExplanation1": "ABP कमर्शियल लाइसेंस का प्रकार स्थायी लाइसेंस है। आपके लाइसेंस की समय सीमा समाप्त होने के बाद, आप अपना प्रोजेक्ट विकसित करना जारी रख सकते हैं। और आप अपने लाइसेंस को नवीनीकृत करने के लिए बाध्य नहीं हैं। आपका लाइसेंस एक वर्ष के अपडेट और समर्थन योजना के साथ आता है। नई सुविधाओं को प्राप्त करने के लिए, प्रदर्शन में वृद्धि, बग फिक्स, समर्थन और एबीपी सूट का उपयोग करना जारी रखें, प्रत्येक वर्ष अपनी योजना को नवीनीकृत करना सुनिश्चित करें। जब आपका लाइसेंस समाप्त हो जाता है, तो आप निम्नलिखित लाभ प्राप्त नहीं कर पाएंगे;", + "WhatHappensWhenLicenseEndsExplanation1": "ABP वाणिज्यिक लाइसेंस प्रकार स्थायी लाइसेंस है। आपके लाइसेंस की समय सीमा समाप्त होने के बाद, आप अपने प्रोजेक्ट को विकसित करना जारी रख सकते हैं। और आप अपने लाइसेंस को नवीनीकृत करने के लिए बाध्य नहीं हैं। आपका लाइसेंस बॉक्स से बाहर एक साल के अपडेट और समर्थन योजना के साथ आता है। नई सुविधाओं, प्रदर्शन में सुधार, बग फिक्स, समर्थन प्राप्त करना जारी रखने और एबीपी सूट का उपयोग जारी रखने के लिए, हर साल अपनी योजना को नवीनीकृत करना सुनिश्चित करें। जब आपका लाइसेंस समाप्त हो जाता है, तो आप निम्नलिखित में से अधिक लाभ प्राप्त नहीं कर पाएंगे;", "WhatHappensWhenLicenseEndsExplanation2": "आप एबीपी कमर्शियल का उपयोग करके नए समाधान नहीं बना सकते हैं, लेकिन आप अपने मौजूदा अनुप्रयोगों को हमेशा के लिए विकसित कर सकते हैं।", "WhatHappensWhenLicenseEndsExplanation3": "आप अपने मुख्य संस्करण के भीतर मॉड्यूल और विषयों के लिए अद्यतन प्राप्त करने में सक्षम होंगे। उदाहरण के लिए; यदि आप किसी मॉड्यूल के v3.2.0 का उपयोग कर रहे हैं, तो आप उस मॉड्यूल के v3.x.x (v3.3.0, v3.5.2 ... आदि) के लिए अपडेट प्राप्त कर सकते हैं। लेकिन आपको अगले प्रमुख संस्करण के लिए अपडेट नहीं मिल सकता है (जैसे v4.x, v5.x)", "WhatHappensWhenLicenseEndsExplanation4": "आप अपने लाइसेंस समाप्त होने के बाद एबीपी वाणिज्यिक मंच में जोड़े गए नए मॉड्यूल और थीम स्थापित नहीं कर सकते।", "WhatHappensWhenLicenseEndsExplanation5": "आप एबीपी सूट का उपयोग नहीं कर सकते।", - "WhatHappensWhenLicenseEndsExplanation6": "आपको अब और प्रीमियम सहायता नहीं मिल सकती है।", + "WhatHappensWhenLicenseEndsExplanation6": "अब आपको प्रीमियम सहायता नहीं मिल सकती है।", "WhatHappensWhenLicenseEndsExplanation7": "यदि आप इन लाभों को प्राप्त करना जारी रखना चाहते हैं तो आप अपनी सदस्यता को नवीनीकृत कर सकते हैं। जब आप अपनी सदस्यता को नवीनीकृत करते हैं तो 20% छूट मिलती है।", "WhenShouldIRenewMyLicense": "मुझे अपना लाइसेंस कब नवीनीकृत करना चाहिए?", "WhenShouldIRenewMyLicenseExplanation1": "यदि आप अपना लाइसेंस समाप्त होने के बाद अपने लाइसेंस का नवीनीकरण 1 महीने के भीतर करते हैं, तो कुल लाइसेंस मूल्य पर% 20 छूट लागू होगी।", @@ -206,21 +206,21 @@ "DoYouAcceptBankWireTransferExplanation": "हां, हम बैंक वायर ट्रांसफर स्वीकार करते हैं।
बैंक वायर ट्रांसफर के माध्यम से लाइसेंस राशि भेजने के बाद, हमें अपनी रसीद और अनुरोधित लाइसेंस प्रकार ई-मेल के माध्यम से भेजें।
हमारे अंतरराष्ट्रीय बैंक खाते की जानकारी:", "HowToUpgrade": "नया संस्करण उपलब्ध होने पर मौजूदा एप्लिकेशन को कैसे अपग्रेड किया जाए?", "HowToUpgradeExplanation1": "जब आप ABP कमर्शियल का उपयोग करके एक नया एप्लिकेशन बनाते हैं, तो सभी मॉड्यूल और थीम को NuGet और NPM पैकेज के रूप में उपयोग किया जाता है। इसलिए, नया संस्करण उपलब्ध होने पर आप आसानी से संकुल को अपग्रेड कर सकते हैं।", - "HowToUpgradeExplanation2": "मानक NuGet / NPM अपग्रेड के अलावा, ABP CLI एक अपडेट कमांड प्रदान करता है जो आपके समाधान में सभी एबीपी से संबंधित पैकेजों को स्वचालित रूप से ढूंढता है और उन्हें अपग्रेड करता है।", + "HowToUpgradeExplanation2": "मानक NuGet/NPM अपग्रेड के अलावा, ABP CLI एक अपडेट कमांड प्रदान करता है जो आपके समाधान में सभी ABP संबंधित पैकेजों को स्वचालित रूप से ढूंढता और अपग्रेड करता है।", "DatabaseSupport": "कौन से डेटाबेस सिस्टम समर्थित हैं?", - "DatabaseSupportExplanation": "ABP फ्रेमवर्क स्वयं ही डेटाबेस अज्ञेयवादी है और अपनी प्रकृति के अनुसार किसी भी डेटाबेस प्रदाता के साथ काम कर सकता है। वर्तमान में कार्यान्वित प्रदाताओं की सूची के लिए डेटा एक्सेस दस्तावेज़ देखें।", + "DatabaseSupportExplanation": "एबीपी फ्रेमवर्क अपने आप में डेटाबेस अज्ञेयवादी है और अपनी प्रकृति से किसी भी डेटाबेस प्रदाता के साथ काम कर सकता है। वर्तमान में कार्यान्वित प्रदाताओं की सूची के लिए डेटा एक्सेस दस्तावेज़ देखें।", "UISupport": "कौन से UI फ्रेमवर्क समर्थित हैं?", "Supported": "समर्थित", - "UISupportExplanation": "ABP फ्रेमवर्क स्वयं UI फ्रेमवर्क अज्ञेयवादी है और किसी भी UI फ्रेमवर्क के साथ काम कर सकता है। हालाँकि, सभी UI फ्रेमवर्क के लिए स्टार्टअप टेम्प्लेट, मॉड्यूल UI और थीम लागू नहीं किए गए थे। UI विकल्पों की अप-टू-डेट सूची के लिए आरंभ किया गया दस्तावेज़ देखें।", + "UISupportExplanation": "एबीपी फ्रेमवर्क अपने आप में यूआई फ्रेमवर्क अज्ञेयवादी है और किसी भी यूआई फ्रेमवर्क के साथ काम कर सकता है। हालांकि, स्टार्टअप टेम्प्लेट, मॉड्यूल UI और थीम सभी UI फ्रेमवर्क के लिए लागू नहीं किए गए थे। UI विकल्पों की अप-टू-डेट सूची के लिए आरंभ करने वाला दस्तावेज़ देखें।", "MicroserviceSupport": "क्या यह सूक्ष्म सेवा वास्तुकला का समर्थन करता है?", - "MicroserviceSupportExplanation1": "एबीपी ढांचे का एक प्रमुख लक्ष्य सूक्ष्म सेवा समाधान बनाने के लिए एक सुविधाजनक बुनियादी ढांचा प्रदान करना है। यह समझने के लिए कि यह माइक्रो-सर्विस सिस्टम बनाने में कैसे मदद करता है, यह समझने के लिए माइक्रो-सर्विस आर्किटेक्चर दस्तावेज़ देखें।", - "MicroserviceSupportExplanation2": "सभी एबीपी कमर्शियल मॉड्यूल्स को मॉड्यूल डेवलपमेंट बेस्ट प्रैक्टिस दस्तावेज़ का पालन करके माइक्रो-सर्विस परिनियोजन परिदृश्य (अपने एपीआई और डेटाबेस के साथ) का समर्थन करने के लिए डिज़ाइन किया गया है।", - "MicroserviceSupportExplanation3": "हम आपको अपना स्वयं का समाधान बनाने में मदद करने के लिए एक माइक्रो-सेवा वास्तुकला कार्यान्वयन को प्रदर्शित करने वाला एक नमूना माइक्रो-सर्विस डेमो समाधान प्रदान करते हैं।", + "MicroserviceSupportExplanation1": "एबीपी ढांचे के प्रमुख लक्ष्यों में से एक सूक्ष्म सेवा समाधान बनाने के लिए एक सुविधाजनक बुनियादी ढांचा प्रदान करना है। यह समझने के लिए कि यह माइक्रो-सर्विस सिस्टम बनाने में कैसे मदद करता है, माइक्रो-सर्विस आर्किटेक्चर दस्तावेज़ देखें।", + "MicroserviceSupportExplanation2": "सभी एबीपी वाणिज्यिक मॉड्यूल मॉड्यूल विकास सर्वोत्तम प्रथाओं दस्तावेज़ का पालन करके माइक्रो-सेवा परिनियोजन परिदृश्यों (अपने स्वयं के एपीआई और डेटाबेस के साथ) का समर्थन करने के लिए डिज़ाइन किए गए हैं।", + "MicroserviceSupportExplanation3": "हम एक नमूना माइक्रो-सर्विस डेमो सॉल्यूशन प्रदान करते हैं जो आपको अपना समाधान बनाने में मदद करने के लिए एक माइक्रो-सर्विस आर्किटेक्चर कार्यान्वयन दर्शाता है।", "MicroserviceSupportExplanation4": "तो, संक्षिप्त उत्तर \" हां है, यह सूक्ष्म सेवा वास्तुकला का समर्थन करता है \"।", "MicroserviceSupportExplanation5": "हालाँकि, एक माइक्रो-सर्विस सिस्टम एक समाधान है और हर समाधान में अलग-अलग आवश्यकताएं, नेटवर्क टोपोलॉजी, संचार परिदृश्य, प्रमाणीकरण संभावनाएं, डेटाबेस पृथक्करण / साझा करने के निर्णय, रनटाइम कॉन्फ़िगरेशन, 3 पार्टी सिस्टम एकीकरण और कई और अधिक होंगे।", "MicroserviceSupportExplanation6": "ABP फ्रेमवर्क और ABP कमर्शियल आपको अपने स्वयं के समाधान का निर्माण करने में मदद करने के लिए सूक्ष्म सेवा परिदृश्य, सूक्ष्म सेवा संगत मॉड्यूल, नमूने और प्रलेखन के लिए बुनियादी ढाँचा प्रदान करता है। लेकिन अपने सपनों के समाधान को सीधे आपके लिए पहले से डाउनलोड करने की उम्मीद न करें। आपको इसे समझने और अपनी आवश्यकताओं के आधार पर कुछ हिस्सों को एक साथ लाने की आवश्यकता होगी।", "WhereCanIDownloadSourceCode": "मैं स्रोत-कोड कहां से डाउनलोड कर सकता हूं?", - "WhereCanIDownloadSourceCodeExplanation": "आप एबीपी सूट या एबीपी सीएलआई के माध्यम से सभी एबीपी मॉड्यूल, कोणीय पैकेज और थीम के स्रोत कोड डाउनलोड कर सकते हैं। स्रोत-कोड डाउनलोड कैसे करें? देखें", + "WhereCanIDownloadSourceCodeExplanation": "आप एबीपी सूट या एबीपी सीएलआई के माध्यम से सभी एबीपी मॉड्यूल, एंगुलर पैकेज और थीम का सोर्स कोड डाउनलोड कर सकते हैं। देखें स्रोत-कोड कैसे डाउनलोड करें?", "ComputerLimitation": "एबीपी विकसित करते समय एक डेवलपर कितने कंप्यूटरों पर लॉगिन कर सकता है?", "ComputerLimitationExplanation": "हम विशेष रूप से प्रति व्यक्ति / लाइसेंस प्राप्त डेवलपर के लिए {0} कंप्यूटर की अनुमति देते हैं। जब भी किसी तीसरे मशीन पर एबीपी कमर्शियल उत्पादों को विकसित करने के लिए डेवलपर की आवश्यकता होती है, तो स्थिति को समझाते हुए लाइसेंस@abp.io को एक ई-मेल भेजा जाना चाहिए और फिर हम अपने सिस्टम में उचित आवंटन करेंगे।", "RefundPolicy": "क्या आपके पास धनवापसी नीति है?", @@ -230,17 +230,17 @@ "HowCanIRefundVatExplanation2": "अपने 2 चेकआउट खाते में लॉग इन करें", "HowCanIRefundVatExplanation3": "उपयुक्त आदेश खोजें और \"रिफंड बेल्ड वैट\" दबाएं (अपनी वैट आईडी दर्ज करें)", "HowCanIGetMyInvoice": "मैं अपना चालान कैसे प्राप्त कर सकता हूं?", - "HowCanIGetMyInvoiceExplanation": "लाइसेंस खरीदने के लिए 2 भुगतान गेटवे हैं: PayU और 2 चेकआउट। यदि आप 2Checkout गेटवे के माध्यम से अपना लाइसेंस खरीदते हैं, तो यह आपके ईमेल पते पर पीडीएफ चालान भेजता है, देखें 2 चेकआउट चालान। यदि आप पेयू गेटवे या बैंक वायर ट्रांसफर के माध्यम से खरीदते हैं, तो हम आपका चालान तैयार करेंगे और भेजेंगे। आप अपने चालान का अनुरोध संगठन प्रबंधन पृष्ठ से कर सकते हैं", + "HowCanIGetMyInvoiceExplanation": "लाइसेंस खरीदने के लिए 2 भुगतान गेटवे हैं: PayU और 2 चेकआउट। यदि आप 2Checkout गेटवे के माध्यम से अपना लाइसेंस खरीदते हैं, तो यह आपके ईमेल पते पर पीडीएफ चालान भेजता है, देखें 2 चेकआउट चालान। यदि आप पेयू गेटवे या बैंक वायर ट्रांसफर के माध्यम से खरीदते हैं, तो हम आपका चालान तैयार करेंगे और भेजेंगे। आप अपने चालान का अनुरोध संगठन प्रबंधन पृष्ठ से कर सकते हैं", "Forum": "मंच", "SupportExplanation": "ABP कमर्शियल लाइसेंस एक टीम द्वारा प्रीमियम फ़ोरम सपोर्ट प्रदान करता है जिसमें ABP फ्रेमवर्क विशेषज्ञ होते हैं।", "PrivateTicket": "निजी टिकट", "PrivateTicketExplanation": "एंटरप्राइज लाइसेंस में ई-मेल और टिकट प्रणाली के साथ एक निजी सहायता भी शामिल है।", "AbpSuiteExplanation1": "ABP सुइट आपको कुछ ही मिनटों में वेब पेज बनाने की अनुमति देता है। यह .NET कोर ग्लोबल टूल है जिसे कमांड लाइन से इंस्टॉल किया जा सकता है।", - "AbpSuiteExplanation2": "यह एक नया ABP समाधान बना सकता है, डेटाबेस से फ्रंट-एंड तक CRUD पेज बना सकता है। तकनीकी ओवरव्यू के लिए दस्तावेज़ देखें", + "AbpSuiteExplanation2": "यह एक नया ABP समाधान बना सकता है, डेटाबेस से फ्रंट-एंड तक CRUD पेज बना सकता है। तकनीकी ओवरव्यू के लिए दस्तावेज़ देखें", "FastEasy": "तेज और आसान", "AbpSuiteExplanation3": "ABP सुइट आपको आसानी से CRUD पेज बनाने की अनुमति देता है। आपको बस अपनी इकाई और उसके गुणों को परिभाषित करने की आवश्यकता है, बाकी को आप के लिए एबीपी सूट करने दें! एबीपी सूट कुछ ही सेकंड में आपके सीआरयूडी पृष्ठ के लिए सभी आवश्यक कोड उत्पन्न करता है। यह Angular, MVC और Blazor यूजर इंटरफेस को सपोर्ट करता है।", "RichOptions": "अमीर विकल्प", - "AbpSuiteExplanation4": "ABP सुइट रेजर पेज और Angular । यह MongoDB जैसे कई डेटाबेस का समर्थन करता है और सभी डेटाबेस EntityFramework Core <द्वारा समर्थित है / strong> (MS SQL सर्वर, Oracle, MySql, PostgreSQL और )।", + "AbpSuiteExplanation4": "ABP Suite supports multiple UI options like Razor Pages and Angular.It also supports multiple databases like MongoDB and all databases supported by EntityFramework Core (MS SQL Server, Oracle, MySql, PostgreSQL and more).", "AbpSuiteExplanation5": "अच्छी बात यह है कि, आपको उन विकल्पों के बारे में चिंता करने की ज़रूरत नहीं है। एबीपी सूट आपके प्रोजेक्ट के प्रकार को समझता है और आपकी परियोजना के लिए कोड बनाता है और उत्पन्न कोड को आपके प्रोजेक्ट में सही जगह पर रखता है।", "SourceCode": "सोर्स कोड", "AbpSuiteExplanation6": "ABP स्वीट आपके लिए सोर्स कोड जेनरेट करता है! यह वेब पेज जनरेट करने के लिए मैजिक फाइल्स जेनरेट नहीं करता है। एबीपी सूट इकाई, रिपोजिटरी, एप्लीकेशन सर्विस, कोड फर्स्ट माइग्रेशन, जावास्क्रिप्ट / टाइपस्क्रिप्ट और सीएसएचटीएमएल / एचटीएमएल और आवश्यक इंटरफेस के लिए भी स्रोत कोड उत्पन्न करता है। ABP Suite सॉफ्टवेयर डेवलपमेंट के बेस्ट प्रैक्टिसेस के अनुसार कोड भी तैयार करता है, इसलिए आपको जनरेट किए गए कोड की गुणवत्ता के बारे में चिंता करने की आवश्यकता नहीं है।", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json index 766702a92b..2eaef28623 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json @@ -151,7 +151,7 @@ "SeeAllModules": "Vedi tutti i moduli", "ABPCLIExplanation": "ABP CLI (Command Line Interface) è uno strumento a riga di comando per eseguire alcune operazioni comuni per soluzioni basate su ABP.", "ABPSuiteEasilyCURD": "ABP Suite è uno strumento che ti permette di creare facilmente pagine CRUD", - "WeAreHereToHelp": "Siamo qui per Aiuto ", + "WeAreHereToHelp": "Siamo qui per Aiuto ", "BrowseOrAskQuestion": "Puoi sfogliare i nostri argomenti della guida o cercare nelle domande frequenti oppure puoi farci una domanda utilizzando il modulo di contatto .", "SearchQuestionPlaceholder": "Cerca nelle domande frequenti", "WhatIsTheABPCommercial": "Cos'è l'ABP Commercial?", @@ -177,7 +177,7 @@ "ChangingLicenseType": "Posso cambiare il mio tipo di licenza in futuro?", "ChangingLicenseTypeExplanation": "Puoi sempre aggiungere nuovi sviluppatori con lo stesso tipo di licenza. Vedi anche \"Quanti sviluppatori possono lavorare su ABP Commercial?\". Puoi anche passare a una licenza superiore pagando la differenza di prezzo calcolata. Quando esegui l'aggiornamento a un piano di licenza superiore, ottieni i vantaggi del nuovo piano, ma l'aggiornamento della licenza non modifica la data di scadenza della licenza.", "LicenseExtendUpgradeDiff": "Qual è la differenza tra estensione della licenza e aggiornamento?", - "LicenseExtendUpgradeDiffExplanation": " Estensione: estendendo / rinnovando la tua licenza, continuerai a ricevere supporto premium e a ricevere aggiornamenti importanti per moduli e temi. Inoltre, potrai continuare a creare nuovi progetti. E sarai ancora in grado di utilizzare ABP Suite che accelera il tuo sviluppo.
Upgrade: aggiornando la tua licenza, promuoverai un piano di licenza superiore che ti consentirà di ottenere ulteriori vantaggi . Consulta la tabella di confronto delle licenze per verificare le differenze tra i piani di licenza. D'altra parte, quando esegui l'upgrade, la data di scadenza della licenza non cambierà! Per estendere la data di fine della licenza, è necessario estendere la licenza.", + "LicenseExtendUpgradeDiffExplanation": " Estensione: estendendo/rinnovando la tua licenza, continuerai a ricevere supporto premium e a ricevere aggiornamenti importanti per moduli e temi. Inoltre, potrai continuare a creare nuovi progetti. E sarai ancora in grado di utilizzare ABP Suite che accelera il tuo sviluppo.
Upgrade: aggiornando la tua licenza, promuoverai un piano di licenza superiore che ti consentirà di ottenere ulteriori vantaggi . Consulta la tabella di confronto delle licenze per verificare le differenze tra i piani di licenza. D'altra parte, quando esegui l'upgrade, la data di scadenza della licenza non cambierà! Per estendere la data di fine della licenza, è necessario estendere la licenza.", "LicenseRenewalCost": "Qual è il costo del rinnovo della licenza dopo 1 anno?", "LicenseRenewalCostExplanation": "La tariffa di rinnovo (estensione) di tutte le licenze perpetue ABP Commercial è {0} del prezzo di listino della licenza. Il prezzo di rinnovo della licenza Team standard è $ {1}, la licenza Business standard è $ {2} e la licenza Enterprise standard è $ {3}. Se sei già un cliente, accedi al tuo account per esaminare i prezzi di rinnovo disponibili.", "HowDoIRenewMyLicense": "Come rinnovo la mia licenza?", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json index 76d6fc7c57..c07678b890 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json @@ -97,6 +97,7 @@ "VolosoftSharingInformationMessage": "Volosoft'un ürünlerimi seçkin ortaklarla paylaşmasını kabul ediyorum, böylece ilgili ortakların ürünleri ve hizmetleri hakkında ilgili bilgileri alabilirim.", "WeWillSendYouADownloadLink": "{0} adresine email gönderilmiştir.", "InvalidFormInputs": "Lütfen formda belirtilen geçerli bilgileri yazınız.", - "DDDBookEmailBody": "Teşekkürler.
Kitabı indirmek için, buraya tıklayınız." + "DDDBookEmailBody": "Teşekkürler.
Kitabı indirmek için, buraya tıklayınız.", + "FreeDDDEBook": "Ücretsiz DDD E-Kitap" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json index cba33bfc30..3d06abb52e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/fi.json @@ -118,7 +118,7 @@ "CreatePostCoverInfo": "Lisää kansikuva, jotta voit luoda tehokkaan viestin. Lataa 16: 9-kuvasuhteen kuvat parhaan näkymän saamiseksi. Tiedoston enimmäiskoko: 1 Mt.", "ThankYouForContribution": "Kiitos osallistumisesta ABP-yhteisöön.", "GithubArticle": "Github-artikkeli", - "GithubArticleSubmitStepOne": " 1. Kirjoita artikkeli mistä tahansa julkisesta GitHub-arkistosta Markdown-muodossa. esimerkki ", + "GithubArticleSubmitStepOne": "1. Kirjoita artikkeli mistä tahansa julkisesta GitHub-arkistosta Markdown-muodossa. esimerkki ", "GithubArticleSubmitStepTwo": " 2. Lähetä artikkelin URL-osoite lomaketta käyttämällä.", "GithubArticleSubmitStepThree": " 3. Artikkelisi renderöidään tällä verkkosivustolla.", "YoutubeVideo": "Youtube-video", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json index a3f824d6ba..546531445e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/hi.json @@ -96,7 +96,7 @@ "JoinOurArticleNewsletter": "हमारे लेख समाचार पत्र में शामिल हों", "Community": "समुदाय", "Marketing": "विपणन", - "CommunityPrivacyPolicyConfirmation": "मैं नियम और शर्तों और गोपनीयता नीति से सहमत हूं।", + "CommunityPrivacyPolicyConfirmation": "मैं नियम और शर्तों और गोपनीयता नीति से सहमत हूं।", "ArticleRequestMessageTitle": "GitHub पर एक लेख / ट्यूटोरियल जिसे आप इस वेब साइट पर देखना चाहते हैं, का अनुरोध करने के लिए एक समस्या खोलें ।", "ArticleRequestMessageBody": "यहाँ, समुदाय द्वारा अनुरोधित लेखों की सूची। क्या आप एक अनुरोधित लेख लिखना चाहते हैं? कृपया अनुरोध पर क्लिक करें और चर्चा में शामिल हों।", "Language": "भाषा: हिन्दी", @@ -118,7 +118,7 @@ "CreatePostCoverInfo": "एक प्रभावी पोस्ट बनाने के लिए, एक कवर फ़ोटो जोड़ें। सर्वश्रेष्ठ दृश्य के लिए 16: 9 पहलू अनुपात चित्र अपलोड करें। अधिकतम फ़ाइल आकार: 1 एमबी।", "ThankYouForContribution": "ABP समुदाय में योगदान के लिए धन्यवाद।", "GithubArticle": "गीथब लेख", - "GithubArticleSubmitStepOne": " 1। मार्कडाउन प्रारूप के साथ किसी भी सार्वजनिक GitHub रिपॉजिटरी पर एक लेख लिखें। उदाहरण ", + "GithubArticleSubmitStepOne": "1. मार्कडाउन प्रारूप के साथ किसी भी सार्वजनिक GitHub रिपॉजिटरी पर एक लेख लिखें। उदाहरण ", "GithubArticleSubmitStepTwo": " 2। फ़ॉर्म का उपयोग करके अपना लेख URL सबमिट करें।", "GithubArticleSubmitStepThree": " 3। इस वेब साइट में आपका लेख प्रस्तुत किया जाएगा।", "YoutubeVideo": "यूट्यूब वीडियो", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json index 1f060d00b0..c53bf82d37 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json @@ -255,8 +255,6 @@ "Surname": "Surname", "CompanyName": "Company Name", "DoYouAgreePrivacyPolicy": "I agree to the Terms & Conditions and Privacy Policy.", - "VolosoftMarketingInformationMessage": "I would like information, tips, and offers about Solutions for Businesses and Organizations and other Volosoft products and services.", - "VolosoftSharingInformationMessage": "I would like Volosoft to share my information with select partners so I can receive relevant information about their products and services.", "Free": "Free", "DDDEBook": "DDD E-book", "PracticalGuideForImplementingDDD": "This book is a practical guide for implementing the Domain Driven Design with the ABP Framework.", @@ -270,6 +268,8 @@ "WeWillSendYouADownloadLink": "We've sent the file to {0}.", "GoHome": "Go Home", "InvalidFormInputs": "Please, type the valid information specified on the form.", - "DDDBookEmailBody": "Thank you.
To download your book, click here." + "DDDBookEmailBody": "Thank you.
To download your book, click here.", + "SubscribeToNewsletter": "Subscribe to the newsletter to get information about happenings in the ABP.IO Platform, like new releases, articles, offers, and more.", + "FirstEdition": "First Edition" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json index 87da55dbab..1385845f2e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json @@ -244,7 +244,7 @@ "ExampleUseCase": "Example Use Case", "DomainAndApplicationLogic": "Domain Logic & Application Logic", "Author": "Author", - "Page": "Page", + "Pages": "Pages", "PublishedOn": "Published on", "FreeEBook": "Free E-Book", "Download": "Download", @@ -256,8 +256,6 @@ "Surname": "Surname", "CompanyName": "Company Name", "DoYouAgreePrivacyPolicy": "I agree to the Terms & Conditions and Privacy Policy.", - "VolosoftMarketingInformationMessage": "I would like information, tips, and offers about Solutions for Businesses and Organizations and other Volosoft products and services.", - "VolosoftSharingInformationMessage": "I would like Volosoft to share my information with select partners so I can receive relevant information about their products and services.", "Free": "Free", "DDDEBook": "DDD E-book", "PracticalGuideForImplementingDDD": "This book is a practical guide for implementing the Domain Driven Design with the ABP Framework.", @@ -268,9 +266,13 @@ "DomainVsApplicationLogic": "Domain Logic vs Application Logic", "SamplesAndDiscussions": "Samples & Discussions", "EmailNotValid": "Please enter a valid email address.", - "WeWillSendYouADownloadLink": "A link to download the e-book has been sent to {0}.
Check your inbox / junk / spam boxes!", + "WeWillSendYouADownloadLink": "A link to download the e-book has been sent to {0}. Check your inbox, junk or spam boxes!", "GoHome": "Go Home", "InvalidFormInputs": "Please, type the valid information specified on the form.", - "DDDBookEmailBody": "Thank you.
To download your book, click here." + "DDDBookEmailBody": "Thank you.
To download your book, click here.", + "SubscribeToNewsletter": "Subscribe to the newsletter to get information about happenings in the ABP.IO Platform, like new releases, articles, offers, and more.", + "FirstEdition": "First Edition", + "ThankYou": "Thank you!", + "CheckboxMandatory": "You need to check this to proceed!" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json index 878af5e830..23ae2cc444 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json @@ -155,7 +155,7 @@ "Code": "Code", "Result": "Résultat", "SeeTheDocumentForMoreInformation": "Consultez le {0} document pour plus d'informations", - "IndexPageHeroSection": " open source Application Web
Framework
pour asp.net core ", + "IndexPageHeroSection": "open sourceWeb Application
Framework
for asp.net core", "UiFramework": "Framework de l'interface utilisateur", "EmailAddress": "Adresse e-mail", "Mobile": "Mobile", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json index a7974d8658..a36dbf5aeb 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json @@ -94,7 +94,7 @@ "DynamicForms": "गतिशील रूप", "BundlingMinification": "बंडलिंग और न्यूनतमकरण", "BackgroundJobs": "बैकग्राउंड जॉब्स", - "BackgroundJobsExplanation": "सरल कक्षाओं को परिभाषित करें ताकि पृष्ठभूमि में नौकरियों को निष्पादित किया जा सके। अंतर्निहित नौकरी प्रबंधक का उपयोग करें या अपने स्वयं के एकीकृत करें। Hangfire और RabbitMQ एकीकरण पहले से ही उपलब्ध हैं।", + "BackgroundJobsExplanation": "कतारबद्ध के रूप में पृष्ठभूमि में कार्य निष्पादित करने के लिए सरल वर्गों को परिभाषित करें। बिल्ट-इन जॉब मैनेजर का उपयोग करें या अपना खुद का एकीकृत करें। Hangfire और RabbitMQ एकीकरण पहले से ही उपलब्ध हैं।", "DDDInfrastructure": "डीडीडी इन्फ्रास्ट्रक्चर", "DomainDrivenDesignInfrastructure": "डोमेन संचालित डिज़ाइन इन्फ्रास्ट्रक्चर", "AutoRESTAPIs": "ऑटो रीस्ट एपीआई", @@ -104,7 +104,7 @@ "TestInfrastructure": "टेस्ट इन्फ्रास्ट्रक्चर", "AuditLoggingEntityHistories": "ऑडिट लॉगिंग और इकाई इतिहास", "ObjectToObjectMapping": "ऑब्जेक्ट टू ऑब्जेक्ट मैपिंग", - "ObjectToObjectMappingExplanation": "AutoMapper एकीकरण के साथ अमूर्तता के लिए ऑब्जेक्ट मैपिंग पर ऑब्जेक्ट ।", + "ObjectToObjectMappingExplanation": "ऑटोमैपर एकीकरण के साथ ऑब्जेक्ट टू ऑब्जेक्ट मैपिंग एब्स्ट्रैक्शन।", "EmailSMSAbstractions": "ईमेल और एसएमएस अंश", "EmailSMSAbstractionsWithTemplatingSupport": "ईमेल और एसएमएस अंशांकन समर्थन के साथ", "Localization": "स्थानीयकरण", @@ -154,8 +154,8 @@ "AndMore": "और अधिक...", "Code": "कोड", "Result": "परिणाम", - "SeeTheDocumentForMoreInformation": "अधिक जानकारी के लिए {0} दस्तावेज़ देखें", - "IndexPageHeroSection": "<स्पैन क्लास = \"फर्स्ट-लाइन शाइन\"> ओपन सोर्स <स्पैन क्लास = \"सेकंड-लाइन टेक्स्ट-अपरकेस\"> वेब एप्लिकेशन
फ्रेमवर्क asp.net core के लिए ", + "SeeTheDocumentForMoreInformation": "अधिक जानकारी के लिए {0} दस्तावेज़ देखें", + "IndexPageHeroSection": "open sourceWeb Application
Framework
for asp.net core", "UiFramework": "यूआई फ्रेमवर्क", "EmailAddress": "ईमेल पता", "Mobile": "मोबाइल", @@ -169,13 +169,13 @@ "JoinTheABPCommunityInfo": "एक जीवंत समुदाय के साथ शामिल हों और ABP फ्रेमवर्क में योगदानकर्ता बनें!", "AllArticles": "सभी चीज़ें", "SubmitYourArticle": "अपना लेख प्रस्तुत करें", - "DynamicClientProxyDocument": " JavaScript और C # के लिए डायनेमिक क्लाइंट प्रॉक्सी दस्तावेज़ देखें।", - "EmailSMSAbstractionsDocument": "अधिक जानकारी के लिए ईमेल करना और एसएमएस भेजने के दस्तावेज़ देखें।", + "DynamicClientProxyDocument": "JavaScript और C# के लिए गतिशील क्लाइंट प्रॉक्सी दस्तावेज़ देखें।", + "EmailSMSAbstractionsDocument": "अधिक जानकारी के लिए ईमेलिंग और एसएमएस भेजना दस्तावेज़ देखें।", "CreateProjectWizard": "यह विज़ार्ड स्टार्टअप टेम्प्लेट से एक नई परियोजना बनाता है जो आपकी परियोजना को शुरू करने के लिए ठीक से कॉन्फ़िगर किया गया है।", "TieredOption": "एक ऐसा समाधान तैयार करता है जहाँ वेब और Http API परतें शारीरिक रूप से अलग हो जाती हैं। यदि जांच नहीं की जाती है, तो एक स्तरित समाधान बनाता है जो कम जटिल है और अधिकांश परिदृश्यों के लिए उपयुक्त है।", "SeparateIdentityServerOption": "सर्वर एप्लिकेशन को दो अनुप्रयोगों में अलग करता है: पहला पहचान सर्वर के लिए है और दूसरा आपके सर्वर साइड HTTP एपीआई के लिए है।", "UseslatestPreVersion": "नवीनतम पूर्व-रिलीज़ संस्करण का उपयोग करता है", - "ReadTheDocumentation": "<स्पैन क्लास = \"टेक्स्ट-प्राइमरी\"> पढ़ें <स्पैन क्लास = \"टेक्स्ट-सक्सेस\"> डॉक्यूमेंटेशन ", + "ReadTheDocumentation": "पढ़ेंदस्तावेज़ीकरण", "Documentation": "प्रलेखन", "GettingStartedTutorial": "स्टार्टिंग ट्यूटोरियल", "ApplicationDevelopmentTutorial": "अनुप्रयोग विकास ट्यूटोरियल", @@ -183,7 +183,7 @@ "InstallABPCLIInfo": "एबीपी सीएलआई एबीपी ढांचे के साथ एक नया समाधान शुरू करने का सबसे तेज़ तरीका है। कमांड लाइन विंडो का उपयोग करके ABP CLI स्थापित करें:", "DifferentLevelOfNamespaces": "आप विभिन्न स्तरों के नामस्थानों का उपयोग कर सकते हैं; जैसे BookStore, Acme.BookStore या Acme.Retail.BookStore।", "ABPCLIExamplesInfo": " नया कमांड डेटाबेस प्रदाता के रूप में एंटिटी फ्रेमवर्क कोर के साथ स्तरित MVC एप्लिकेशन बनाता है। हालांकि, इसके पास अतिरिक्त विकल्प हैं। उदाहरण:", - "SeeCliDocumentForMoreInformation": "अधिक विकल्पों के लिए ABP CLI दस्तावेज़ देखें या ऊपर \"डायरेक्ट डाउनलोड\" टैब चुनें।", + "SeeCliDocumentForMoreInformation": "अधिक विकल्पों के लिए ABP CLI दस्तावेज़ देखें या ऊपर \"डायरेक्ट डाउनलोड\" टैब चुनें।", "Optional": "ऐच्छिक", "LocalFrameworkRef": "फ्रेमवर्क पैकेज के लिए स्थानीय प्रोजेक्ट संदर्भ रखें।", "BlobStoring": "ब्लॉब भंडारण", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json index e4cdc73bf2..35d86ceefb 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json @@ -155,7 +155,7 @@ "Code": "Codice", "Result": "Risultato", "SeeTheDocumentForMoreInformation": "Consulta il {0} documento per ulteriori informazioni", - "IndexPageHeroSection": " open source Framework
applicazione web
per asp.net core ", + "IndexPageHeroSection": " open source Framework
applicazione web
per asp.net core ", "UiFramework": "Framework dell'interfaccia utente", "EmailAddress": "Indirizzo e-mail", "Mobile": "Mobile", @@ -175,7 +175,7 @@ "TieredOption": "Crea una soluzione a più livelli in cui i livelli API Web e Http sono fisicamente separati. Se non selezionata, crea una soluzione a più livelli meno complessa e adatta alla maggior parte degli scenari.", "SeparateIdentityServerOption": "Separa il lato server in due applicazioni: la prima è per il server di identità e la seconda è per l'API HTTP lato server.", "UseslatestPreVersion": "Utilizza l'ultima versione pre-rilascio", - "ReadTheDocumentation": " Leggi La documentazione ", + "ReadTheDocumentation": " Leggi La documentazione ", "Documentation": "Documentazione", "GettingStartedTutorial": "Tutorial introduttivo", "ApplicationDevelopmentTutorial": "Tutorial sullo sviluppo di applicazioni", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json index 84a0173273..0d02300061 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json @@ -218,8 +218,6 @@ "Surname": "Soyad", "CompanyName": "Şirket adı", "DoYouAgreePrivacyPolicy": "Şartlar & Koşulları ve Gizlilik Politikasını kabul ediyorum.", - "VolosoftMarketingInformationMessage": "İşletmeler ve Organizasyonlar için çözümler ve diğer Volosoft ürün ve hizmetleri hakkında bilgi, ipucu ve teklifler almak istiyorum.", - "VolosoftSharingInformationMessage": "Volosoft'un ürünlerimi seçkin ortaklarla paylaşmasını kabul ediyorum, böylece ilgili ortakların ürünleri ve hizmetleri hakkında ilgili bilgileri alabilirim.", "Free": "Ücretsiz", "DDDEBook": "DDD E-kitap", "PracticalGuideForImplementingDDD": "Bu kitap ABP Framework ile birlikte Domain Driven Design'ın uygulanması için pratik bir kılavuz görevi görür.", @@ -233,6 +231,8 @@ "WeWillSendYouADownloadLink": "{0} adresine email gönderilmiştir.", "GoHome": "Anasayfaya Dön", "InvalidFormInputs": "Lütfen formda belirtilen geçerli bilgileri yazınız.", - "DDDBookEmailBody": "Teşekkürler.
Kitabı indirmek için, buraya tıklayınız." + "DDDBookEmailBody": "Teşekkürler.
Kitabı indirmek için, buraya tıklayınız.", + "SubscribeToNewsletter": "ABP.IO Platform'u ile ilgili yeni haberler, makaleler, teklifler ve daha fazlası gibi gelişmeler hakkında bilgi almak için bültene abone olun.", + "FirstEdition": "İlk Baskı" } } \ No newline at end of file diff --git a/docs/en/CLI.md b/docs/en/CLI.md index f2e7df219b..829b9480c7 100644 --- a/docs/en/CLI.md +++ b/docs/en/CLI.md @@ -42,6 +42,7 @@ Here, the list of all available commands before explaining their details: * **`login`**: Authenticates on your computer with your [abp.io](https://abp.io/) username and password. * **`logout`**: Logouts from your computer if you've authenticated before. * **`bundle`**: Generates script and style references for an ABP Blazor project. +* **`install-libs`**: Install NPM Packages for MVC / Razor Pages and Blazor Server UI types. ### help @@ -433,3 +434,18 @@ abp bundle [options] `bundle` command reads the `appsettings.json` file inside the Blazor project for bundling options. For more details about managing style and script references in Blazor apps, see [Managing Global Scripts & Styles](UI/Blazor/Global-Scripts-Styles.md) +### install-libs + +This command install NPM Packages for MVC / Razor Pages and Blazor Server UI types. Its **executing directory** or passed ```--working-directory``` parameter's directory must contain a project file(*.csproj). + +`install-libs` command reads the `abp.resourcemapping.js` file to manage package. For more details see [Client Side Package Management](UI/AspNetCore/Client-Side-Package-Management.md). + +Usage: + +````bash +abp install-libs [options] +```` + +#### Options + +* ```--working-directory``` or ```-wd```: Specifies the working directory. This option is useful when executing directory doesn't contain a project file. \ No newline at end of file diff --git a/docs/en/Community-Articles/2020-04-27-Use-Azure-Active-Directory-Authentication-for-MVC-Razor-Page-Applications/POST.md b/docs/en/Community-Articles/2020-04-27-Use-Azure-Active-Directory-Authentication-for-MVC-Razor-Page-Applications/POST.md index 146d250d1f..b2c307bcb3 100644 --- a/docs/en/Community-Articles/2020-04-27-Use-Azure-Active-Directory-Authentication-for-MVC-Razor-Page-Applications/POST.md +++ b/docs/en/Community-Articles/2020-04-27-Use-Azure-Active-Directory-Authentication-for-MVC-Razor-Page-Applications/POST.md @@ -6,23 +6,21 @@ Adding Azure Active Directory is pretty straightforward in ABP framework. Couple Two different **alternative approaches** for AzureAD integration will be demonstrated for better coverage. -1. ~~**AddAzureAD**: This approach uses Microsoft [AzureAD UI nuget package](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.AzureAD.UI/) which is very popular when users search the web about how to integrate AzureAD to their web application.~~ Now marked **Obsolete** (see https://github.com/aspnet/Announcements/issues/439). -2. **AddOpenIdConnect**: This approach uses default [OpenIdConnect](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.OpenIdConnect/) which can be used for not only AzureAD but for all OpenId connections. +1. **AddOpenIdConnect**: This approach uses default [OpenIdConnect](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.OpenIdConnect/) which can be used for not only AzureAD but for all OpenId connections. 3. **AddMicrosoftIdentityWebAppAuthentication:** This approach uses newly introduced [Microsoft.Identity.Web nuget package](https://www.nuget.org/packages/Microsoft.Identity.Web/) to replace AddAzureAD. +3. ~~**AddAzureAD**: This approach uses Microsoft [AzureAD UI nuget package](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.AzureAD.UI/) which is very popular when users search the web about how to integrate AzureAD to their web application.~~ Now marked **Obsolete** (see https://github.com/aspnet/Announcements/issues/439). > There is **no difference** in functionality between these approaches. AddAzureAD is an abstracted way of OpenIdConnection ([source](https://github.com/dotnet/aspnetcore/blob/c56aa320c32ee5429d60647782c91d53ac765865/src/Azure/AzureAD/Authentication.AzureAD.UI/src/AzureADAuthenticationBuilderExtensions.cs#L122)) with predefined cookie settings. > > However there are key differences in integration to ABP applications because of default configurated signin schemes which will be explained below. -## 1. AddAzureAD +## 1. AddOpenIdConnect -This approach uses the most common way to integrate AzureAD by using the [Microsoft AzureAD UI nuget package](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.AzureAD.UI/). - -If you choose this approach, you will need to install `Microsoft.AspNetCore.Authentication.AzureAD.UI` package to your **.Web** project. Also, since AddAzureAD extension uses [configuration binding](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1#default-configuration), you need to update your appsettings.json file located in your **.Web** project. +If you don't want to use an extra nuget package in your application, you can use the straight default [OpenIdConnect](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.OpenIdConnect/) which can be used for all OpenId connections including AzureAD external authentication. -#### **Updating `appsettings.json`** +You don't have to use `appsettings.json` configuration but it is a good practice to set AzureAD information in the `appsettings.json`. -You need to add a new section to your `appsettings.json` which will be binded to configuration when configuring the `OpenIdConnectOptions`: +To get the AzureAD information from `appsettings.json`, which will be used in `OpenIdConnectOptions` configuration, simply add a new section to `appsettings.json` located in your **.Web** project: ````json "AzureAd": { @@ -34,63 +32,90 @@ You need to add a new section to your `appsettings.json` which will be binded to } ```` -> Important configuration here is the CallbackPath. This value must be the same with one of your Azure AD-> app registrations-> Authentication -> RedirectUri. - -Then, you need to configure the `OpenIdConnectOptions` to complete the integration. - -#### Configuring OpenIdConnectOptions - -In your **.Web** project, locate your **ApplicationWebModule** and modify `ConfigureAuthentication` method with the following: +Then, In your **.Web** project; you can modify the `ConfigureAuthentication` method located in your **ApplicationWebModule** with the following: ````csharp private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration) { - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Add("sub", ClaimTypes.NameIdentifier); context.Services.AddAuthentication() - .AddIdentityServerAuthentication(options => - { - options.Authority = configuration["AuthServer:Authority"]; + ... //Omitted other third party configurations + .AddOpenIdConnect("AzureOpenId", "Azure Active Directory OpenId", options => + { + options.Authority = "https://login.microsoftonline.com/" + configuration["AzureAd:TenantId"] + "/v2.0/"; + options.ClientId = configuration["AzureAd:ClientId"]; + options.ResponseType = OpenIdConnectResponseType.CodeIdToken; + options.CallbackPath = configuration["AzureAd:CallbackPath"]; + options.ClientSecret = configuration["AzureAd:ClientSecret"]; options.RequireHttpsMetadata = false; - options.ApiName = "Acme.BookStore"; - }) - .AddAzureAD(options => configuration.Bind("AzureAd", options)); + options.SaveTokens = true; + options.GetClaimsFromUserInfoEndpoint = true; + options.Scope.Add("email"); - context.Services.Configure(AzureADDefaults.OpenIdScheme, options => + options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub"); + }); + } +```` + +> **Don't forget to:** +> +> * Add `options.Scope.Add("email");` since [default signin scheme is `AzureADOpenID`](https://github.com/dotnet/aspnetcore/blob/c56aa320c32ee5429d60647782c91d53ac765865/src/Azure/AzureAD/Authentication.AzureAD.UI/src/AzureADOpenIdConnectOptionsConfiguration.cs#L35). +> * Add `options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub");`. Mapping this to [ClaimTypes.NameIdentifier](https://github.com/dotnet/runtime/blob/6d395de48ac718a913e567ae80961050f2a9a4fa/src/libraries/System.Security.Claims/src/System/Security/Claims/ClaimTypes.cs#L59) is important since default SignIn Manager behavior uses this claim type for external login information. + + + +And that's it, integration is completed. Keep on mind that you can connect any other external authentication providers. + +## 2. Alternative Approach: AddMicrosoftIdentityWebApp + +With .Net 5.0, AzureAd is marked [obsolete](https://github.com/dotnet/aspnetcore/issues/25807) and will not be supported in the near future. However its expanded functionality is available in [microsoft-identity-web](https://github.com/AzureAD/microsoft-identity-web/wiki) packages. + +Add (or replace with) the new nuget package Microsoft.Identity.Web nuget package](https://www.nuget.org/packages/Microsoft.Identity.Web/). + +In your **.Web** project; you update the `ConfigureAuthentication` method located in your **ApplicationWebModule** with the following while having the AzureAd appsettings section as defined before: + +````csharp +private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration) + { + context.Services.AddAuthentication() + ... //Omitted other third party configurations + .AddMicrosoftIdentityWebApp(configuration.GetSection("AzureAd")); + + context.Services.Configure(OpenIdConnectDefaults.AuthenticationScheme, options => { - options.Authority = options.Authority + "/v2.0/"; + options.Authority = "https://login.microsoftonline.com/" + configuration["AzureAd:TenantId"] + "/v2.0/"; options.ClientId = configuration["AzureAd:ClientId"]; - options.CallbackPath = configuration["AzureAd:CallbackPath"]; options.ResponseType = OpenIdConnectResponseType.CodeIdToken; + options.CallbackPath = configuration["AzureAd:CallbackPath"]; + options.ClientSecret = configuration["AzureAd:ClientSecret"]; options.RequireHttpsMetadata = false; - - options.TokenValidationParameters.ValidateIssuer = false; + options.SaveTokens = false; options.GetClaimsFromUserInfoEndpoint = true; - options.SaveTokens = true; - options.SignInScheme = IdentityConstants.ExternalScheme; - options.Scope.Add("email"); + options.SignInScheme = IdentityConstants.ExternalScheme; + + options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub"); }); } ```` +And that's all to add new Microsoft-Identity-Web. + > **Don't forget to:** > -> * Add `.AddAzureAD(options => configuration.Bind("AzureAd", options))` after `.AddAuthentication()`. This binds your AzureAD appsettings and easy to miss out. -> * Add `JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear()`. This will disable the default Microsoft claim type mapping. -> * Add `JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Add("sub", ClaimTypes.NameIdentifier)`. Mapping this to [ClaimTypes.NameIdentifier](https://github.com/dotnet/runtime/blob/6d395de48ac718a913e567ae80961050f2a9a4fa/src/libraries/System.Security.Claims/src/System/Security/Claims/ClaimTypes.cs#L59) is important since default SignIn Manager behavior uses this claim type for external login information. > * Add `options.SignInScheme = IdentityConstants.ExternalScheme` since [default signin scheme is `AzureADOpenID`](https://github.com/dotnet/aspnetcore/blob/c56aa320c32ee5429d60647782c91d53ac765865/src/Azure/AzureAD/Authentication.AzureAD.UI/src/AzureADOpenIdConnectOptionsConfiguration.cs#L35). -> * Add `options.Scope.Add("email")` if you are using **v2.0** endpoint of AzureAD since v2.0 endpoint doesn't return the `email` claim as default. The [Account Module](https://docs.abp.io/en/abp/latest/Modules/Account) uses `email` claim to [register external users](https://github.com/abpframework/abp/blob/be32a55449e270d2d456df3dabdc91f3ffdd4fa9/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs#L215). +> * Add `options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub");`. Mapping this to [ClaimTypes.NameIdentifier](https://github.com/dotnet/runtime/blob/6d395de48ac718a913e567ae80961050f2a9a4fa/src/libraries/System.Security.Claims/src/System/Security/Claims/ClaimTypes.cs#L59) is important since default SignIn Manager behavior uses this claim type for external login information. -You are done and integration is completed. +Keep in mind that [Microsoft-Identity-Web](https://github.com/AzureAD/microsoft-identity-web) is relatively new and keeps getting new enhancements, features and documentation. -## 2. Alternative Approach: AddOpenIdConnect +## 3. Obsolete Alternative Approach: AddAzureAD -If you don't want to use an extra nuget package in your application, you can use the straight default [OpenIdConnect](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.OpenIdConnect/) which can be used for all OpenId connections including AzureAD external authentication. +This approach uses the most common way to integrate AzureAD by using the [Microsoft AzureAD UI nuget package](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.AzureAD.UI/). -You don't have to use `appsettings.json` configuration but it is a good practice to set AzureAD information in the `appsettings.json`. +If you choose this approach, you will need to install `Microsoft.AspNetCore.Authentication.AzureAD.UI` package to your **.Web** project. Also, since AddAzureAD extension uses [configuration binding](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1#default-configuration), you need to update your appsettings.json file located in your **.Web** project. -To get the AzureAD information from `appsettings.json`, which will be used in `OpenIdConnectOptions` configuration, simply add a new section to `appsettings.json` located in your **.Web** project: +#### **Updating `appsettings.json`** + +You need to add a new section to your `appsettings.json` which will be binded to configuration when configuring the `OpenIdConnectOptions`: ````json "AzureAd": { @@ -102,74 +127,49 @@ To get the AzureAD information from `appsettings.json`, which will be used in `O } ```` -Then, In your **.Web** project; you can modify the `ConfigureAuthentication` method located in your **ApplicationWebModule** with the following: - -````csharp -private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration) - { - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Add("sub", ClaimTypes.NameIdentifier); - - context.Services.AddAuthentication() - .AddIdentityServerAuthentication(options => - { - options.Authority = configuration["AuthServer:Authority"]; - options.RequireHttpsMetadata = false; - options.ApiName = "BookStore"; - }) - .AddOpenIdConnect("AzureOpenId", "Azure Active Directory OpenId", options => - { - options.Authority = "https://login.microsoftonline.com/" + configuration["AzureAd:TenantId"] + "/v2.0/"; - options.ClientId = configuration["AzureAd:ClientId"]; - options.ResponseType = OpenIdConnectResponseType.CodeIdToken; - options.CallbackPath = configuration["AzureAd:CallbackPath"]; - options.RequireHttpsMetadata = false; - options.SaveTokens = true; - options.GetClaimsFromUserInfoEndpoint = true; - - options.Scope.Add("email"); - }); - } -```` - -And that's it, integration is completed. Keep on mind that you can connect any other external authentication providers. - -## 3. AddMicrosoftIdentityWebAppAuthentication +> Important configuration here is the CallbackPath. This value must be the same with one of your Azure AD-> app registrations-> Authentication -> RedirectUri. -With .Net 5.0, AzureAd is marked [obsolete](https://github.com/dotnet/aspnetcore/issues/25807) and will not be supported in the near future. However its expanded functionality is available in [microsoft-identity-web](https://github.com/AzureAD/microsoft-identity-web/wiki) packages. +Then, you need to configure the `OpenIdConnectOptions` to complete the integration. -Add (or replace with) the new nuget package Microsoft.Identity.Web nuget package](https://www.nuget.org/packages/Microsoft.Identity.Web/). +#### Configuring OpenIdConnectOptions -In your **.Web** project; you update the `ConfigureAuthentication` method located in your **ApplicationWebModule** with the following while having the AzureAd appsettings section as defined before: +In your **.Web** project, locate your **ApplicationWebModule** and modify `ConfigureAuthentication` method with the following: ````csharp private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration) { - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Add("sub", ClaimTypes.NameIdentifier); context.Services.AddAuthentication() - .AddIdentityServerAuthentication(options => - { - options.Authority = configuration["AuthServer:Authority"]; - options.RequireHttpsMetadata = false; - options.ApiName = "Acme.BookStore"; - }); - - context.Services.AddMicrosoftIdentityWebAppAuthentication( - configuration: configuration, - configSectionName: "AzureAd", - openIdConnectScheme:"AzureAD", - cookieScheme:null); + ... //Omitted other third party configurations + .AddAzureAD(options => configuration.Bind("AzureAd", options)); + + context.Services.Configure(AzureADDefaults.OpenIdScheme, options => + { + options.Authority = options.Authority + "/v2.0/"; + options.ClientId = configuration["AzureAd:ClientId"]; + options.CallbackPath = configuration["AzureAd:CallbackPath"]; + options.ResponseType = OpenIdConnectResponseType.CodeIdToken; + options.RequireHttpsMetadata = false; + + options.TokenValidationParameters.ValidateIssuer = false; + options.GetClaimsFromUserInfoEndpoint = true; + options.SaveTokens = true; + options.SignInScheme = IdentityConstants.ExternalScheme; + + options.Scope.Add("email"); + + options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub"); + }); } ```` -And that's all to add new Microsoft-Identity-Web. - > **Don't forget to:** > -> * Pass **cookieScheme** parameter as **null** or your [*GetExternalLoginInfoAsync* method will always return null](https://github.com/AzureAD/microsoft-identity-web/issues/133#). +> * Add `.AddAzureAD(options => configuration.Bind("AzureAd", options))` after `.AddAuthentication()`. This binds your AzureAD appsettings and easy to miss out. +> * Add `options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub");`. Mapping this to [ClaimTypes.NameIdentifier](https://github.com/dotnet/runtime/blob/6d395de48ac718a913e567ae80961050f2a9a4fa/src/libraries/System.Security.Claims/src/System/Security/Claims/ClaimTypes.cs#L59) is important since default SignIn Manager behavior uses this claim type for external login information. +> * Add `options.SignInScheme = IdentityConstants.ExternalScheme` since [default signin scheme is `AzureADOpenID`](https://github.com/dotnet/aspnetcore/blob/c56aa320c32ee5429d60647782c91d53ac765865/src/Azure/AzureAD/Authentication.AzureAD.UI/src/AzureADOpenIdConnectOptionsConfiguration.cs#L35). +> * Add `options.Scope.Add("email")` if you are using **v2.0** endpoint of AzureAD since v2.0 endpoint doesn't return the `email` claim as default. The [Account Module](https://docs.abp.io/en/abp/latest/Modules/Account) uses `email` claim to [register external users](https://github.com/abpframework/abp/blob/be32a55449e270d2d456df3dabdc91f3ffdd4fa9/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs#L215). -Keep in mind that [Microsoft-Identity-Web](https://github.com/AzureAD/microsoft-identity-web) is relatively new and keeps getting new enhancements, features and documentation. +You are done and integration is completed. ## The Source Code @@ -247,3 +247,14 @@ You can find the source code of the completed example [here](https://github.com/ await Task.CompletedTask; }); ```` + +* I get page not found error on redirection to **https://login.live.com/oauth20_authorize.srf?**! + + * Probably you are trying to login with Microsoft account to Azure portal instead of the Azure AD account. Try azure AD user account for login instead of microsoft account. You can also check the answers for [this question](https://answers.microsoft.com/en-us/msoffice/forum/msoffice_o365admin-mso_dirservices-mso_o365b/cant-login-in-loginlivecom-with-a-ms-account-valid/6da991e6-9528-461a-9638-9c5680e95888) and [this question](https://docs.microsoft.com/en-us/answers/questions/34806/azure-ad-404-error-when-login-with-microsoft-accou.html) for more details. + +# May 2021 Update + +- **AddOpenIdConnect**: Removed `JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();` and added `sub` claim mapping in ClaimActions rather than global mapping. +- Updated `AddMicrosoftIdentityWebAppAuthentication ` to `AddMicrosoftIdentityWebApp`. +- Updated OpenIdConnect and AddMicrosoftIdentityWebApp configurations. +- Obsolete approach moved to third place in the list. diff --git a/docs/en/Community-Articles/2020-09-16-How-to-Setup-Azure-Active-Directory-and-Integrate-Abp-Angular-Application/POST.md b/docs/en/Community-Articles/2020-09-16-How-to-Setup-Azure-Active-Directory-and-Integrate-Abp-Angular-Application/POST.md index c7f4f40917..a1c63529a2 100644 --- a/docs/en/Community-Articles/2020-09-16-How-to-Setup-Azure-Active-Directory-and-Integrate-Abp-Angular-Application/POST.md +++ b/docs/en/Community-Articles/2020-09-16-How-to-Setup-Azure-Active-Directory-and-Integrate-Abp-Angular-Application/POST.md @@ -23,20 +23,9 @@ This means your application will be using AzureAD user store for authentication. Lets start with adding OpenId connection. Open the **HttpApiHostModule.cs** and update the **ConfigureAuthentication** method as below: ```csharp -JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); -JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Add("sub", ClaimTypes.NameIdentifier); context.Services.AddAuthentication() - .AddIdentityServerAuthentication(options => - { - options.Authority = configuration["AuthServer:Authority"]; - options.RequireHttpsMetadata = false; - options.ApiName = "NonTieredAngular"; - options.JwtBackChannelHandler = new HttpClientHandler() - { - ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator - }; - }) + ... //Omitted other third party configurations .AddOpenIdConnect("AzureOpenId", "Azure AD OpenId", options => { options.Authority = "https://login.microsoftonline.com/" + configuration["AzureAd:TenantId"] + "/v2.0/"; @@ -48,6 +37,8 @@ context.Services.AddAuthentication() options.SaveTokens = true; options.GetClaimsFromUserInfoEndpoint = true; options.Scope.Add("email"); + + options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub"); }); ``` @@ -58,10 +49,7 @@ public override void ConfigureServices(ServiceConfigurationContext context) { var hostingEnvironment = context.Services.GetHostingEnvironment(); var configuration = context.Services.GetConfiguration(); - - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); - JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Add("sub", ClaimTypes.NameIdentifier); - + context.Services.AddAuthentication() .AddOpenIdConnect("AzureOpenId", "Azure AD OpenId", options => { @@ -120,3 +108,8 @@ Next time you hit login, you should be seeing login screen enabled Azure AD like * But I don't want my users to see default login screen. I want my users to login **only** from AzureAD. * You can **mimic** this behaviour by customizing the login page and instantly trigger Azure AD provider click. For more info, you can check [this article](https://community.abp.io/articles/how-to-customize-the-login-page-for-mvc-razor-page-applications-9a40f3cd). + +# May 2021 Update + +- **AddOpenIdConnect**: Removed `JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();` and added `sub` claim mapping in ClaimActions rather than global mapping. +- Updated OpenIdConnect configurations. diff --git a/docs/en/Domain-Driven-Design-Implementation-Guide.md b/docs/en/Domain-Driven-Design-Implementation-Guide.md index bf466e04c8..dc28845396 100644 --- a/docs/en/Domain-Driven-Design-Implementation-Guide.md +++ b/docs/en/Domain-Driven-Design-Implementation-Guide.md @@ -1,1982 +1,5 @@ # Implementing Domain Driven Design -## Introduction +This document has been packaged as a **free e-book** and can be downloaded from the following URL: -This is a **practical guide** for implementing the Domain Driven Design (DDD). While the implementation details rely on the ABP Framework infrastructure, core concepts, principles and patterns are applicable in any kind of solution, even if it is not a .NET solution. - -### Goals - -The goals of this document are to - -* **Introduce and explain** the DDD architecture, concepts, principles, patterns and building blocks. -* Explain the **layered architecture** & solution structure offered by the ABP Framework. -* Introduce **explicit rules** to implement DDD patterns and best practices by giving **concrete examples**. -* Show what **ABP Framework provides** you as the infrastructure for implementing DDD in a proper way. -* And finally, provide **suggestions** based on software development **best practices** and our experiences to create a **maintainable codebase**. - -### Simple Code! - -> **Playing football** is very **simple**, but **playing simple football** is the **hardest thing** there is. -> — Johan Cruyff - -If we take this famous quote for programming, we can say; - -> **Writing code** is very **simple**, but **writing simple code** is the **hardest thing** there is. -> — ??? - -In this document, we will introduce **simple rules**, those are **easy to implement**. - -Once your **application grows**, it will be **hard to follow** these rules. Sometimes you find **breaking rules** will save you time in a short term. However, the saved time in the short term will bring much **more time loss** in the middle and long term. Your code base becomes **complicated** and hard to maintain. Most of the business applications are **re-written** just because you **can't maintain** it anymore. - -If you **follow the rules and best practices**, your code base will be simpler and easier to maintain. Your application **reacts to changes** faster. - -## What is the Domain Driven Design? - -Domain-driven design (DDD) is an approach to software development for **complex** needs by connecting the implementation to an **evolving** model; - -DDD is suitable for **complex domains** and **large-scale** applications rather than simple CRUD applications. It focuses on the **core domain logic** rather than the infrastructure details. It helps to build a **flexible**, modular and **maintainable** code base. - -### OOP & SOLID - -Implementing DDD highly relies on the Object Oriented Programming (OOP) and [SOLID](https://en.wikipedia.org/wiki/SOLID) principles. Actually, it **implements** and **extends** these principles. So, a **good understanding** of OOP & SOLID helps you a lot while truly implementing the DDD. - -### DDD Layers & Clean Architecture - -There are four fundamental layers of a Domain Driven Based Solution; - -![domain-driven-design-layers](images/domain-driven-design-layers.png) - -**Business Logic** places into two layers, the *Domain layer* and the *Application Layer*, while they contain different kinds of business logic; - -* **Domain Layer** implements the core, use-case independent business logic of the domain/system. -* **Application Layer** implements the use cases of the application based on the domain. A use case can be thought as a user interaction on the User Interface (UI). -* **Presentation Layer** contains the UI elements (pages, components) of the application. -* **Infrastructure Layer** supports other layer by implementing the abstractions and integrations to 3rd-party library and systems. - -The same layering can be shown as the diagram below and known as the **Clean Architecture**, or sometimes the **Onion Architecture**: - -![domain-driven-design-clean-architecture](images/domain-driven-design-clean-architecture.png) - -In the Clean Architecture, each layer only **depends on the layer directly inside it**. The most independent layer is shown in the most inner circle and it is the Domain Layer. - -### Core Building Blocks - -DDD mostly **focuses on the Domain & Application Layers** and ignores the Presentation and Infrastructure. They are seen as *details* and the business layers should not depend on them. - -That doesn't mean the Presentation and Infrastructure layers are not important. They are very important. UI frameworks and database providers have their own rules and best practices that you need to know and apply. However these are not in the topics of DDD. - -This section introduces the essential building blocks of the Domain & Application Layers. - -#### Domain Layer Building Blocks - -* **Entity**: An [Entity](Entities.md) is an object with its own properties (state, data) and methods that implements the business logic that is executed on these properties. An entity is represented by its unique identifier (Id). Two entity object with different Ids are considered as different entities. -* **Value Object**: A [Value Object](Value-Objects.md) is another kind of domain object that is identified by its properties rather than a unique Id. That means two Value Objects with same properties are considered as the same object. Value objects are generally implemented as immutable and mostly are much simpler than the Entities. -* **Aggregate & Aggregate Root**: An [Aggregate](Entities.md) is a cluster of objects (entities and value objects) bound together by an **Aggregate Root** object. The Aggregate Root is a specific type of an entity with some additional responsibilities. -* **Repository** (interface): A [Repository](Repositories.md) is a collection-like interface that is used by the Domain and Application Layers to access to the data persistence system (the database). It hides the complexity of the DBMS from the business code. Domain Layer contains the `interface`s of the repositories. -* **Domain Service**: A [Domain Service](Domain-Services.md) is a stateless service that implements core business rules of the domain. It is useful to implement domain logic that depends on multiple aggregate (entity) type or some external services. -* **Specification**: A [Specification](Specifications.md) is used to define named, reusable and combinable filters for entities and other business objects. -* **Domain Event**: A [Domain Event](Event-Bus.md) is a way of informing other services in a loosely coupled manner, when a domain specific event occurs. - -#### Application Layer Building Blocks - -* **Application Service**: An [Application Service](Application-Services.md) is a stateless service that implements use cases of the application. An application service typically gets and returns DTOs. It is used by the Presentation Layer. It uses and coordinates the domain objects to implement the use cases. A use case is typically considered as a Unit Of Work. -* **Data Transfer Object (DTO)**: A [DTO](Data-Transfer-Objects.md) is a simple object without any business logic that is used to transfer state (data) between the Application and Presentation Layers. -* **Unit of Work (UOW)**: A [Unit of Work](Unit-Of-Work.md) is an atomic work that should be done as a transaction unit. All the operations inside a UOW should be committed on success or rolled back on a failure. - -## Implementation: The Big Picture - -### Layering of a .NET Solution - -The picture below shows a Visual Studio Solution created using the ABP's [application startup template](Startup-Templates/Application.md): - -![domain-driven-design-vs-solution](images/domain-driven-design-vs-solution.png) - -The solution name is `IssueTracking` and it consists of multiple projects. The solution is layered by considering **DDD principles** as well as **development** and **deployment** practicals. The sub sections below explains the projects in the solution; - -> Your solution structure may be slightly different if you choose a different UI or Database provider. However, the Domain and Application layers will be same and this is the essential point for the DDD perspective. See the [Application Startup Template](Startup-Templates/Application.md) document if you want to know more about the solution structure. - -#### The Domain Layer - -The Domain Layer is splitted into two projects; - -* `IssueTracking.Domain` is the **essential domain layer** that contains all the **building blocks** (entities, value objects, domain services, specifications, repository interfaces, etc.) introduced before. -* `IssueTracking.Domain.Shared` is a thin project that contains some types those belong to the Domain Layer, but shared with all other layers. For example, it may contain some constants and `enum`s related to the Domain Objects but need to be **reused by other layers**. - -#### The Application Layer - -The Application Layer is also splitted into two projects; - -* `IssueTracking.Application.Contracts` contains the application service **interfaces** and the **DTO**s used by these interfaces. This project can be shared by the client applications (including the UI). -* `IssueTracking.Application` is the **essential application layer** that **implements** the interfaces defined in the Contracts project. - -#### The Presentation Layer - -* `IssueTracking.Web` is an ASP.NET Core MVC / Razor Pages application for this example. This is the only executable application that serves the application and the APIs. - -> ABP Framework also supports different kind of UI frameworks including [Angular](UI/Angular/Quick-Start.md) and [Blazor](UI/Blazor/Overall.md). In these cases, the `IssueTracking.Web` doesn't exist in the solution. Instead, an `IssueTracking.HttpApi.Host` application will be in the solution to serve the HTTP APIs as a standalone endpoint to be consumed by the UI applications via HTTP API calls. - -#### The Remote Service Layer - -* `IssueTracking.HttpApi` project contains HTTP APIs defined by the solution. It typically contains MVC `Controller`s and related models, if available. So, you write your HTTP APIs in this project. - -> Most of the time, API Controllers are just wrappers around the Application Services to expose them to the remote clients. Since ABP Framework's [Automatic API Controller System](API/Auto-API-Controllers.md) **automatically configures and exposes your Application Services as API Controllers**, you typically don't create Controllers in this project. However, the startup solution includes it for the cases you need to manually create API controllers. - -* `IssueTracking.HttpApi.Client` project is useful when you have a C# application that needs to consume your HTTP APIs. Once the client application references this project, it can directly [inject](Dependency-Injection.md) & use the Application Services. This is possible by the help of the ABP Framework's [Dynamic C# Client API Proxies System](API/Dynamic-CSharp-API-Clients.md). - -> There is a Console Application in the `test` folder of the solution, named `IssueTracking.HttpApi.Client.ConsoleTestApp`. It simply uses the `IssueTracking.HttpApi.Client` project to consume the APIs exposed by the application. It is just a demo application and you can safely delete it. You can even delete the `IssueTracking.HttpApi.Client` project if you think that you don't need to them. - -#### The Infrastructure Layer - -In a DDD implementation, you may have a single Infrastructure project to implement all the abstractions and integrations, or you may have different projects for each dependency. - -We suggest a balanced approach; Create separate projects for main infrastructure dependencies (like Entity Framework Core) and a common infrastructure project for other infrastructure. - -ABP's startup solution has two projects for the Entity Framework Core integration; - -* `IssueTracking.EntityFrameworkCore` is the essential integration package for the EF Core. Your application's `DbContext`, database mappings, implementations of the repositories and other EF Core related stuff are located here. -* `IssueTracking.EntityFrameworkCore.DbMigrations` is a special project to manage the Code First database migrations. There is a separate `DbContext` in this project to track the migrations. You typically don't touch this project much except you need to create a new database migration or add an [application module](Modules/Index.md) that has some database tables and naturally requires to create a new database migration. - -> You may wonder why there are two projects for the EF Core. It is mostly related to [modularity](Module-Development-Basics.md). Each module has its own independent `DbContext` and your application has also one `DbContext`. `DbMigrations` project contains a **union** of the modules to track and apply a **single migration path**. While most of the time you don't need to know it, you can see the [EF Core migrations](Entity-Framework-Core-Migrations.md) document for more information. - -#### Other Projects - -There is one more project, `IssueTracking.DbMigrator`, that is a simple Console Application that **migrates** the database schema and **[seeds](Data-Seeding.md) the initial** data when you execute it. It is a useful **utility application** that you can use it in development as well as in production environment. - -### Dependencies of the Projects in the Solution - -The diagram below shows the essential dependencies (project references) between the projects in the solution (`IssueTracking.` part is not shown to be simple) - -![domain-driven-design-project-relations](images/domain-driven-design-project-relations.png) - -The projects have been explained before. Now, we can explain the reasons of the dependencies; - -* `Domain.Shared` is the project that all other projects directly or indirectly depend on. So, all the types in this project are available to all projects. -* `Domain` only depends on the `Domain.Shared` because it is already a (shared) part of the domain. For example, an `IssueType` enum in the `Domain.Shared` can be used by an `Issue` entity in the `Domain` project. -* `Application.Contracts` depends on the `Domain.Shared`. In this way, you can reuse these types in the DTOs. For example, the same `IssueType` enum in the `Domain.Shared` can be used by a `CreateIssueDto` as a property. -* `Application` depends on the `Application.Contracts` since it implements the Application Service interfaces and uses the DTOs inside it. It also depends on the `Domain` since the Application Services are implemented using the Domain Objects defined inside it. -* `EntityFrameworkCore` depends on the `Domain` since it maps the Domain Objects (entities and value types) to database tables (as it is an ORM) and implements the repository interfaces defined in the `Domain`. -* `HttpApi` depends on the `Application.Contracts` since the Controllers inside it inject and use the Application Service interfaces as explained before. -* `HttpApi.Client` depends on the `Application.Contracts` since it can consume the Application Services as explained before. -* `Web` depends on the `HttpApi` since it serves the HTTP APIs defined inside it. Also, in this way, it indirectly depends on the `Application.Contracts` project to consume the Application Services in the Pages/Components. - -#### Dashed Dependencies - -When you investigate the solution, you will see two more dependencies shown with the dashed lines in the figure above. `Web` project depends on the `Application` and `EntityFrameworkCore` projects which *theoretically* should not be like that but actually it is. - -This is because the `Web` is the final project that runs and hosts the application and the **application needs the implementations of the Application Services and the Repositories** while running. - -This design decision potentially allows you to use Entities and EF Core objects in the Presentation Layer which **should be strictly avoided**. However, we find the alternative designs over complicated. Here, two of the alternatives if you want to remove this dependency; - -* Convert `Web` project to a razor class library and create a new project, like `Web.Host`, that depends on the `Web`, `Application` and `EntityFrameworkCore` projects and hosts the application. You don't write any UI code here, but use **only for hosting**. -* Remove `Application` and `EntityFrameworkCore` dependencies from the `Web` project and load their assemblies on application initialization. You can use ABP's [Plug-In Modules](PlugIn-Modules.md) system for that purpose. - -### Execution Flow a DDD Based Application - -The figure below shows a typical request flow for a web application that has been developed based on DDD patterns. - -![](images/domain-driven-design-web-request-flow.png) - -* The request typically begins with a user interaction on the UI (a *use case*) that causes an HTTP request to the server. -* An MVC Controller or a Razor Page Handler in the Presentation Layer (or in the Distributed Services Layer) handles the request and can perform some cross cutting concerns in this stage ([Authorization](Authorization.md), [Validation](Validation.md), [Exception Handling](Exception-Handling.md), etc.). A Controller/Page injects the related Application Service interface and calls its method(s) by sending and receiving DTOs. -* The Application Service uses the Domain Objects (Entities, Repository interfaces, Domain Services, etc.) to implement the *use case*. Application Layer implements some cross cutting concerns (Authorization, Validation, etc.). An Application Service method should be a [Unit Of Work](Unit-Of-Work.md). That means it should be atomic. - -Most of the cross cutting concerns are **automatically and conventionally implemented by the ABP Framework** and you typically don't need to write code for them. - -### Common Principles - -Before going into details, let's see some overall DDD principles; - -#### Database Provider / ORM Independence - -The domain and the application layers should be ORM / Database Provider agnostic. They should only depend on the Repository interfaces and the Repository interfaces don't use any ORM specific objects. - -Here, the main reasons of this principle; - -1. To make your domain/application **infrastructure independent** since the infrastructure may change in the future or you may need to support a second database type later. -2. To make your domain/application **focus on the business code** by hiding the infrastructure details behind the repositories. -3. To make your **automated tests** easier since you can mock the repositories in this case. - -> As a respect to this principle, none of the projects in the solution has reference to the `EntityFrameworkCore` project, except the startup application. - -##### Discussion About the Database Independence Principle - -Especially, the **reason 1** deeply effects your domain **object design** (especially, the entity relations) and **application code**. Assume that you are using [Entity Framework Core](Entity-Framework-Core.md) with a relational database. If you are willing to make your application switchable to [MongoDB](MongoDB.md) later, you can't use some very **useful EF Core features**. Examples; - -* You can't assume [Change Tracking](https://docs.microsoft.com/en-us/ef/core/querying/tracking) since MongoDB provider can't do it. So, you always need to explicitly update the changed entities. -* You can't use [Navigation Properties](https://docs.microsoft.com/en-us/ef/core/modeling/relationships) (or Collections) to other Aggregates in your entities since this is not possible for a Document Database. See the "Rule: Reference Other Aggregates Only By Id" section for more info. - -If you think such features are **important** for you and you **will never stray** from the EF Core, we believe that it is worth **stretching this principle**. We still suggest to use the repository pattern to hide the infrastructure details. But you can assume that you are using EF Core while designing your entity relations and writing your application code. You can even reference to the EF Core NuGet Package from your application layer to be able to directly use the asynchronous LINQ extension methods, like `ToListAsync()` (see the *IQueryable & Async Operations* section in the [Repositories](Repositories.md) document for more info). - -#### Presentation Technology Agnostic - -The presentation technology (UI Framework) is one of the most changed parts of a real world application. It is very important to design the **Domain and Application Layers** to be completely **unaware** of the presentation technology/framework. This principle is relatively easy to implement and ABP's startup template makes it even easier. - -In some cases, you may need to have **duplicate logic** in the application and presentation layers. For example, you may need to duplicate the **validation** and **authorization** checks in both layers. The checks in the UI layer is mostly for **user experience** while checks in the application and domain layers are for **security and data integrity**. That's perfectly normal and necessary. - -#### Focus on the State Changes, Not Reporting - -DDD focuses on how the domain objects **changes and interactions**; How to create an entity and change its properties by preserving the data **integrity/validity** and implementing the **business rules**. - -DDD **ignores reporting** and mass querying. That doesn't mean they are not important. If your application doesn't have fancy dashboards and reports, who would use it? However, reporting is another topic. You typically want to use the full power of the SQL Server or even use a separate data source (like ElasticSearch) for reporting purpose. You will write optimized queries, create indexes and even stored procedures(!). You are free to do all these things as long as you don't infect them into your business logic. - -## Implementation: The Building Blocks - -This is the essential part of this guide. We will introduce and explain some **explicit rules** with examples. You can follow these rules and apply in your solution while implementing the Domain Driven Design. - -### The Example Domain - -The examples will use some concepts those are used by GitHub, like `Issue`, `Repository`, `Label` and `User`, you are already familiar with. The figure below shows some of the aggregates, aggregate roots, entities, value object and the relations between them: - -![domain driven design example schema](images/domain-driven-design-example-domain-schema.png) - -**Issue Aggregate** consists of an `Issue` Aggregate Root that contains `Comment` and `IssueLabel` collections. Other aggregates are shown as simple since we will focus on the Issue Aggregate: - -![domain-driven-design-issue-aggregate-diagram](images/domain-driven-design-issue-aggregate-diagram.png) - -### Aggregates - -As said before, an [Aggregate](Entities.md) is a cluster of objects (entities and value objects) bound together by an Aggregate Root object. This section will introduce the principles and rules related to the Aggregates. - -> We refer the term *Entity* both for *Aggregate Root* and *sub-collection entities* unless we explicitly write *Aggregate Root* or *sub-collection entity*. - -#### Aggregate / Aggregate Root Principles - -##### Business Rules - -Entities are responsible to implement the business rules related to the properties of their own. The *Aggregate Root Entities* are also responsible for their sub-collection entities. - -An aggregate should maintain its self **integrity** and **validity** by implementing domain rules and constraints. That means, unlike the DTOs, Entities have **methods to implement some business logic**. Actually, we should try to implement business rules in the entities wherever possible. - -##### Single Unit - -An aggregate is **retrieved and saved as a single unit**, with all the sub-collections and properties. For example, if you want to add a `Comment` to an `Issue`, you need to; - -* Get the `Issue` from database with including all the sub-collections (`Comment`s and `IssueLabel`s). -* Use methods on the `Issue` class to add a new comment, like `Issue.AddComment(...);`. -* Save the `Issue` (with all sub-collections) to the database as a single database operation (update). - -That may seem strange to the developers used to work with **EF Core & Relational Databases** before. Getting the `Issue` with all details seems **unnecessary and inefficient**. Why don't we just execute an SQL `Insert` command to database without querying any data? - -The answer is that we should **implement the business** rules and preserve the data **consistency** and **integrity** in the **code**. If we have a business rule like "*Users can not comment on the locked issues*", how can we check the `Issue`'s lock state without retrieving it from the database? So, we can execute the business rules only if the related objects available in the application code. - -On the other hand, **MongoDB** developers will find this rule very natural. In MongoDB, an aggregate object (with sub-collections) is saved in a **single collection** in the database (while it is distributed into several tables in a relational database). So, when you get an aggregate, all the sub-collections are already retrieved as a part of the query, without any additional configuration. - -ABP Framework helps to implement this principle in your applications. - -**Example: Add a comment to an issue** - -````csharp -public class IssueAppService : ApplicationService, IIssueAppService -{ - private readonly IRepository _issueRepository; - - public IssueAppService(IRepository issueRepository) - { - _issueRepository = issueRepository; - } - - [Authorize] - public async Task CreateCommentAsync(CreateCommentDto input) - { - var issue = await _issueRepository.GetAsync(input.IssueId); - issue.AddComment(CurrentUser.GetId(), input.Text); - await _issueRepository.UpdateAsync(issue); - } -} -```` - -`_issueRepository.GetAsync` method retrieves the `Issue` with all details (sub-collections) as a single unit by default. While this works out of the box for MongoDB, you need to configure your aggregate details for the EF Core. But, once you configure, repositories automatically handle it. `_issueRepository.GetAsync` method gets an optional parameter, `includeDetails`, that you can pass `false` to disable this behavior when you need it. - -> See the *Loading Related Entities* section of the [EF Core document](Entity-Framework-Core.md) for the configuration and alternative scenarios. - -`Issue.AddComment` gets a `userId` and comment `text`, implements the necessary business rules and adds the comment to the Comments collection of the `Issue`. - -Finally, we use `_issueRepository.UpdateAsync` to save changes to the database. - -> EF Core has a **change tracking** feature. So, you actually don't need to call `_issueRepository.UpdateAsync`. It will be automatically saved thanks to ABP's Unit Of Work system that automatically calls `DbContext.SaveChanges()` at the end of the method. However, for MongoDB, you need to explicitly update the changed entity. -> -> So, if you want to write your code Database Provider independent, you should always call the `UpdateAsync` method for the changed entities. - -##### Transaction Boundary - -An aggregate is generally considered as a transaction boundary. If a use case works with a single aggregate, reads and saves it as a single unit, all the changes made to the aggregate objects are saved together as an atomic operation and you don't need to an explicit database transaction. - -However, in real life, you may need to change **more than one aggregate instances** in a single use case and you need to use database transactions to ensure **atomic update** and **data consistency**. Because of that, ABP Framework uses an explicit database transaction for a use case (an application service method boundary). See the [Unit Of Work](Unit-Of-Work.md) documentation for more info. - -##### Serializability - -An aggregate (with the root entity and sub-collections) should be serializable and transferrable on the wire as a single unit. For example, MongoDB serializes the aggregate to JSON document while saving to the database and deserializes from JSON while reading from the database. - -> This requirement is not necessary when you use relational databases and ORMs. However, it is an important practice of Domain Driven Design. - -The following rules will already bring the serializability. - -#### Aggregate / Aggregate Root Rules & Best Practices - -The following rules ensures implementing the principles introduced above. - -##### Reference Other Aggregates Only By Id - -The first rule says an Aggregate should reference to other aggregates only by their Id. That means you can not add navigation properties to other aggregates. - -* This rule makes it possible to implement the serializability principle. -* It also prevents different aggregates manipulate each other and leaking business logic of an aggregate to one another. - -You see two aggregate roots, `GitRepository` and `Issue` in the example below; - -![domain-driven-design-reference-by-id-sample](images/domain-driven-design-reference-by-id-sample.png) - -* `GitRepository` should not have a collection of the `Issue`s since they are different aggregates. -* `Issue` should not have a navigation property for the related `GitRepository` since it is a different aggregate. -* `Issue` can have `RepositoryId` (as a `Guid`). - -So, when you have an `Issue` and need to have `GitRepository` related to this issue, you need to explicitly query it from database by the `RepositoryId`. - -###### For EF Core & Relational Databases - -In MongoDB, it is naturally not suitable to have such navigation properties/collections. If you do that, you find a copy of the destination aggregate object in the database collection of the source aggregate since it is being serialized to JSON on save. - -However, EF Core & relational database developers may find this restrictive rule unnecessary since EF Core can handle it on database read and write. We see this an important rule that helps to **reduce the complexity** of the domain prevents potential problems and we strongly suggest to implement this rule. However, if you think it is practical to ignore this rule, see the *Discussion About the Database Independence Principle* section above. - -##### Keep Aggregates Small - -One good practice is to keep an aggregate simple and small. This is because an aggregate will be loaded and saved as a single unit and reading/writing a big object has performance problems. See the example below: - -![domain-driven-design-aggregate-keep-small](images/domain-driven-design-aggregate-keep-small.png) - -Role aggregate has a collection of `UserRole` value objects to track the users assigned for this role. Notice that `UserRole` is not another aggregate and it is not a problem for the rule *Reference Other Aggregates Only By Id*. However, it is a problem in practical. A role may be assigned to thousands (even millions) of users in a real life scenario and it is a significant performance problem to load thousands of items whenever you query a `Role` from database (remember: Aggregates are loaded by their sub-collections as a single unit). - -On the other hand, `User` may have such a `Roles` collection since a user doesn't have much roles in practical and it can be useful to have a list of roles while you are working with a User Aggregate. - -If you think carefully, there is one more problem when Role and User both have the list of relation when use a **non-relational database, like MongoDB**. In this case, the same information is duplicated in different collections and it will be hard to maintain data consistency (whenever you add an item to `User.Roles`, you need to add it to `Role.Users` too). - -So, determine your aggregate boundaries and size based on the following considerations; - -* Objects used together. -* Query (load/save) performance and memory consumption. -* Data integrity, validity and consistency. - -In practical; - -* Most of the aggregate roots will **not have sub-collections**. -* A sub-collection should not have more than **100-150 items** inside it at the most case. If you think a collection potentially can have more items, don't define the collection as a part of the aggregate and consider to extract another aggregate root for the entity inside the collection. - -##### Primary Keys of the Aggregate Roots / Entities - -* An aggregate root typically has a single `Id` property for its identifier (Primark Key: PK). We prefer `Guid` as the PK of an aggregate root entity (see the [Guid Genertation document](Guid-Generation.md) to learn why). -* An entity (that's not the aggregate root) in an aggregate can use a composite primary key. - -For example, see the Aggregate root and the Entity below: - -![domain-driven-design-entity-primary-keys](images/domain-driven-design-entity-primary-keys.png) - -* `Organization` has a `Guid` identifier (`Id`). -* `OrganizationUser` is a sub-collection of an `Organization` and has a composite primary key consists of the `OrganizationId` and `UserId`. - -That doesn't mean sub-collection entities should always have composite PKs. They may have single `Id` properties when it's needed. - -> Composite PKs are actually a concept of relational databases since the sub-collection entities have their own tables and needs to a PK. On the other hand, for example, in MongoDB you don't need to define PK for the sub-collection entities at all since they are stored as a part of the aggregate root. - -##### Constructors of the Aggregate Roots / Entities - -The constructor is located where the lifecycle of an entity begins. There are a some responsibilities of a well designed constructor: - -* Gets the **required entity properties** as parameters to **create a valid entity**. Should force to pass only for the required parameters and may get non-required properties as optional parameters. -* **Checks validity** of the parameters. -* Initializes **sub-collections**. - -**Example: `Issue` (Aggregate Root) constructor** - -````csharp -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using Volo.Abp; -using Volo.Abp.Domain.Entities; - -namespace IssueTracking.Issues -{ - public class Issue : AggregateRoot - { - public Guid RepositoryId { get; set; } - public string Title { get; set; } - public string Text { get; set; } - public Guid? AssignedUserId { get; set; } - public bool IsClosed { get; set; } - public IssueCloseReason? CloseReason { get; set; } //enum - - public ICollection Labels { get; set; } - - public Issue( - Guid id, - Guid repositoryId, - string title, - string text = null, - Guid? assignedUserId = null - ) : base(id) - { - RepositoryId = repositoryId; - Title = Check.NotNullOrWhiteSpace(title, nameof(title)); - - Text = text; - AssignedUserId = assignedUserId; - - Labels = new Collection(); - } - - private Issue() { /* for deserialization & ORMs */ } - } -} -```` - -* `Issue` class properly **forces to create a valid entity** by getting minimum required properties in its constructor as parameters. -* The constructor **validates** the inputs (`Check.NotNullOrWhiteSpace(...)` throws `ArgumentException` if the given value is empty). -* It **initializes the sub-collections**, so you don't get a null reference exception when you try to use the `Labels` collection after creating the `Issue`. -* The constructor also **takes the `id`** and passes to the `base` class. We don't generate `Guid`s inside the constructor to be able to delegate this responsibility to another service (see [Guid Generation](Guid-Generation.md)). -* Private **empty constructor** is necessary for ORMs. We made it `private` to prevent accidently using it in our own code. - -> See the [Entities](Entities.md) document to learn more about creating entities with the ABP Framework. - -##### Entity Property Accessors & Methods - -The example above may seem strange to you! For example, we force to pass a non-null `Title` in the constructor. However, the developer may then set the `Title` property to `null` without any control. This is because the example code above just focuses on the constructor. - -If we declare all the properties with **public setters** (like the example `Issue` class above), we can't force **validity** and **integrity** of the entity in its lifecycle. So; - -* Use **private setter** for a property when you need to perform any **logic** while setting that property. -* Define public methods to manipulate such properties. - -**Example: Methods to change the properties in a controlled way** - -````csharp -using System; -using Volo.Abp; -using Volo.Abp.Domain.Entities; - -namespace IssueTracking.Issues -{ - public class Issue : AggregateRoot - { - public Guid RepositoryId { get; private set; } //Never changes - public string Title { get; private set; } //Needs validation - public string Text { get; set; } //No validation - public Guid? AssignedUserId { get; set; } //No validation - public bool IsClosed { get; private set; } //Should be changed with CloseReason - public IssueCloseReason? CloseReason { get; private set; } //Should be changed with IsClosed - - //... - - public void SetTitle(string title) - { - Title = Check.NotNullOrWhiteSpace(title, nameof(title)); - } - - public void Close(IssueCloseReason reason) - { - IsClosed = true; - CloseReason = reason; - } - - public void ReOpen() - { - IsClosed = false; - CloseReason = null; - } - } -} -```` - -* `RepositoryId` setter made private and there is no way to change it after creating an `Issue` because this is what we want in this domain: An issue can't be moved to another repository. -* `Title` setter made private and `SetTitle` method has been created if you want to change it later in a controlled way. -* `Text` and `AssignedUserId` has public setters since there is no restriction on them. They can be null or any other value. We think it is unnecessary to define separate methods to set them. If we need later, we can add methods and make the setters private. Breaking changes are not problem in the domain layer since the domain layer is an internal project, it is not exposed to clients. -* `IsClosed` and `IssueCloseReason` are pair properties. Defined `Close` and `ReOpen` methods to change them together. In this way, we prevent to close an issue without any reason. - -##### Business Logic & Exceptions in the Entities - -When you implement validation and business logic in the entities, you frequently need to manage the exceptional cases. In these cases; - -* Create **domain specific exceptions**. -* **Throw these exceptions** in the entity methods when necessary. - -**Example** - -````csharp -public class Issue : AggregateRoot -{ - //... - - public bool IsLocked { get; private set; } - public bool IsClosed { get; private set; } - public IssueCloseReason? CloseReason { get; private set; } - - public void Close(IssueCloseReason reason) - { - IsClosed = true; - CloseReason = reason; - } - - public void ReOpen() - { - if (IsLocked) - { - throw new IssueStateException( - "Can not open a locked issue! Unlock it first." - ); - } - - IsClosed = false; - CloseReason = null; - } - - public void Lock() - { - if (!IsClosed) - { - throw new IssueStateException( - "Can not open a locked issue! Unlock it first." - ); - } - - IsLocked = true; - } - - public void Unlock() - { - IsLocked = false; - } -} -```` - -There are two business rules here; - -* A locked issue can not be re-opened. -* You can not lock an open issue. - -`Issue` class throws an `IssueStateException` in these cases to force the business rules: - -````csharp -using System; - -namespace IssueTracking.Issues -{ - public class IssueStateException : Exception - { - public IssueStateException(string message) - : base(message) - { - - } - } -} -```` - -There are two potential problems of throwing such exceptions; - -1. In case of such an exception, should the **end user** see the exception (error) message? If so, how do you **localize** the exception message? You can not use the [localization](Localization.md) system, because you can't inject and use `IStringLocalizer` in the entities. -2. For a web application or HTTP API, what **HTTP Status Code** should return to the client? - -ABP's [Exception Handling](Exception-Handling.md) system solves these and similar problems. - -**Example: Throwing a business exception with code** - -````csharp -using Volo.Abp; - -namespace IssueTracking.Issues -{ - public class IssueStateException : BusinessException - { - public IssueStateException(string code) - : base(code) - { - - } - } -} -```` - -* `IssueStateException` class inherits the `BusinessException` class. ABP returns 403 (forbidden) HTTP Status code by default (instead of 500 - Internal Server Error) for the exceptions derived from the `BusinessException`. -* The `code` is used as a key in the localization resource file to find the localized message. - -Now, we can change the `ReOpen` method as shown below: - -````csharp -public void ReOpen() -{ - if (IsLocked) - { - throw new IssueStateException("IssueTracking:CanNotOpenLockedIssue"); - } - - IsClosed = false; - CloseReason = null; -} -```` - -> Use constants instead of magic strings. - -And add an entry to the localization resource like below: - -````json -"IssueTracking:CanNotOpenLockedIssue": "Can not open a locked issue! Unlock it first." -```` - -* When you throw the exception, ABP automatically uses this localized message (based on the current language) to show to the end user. -* The exception code (`IssueTracking:CanNotOpenLockedIssue` here) is also sent to the client, so it may handle the error case programmatically. - -> For this example, you could directly throw `BusinessException` instead of defining a specialized `IssueStateException`. The result will be same. See the [exception handling document](Exception-Handling.md) for all the details. - -##### Business Logic in Entities Requiring External Services - -It is simple to implement a business rule in an entity method when the business logic only uses the properties of that entity. What if the business logic requires to **query database** or **use any external services** that should be resolved from the [dependency injection](Dependency-Injection.md) system. Remember; **Entities can not inject services!** - -There are two common ways of implementing such a business logic: - -* Implement the business logic on an entity method and **get external dependencies as parameters** of the method. -* Create a **Domain Service**. - -Domain Services will be explained later. But, now let's see how it can be implemented in the entity class. - -**Example: Business Rule: Can not assign more than 3 open issues to a user concurrently** - -````csharp -public class Issue : AggregateRoot -{ - //... - public Guid? AssignedUserId { get; private set; } - - public async Task AssignToAsync(AppUser user, IUserIssueService userIssueService) - { - var openIssueCount = await userIssueService.GetOpenIssueCountAsync(user.Id); - - if (openIssueCount >= 3) - { - throw new BusinessException("IssueTracking:ConcurrentOpenIssueLimit"); - } - - AssignedUserId = user.Id; - } - - public void CleanAssignment() - { - AssignedUserId = null; - } -} -```` - -* `AssignedUserId` property setter made private. So, the only way to change it to use the `AssignToAsync` and `CleanAssignment` methods. -* `AssignToAsync` gets an `AppUser` entity. Actually, it only uses the `user.Id`, so you could get a `Guid` value, like `userId`. However, this way ensures that the `Guid` value is `Id` of an existing user and not a random `Guid` value. -* `IUserIssueService` is an arbitrary service that is used to get open issue count for a user. It's the responsibility of the code part (that calls the `AssignToAsync`) to resolve the `IUserIssueService` and pass here. -* `AssignToAsync` throws exception if the business rule doesn't meet. -* Finally, if everything is correct, `AssignedUserId` property is set. - -This method perfectly guarantees to apply the business logic when you want to assign an issue to a user. However, it has some problems; - -* It makes the entity class **depending on an external service** which makes the entity **complicated**. -* It makes **hard to use** the entity. The code that uses the entity now needs to inject `IUserIssueService` and pass to the `AssignToAsync` method. - -An alternative way of implementing this business logic is to introduce a **Domain Service**, which will be explained later. - -### Repositories - -A [Repository](Repositories.md) is a collection-like interface that is used by the Domain and Application Layers to access to the data persistence system (the database) to read and write the Business Objects, generally the Aggregates. - -Common Repository principles are; - -* Define a repository **interface in the Domain Layer** (because it is used in the Domain and Application Layers), **implement in the Infrastructure Layer** (*EntityFrameworkCore* project in the startup template). -* **Do not include business logic** inside the repositories. -* Repository interface should be **database provider / ORM independent**. For example, do not return a `DbSet` from a repository method. `DbSet` is an object provided by the EF Core. -* **Create repositories for aggregate roots**, not for all entities. Because, sub-collection entities (of an aggregate) should be accessed over the aggregate root. - -#### Do Not Include Domain Logic in Repositories - -While this rule seems obvious at the beginning, it is easy to leak business logic into repositories. - -**Example: Get inactive issues from a repository** - -````csharp -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Volo.Abp.Domain.Repositories; - -namespace IssueTracking.Issues -{ - public interface IIssueRepository : IRepository - { - Task> GetInActiveIssuesAsync(); - } -} -```` - -`IIssueRepository` extends the standard `IRepository<...>` interface by adding a `GetInActiveIssuesAsync` method. This repository works with such an `Issue` class: - -````csharp -public class Issue : AggregateRoot, IHasCreationTime -{ - public bool IsClosed { get; private set; } - public Guid? AssignedUserId { get; private set; } - public DateTime CreationTime { get; private set; } - public DateTime? LastCommentTime { get; private set; } - //... -} -```` - -(the code shows only the properties we need for this example) - -The rule says the repository shouldn't know the business rules. The question here is "**What is an inactive issue**? Is it a business rule definition?" - -Let's see the implementation to understand it: - -````csharp -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using IssueTracking.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore; -using Volo.Abp.Domain.Repositories.EntityFrameworkCore; -using Volo.Abp.EntityFrameworkCore; - -namespace IssueTracking.Issues -{ - public class EfCoreIssueRepository : - EfCoreRepository, - IIssueRepository - { - public EfCoreIssueRepository( - IDbContextProvider dbContextProvider) - : base(dbContextProvider) - { - } - - public async Task> GetInActiveIssuesAsync() - { - var daysAgo30 = DateTime.Now.Subtract(TimeSpan.FromDays(30)); - - var dbSet = await GetDbSetAsync(); - return await dbSet.Where(i => - - //Open - !i.IsClosed && - - //Assigned to nobody - i.AssignedUserId == null && - - //Created 30+ days ago - i.CreationTime < daysAgo30 && - - //No comment or the last comment was 30+ days ago - (i.LastCommentTime == null || i.LastCommentTime < daysAgo30) - - ).ToListAsync(); - } - } -} -```` - -(Used EF Core for the implementation. See the [EF Core integration document](Entity-Framework-Core.md) to learn how to create custom repositories with the EF Core.) - -When we check the `GetInActiveIssuesAsync` implementation, we see a **business rule that defines an in-active issue**: The issue should be **open**, **assigned to nobody**, **created 30+ days ago** and has **no comment in the last 30 days**. - -This is an implicit definition of a business rule that is hidden inside a repository method. The problem occurs when we need to reuse this business logic. - -For example, let's say that we want to add an `bool IsInActive()` method on the `Issue` entity. In this way, we can check activeness when we have an issue entity. - -Let's see the implementation: - -````csharp -public class Issue : AggregateRoot, IHasCreationTime -{ - public bool IsClosed { get; private set; } - public Guid? AssignedUserId { get; private set; } - public DateTime CreationTime { get; private set; } - public DateTime? LastCommentTime { get; private set; } - //... - - public bool IsInActive() - { - var daysAgo30 = DateTime.Now.Subtract(TimeSpan.FromDays(30)); - return - //Open - !IsClosed && - - //Assigned to nobody - AssignedUserId == null && - - //Created 30+ days ago - CreationTime < daysAgo30 && - - //No comment or the last comment was 30+ days ago - (LastCommentTime == null || LastCommentTime < daysAgo30); - } -} -```` - -We had to copy/paste/modify the code. What if the definition of the activeness changes? We should not forget to update both places. This is a duplication of a business logic, which is pretty dangerous. - -A good solution to this problem is the *Specification Pattern*! - -### Specifications - -A [specification](Specifications.md) is a **named**, **reusable**, **combinable** and **testable** class to filter the Domain Objects based on the business rules. - -ABP Framework provides necessary infrastructure to easily create specification classes and use them inside your application code. Let's implement the in-active issue filter as a specification class: - -````csharp -using System; -using System.Linq.Expressions; -using Volo.Abp.Specifications; - -namespace IssueTracking.Issues -{ - public class InActiveIssueSpecification : Specification - { - public override Expression> ToExpression() - { - var daysAgo30 = DateTime.Now.Subtract(TimeSpan.FromDays(30)); - return i => - - //Open - !i.IsClosed && - - //Assigned to nobody - i.AssignedUserId == null && - - //Created 30+ days ago - i.CreationTime < daysAgo30 && - - //No comment or the last comment was 30+ days ago - (i.LastCommentTime == null || i.LastCommentTime < daysAgo30); - } - } -} -```` - -`Specification` base class simplifies to create a specification class by defining an expression. Just moved the expression here, from the repository. - -Now, we can re-use the `InActiveIssueSpecification` in the `Issue` entity and `EfCoreIssueRepository` classes. - -#### Using within the Entity - -`Specification` class provides an `IsSatisfiedBy` method that returns `true` if the given object (entity) satisfies the specification. We can re-write the `Issue.IsInActive` method as shown below: - -````csharp -public class Issue : AggregateRoot, IHasCreationTime -{ - public bool IsClosed { get; private set; } - public Guid? AssignedUserId { get; private set; } - public DateTime CreationTime { get; private set; } - public DateTime? LastCommentTime { get; private set; } - //... - - public bool IsInActive() - { - return new InActiveIssueSpecification().IsSatisfiedBy(this); - } -} -```` - -Just created a new instance of the `InActiveIssueSpecification` and used its `IsSatisfiedBy` method to re-use the expression defined by the specification. - -#### Using with the Repositories - -First, starting from the repository interface: - -````csharp -public interface IIssueRepository : IRepository -{ - Task> GetIssuesAsync(ISpecification spec); -} -```` - -Renamed `GetInActiveIssuesAsync` to simple `GetIssuesAsync` by taking a specification object. Since the **specification (the filter) has been moved out of the repository**, we no longer need to create different methods to get issues with different conditions (like `GetAssignedIssues(...)`, `GetLockedIssues(...)`, etc.) - -Updated implementation of the repository can be like that: - -````csharp -public class EfCoreIssueRepository : - EfCoreRepository, - IIssueRepository -{ - public EfCoreIssueRepository( - IDbContextProvider dbContextProvider) - : base(dbContextProvider) - { - } - - public async Task> GetIssuesAsync(ISpecification spec) - { - var dbSet = await GetDbSetAsync(); - return await dbSet - .Where(spec.ToExpression()) - .ToListAsync(); - } -} -```` - -Since `ToExpression()` method returns an expression, it can be directly passed to the `Where` method to filter the entities. - -Finally, we can pass any Specification instance to the `GetIssuesAsync` method: - -````csharp -public class IssueAppService : ApplicationService, IIssueAppService -{ - private readonly IIssueRepository _issueRepository; - - public IssueAppService(IIssueRepository issueRepository) - { - _issueRepository = issueRepository; - } - - public async Task DoItAsync() - { - var issues = await _issueRepository.GetIssuesAsync( - new InActiveIssueSpecification() - ); - } -} -```` - -##### With Default Repositories - -Actually, you don't have to create custom repositories to be able to use specifications. The standard `IRepository` already extends the `IQueryable`, so you can use the standard LINQ extension methods over it: - -````csharp -public class IssueAppService : ApplicationService, IIssueAppService -{ - private readonly IRepository _issueRepository; - - public IssueAppService(IRepository issueRepository) - { - _issueRepository = issueRepository; - } - - public async Task DoItAsync() - { - var queryable = await _issueRepository.GetQueryableAsync(); - var issues = AsyncExecuter.ToListAsync( - queryable.Where(new InActiveIssueSpecification()) - ); - } -} -```` - -`AsyncExecuter` is a utility provided by the ABP Framework to use asynchronous LINQ extension methods (like `ToListAsync` here) without depending on the EF Core NuGet package. See the [Repositories document](Repositories.md) for more information. - -#### Combining the Specifications - -One powerful side of the Specifications is they are combinable. Assume that we have another specification that returns `true` only if the `Issue` is in a Milestone: - -````csharp -public class MilestoneSpecification : Specification -{ - public Guid MilestoneId { get; } - - public MilestoneSpecification(Guid milestoneId) - { - MilestoneId = milestoneId; - } - - public override Expression> ToExpression() - { - return i => i.MilestoneId == MilestoneId; - } -} -```` - -This Specification is *parametric* as a difference from the `InActiveIssueSpecification`. We can combine both specifications to get a list of inactive issues in a specific milestone: - -````csharp -public class IssueAppService : ApplicationService, IIssueAppService -{ - private readonly IRepository _issueRepository; - - public IssueAppService(IRepository issueRepository) - { - _issueRepository = issueRepository; - } - - public async Task DoItAsync(Guid milestoneId) - { - var queryable = await _issueRepository.GetQueryableAsync(); - var issues = AsyncExecuter.ToListAsync( - queryable - .Where( - new InActiveIssueSpecification() - .And(new MilestoneSpecification(milestoneId)) - .ToExpression() - ) - ); - } -} -```` - -The example above uses the `And` extension method to combine the specifications. There are more combining methods are available, like `Or(...)` and `AndNot(...)`. - -> See the [Specifications document](Specifications.md) for more details about the specification infrastructure provided by the ABP Framework. - -### Domain Services - -Domain Services implement domain logic which; - -* Depends on **services and repositories**. -* Needs to work with **multiple aggregates**, so the logic doesn't properly fit in any of the aggregates. - -Domain Services work with Domain Objects. Their methods can **get and return entities, value objects, primitive types**... etc. However, **they don't get/return DTOs**. DTOs is a part of the Application Layer. - -**Example: Assigning an issue to a user** - -Remember how an issue assignment has been implemented in the `Issue` entity: - -````csharp -public class Issue : AggregateRoot -{ - //... - public Guid? AssignedUserId { get; private set; } - - public async Task AssignToAsync(AppUser user, IUserIssueService userIssueService) - { - var openIssueCount = await userIssueService.GetOpenIssueCountAsync(user.Id); - - if (openIssueCount >= 3) - { - throw new BusinessException("IssueTracking:ConcurrentOpenIssueLimit"); - } - - AssignedUserId = user.Id; - } - - public void CleanAssignment() - { - AssignedUserId = null; - } -} -```` - -Here, we will move this logic into a Domain Service. - -First, changing the `Issue` class: - -````csharp -public class Issue : AggregateRoot -{ - //... - public Guid? AssignedUserId { get; internal set; } -} -```` - -* Removed the assign-related methods. -* Changed `AssignedUserId` property's setter from `private` to `internal`, to allow to set it from the Domain Service. - -The next step is to create a domain service, named `IssueManager`, that has `AssignToAsync` to assign the given issue to the given user. - -````csharp -public class IssueManager : DomainService -{ - private readonly IRepository _issueRepository; - - public IssueManager(IRepository issueRepository) - { - _issueRepository = issueRepository; - } - - public async Task AssignToAsync(Issue issue, AppUser user) - { - var openIssueCount = await _issueRepository.CountAsync( - i => i.AssignedUserId == user.Id && !i.IsClosed - ); - - if (openIssueCount >= 3) - { - throw new BusinessException("IssueTracking:ConcurrentOpenIssueLimit"); - } - - issue.AssignedUserId = user.Id; - } -} -```` - -`IssueManager` can inject any service dependency and use to query open issue count on the user. - -> We prefer and suggest to use the `Manager` suffix for the Domain Services. - -The only problem of this design is that `Issue.AssignedUserId` is now open to set out of the class. However, it is not `public`. It is `internal` and changing it is possible only inside the same Assembly, the `IssueTracking.Domain` project for this example solution. We think this is reasonable; - -* Domain Layer developers are already aware of domain rules and they use the `IssueManager`. -* Application Layer developers are already forces to use the `IssueManager` since they don't directly set it. - -While there is a tradeoff between two approaches, we prefer to create Domain Services when the business logic requires to work with external services. - -> If you don't have a good reason, we think **there is no need to create interfaces** (like `IIssueManager` for the `IssueManager`) for Domain Services. - -### Application Services - -An [Application Service](Application-Services.md) is a stateless service that implements **use cases** of the application. An application service typically **gets and returns DTOs**. It is used by the Presentation Layer. It **uses and coordinates the domain objects** (entities, repositories, etc.) to implement the use cases. - -Common principles of an application service are; - -* Implement the **application logic** that is specific to the current use-case. Do not implement the core domain logic inside the application services. We will come back to differences between Application Domain logics. -* **Never get or return entities** for an application service method. This breaks the encapsulation of the Domain Layer. Always get and return DTOs. - -**Example: Assign an Issue to a User** - -````csharp -using System; -using System.Threading.Tasks; -using IssueTracking.Users; -using Microsoft.AspNetCore.Authorization; -using Volo.Abp.Application.Services; -using Volo.Abp.Domain.Repositories; - -namespace IssueTracking.Issues -{ - public class IssueAppService : ApplicationService, IIssueAppService - { - private readonly IssueManager _issueManager; - private readonly IRepository _issueRepository; - private readonly IRepository _userRepository; - - public IssueAppService( - IssueManager issueManager, - IRepository issueRepository, - IRepository userRepository) - { - _issueManager = issueManager; - _issueRepository = issueRepository; - _userRepository = userRepository; - } - - [Authorize] - public async Task AssignAsync(IssueAssignDto input) - { - var issue = await _issueRepository.GetAsync(input.IssueId); - var user = await _userRepository.GetAsync(input.UserId); - - await _issueManager.AssignToAsync(issue, user); - - await _issueRepository.UpdateAsync(issue); - } - } -} -```` - -An application service method typically has three steps those are implemented here; - -1. Get the related domain objects from database to implement the use case. -2. Use domain objects (domain services, entities, etc.) to perform the actual operation. -3. Update the changed entities in the database. - -> The last *Update* is not necessary if your are using EF Core since it has a Change Tracking system. If you want to take advantage of this EF Core feature, please see the *Discussion About the Database Independence Principle* section above. - -`IssueAssignDto` in this example is a simple DTO class: - -````csharp -using System; - -namespace IssueTracking.Issues -{ - public class IssueAssignDto - { - public Guid IssueId { get; set; } - public Guid UserId { get; set; } - } -} -```` - -### Data Transfer Objects - -A [DTO](Data-Transfer-Objects.md) is a simple object that is used to transfer state (data) between the Application and Presentation Layers. So, Application Service methods gets and returns DTOs. - -#### Common DTO Principles & Best Practices - -* A DTO **should be serializable**, by its nature. Because, most of the time it is transferred over network. So, it should have a **parameterless (empty) constructor**. -* Should not contain any **business logic**. -* **Never** inherit from or reference to **entities**. - -**Input DTOs** (those are passed to the Application Service methods) have different natures than **Output DTOs** (those are returned from the Application Service methods). So, they will be treated differently. - -#### Input DTO Best Practices - -##### Do not Define Unused Properties for Input DTOs - -Define **only the properties needed** for the use case! Otherwise, it will be **confusing for the clients** to use the Application Service method. You can surely define **optional properties**, but they should effect how the use case is working, when the client provides them. - -This rule seems unnecessary first. Who would define unused parameters (input DTO properties) for a method? But it happens, especially when you try to reuse input DTOs. - -##### Do not Re-Use Input DTOs - -Define a **specialized input DTO for each use case** (Application Service method). Otherwise, some properties are not used in some cases and this violates the rule defined above: *Do not Define Unused Properties for Input DTOs*. - -Sometimes, it seems appealing to reuse the same DTO class for two use cases, because they are almost same. Even if they are same now, they will probably become different by the time and you will come to the same problem. **Code duplication is a better practice than coupling use cases**. - -Another way of reusing input DTOs is **inheriting** DTOs from each other. While this can be useful in some rare cases, most of the time it brings you to the same point. - -**Example: User Application Service** - -````csharp -public interface IUserAppService : IApplicationService -{ - Task CreateAsync(UserDto input); - Task UpdateAsync(UserDto input); - Task ChangePasswordAsync(UserDto input); -} -```` - -`IUserAppService` uses `UserDto` as the input DTO in all methods (use cases). `UserDto` is defined below: - -````csharp -public class UserDto -{ - public Guid Id { get; set; } - public string UserName { get; set; } - public string Email { get; set; } - public string Password { get; set; } - public DateTime CreationTime { get; set; } -} -```` - -For this example; - -* `Id` is not used in *Create* since the server determines it. -* `Password` is not used in *Update* since we have another method for it. -* `CreationTime` is never used since we can't allow client to send the Creation Time. It should be set in the server. - -A true implementation can be like that: - -````csharp -public interface IUserAppService : IApplicationService -{ - Task CreateAsync(UserCreationDto input); - Task UpdateAsync(UserUpdateDto input); - Task ChangePasswordAsync(UserChangePasswordDto input); -} -```` - -With the given input DTO classes: - -````csharp -public class UserCreationDto -{ - public string UserName { get; set; } - public string Email { get; set; } - public string Password { get; set; } -} - -public class UserUpdateDto -{ - public Guid Id { get; set; } - public string UserName { get; set; } - public string Email { get; set; } -} - -public class UserChangePasswordDto -{ - public Guid Id { get; set; } - public string Password { get; set; } -} -```` - -This is more maintainable approach although more code is written. - -**Exceptional Case**: There can be some exceptions for this rule: If you always want to develop two methods **in parallel**, they may share the same input DTO (by inheritance or direct reuse). For example, if you have a reporting page that has some filters and you have multiple Application Service methods (like screen report, excel report and csv report methods) use the same filters but returns different results, you may want to reuse the same filter input DTO to **couple these use cases**. Because, in this example, whenever you change a filter, you have to make the necessary changes in all the methods to have a consistent reporting system. - -##### Input DTO Validation Logic - -* Implement only **formal validation** inside the DTO. Use Data Annotation Validation Attributes or implement `IValidatableObject` for formal validation. -* **Do not perform domain validation**. For example, don't try to check unique username constraint in the DTOs. - -**Example: Using Data Annotation Attributes** - -````csharp -using System.ComponentModel.DataAnnotations; - -namespace IssueTracking.Users -{ - public class UserCreationDto - { - [Required] - [StringLength(UserConsts.MaxUserNameLength)] - public string UserName { get; set; } - - [Required] - [EmailAddress] - [StringLength(UserConsts.MaxEmailLength)] - public string Email { get; set; } - - [Required] - [StringLength(UserConsts.MaxEmailLength, - MinimumLength = UserConsts.MinPasswordLength)] - public string Password { get; set; } - } -} -```` - -ABP Framework automatically validates input DTOs, throws `AbpValidationException` and returns HTTP Status `400` to the client in case of an invalid input. - -> Some developers think it is better to separate the validation rules and DTO classes. We think the declarative (Data Annotation) approach is practical and useful and doesn't cause any design problem. However, ABP also supports [FluentValidation integration](FluentValidation.md) if you prefer the other approach. - -> See the [Validation document](Validation.md) for all validation options. - -#### Output DTO Best Practices - -* Keep output **DTO count minimum**. **Reuse** where possible (exception: Do not reuse input DTOs as output DTOs). -* Output DTOs can contain **more properties** than used in the client code. -* Return entity DTO from **Create** and **Update** methods. - -The main goals of these suggestions are; - -* Make client code easy to develop and extend; - * Dealing with **similar, but not same** DTOs are problematic on the client side. - * It is common to **need to other properties** on the UI/client in the future. Returning all properties (by considering security and privileges) of an entity makes client code easy to improve without requiring to touch to the backend code. - * If you are opening your API to **3rd-party clients** that you don't know requirements of each client. -* Make the server side code easy to develop and extend; - * You have less class to **understand and maintain**. - * You can reuse the Entity->DTO **object mapping** code. - * Returning same types from different methods make it easy and clear to create **new methods**. - -**Example: Returning Different DTO types from different methods** - -````csharp -public interface IUserAppService : IApplicationService -{ - UserDto Get(Guid id); - List GetUserNameAndEmail(Guid id); - List GetRoles(Guid id); - List GetList(); - UserCreateResultDto Create(UserCreationDto input); - UserUpdateResultDto Update(UserUpdateDto input); -} -```` - -*(We didn't use async methods to make the example cleaner, but use async in your real world application!)* - -The example code above returns different DTO types for each method. As you can guess, there will be a lot of code duplications for querying data, mapping entities to DTOs. - -The `IUserAppService` service above can be simplified: - -````csharp -public interface IUserAppService : IApplicationService -{ - UserDto Get(Guid id); - List GetList(); - UserDto Create(UserCreationDto input); - UserDto Update(UserUpdateDto input); -} -```` - -With a single output DTO: - -````csharp -public class UserDto -{ - public Guid Id { get; set; } - public string UserName { get; set; } - public string Email { get; set; } - public DateTime CreationTime { get; set; } - public List Roles { get; set; } -} -```` - -* Removed `GetUserNameAndEmail` and `GetRoles` since `Get` method already returns the necessary information. -* `GetList` now returns the same with `Get`. -* `Create` and `Update` also returns the same `UserDto`. - -Using the same DTO has a lot of advantages as explained before. For example, think a scenario where you show a **data grid** of Users on the UI. After updating a user, you can get the return value and **update it on the UI**. So, you don't need to call `GetList` again. This is why we suggest to return the entity DTO (`UserDto` here) as return value from the `Create` and `Update` operations. - -##### Discussion - -Some of the output DTO suggestions may not fit in every scenario. These suggestions can be ignored for **performance** reasons, especially when **large data sets** returned or when you create services for your own UI and you have **too many concurrent requests**. - -In these cases, you may want to create **specialized output DTOs with minimal information**. The suggestions above are especially for applications where **maintaining the codebase** is more important than **negligible performance lost**. - -#### Object to Object Mapping - -Automatic [object to object mapping](Object-To-Object-Mapping.md) is a useful approach to copy values from one object to another when two objects have same or similar properties. - -DTO and Entity classes generally have same/similar properties and you typically need to create DTO objects from Entities. ABP's [object to object mapping system](Object-To-Object-Mapping.md) with [AutoMapper](http://automapper.org/) integration makes these operations much easier comparing to manual mapping. - -* **Use** auto object mapping only for **Entity to output DTO** mappings. -* **Do not use** auto object mapping for **input DTO to Entity** mappings. - -There are some reasons why you **should not use** input DTO to Entity auto mapping; - -1. An Entity class typically has a **constructor** that takes parameters and ensures valid object creation. Auto object mapping operation generally requires an empty constructor. -2. Most of the entity properties will have **private setters** and you should use methods to change these properties in a controlled way. -3. You typically need to **carefully validate and process** the user/client input rather than blindly mapping to the entity properties. - -While some of these problems can be solved through mapping configurations (For example, AutoMapper allows to define custom mapping rules), it makes your business code **implicit/hidden** and **tightly coupled** to the infrastructure. We think the business code should be explicit, clear and easy to understand. - -See the *Entity Creation* section below for an example implementation of the suggestions made in this section. - -## Example Use Cases - -This section will demonstrate some example use cases and discuss alternative scenarios. - -### Entity Creation - -Creating an object from an Entity / Aggregate Root class is the first step of the lifecycle of that entity. The *Aggregate / Aggregate Root Rules & Best Practices* section suggests to **create a primary constructor** for the Entity class that guarantees to **create a valid entity**. So, whenever we need to create an instance of that entity, we should always **use that constructor**. - -See the `Issue` Aggregate Root class below: - -````csharp -public class Issue : AggregateRoot -{ - public Guid RepositoryId { get; private set; } - public string Title { get; private set; } - public string Text { get; set; } - public Guid? AssignedUserId { get; internal set; } - - public Issue( - Guid id, - Guid repositoryId, - string title, - string text = null - ) : base(id) - { - RepositoryId = repositoryId; - Title = Check.NotNullOrWhiteSpace(title, nameof(title)); - Text = text; //Allow empty/null - } - - private Issue() { /* Empty constructor is for ORMs */ } - - public void SetTitle(string title) - { - Title = Check.NotNullOrWhiteSpace(title, nameof(title)); - } - - //... -} -```` - -* This class guarantees to create a valid entity by its constructor. -* If you need to change the `Title` later, you need to use the `SetTitle` method which continues to keep `Title` in a valid state. -* If you want to assign this issue to a user, you need to use `IssueManager` (it implements some business rules before the assignment - see the *Domain Services* section above to remember). -* The `Text` property has a public setter, because it also accepts null values and does not have any validation rules for this example. It is also optional in the constructor. - -Let's see an Application Service method that is used to create an issue: - -````csharp -public class IssueAppService : ApplicationService, IIssueAppService -{ - private readonly IssueManager _issueManager; - private readonly IRepository _issueRepository; - private readonly IRepository _userRepository; - - public IssueAppService( - IssueManager issueManager, - IRepository issueRepository, - IRepository userRepository) - { - _issueManager = issueManager; - _issueRepository = issueRepository; - _userRepository = userRepository; - } - - public async Task CreateAsync(IssueCreationDto input) - { - // Create a valid entity - var issue = new Issue( - GuidGenerator.Create(), - input.RepositoryId, - input.Title, - input.Text - ); - - // Apply additional domain actions - if (input.AssignedUserId.HasValue) - { - var user = await _userRepository.GetAsync(input.AssignedUserId.Value); - await _issueManager.AssignToAsync(issue, user); - } - - // Save - await _issueRepository.InsertAsync(issue); - - // Return a DTO represents the new Issue - return ObjectMapper.Map(issue); - } -} -```` - -`CreateAsync` method; - -* Uses the `Issue` **constructor** to create a valid issue. It passes the `Id` using the [IGuidGenerator](Guid-Generation.md) service. It doesn't use auto object mapping here. -* If the client wants to **assign this issue to a user** on object creation, it uses the `IssueManager` to do it by allowing the `IssueManager` to perform the necessary checks before this assignment. -* **Saves** the entity to the database. -* Finally uses the `IObjectMapper` to return an `IssueDto` that is automatically created by **mapping** from the new `Issue` entity. - -#### Applying Domain Rules on Entity Creation - -The example `Issue` entity has no business rule on entity creation, except some formal validations in the constructor. However, there maybe scenarios where entity creation should check some extra business rules. - -For example, assume that you **don't want** to allow to create an issue if there is already an issue with **exactly the same `Title`**. Where to implement this rule? It is **not proper** to implement this rule in the **Application Service**, because it is a **core business (domain) rule** that should always be checked. - -This rule should be implemented in a **Domain Service**, `IssueManager` in this case. So, we need to force the Application Layer always to use the `IssueManager` to create a new `Issue.` - -First, we can make the `Issue` constructor `internal`, instead of `public`: - -````csharp -public class Issue : AggregateRoot -{ - //... - - internal Issue( - Guid id, - Guid repositoryId, - string title, - string text = null - ) : base(id) - { - RepositoryId = repositoryId; - Title = Check.NotNullOrWhiteSpace(title, nameof(title)); - Text = text; //Allow empty/null - } - - //... -} -```` - -This prevents Application Services to directly use the constructor, so they will use the `IssueManager`. Then we can add a `CreateAsync` method to the `IssueManager`: - -````csharp -using System; -using System.Threading.Tasks; -using Volo.Abp; -using Volo.Abp.Domain.Repositories; -using Volo.Abp.Domain.Services; - -namespace IssueTracking.Issues -{ - public class IssueManager : DomainService - { - private readonly IRepository _issueRepository; - - public IssueManager(IRepository issueRepository) - { - _issueRepository = issueRepository; - } - - public async Task CreateAsync( - Guid repositoryId, - string title, - string text = null) - { - if (await _issueRepository.AnyAsync(i => i.Title == title)) - { - throw new BusinessException("IssueTracking:IssueWithSameTitleExists"); - } - - return new Issue( - GuidGenerator.Create(), - repositoryId, - title, - text - ); - } - } -} -```` - -* `CreateAsync` method checks if there is already an issue with the same title and throws a business exception in this case. -* If there is no duplication, it creates and returns a new `Issue`. - -The `IssueAppService` is changed as shown below in order to use the `IssueManager`'s `CreateAsync` method: - -````csharp -public class IssueAppService : ApplicationService, IIssueAppService -{ - private readonly IssueManager _issueManager; - private readonly IRepository _issueRepository; - private readonly IRepository _userRepository; - - public IssueAppService( - IssueManager issueManager, - IRepository issueRepository, - IRepository userRepository) - { - _issueManager = issueManager; - _issueRepository = issueRepository; - _userRepository = userRepository; - } - - public async Task CreateAsync(IssueCreationDto input) - { - // Create a valid entity using the IssueManager - var issue = await _issueManager.CreateAsync( - input.RepositoryId, - input.Title, - input.Text - ); - - // Apply additional domain actions - if (input.AssignedUserId.HasValue) - { - var user = await _userRepository.GetAsync(input.AssignedUserId.Value); - await _issueManager.AssignToAsync(issue, user); - } - - // Save - await _issueRepository.InsertAsync(issue); - - // Return a DTO represents the new Issue - return ObjectMapper.Map(issue); - } -} - -// *** IssueCreationDto class *** -public class IssueCreationDto -{ - public Guid RepositoryId { get; set; } - [Required] - public string Title { get; set; } - public Guid? AssignedUserId { get; set; } - public string Text { get; set; } -} -```` - -##### Discussion: Why is the Issue not saved to the database in `IssueManager`? - -You may ask "**Why didn't `IssueManager` save the `Issue` to the database?**". We think it is the responsibility of the Application Service. - -Because, the Application Service may require additional changes/operations on the `Issue` object before saving it. If Domain Service saves it, then the *Save* operation is duplicated; - -* It causes performance lost because of double database round trip. -* It requires explicit database transaction that covers both operations. -* If additional actions cancel the entity creation because of a business rule, the transaction should be rolled back in the database. - -When you check the `IssueAppService`, you will see the advantage of **not saving** `Issue` to the database in the `IssueManager.CreateAsync`. Otherwise, we would need to perform one *Insert* (in the `IssueManager`) and one *Update* (after the Assignment). - -##### Discussion: Why is the duplicate Title check not implemented in the Application Service? - -We could simple say "Because it is a **core domain logic** and should be implemented in the Domain Layer". However, it brings a new question "**How did you decide** that it is a core domain logic, but not an application logic?" (we will discuss the difference later with more details). - -For this example, a simple question can help us to make the decision: "If we have another way (use case) of creating an issue, should we still apply the same rule? Is that rule should *always* be implemented". You may think "Why do we have a second way of creating an issue?". However, in real life, you have; - -* **End users** of the application may create issues in your application's standard UI. -* You may have a second **back office** application that is used by your own employees and you may want to provide a way of creating issues (probably with different authorization rules in this case). -* You may have an HTTP API that is open to **3rd-party clients** and they create issues. -* You may have a **background worker** service that do something and creates issues if it detects some problems. In this way, it will create an issue without any user interaction (and probably without any standard authorization check). -* You may have a button on the UI that **converts** something (for example, a discussion) to an issue. - -We can give more examples. All of these are should be implemented by **different Application Service methods** (see the *Multiple Application Layers* section below), but they **always** follow the rule: Title of the new issue can not be same of any existing issue! That's why this logic is a **core domain logic**, should be located in the Domain Layer and **should not be duplicated** in all these application service methods. - -### Updating / Manipulating An Entity - -Once an entity is created, it is updated/manipulated by the use cases until it is deleted from the system. There can be different types of the use cases directly or indirectly changes an entity. - -In this section, we will discuss a typical update operation that changes multiple properties of an `Issue`. - -This time, beginning from the *Update* DTO: - -````csharp -public class UpdateIssueDto -{ - [Required] - public string Title { get; set; } - public string Text { get; set; } - public Guid? AssignedUserId { get; set; } -} -```` - -By comparing to `IssueCreationDto`, you see no `RepositoryId`. Because, our system doesn't allow to move issues across repositories (think as GitHub repositories). Only `Title` is required and the other properties are optional. - -Let's see the *Update* implementation in the `IssueAppService`: - -````csharp -public class IssueAppService : ApplicationService, IIssueAppService -{ - private readonly IssueManager _issueManager; - private readonly IRepository _issueRepository; - private readonly IRepository _userRepository; - - public IssueAppService( - IssueManager issueManager, - IRepository issueRepository, - IRepository userRepository) - { - _issueManager = issueManager; - _issueRepository = issueRepository; - _userRepository = userRepository; - } - - public async Task UpdateAsync(Guid id, UpdateIssueDto input) - { - // Get entity from database - var issue = await _issueRepository.GetAsync(id); - - // Change Title - await _issueManager.ChangeTitleAsync(issue, input.Title); - - // Change Assigned User - if (input.AssignedUserId.HasValue) - { - var user = await _userRepository.GetAsync(input.AssignedUserId.Value); - await _issueManager.AssignToAsync(issue, user); - } - - // Change Text (no business rule, all values accepted) - issue.Text = input.Text; - - // Update entity in the database - await _issueRepository.UpdateAsync(issue); - - // Return a DTO represents the new Issue - return ObjectMapper.Map(issue); - } -} -```` - -* `UpdateAsync` method gets `id` as a separate parameter. It is not included in the `UpdateIssueDto`. This is a design decision that helps ABP to properly define HTTP routes when you [auto expose](API/Auto-API-Controllers.md) this service as an HTTP API endpoint. So, that's not related to DDD. -* It starts by **getting** the `Issue` entity **from the database**. -* Uses `IssueManager`'s `ChangeTitleAsync` instead of directly calling `Issue.SetTitle(...)`. Because we need to implement the **duplicate Title check** as just done in the *Entity Creation*. This requires some changes in the `Issue` and `IssueManager` classes (will be explained below). -* Uses `IssueManager`'s `AssignToAsync` method if the **assigned user** is being changed with this request. -* Directly sets the `Issue.Text` since there is **no business rule** for that. If we need later, we can always refactor. -* **Saves changes** to the database. Again, saving changed entities is a responsibility of the Application Service method that coordinates the business objects and the transaction. If the `IssueManager` had saved internally in `ChangeTitleAsync` and `AssignToAsync` method, there would be double database operation (see the *Discussion: Why is the Issue not saved to the database in `IssueManager`?* above). -* Finally uses the `IObjectMapper` to return an `IssueDto` that is automatically created by **mapping** from the updated `Issue` entity. - -As said, we need some changes in the `Issue` and `IssueManager` classes. - -First, made `SetTitle` internal in the `Issue` class: - -````csharp -internal void SetTitle(string title) -{ - Title = Check.NotNullOrWhiteSpace(title, nameof(title)); -} -```` - -Then added a new method to the `IssueManager` to change the Title: - -````csharp -public async Task ChangeTitleAsync(Issue issue, string title) -{ - if (issue.Title == title) - { - return; - } - - if (await _issueRepository.AnyAsync(i => i.Title == title)) - { - throw new BusinessException("IssueTracking:IssueWithSameTitleExists"); - } - - issue.SetTitle(title); -} -```` - -## Domain Logic & Application Logic - -As mentioned before, *Business Logic* in the Domain Driven Design is spitted into two parts (layers): *Domain Logic* and *Application Logic*: - -![domain-driven-design-domain-vs-application-logic](images/domain-driven-design-domain-vs-application-logic.png) - -Domain Logic consists of the *Core Domain Rules* of the system while Application Logic implements application specific *Use Cases*. - -While the definition is clear, the implementation may not be easy. You may be undecided which code should stand in the Application Layer, which code should be in the Domain Layer. This section tries to explain the differences. - -### Multiple Application Layers - -DDD helps to **deal with complexity** when your system is large. Especially, if there are **multiple applications** are being developed in a **single domain,** then the **Domain Logic vs Application Logic separation** becomes much more important. - -Assume that you are building a system that has multiple applications; - -* A **Public Web Site Application**, built with ASP.NET Core MVC, to show your products to users. Such a web site doesn't require authentication to see the products. The users login to the web site, only if they are performing some actions (like adding a product to the basket). -* A **Back Office Application**, built with Angular UI (that uses REST APIs). This application used by office workers of the company to manage the system (like editing product descriptions). -* A **Mobile Application** that has much simpler UI compared to the Public Web Site. It may communicate to the server via REST APIs or another technology (like TCP sockets). - -![domain-driven-design-multiple-applications](images/domain-driven-design-multiple-applications.png) - -Every application will have different **requirements**, different **use cases** (Application Service methods), different **DTOs**, different **validation** and **authorization** rules... etc. - -Mixing all these logics into a single application layer makes your services contain too many `if` conditions with **complicated business logic** makes your code **harder to develop, maintain and test** and leads to potential bugs. - -If you've multiple applications with a single domain; - -* Create **separate application layers** for each application/client type and implement application specific business logic in these separate layers. -* Use a **single domain layer** to share the core domain logic. - -Such a design makes it even more important to distinguish between Domain logic and Application Logic. - -To be more clear about the implementation, you can create different projects (`.csproj`) for each application types. For example; - -* `IssueTracker.Admin.Application` & `IssueTracker.Admin.Application.Contracts` projects for the Back Office (admin) Application. -* `IssueTracker.Public.Application` & `IssueTracker.Public.Application.Contracts` projects for the Public Web Application. -* `IssueTracker.Mobile.Application` & `IssueTracker.Mobile.Application.Contracts` projects for the Mobile Application. - -### Examples - -This section contains some Application Service and Domain Service examples to discuss how to decide to place business logic inside these services. - -**Example: Creating a new `Organization` in a Domain Service** - -````csharp -public class OrganizationManager : DomainService -{ - private readonly IRepository _organizationRepository; - private readonly ICurrentUser _currentUser; - private readonly IAuthorizationService _authorizationService; - private readonly IEmailSender _emailSender; - - public OrganizationManager( - IRepository organizationRepository, - ICurrentUser currentUser, - IAuthorizationService authorizationService, - IEmailSender emailSender) - { - _organizationRepository = organizationRepository; - _currentUser = currentUser; - _authorizationService = authorizationService; - _emailSender = emailSender; - } - - public async Task CreateAsync(string name) - { - if (await _organizationRepository.AnyAsync(x => x.Name == name)) - { - throw new BusinessException("IssueTracking:DuplicateOrganizationName"); - } - - await _authorizationService.CheckAsync("OrganizationCreationPermission"); - - Logger.LogDebug($"Creating organization {name} by {_currentUser.UserName}"); - - var organization = new Organization(); - - await _emailSender.SendAsync( - "systemadmin@issuetracking.com", - "New Organization", - "A new organization created with name: " + name - ); - - return organization; - } -} -```` - -Let's see the `CreateAsync` method step by step to discuss if the code part should be in the Domain Service, or not; - -* **CORRECT**: It first checks for **duplicate organization name** and and throws exception in this case. This is something related to core domain rule and we never allow duplicated names. -* **WRONG**: Domain Services should not perform **authorization**. [Authorization](Authorization.md) should be done in the Application Layer. -* **WRONG**: It logs a message with including the [Current User](CurrentUser.md)'s `UserName`. Domain service should not be depend on the Current User. Domain Services should be usable even if there is no user in the system. Current User (Session) should be a Presentation/Application Layer related concept. -* **WRONG**: It sends an [email](Emailing.md) about this new organization creation. We think this is also a use case specific business logic. You may want to create different type of emails in different use cases or don't need to send emails in some cases. - -**Example: Creating a new `Organization` in an Application Service** - -````csharp -public class OrganizationAppService : ApplicationService -{ - private readonly OrganizationManager _organizationManager; - private readonly IPaymentService _paymentService; - private readonly IEmailSender _emailSender; - - public OrganizationAppService( - OrganizationManager organizationManager, - IPaymentService paymentService, - IEmailSender emailSender) - { - _organizationManager = organizationManager; - _paymentService = paymentService; - _emailSender = emailSender; - } - - [UnitOfWork] - [Authorize("OrganizationCreationPermission")] - public async Task CreateAsync(CreateOrganizationDto input) - { - await _paymentService.ChargeAsync( - CurrentUser.Id, - GetOrganizationPrice() - ); - - var organization = await _organizationManager.CreateAsync(input.Name); - - await _organizationManager.InsertAsync(organization); - - await _emailSender.SendAsync( - "systemadmin@issuetracking.com", - "New Organization", - "A new organization created with name: " + input.Name - ); - - return organization; // !!! - } - - private double GetOrganizationPrice() - { - return 42; //Gets from somewhere else... - } -} -```` - -Let's see the `CreateAsync` method step by step to discuss if the code part should be in the Application Service, or not; - -* **CORRECT**: Application Service methods should be unit of work (transactional). ABP's [Unit Of Work](Unit-Of-Work.md) system makes this automatic (even without need to add `[UnitOfWork]` attribute for the Application Services). -* **CORRECT**: [Authorization](Authorization.md) should be done in the application layer. Here, it is done by using the `[Authorize]` attribute. -* **CORRECT**: Payment (an infrastructure service) is called to charge money for this operation (Creating an Organization is a paid service in our business). -* **CORRECT**: Application Service method is responsible to save changes to the database. -* **CORRECT**: We can send [email](Emailing.md) as a notification to the system admin. -* **WRONG**: Do not return entities from the Application Services. Return a DTO instead. - -**Discussion: Why don't we move the payment logic into the domain service?** - -You may wonder why the payment code is not inside the `OrganizationManager`. It is an **important thing** and we never want to **miss the payment**. - -However, **being important is not sufficient** to consider a code as a Core Business Logic. We may have **other use cases** where we don't charge money to create a new Organization. Examples; - -* An admin user can use a Back Office Application to create a new organization without any payment. -* A background-working data import/integration/synchronization system may also need to create organizations without any payment operation. - -As you see, **payment is not a necessary operation to create a valid organization**. It is a use-case specific application logic. - -**Example: CRUD Operations** - -````csharp -public class IssueAppService -{ - private readonly IssueManager _issueManager; - - public IssueAppService(IssueManager issueManager) - { - _issueManager = issueManager; - } - - public async Task GetAsync(Guid id) - { - return await _issueManager.GetAsync(id); - } - - public async Task CreateAsync(IssueCreationDto input) - { - await _issueManager.CreateAsync(input); - } - - public async Task UpdateAsync(UpdateIssueDto input) - { - await _issueManager.UpdateAsync(input); - } - - public async Task DeleteAsync(Guid id) - { - await _issueManager.DeleteAsync(id); - } -} -```` - -This Application Service **does nothing** itself and **delegates all the work** to the *Domain Service*. It even passes the DTOs to the `IssueManager`. - -* **Do not** create Domain Service methods just for simple **CRUD** operations **without any domain logic**. -* **Never** pass **DTOs** to or return **DTOs** from the Domain Services. - -Application Services can directly work with repositories to query, create, update or delete data unless there are some domain logics should be performed during these operations. In such cases, create Domain Service methods, but only for those really necessary. - -> Do not create such CRUD domain service methods just by thinking that they may be needed in the future ([YAGNI](https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it))! Do it when you need and refactor the existing code. Since the Application Layer gracefully abstracts the Domain Layer, the refactoring process doesn't effect the UI Layer and other clients. - -## Reference Books - -If you are more interested in the Domain Driven Design and building large-scale enterprise systems, the following books are recommended as reference books; - -* "*Domain Driven Design*" by Eric Evans -* "*Implementing Domain Driven Design*" by Vaughn Vernon -* "*Clean Architecture*" by Robert C. Martin +https://abp.io/books/implementing-domain-driven-design diff --git a/docs/en/Domain-Driven-Design.md b/docs/en/Domain-Driven-Design.md index f18c1882ef..03a6232ba3 100644 --- a/docs/en/Domain-Driven-Design.md +++ b/docs/en/Domain-Driven-Design.md @@ -32,6 +32,6 @@ DDD mostly interest in the **Domain** and the **Application** layers, rather tha * [Data Transfer Objects (DTOs)](Data-Transfer-Objects.md) * [Unit of Work](Unit-Of-Work.md) -## The Ultimate DDD Implementation Guide +## Free E-Book: Implementing DDD -See the [Implementing Domain Driven Design](Domain-Driven-Design-Implementation-Guide.md) guide as a **complete reference**. The Guide explains the Domain Driven Design and introduces explicit **rules and examples** to give a deep understanding of the **implementation details**. \ No newline at end of file +See the [Implementing Domain Driven Design book](https://abp.io/books/implementing-domain-driven-design) as a **complete reference**. This book explains the Domain Driven Design and introduces explicit **rules and examples** to give a deep understanding of the **implementation details**. \ No newline at end of file diff --git a/docs/en/Entity-Framework-Core.md b/docs/en/Entity-Framework-Core.md index fcbf5d8091..f60fcfc490 100644 --- a/docs/en/Entity-Framework-Core.md +++ b/docs/en/Entity-Framework-Core.md @@ -604,23 +604,77 @@ ObjectExtensionManager.Instance ); ```` -If the related module has implemented this feature (by using the `ConfigureEfCoreEntity` explained below), then the new property is added to the model. Then you need to run the standard `Add-Migration` and `Update-Database` commands to update your database to add the new field. +### MapEfCoreEntity ->`MapEfCoreProperty` method must be called before using the related `DbContext`. It is a static method. The best way is to use it in your application as earlier as possible. The application startup template has a `YourProjectNameEfCoreEntityExtensionMappings` class that is safe to use this method inside. +`MapEfCoreEntity` is a shortcut extension method to configure the `Entity`. -### ConfigureEfCoreEntity +**Example**: Set the max length of `Name` to the `IdentityRole` entity: -If you are building a reusable module and want to allow application developers to add properties to your entities, you can use the `ConfigureEfCoreEntity` extension method in your entity mapping. However, there is a shortcut extension method `ConfigureObjectExtensions` that can be used while configuring the entity mapping: +````csharp +ObjectExtensionManager.Instance + .MapEfCoreEntity(builder => + { + builder.As>().Property(x => x.Name).HasMaxLength(200); + }); +```` + +### MapEfCoreDbContext + +`MapEfCoreDbContext` is a shortcut extension method to configure the `DbContext`. + +**Example**: Set the max length of `Name` to the `IdentityRole` entity of `IdentityDbContext`: ````csharp -builder.Entity(b => +ObjectExtensionManager.Instance.MapEfCoreDbContext(b => { - b.ConfigureObjectExtensions(); - //... + b.Entity().Property(x => x.Name).HasMaxLength(200); }); ```` -> If you call `ConfigureByConvention()` extension method (like `b.ConfigureByConvention()` for this example), ABP Framework internally calls the `ConfigureObjectExtensions` method. It is a **best practice** to use the `ConfigureByConvention()` method since it also configures database mapping for base properties by convention. +If the related module has implemented this feature(explained below), then the new property is added to the model or the DbContext/Entity configure changed. Then you need to run the standard `Add-Migration` and `Update-Database` commands to update your database to add the new field. + +> The `MapEfCoreProperty`, `MapEfCoreEntity` and `MapEfCoreDbContext` methods must be called before using the related `DbContext`. It is a static method. The best way is to use it in your application as earlier as possible. The application startup template has a `YourProjectNameEfCoreEntityExtensionMappings` class that is safe to use this method inside. + +### ConfigureEfCoreEntity, ApplyObjectExtensionMappings and TryConfigureObjectExtensions + +If you are building a reusable module and want to allow application developers to add properties to your entities, you can use the `ConfigureEfCoreEntity`, `ApplyObjectExtensionMappings` and `TryConfigureObjectExtensions` extension methods in your entity mapping. + +**Example**: +````csharp +public static class QADbContextModelCreatingExtensions +{ + public static void ConfigureQA( + this ModelBuilder builder, + Action optionsAction = null) + { + Check.NotNull(builder, nameof(builder)); + + var options = new QAModelBuilderConfigurationOptions( + QADatabaseDbProperties.DbTablePrefix, + QADatabaseDbProperties.DbSchema + ); + + optionsAction?.Invoke(options); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "Questions", options.Schema); + b.ConfigureByConvention(); + //... + + //Call this in the end of buildAction. + b.ApplyObjectExtensionMappings(); + }); + + //... + + //Call this in the end of ConfigureQA. + builder.TryConfigureObjectExtensions(); + } +} +```` + +> If you call `ConfigureByConvention()` extension method (like `b.ConfigureByConvention()` for this example), ABP Framework internally calls the `ConfigureObjectExtensions` and `ConfigureEfCoreEntity` methods. It is a **best practice** to use the `ConfigureByConvention()` method since it also configures database mapping for base properties by convention. See the "*ConfigureByConvention Method*" section above for more information. @@ -812,4 +866,4 @@ public class MyCustomEfCoreBulkOperationProvider ## See Also * [Entities](Entities.md) -* [Repositories](Repositories.md) \ No newline at end of file +* [Repositories](Repositories.md) diff --git a/docs/en/Index.md b/docs/en/Index.md index de88e2f2f8..8483d61612 100644 --- a/docs/en/Index.md +++ b/docs/en/Index.md @@ -29,8 +29,9 @@ ABP has a **comprehensive documentation** that not only explains the ABP Framewo ABP offers a complete, modular and layered software architecture based on [Domain Driven Design](Domain-Driven-Design.md) principles and patterns. It also provides the necessary infrastructure to implement this architecture. * See the [Modularity](Module-Development-Basics.md) document to understand the module system. -* [Implementing Domain Driven Design](Domain-Driven-Design-Implementation-Guide.md) document is an ultimate guide for who want to understand and implement the DDD. +* [Implementing Domain Driven Design book](https://abp.io/books/implementing-domain-driven-design?ref=doc) is an ultimate guide for who want to understand and implement the DDD with the ABP Framework. * [Microservice Architecture](Microservice-Architecture.md) document explains how ABP helps to create a microservice solution. +* [Multi-Tenancy](Multi-Tenancy.md) document introduces multi-tenancy and explores the ABP multi-tenancy infrastructure. ### Infrastructure @@ -55,6 +56,14 @@ See the [Application Modules](Modules/Index.md) document for all pre-built modul The [Startup templates](Startup-Templates/Index.md) are pre-built Visual Studio solution templates. You can create your own solution based on these templates to **immediately start your development**. +## Free E-Book: Implementing Domain Driven Design + +![Implementing Domain Driven Design](images/implementing-domain-driven-design-book.png) + +A **practical guide** for implementing Domain Driven Design (DDD). While the implementation details are **based on the ABP Framework** infrastructure, the basic concepts, principles and models can be applied to any solution, even if it is not a .NET solution. + +[Click here to get your free copy](https://abp.io/books/implementing-domain-driven-design?ref=doc). + ## ABP Community ### The Source Code diff --git a/docs/en/Modules/Setting-Management.md b/docs/en/Modules/Setting-Management.md index dff8da3f8e..255efc9a5f 100644 --- a/docs/en/Modules/Setting-Management.md +++ b/docs/en/Modules/Setting-Management.md @@ -83,4 +83,192 @@ Setting Management module is extensible, just like the [setting system](../Setti * `TenantSettingManagementProvider`: Gets or sets the setting value for a tenant. * `UserSettingManagementProvider`: Gets the setting value for a user. -`ISettingManager` uses the setting management providers on get/set methods. Typically, every setting management provider defines extension methods on the `ISettingManagement` service (like `SetForUserAsync` defined by the user setting management provider). \ No newline at end of file +`ISettingManager` uses the setting management providers on get/set methods. Typically, every setting management provider defines extension methods on the `ISettingManagement` service (like `SetForUserAsync` defined by the user setting management provider). + +## Setting Management UI + +Setting Mangement module provided the email setting UI by default, and it is extensible; You can add your tabs to this page for your application settings. + +### MVC UI + +#### Create a setting View Component + +Create `MySettingGroup` folder under the `Components` folder. Add a new view component. Name it as `MySettingGroupViewComponent`: + +![MySettingGroupViewComponent](../images/my-setting-group-view-component.png) + +Open the `MySettingGroupViewComponent.cs` and change the whole content as shown below: + +```csharp +public class MySettingGroupViewComponent : AbpViewComponent +{ + public virtual IViewComponentResult Invoke() + { + return View("~/Components/MySettingGroup/Default.cshtml"); + } +} +``` + +> You can also use the `InvokeAsync` method, In this example, we use the `Invoke` method. + +#### Default.cshtml + +Create a `Default.cshtml` file under the `MySettingGroup` folder. + +Open the `Default.cshtml` and change the whole content as shown below: + +```html +
+

My setting group page

+
+``` + +#### BookStoreSettingPageContributor + +Create a `BookStoreSettingPageContributor.cs` file under the `Settings` folder: + +![BookStoreSettingPageContributor](../images/my-setting-group-page-contributor.png) + +The content of the file is shown below: + +```csharp +public class BookStoreSettingPageContributor : ISettingPageContributor +{ + public Task ConfigureAsync(SettingPageCreationContext context) + { + context.Groups.Add( + new SettingPageGroup( + "Volo.Abp.MySettingGroup", + "MySettingGroup", + typeof(MySettingGroupViewComponent) + ) + ); + + return Task.CompletedTask; + } + + public Task CheckPermissionsAsync(SettingPageCreationContext context) + { + // You can check the permissions here + return Task.FromResult(true); + } +} +``` + +Open the `BookStoreWebModule.cs` file and add the following code: + +```csharp +Configure(options => +{ + options.Contributors.Add(new BookStoreSettingPageContributor()); +}); +``` + +#### Run the Application + +Navigate to `/SettingManagement` route to see the changes: + +![Custom Settings Tab](../images/my-setting-group-ui.png) + +### Blazor UI + +#### Create a Razor Component + +Create `MySettingGroup` folder under the `Pages` folder. Add a new razor component. Name it as `MySettingGroupComponent`: + +![MySettingGroupComponent](../images/my-setting-group-component.png) + +Open the `MySettingGroupComponent.razor` and change the whole content as shown below: + +```csharp + +

my setting group

+
+``` + +#### BookStoreSettingComponentContributor + +Create a `BookStoreSettingComponentContributor.cs` file under the `Settings` folder: + +![BookStoreSettingComponentContributor](../images/my-setting-group-component-contributor.png) + +The content of the file is shown below: + +```csharp +public class BookStoreSettingComponentContributor : ISettingComponentContributor +{ + public Task ConfigureAsync(SettingComponentCreationContext context) + { + context.Groups.Add( + new SettingComponentGroup( + "Volo.Abp.MySettingGroup", + "MySettingGroup", + typeof(MySettingGroupComponent) + ) + ); + + return Task.CompletedTask; + } + + public Task CheckPermissionsAsync(SettingComponentCreationContext context) + { + // You can check the permissions here + return Task.FromResult(true); + } +} +``` + +Open the `BookStoreBlazorModule.cs` file and add the following code: + +```csharp +Configure(options => +{ + options.Contributors.Add(new BookStoreSettingComponentContributor()); +}); +``` + +#### Run the Application + +Navigate to `/setting-management` route to see the changes: + +![Custom Settings Tab](../images/my-setting-group-blazor.png) + +### Angular UI + +#### Create a Component + +Create a component with the following command: + +```bash +yarn ng generate component my-settings +``` + +Open the `app.component.ts` and modify the file as shown below: + +```js +import { Component } from '@angular/core'; +import { SettingTabsService } from '@abp/ng.core'; // imported SettingTabsService +import { MySettingsComponent } from './my-settings/my-settings.component'; // imported MySettingsComponent + +@Component(/* component metadata */) +export class AppComponent { + constructor(private settingTabs: SettingTabsService) // injected MySettingsComponent + { + // added below + settingTabs.add([ + { + name: 'MySettings', + order: 1, + requiredPolicy: 'policy key here', + component: MySettingsComponent, + }, + ]); + } +} +``` + +#### Run the Application + +Navigate to `/setting-management` route to see the changes: + +![Custom Settings Tab](../images/custom-settings.png) \ No newline at end of file diff --git a/docs/en/Modules/Tenant-Management.md b/docs/en/Modules/Tenant-Management.md index 73e16aee8e..dca6ea3d1e 100644 --- a/docs/en/Modules/Tenant-Management.md +++ b/docs/en/Modules/Tenant-Management.md @@ -1,3 +1,107 @@ # Tenant Management Module -TODO \ No newline at end of file +[Multi-Tenancy](../Multi-Tenancy.md) is one of the core features of ABP Framework. It provides the fundamental infrastructure to build your own SaaS (Software-as-a-Service) solution. ABP's multi-tenancy system abstracts where your tenants are stored, by providing the `ITenantStore` interface. All you need to do is to implement that interface. + +**The Tenant Management module is an implementation of the the `ITenantStore` interface. It stores tenants in a database. It also provides UI to manage your tenants and their [features](../Features.md).** + +> Please **refer to the [Multi-Tenancy](../Multi-Tenancy.md) documentation** to understand the multi-tenancy system of the ABP Framework. This document focuses on the Tenant Management module. + +### About the ABP Commercial SaaS Module + +The [SaaS Module](https://commercial.abp.io/modules/Volo.Saas) is an alternative implementation of this module with more features and possibilities. It is distributed as a part of the [ABP Commercial](https://commercial.abp.io/) subscription. + +## How to Install + +This module comes as pre-installed (as [NuGet/NPM packages](NuGet/NPM packages)) when you [create a new solution](https://abp.io/get-started) with the ABP Framework. You can continue to use it as package and get updates easily, or you can include its source code into your solution (see `get-source` [CLI](../CLI.md) command) to develop your custom module. + +### The Source Code + +The source code of this module can be accessed [here](https://github.com/abpframework/abp/tree/dev/modules/tenant-management). The source code is licensed with [MIT](https://choosealicense.com/licenses/mit/), so you can freely use and customize it. + +## User Interface + +This module adds "*Administration -> Tenant Management -> Tenants*" menu item to the main menu of the application, which opens the page shown below: + +![module-tenant-management-page](../images/module-tenant-management-page.png) + +In this page, you see the all the tenants. You can create a new tenant as shown below: + +![module-tenant-management-new-tenant](../images/module-tenant-management-new-tenant.png) + +In this modal; + +* **Name**: The unique name of the tenant. If you use subdomains for your tenants (like https://some-tenant.your-domain.com), this will be the subdomain name. +* **Admin Email Address**: Email address of the admin user for this tenant. +* **Admin Password**: The password of the admin user for this tenant. + +When you click to *Actions* button near to a tenant, you will see the actions you can take: + +![module-tenant-management-actions](../images/module-tenant-management-actions.png) + +### Managing the Tenant Features + +The Features action opens a modal to enable/disable/set [features](../Features.md) for the related tenant. Here, an example modal: + +![features-modal](../images/features-modal.png) + +### Managing the Host Features + +*Manage Host features* button is used to set features for the host side, if you use the features of your application also in the host side. + +## Internals + +This section can be used as a reference if you want to [customize](../Customizing-Application-Modules-Guide.md) this module without changing [its source code](https://github.com/abpframework/abp/tree/dev/modules/tenant-management). + +### Domain Layer + +#### Aggregates + +* `Tenant` + +#### Repositories + +* `ITenantRepository` + +#### Domain Services + +* `TenantManager` + +### Application Layer + +#### Application Services + +* `TenantAppService` + +#### Permissions + +- `AbpTenantManagement.Tenants`: Tenant management. +- `AbpTenantManagement.Tenants.Create`: Creating a new tenant. +- `AbpTenantManagement.Tenants.Update`: Editing an existing tenant. +- `AbpTenantManagement.Tenants.Delete`: Deleting an existing tenant. +- `AbpTenantManagement.Tenants.ManageFeatures`: Manage features of the tenants. + +### Entity Framework Core Integration + +* `TenantManagementDbContext` (implements `ITenantManagementDbContext`) + +**Database Tables:** + +* `AbpTenants` +* `AbpTenantConnectionStrings` + +### MongoDB Integration + +* `TenantManagementMongoDbContext` (implements `ITenantManagementMongoDbContext`) + +**Database Collections:** + +* `AbpTenants` (also includes the connection string) + +## Notices + +ABP Framework allows to use *database per tenant* approach that allows a tenant can have a dedicated database. This module has the fundamental infrastructure to make that implementation possible (see its source code), however it doesn't implement the application layer and UI functionalities to provide it as an out of the box implementation. You can implement these features yourself, or consider to use the [ABP Commercial Saas Module](https://docs.abp.io/en/commercial/latest/modules/saas) that fully implements it and provides much more business features. + +## See Also + +* [Multi-Tenancy](../Multi-Tenancy.md) +* [ABP Commercial SaaS Module](https://docs.abp.io/en/commercial/latest/modules/saas) \ No newline at end of file diff --git a/docs/en/Road-Map.md b/docs/en/Road-Map.md index f57e35c863..26de749096 100644 --- a/docs/en/Road-Map.md +++ b/docs/en/Road-Map.md @@ -8,11 +8,9 @@ This document provides a road map, release schedule and planned features for the This version will focus on **documentation** and **improvements** of current features. In addition, the following features are planned: -* Publishing distributed events as transactional ([#6126](https://github.com/abpframework/abp/issues/6126)) * Revisit the microservice demo solution ([#8385](https://github.com/abpframework/abp/issues/8385)) * A new UI Theme alternative to the Basic Theme ([#6132](https://github.com/abpframework/abp/issues/6132)) * Improvements and new features to the [CMS Kit](Modules/Cms-Kit.md) module ([#8380](https://github.com/abpframework/abp/issues/8380) [#8381](https://github.com/abpframework/abp/issues/8381)) -* Pre-configured test project for the [Blazor UI](UI/Blazor/Overall.md) ([#5516](https://github.com/abpframework/abp/issues/5516)) * Razor engine support for text templating ([#8373](https://github.com/abpframework/abp/issues/8373)) **Planned release date**: End of Quarter 2, 2021. See the [4.4 milestone](https://github.com/abpframework/abp/milestone/52) to track the progress. @@ -25,6 +23,7 @@ We planned to focus on the ABP Framework v5.0 after the 4.4 release. This versio * Upgrading to Bootstrap 5.x ([#8922](https://github.com/abpframework/abp/issues/8922)) * Alternative to IdentityServer4 ([#7221](https://github.com/abpframework/abp/issues/7221)) * Dapr integration ([#2183](https://github.com/abpframework/abp/issues/2183)) +* Publishing distributed events as transactional ([#6126](https://github.com/abpframework/abp/issues/6126)) * Resource based authorization system ([#236](https://github.com/abpframework/abp/issues/236)) * API Versioning system: finalize & document ([#497](https://github.com/abpframework/abp/issues/497)) * Performance optimizations; Enabling .NET Trimming, using source generators and reducing reflection, etc. diff --git a/docs/en/Tutorials/Todo/Index.md b/docs/en/Tutorials/Todo/Index.md index e71749544e..64cbca13f3 100644 --- a/docs/en/Tutorials/Todo/Index.md +++ b/docs/en/Tutorials/Todo/Index.md @@ -135,7 +135,7 @@ namespace TodoApp } ```` -`BasicAggregateRoot` is one the simplest base class to create root entities, and `Guid` is the primary key (`Id`) of the entity here. +`BasicAggregateRoot` is the simplest base class to create root entities, and `Guid` is the primary key (`Id`) of the entity here. ## Database Integration @@ -214,7 +214,7 @@ Now, we can use ABP repositories to save and retrieve todo items, as we'll do in ## Application Layer -An [Application Service](../../Application-Services.md) is used to perform use cases of the application. We need to perform the following use cases; +An [Application Service](../../Application-Services.md) is used to perform use cases of the application. We need to perform the following use cases: * Get the list of todo items * Create a new todo item @@ -243,7 +243,7 @@ namespace TodoApp ### Data Transfer Object -`GetListAsync` and `CreateAsync` methods return `TodoItemDto`. Applications Services typically gets and returns DTOs ([Data Transfer Objects](../../Data-Transfer-Objects.md)) instead of entities. So, we should define the DTO class here. Create a new `TodoItemDto` class inside the *TodoApp.Application.Contracts* project: +`GetListAsync` and `CreateAsync` methods return `TodoItemDto`. `ApplicationService` typically gets and returns DTOs ([Data Transfer Objects](../../Data-Transfer-Objects.md)) instead of entities. So, we should define the DTO class here. Create a new `TodoItemDto` class inside the *TodoApp.Application.Contracts* project: ````csharp using System; @@ -465,9 +465,9 @@ $(function () { }); ```` -In the first part, we are registering to click events of the trash icons near to the todo items, deleting the related item on the server and showing a notification on the UI. Also, we are removing the deleted item from DOM, so we don't need to refresh the page. +In the first part, we are subscribing to click events of the trash icons near to the todo items, deleting the related item on the server and showing a notification on the UI. Also, we are removing the deleted item from DOM, so we don't need to refresh the page. -In the second part, we are creating a new todo item on the server. If it succeed, we are then manipulating DOM to insert a new `
  • ` element to the todo list. In this way, no need to refresh the whole page after creating a new todo item. +In the second part, we are creating a new todo item on the server. If it succeeds, we are then manipulating DOM to insert a new `
  • ` element to the todo list. This way we don't need to refresh the whole page after creating a new todo item. The interesting part here is how we communicate with the server. See the *Dynamic JavaScript Proxies & Auto API Controllers* section to understand how it works. But now, let's continue and complete the application. @@ -504,13 +504,13 @@ As the final touch, open the `Index.css` file in the `Pages` folder of the *Todo This is a simple styling for the todo page. We believe that you can do much better :) -Now, you can run the application again to see the result. +Now, you can run the application again and see the result. ### Dynamic JavaScript Proxies & Auto API Controllers In the `Index.js` file, we've used `todoApp.todo.delete(...)` and `todoApp.todo.create(...)` functions to communicate with the server. These functions are dynamically created by the ABP Framework, thanks to the [Dynamic JavaScript Client Proxy](../../UI/AspNetCore/Dynamic-JavaScript-Proxies.md) system. They perform HTTP API calls to the server and return a promise, so you can register a callback to the `then` function as we've done above. -However, you may ask that we haven't created any API Controller, so how server handles these requests? This question brings us the [Auto API Controller](../../API/Auto-API-Controllers.md) feature of the ABP Framework. It automatically converts the application services to API Controllers by conventions. +However, you may notice that we haven't created any API Controller, so how server handles these requests? This question brings us the [Auto API Controller](../../API/Auto-API-Controllers.md) feature of the ABP Framework. It automatically converts the application services to API Controllers by convention. If you open the [Swagger UI](https://swagger.io/tools/swagger-ui/) by entering the `/swagger` URL in your application, you can see the Todo API: @@ -559,7 +559,7 @@ namespace TodoApp.Blazor.Pages } ```` -This class uses the `ITodoAppService` to perform operations for the todo items. It manipulates the `TodoItems` list after create and delete operations. In this way, we don't need to refresh the whole todo list from the server. +This class uses the `ITodoAppService` to perform operations for the todo items. It manipulates the `TodoItems` list after create and delete operations. This way, we don't need to refresh the whole todo list from the server. {{if UI=="Blazor"}} @@ -653,7 +653,7 @@ In the `Index.razor.cs` file, we've injected (with the `[Inject]` attribute) and The magic is done by the ABP Framework's [Dynamic C# Client Proxy](../../API/Dynamic-CSharp-API-Clients.md) system. It uses the standard `HttpClient` and performs HTTP API requests to the remote server. It also handles all the standard tasks for us, including authorization, JSON serialization and exception handling. -However, you may ask that we haven't created any API Controller, so how server handles these requests? This question brings us the [Auto API Controller](../../API/Auto-API-Controllers.md) feature of the ABP Framework. It automatically converts the application services to API Controllers by conventions. +However, you may ask that we haven't created any API Controller, so how server handles these requests? This question brings us the [Auto API Controller](../../API/Auto-API-Controllers.md) feature of the ABP Framework. It automatically converts the application services to API Controllers by convention. If you run the `TodoApp.HttpApi.Host` application, you can see the Todo API: @@ -669,7 +669,7 @@ ABP provides a handy feature to automatically create client-side services to eas You first need to run the `TodoApp.HttpApi.Host` project since the proxy generator reads API definitions from the server application. -> **Warning**: There is a problem with IIS Express; it doesn't allow to connect to the application from another process. If you are using Visual Studio, select the `TodoApp.HttpApi.Host` instead of IIS Express in the run button drop-down list, as shown in the figure below: +> **Warning**: There is an issue with IIS Express: it doesn't allow to connect to the application from another process. If you are using Visual Studio, select the `TodoApp.HttpApi.Host` instead of IIS Express in the run button drop-down list, as shown in the figure below: ![run-without-iisexpress](run-without-iisexpress.png) @@ -813,7 +813,7 @@ Now, you can run the application again to see the result. ## Conclusion -In this tutorial, we've build a very simple application to warm up to the ABP Framework. If you are looking to build a serious application, please check the [web application development tutorial](../Part-1.md) which covers all the aspects of a real-life web application development. +In this tutorial, we've built a very simple application to warm up to the ABP Framework. If you are looking to build a serious application, please check the [web application development tutorial](../Part-1.md) which covers all the aspects of a real-life web application development. ## Source Code @@ -821,4 +821,4 @@ You can find source code of the completed application [here](https://github.com/ ## See Also -* [Web Application Development Tutorial](../Part-1.md) \ No newline at end of file +* [Web Application Development Tutorial](../Part-1.md) diff --git a/docs/en/UI/Angular/Account-Module.md b/docs/en/UI/Angular/Account-Module.md index 9496eb95c5..1b6a15d149 100644 --- a/docs/en/UI/Angular/Account-Module.md +++ b/docs/en/UI/Angular/Account-Module.md @@ -120,6 +120,4 @@ export const environment = { } as Config.Environment; ``` -> Note: The resource owner password flow does not support the two-factor authentication for some technical reasons. - See the [Authorization in Angular UI](./Authorization.md) document for more details. diff --git a/docs/en/UI/Angular/Authorization.md b/docs/en/UI/Angular/Authorization.md index 54850e4569..1bde885180 100644 --- a/docs/en/UI/Angular/Authorization.md +++ b/docs/en/UI/Angular/Authorization.md @@ -52,5 +52,3 @@ export const environment = { ``` According to this flow, the user is redirected to the login page in the account module. - -> Note: The resource owner password flow does not support the two-factor authentication for some technical reasons. \ No newline at end of file diff --git a/docs/en/UI/Angular/Custom-Setting-Page.md b/docs/en/UI/Angular/Custom-Setting-Page.md deleted file mode 100644 index 9a17f6ad7b..0000000000 --- a/docs/en/UI/Angular/Custom-Setting-Page.md +++ /dev/null @@ -1,37 +0,0 @@ -# Custom Setting Page - -There are several settings tabs from different modules. You can add a custom setting page to your project. - -1. Create a component with the following command: - -```bash -yarn ng generate component my-settings -``` - -2. Open the `app.component.ts` and modify the file as shown below: - -```js -import { Component } from '@angular/core'; -import { SettingTabsService } from '@abp/ng.core'; // imported SettingTabsService -import { MySettingsComponent } from './my-settings/my-settings.component'; // imported MySettingsComponent - -@Component(/* component metadata */) -export class AppComponent { - constructor(private settingTabs: SettingTabsService) // injected MySettingsComponent - { - // added below - settingTabs.add([ - { - name: 'MySettings', - order: 1, - requiredPolicy: 'policy key here', - component: MySettingsComponent, - }, - ]); - } -} -``` - -Navigate to `/setting-management` route to see the changes: - -![Custom Settings Tab](./images/custom-settings.png) diff --git a/docs/en/UI/Blazor/Overall.md b/docs/en/UI/Blazor/Overall.md index a249dd354b..112dfec8cc 100644 --- a/docs/en/UI/Blazor/Overall.md +++ b/docs/en/UI/Blazor/Overall.md @@ -93,6 +93,8 @@ These libraries are selected as the base libraries and available to the applicat > Bootstrap's JavaScript part is not used since the Blazorise library already provides the necessary functionalities to the Bootstrap components in a native way. +> Beginning from June, 2021, the Blazorise library has dual licenses; open source & commercial. Based on your yearly revenue, you may need to buy a commercial license. See [this post](https://blazorise.com/news/blazorise-commercial-going-live/) for the announcement. + ### The Layout The themes provide the layout. So, you have a responsive layout with the standard features already implemented. The screenshot below has taken from the layout of the [Basic Theme](Basic-Theme.md): diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 8abfddd251..6615cbce1b 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -543,8 +543,8 @@ ] }, { - "text": "Guide: Implementing DDD", - "path": "Domain-Driven-Design-Implementation-Guide.md" + "text": "E-Book: Implementing DDD", + "path": "https://abp.io/books/implementing-domain-driven-design" } ] }, @@ -1027,10 +1027,6 @@ "text": "Component Replacement", "path": "UI/Angular/Component-Replacement.md" }, - { - "text": "Custom Setting Page", - "path": "UI/Angular/Custom-Setting-Page.md" - }, { "text": "Extensions", "items": [ diff --git a/docs/en/UI/Angular/images/custom-settings.png b/docs/en/images/custom-settings.png similarity index 100% rename from docs/en/UI/Angular/images/custom-settings.png rename to docs/en/images/custom-settings.png diff --git a/docs/en/images/implementing-domain-driven-design-book.png b/docs/en/images/implementing-domain-driven-design-book.png new file mode 100644 index 0000000000..6568b46f66 Binary files /dev/null and b/docs/en/images/implementing-domain-driven-design-book.png differ diff --git a/docs/en/images/module-tenant-management-actions.png b/docs/en/images/module-tenant-management-actions.png new file mode 100644 index 0000000000..d1f01c2e93 Binary files /dev/null and b/docs/en/images/module-tenant-management-actions.png differ diff --git a/docs/en/images/module-tenant-management-new-tenant.png b/docs/en/images/module-tenant-management-new-tenant.png new file mode 100644 index 0000000000..ab9ee6ed56 Binary files /dev/null and b/docs/en/images/module-tenant-management-new-tenant.png differ diff --git a/docs/en/images/module-tenant-management-page.png b/docs/en/images/module-tenant-management-page.png new file mode 100644 index 0000000000..563c64aac8 Binary files /dev/null and b/docs/en/images/module-tenant-management-page.png differ diff --git a/docs/en/images/my-setting-group-blazor.png b/docs/en/images/my-setting-group-blazor.png new file mode 100644 index 0000000000..0e685ff186 Binary files /dev/null and b/docs/en/images/my-setting-group-blazor.png differ diff --git a/docs/en/images/my-setting-group-component-contributor.png b/docs/en/images/my-setting-group-component-contributor.png new file mode 100644 index 0000000000..3ca6dbedfb Binary files /dev/null and b/docs/en/images/my-setting-group-component-contributor.png differ diff --git a/docs/en/images/my-setting-group-component.png b/docs/en/images/my-setting-group-component.png new file mode 100644 index 0000000000..edcf315b2a Binary files /dev/null and b/docs/en/images/my-setting-group-component.png differ diff --git a/docs/en/images/my-setting-group-page-contributor.png b/docs/en/images/my-setting-group-page-contributor.png new file mode 100644 index 0000000000..3be3737e6f Binary files /dev/null and b/docs/en/images/my-setting-group-page-contributor.png differ diff --git a/docs/en/images/my-setting-group-ui.png b/docs/en/images/my-setting-group-ui.png new file mode 100644 index 0000000000..b9d3f1b403 Binary files /dev/null and b/docs/en/images/my-setting-group-ui.png differ diff --git a/docs/en/images/my-setting-group-view-component.png b/docs/en/images/my-setting-group-view-component.png new file mode 100644 index 0000000000..02843f968e Binary files /dev/null and b/docs/en/images/my-setting-group-view-component.png differ diff --git a/docs/zh-Hans/CLI.md b/docs/zh-Hans/CLI.md index 262f546bf2..4325ee1f07 100644 --- a/docs/zh-Hans/CLI.md +++ b/docs/zh-Hans/CLI.md @@ -39,6 +39,7 @@ dotnet tool update -g Volo.Abp.Cli * **`translate`**: 当源代码控制存储库中有多个JSON[本地化](Localization.md文件时,可简化翻译本地化文件的过程. * **`login`**: 使用你在[abp.io](https://abp.io/)的用户名和密码在你的计算机上认证. * **`logout`**: 在你的计算机注销认证. +* **`install-libs`**: 为 MVC / Razor Pages 和 Blazor Server UI 类型安装NPM包. ### help @@ -339,3 +340,19 @@ abp login -p -o # You can enter both your ``` abp logout ``` + +### install-libs + +为 MVC / Razor Pages 和 Blazor Server UI 类型安装NPM包, 它的 **执行目录** 或者传递的 ```--working-directory``` 目录必须包含一个项目文件(*.csproj). + +`install-libs` 命令读取 `abp.resourcemapping.js` 来管理包. 参阅[客户端包管理](UI/AspNetCore/Client-Side-Package-Management.md)了解更多细节. + +用法: + +````bash +abp install-libs [options] +```` + +#### Options + +* ```--working-directory``` 或 ```-wd```: 指定工作目录, 当执行目录不包含项目文件时会很有用. \ No newline at end of file diff --git a/docs/zh-Hans/Modules/Setting-Management.md b/docs/zh-Hans/Modules/Setting-Management.md index fd87dd734c..acb4469fea 100644 --- a/docs/zh-Hans/Modules/Setting-Management.md +++ b/docs/zh-Hans/Modules/Setting-Management.md @@ -83,4 +83,194 @@ namespace Demo * `TenantSettingManagementProvider`: 获取或设定租户的设置值. * `UserSettingManagementProvider`: 获取或设定用户的设置值. -`ISettingManager` 在 `get/set` 方法中使用设置管理提供程序. 通常每个设置程序提供程序都在 `ISettingManagement` 服务上定义了模块方法 (比如用户设置管理程序提供定义了 `SetForUserAsync` 方法). \ No newline at end of file +`ISettingManager` 在 `get/set` 方法中使用设置管理提供程序. 通常每个设置程序提供程序都在 `ISettingManagement` 服务上定义了模块方法 (比如用户设置管理程序提供定义了 `SetForUserAsync` 方法). + +## Setting Management UI. + +设置管理模块默认提供了邮件设置页面并且它是可扩展的; 你可以为你的应用程序设置添加设置标签到设置页面. + +### MVC UI + +#### 创建视图组件 + +在 `Components` 目录下创建 `MySettingGroup` 文件夹, 添加一个名为 `MySettingGroupViewComponent` 的视图组件: + +![MySettingGroupViewComponent](../images/my-setting-group-view-component.png) + +打开 `MySettingGroupViewComponent.cs` 替换为以下内容: + +```csharp +public class MySettingGroupViewComponent : AbpViewComponent +{ + public virtual IViewComponentResult Invoke() + { + return View("~/Components/MySettingGroup/Default.cshtml"); + } +} +``` + +> 你还可以使用 `InvokeAsync` 方法,在这个示例中我们使用 `Invoke` 方法. + +#### Default.cshtml + +在 `MySettingGroup` 目录下创建 `Default.cshtml` 文件. + +打开 `Default.cshtml` 替换为以下内容: + +```html +
    +

    My setting group page

    +
    +``` + +#### BookStoreSettingPageContributor + +在 `Settings` 目录下创建 `BookStoreSettingPageContributor.cs` 文件. + +![BookStoreSettingPageContributor](../images/my-setting-group-page-contributor.png) + +文件内容如下: + +```csharp +public class BookStoreSettingPageContributor : ISettingPageContributor +{ + public Task ConfigureAsync(SettingPageCreationContext context) + { + context.Groups.Add( + new SettingPageGroup( + "Volo.Abp.MySettingGroup", + "MySettingGroup", + typeof(MySettingGroupViewComponent) + ) + ); + + return Task.CompletedTask; + } + + public Task CheckPermissionsAsync(SettingPageCreationContext context) + { + // You can check the permissions here + return Task.FromResult(true); + } +} +``` + +打开 `BookStoreWebModule.cs` 文件添加以下代码: + +```csharp +Configure(options => +{ + options.Contributors.Add(new BookStoreSettingPageContributor()); +}); +``` + +#### 运行应用程序 + +导航到 `/SettingManagement` 路由查看更改: + +![Custom Settings Tab](../images/my-setting-group-ui.png) + +### Blazor UI + +#### 创建 Razor 组件 + +在 `Pages` 目录下创建 `MySettingGroup` 文件夹, 添加一个名为 `MySettingGroupComponent` 的Razor组件: + +![MySettingGroupComponent](../images/my-setting-group-component.png) + +打开 `MySettingGroupComponent.razor` 替换为以下内容: + +```csharp + +

    my setting group

    +
    +``` + +#### BookStoreSettingComponentContributor + +在 `Settings` 目录下创建 `BookStoreSettingComponentContributor.cs` 文件. + +![BookStoreSettingComponentContributor](../images/my-setting-group-component-contributor.png) + +文件内容如下: + +```csharp +public class BookStoreSettingComponentContributor : ISettingComponentContributor +{ + public Task ConfigureAsync(SettingComponentCreationContext context) + { + context.Groups.Add( + new SettingComponentGroup( + "Volo.Abp.MySettingGroup", + "MySettingGroup", + typeof(MySettingGroupComponent) + ) + ); + + return Task.CompletedTask; + } + + public Task CheckPermissionsAsync(SettingComponentCreationContext context) + { + // You can check the permissions here + return Task.FromResult(true); + } +} +``` + +打开 `BookStoreBlazorModule.cs` 文件添加以下代码: + +```csharp +Configure(options => +{ + options.Contributors.Add(new BookStoreSettingComponentContributor()); +}); +``` + +#### 运行应用程序 + +导航到 `/setting-management` 路由查看更改: + +![Custom Settings Tab](../images/my-setting-group-blazor.png) + +### Angular UI + +不同的模块提供它们的设置选项卡. 你可以通过3个步骤在项目中自定义设置页面. + +#### 创建组件 + +使用以下命令创建一个组件 + +```bash +yarn ng generate component my-settings +``` + +打开 `app.component.ts` 做以下修改: + +```js +import { Component } from '@angular/core'; +import { SettingTabsService } from '@abp/ng.core'; // imported SettingTabsService +import { MySettingsComponent } from './my-settings/my-settings.component'; // imported MySettingsComponent + +@Component(/* component metadata */) +export class AppComponent { + constructor(private settingTabs: SettingTabsService) // injected MySettingsComponent + { + // added below + settingTabs.add([ + { + name: 'MySettings', + order: 1, + requiredPolicy: 'policy key here', + component: MySettingsComponent, + }, + ]); + } +} +``` + +#### 运行应用程序 + +导航到 `/setting-management` 路由你会看到以下变化: + +![Custom Settings Tab](../images/custom-settings.png) \ No newline at end of file diff --git a/docs/zh-Hans/UI/Angular/Custom-Setting-Page.md b/docs/zh-Hans/UI/Angular/Custom-Setting-Page.md deleted file mode 100644 index 2b888e8d75..0000000000 --- a/docs/zh-Hans/UI/Angular/Custom-Setting-Page.md +++ /dev/null @@ -1,41 +0,0 @@ -# 自定义设置页面 - -不同的模块提供它们的设置选项卡. 你可以通过3个步骤在项目中自定义设置页面. - -1. 使用以下命令创建一个组件 - -```bash -yarn ng generate component my-settings -``` - -2. 打开 `app.component.ts` 做以下修改: - -```js -import { Component } from '@angular/core'; -import { SettingTabsService } from '@abp/ng.core'; // imported SettingTabsService -import { MySettingsComponent } from './my-settings/my-settings.component'; // imported MySettingsComponent - -@Component(/* component metadata */) -export class AppComponent { - constructor(private settingTabs: SettingTabsService) // injected MySettingsComponent - { - // added below - settingTabs.add([ - { - name: 'MySettings', - order: 1, - requiredPolicy: 'policy key here', - component: MySettingsComponent, - }, - ]); - } -} -``` - -导航到 `/setting-management` 路由你会看到以下变化: - -![Custom Settings Tab](./images/custom-settings.png) - -## 下一步是什么? - -- [懒加载 Scripts 与 Styles](./Lazy-Load-Service.md) diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index 4f47dd2760..28ce41cdb1 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -518,10 +518,6 @@ "text": "替换组件", "path": "UI/Angular/Component-Replacement.md" }, - { - "text": "自定义设置页", - "path": "UI/Angular/Custom-Setting-Page.md" - }, { "text": "懒加载Scripts与Styles", "path": "UI/Angular/Lazy-Load-Service.md" diff --git a/docs/zh-Hans/UI/Angular/images/custom-settings.png b/docs/zh-Hans/images/custom-settings.png similarity index 100% rename from docs/zh-Hans/UI/Angular/images/custom-settings.png rename to docs/zh-Hans/images/custom-settings.png diff --git a/docs/zh-Hans/images/my-setting-group-blazor.png b/docs/zh-Hans/images/my-setting-group-blazor.png new file mode 100644 index 0000000000..0e685ff186 Binary files /dev/null and b/docs/zh-Hans/images/my-setting-group-blazor.png differ diff --git a/docs/zh-Hans/images/my-setting-group-component-contributor.png b/docs/zh-Hans/images/my-setting-group-component-contributor.png new file mode 100644 index 0000000000..3ca6dbedfb Binary files /dev/null and b/docs/zh-Hans/images/my-setting-group-component-contributor.png differ diff --git a/docs/zh-Hans/images/my-setting-group-component.png b/docs/zh-Hans/images/my-setting-group-component.png new file mode 100644 index 0000000000..edcf315b2a Binary files /dev/null and b/docs/zh-Hans/images/my-setting-group-component.png differ diff --git a/docs/zh-Hans/images/my-setting-group-page-contributor.png b/docs/zh-Hans/images/my-setting-group-page-contributor.png new file mode 100644 index 0000000000..3be3737e6f Binary files /dev/null and b/docs/zh-Hans/images/my-setting-group-page-contributor.png differ diff --git a/docs/zh-Hans/images/my-setting-group-ui.png b/docs/zh-Hans/images/my-setting-group-ui.png new file mode 100644 index 0000000000..b9d3f1b403 Binary files /dev/null and b/docs/zh-Hans/images/my-setting-group-ui.png differ diff --git a/docs/zh-Hans/images/my-setting-group-view-component.png b/docs/zh-Hans/images/my-setting-group-view-component.png new file mode 100644 index 0000000000..02843f968e Binary files /dev/null and b/docs/zh-Hans/images/my-setting-group-view-component.png differ diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index b71288ab93..0605f5c103 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -155,16 +155,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.EntityFrameworkCor EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.EventBus.RabbitMQ", "src\Volo.Abp.EventBus.RabbitMQ\Volo.Abp.EventBus.RabbitMQ.csproj", "{468C3DCB-8C00-40E7-AE51-0738EAAB312A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic", "src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj", "{2F5EE6D9-511B-4998-BD62-0B9F03E02432}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared", "src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj", "{86A3BB43-8FA2-4CC2-BAD0-A86C6C9D9585}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Tests", "test\Volo.Abp.AspNetCore.Mvc.UI.Tests\Volo.Abp.AspNetCore.Mvc.UI.Tests.csproj", "{7E0517E0-AE09-4E10-8469-308F065F2F43}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo", "test\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj", "{57E29185-6DAF-4A41-8CE0-3F07EE3E289A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests", "test\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj", "{869F7453-7DDC-4915-B92C-7861466AB68B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Emailing", "src\Volo.Abp.Emailing\Volo.Abp.Emailing.csproj", "{8B1CB44B-BA40-4C78-9447-A7864126D7C3}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Sms", "src\Volo.Abp.Sms\Volo.Abp.Sms.csproj", "{8BB10746-8BAD-4317-8EE5-A36805DB93F6}" @@ -271,8 +265,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BackgroundWorkers. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo", "src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.csproj", "{29E42ADB-85F8-44AE-A9B0-078F84C1B866}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo", "test\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo.csproj", "{0C498CF2-D052-4BF7-AD35-509A90F69707}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Http.Client.IdentityModel.Web.Tests", "test\Volo.Abp.Http.Client.IdentityModel.Web.Tests\Volo.Abp.Http.Client.IdentityModel.Web.Tests.csproj", "{E1963439-2BE5-4DB5-8438-2A9A792A1ADA}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.ObjectExtending", "src\Volo.Abp.ObjectExtending\Volo.Abp.ObjectExtending.csproj", "{D1815C77-16D6-4F99-8814-69065CD89FB3}" @@ -343,8 +335,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Compone EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BlazoriseUI", "src\Volo.Abp.BlazoriseUI\Volo.Abp.BlazoriseUI.csproj", "{4EBDDB1B-D6C5-4FAE-B5A7-2171B18CDFA5}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme", "src\Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme\Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj", "{ABC27C10-C0FF-44CB-B4FF-A09C0B79F695}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Components.WebAssembly.Theming", "src\Volo.Abp.AspNetCore.Components.WebAssembly.Theming\Volo.Abp.AspNetCore.Components.WebAssembly.Theming.csproj", "{29CA7471-4E3E-4E75-8B33-001DDF682F01}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Autofac.WebAssembly", "src\Volo.Abp.Autofac.WebAssembly\Volo.Abp.Autofac.WebAssembly.csproj", "{37F89B0B-1C6B-426F-A5EE-676D1956D9E9}" @@ -365,14 +355,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Http.Tests", "test EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Components.Web", "src\Volo.Abp.AspNetCore.Components.Web\Volo.Abp.AspNetCore.Components.Web.csproj", "{F03A1CEA-FA44-4F30-BFC2-00BC2EAAB4E2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Components.Web.BasicTheme", "src\Volo.Abp.AspNetCore.Components.Web.BasicTheme\Volo.Abp.AspNetCore.Components.Web.BasicTheme.csproj", "{5AD34048-5DAA-4067-9C7D-09295617A057}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Components.Web.Theming", "src\Volo.Abp.AspNetCore.Components.Web.Theming\Volo.Abp.AspNetCore.Components.Web.Theming.csproj", "{B9133C38-AC24-4E2F-B581-D124CF410CDF}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.EventBus.Abstractions", "src\Volo.Abp.EventBus.Abstractions\Volo.Abp.EventBus.Abstractions.csproj", "{8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Components.Server.BasicTheme", "src\Volo.Abp.AspNetCore.Components.Server.BasicTheme\Volo.Abp.AspNetCore.Components.Server.BasicTheme.csproj", "{F35E5CFC-569F-4D7D-A30F-DD8AE97FEC5A}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Sms.Aliyun", "src\Volo.Abp.Sms.Aliyun\Volo.Abp.Sms.Aliyun.csproj", "{ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Sms.Aliyun.Tests", "test\Volo.Abp.Sms.Aliyun.Tests\Volo.Abp.Sms.Aliyun.Tests.csproj", "{DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401}" @@ -699,10 +685,6 @@ Global {468C3DCB-8C00-40E7-AE51-0738EAAB312A}.Debug|Any CPU.Build.0 = Debug|Any CPU {468C3DCB-8C00-40E7-AE51-0738EAAB312A}.Release|Any CPU.ActiveCfg = Release|Any CPU {468C3DCB-8C00-40E7-AE51-0738EAAB312A}.Release|Any CPU.Build.0 = Release|Any CPU - {2F5EE6D9-511B-4998-BD62-0B9F03E02432}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2F5EE6D9-511B-4998-BD62-0B9F03E02432}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2F5EE6D9-511B-4998-BD62-0B9F03E02432}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2F5EE6D9-511B-4998-BD62-0B9F03E02432}.Release|Any CPU.Build.0 = Release|Any CPU {86A3BB43-8FA2-4CC2-BAD0-A86C6C9D9585}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {86A3BB43-8FA2-4CC2-BAD0-A86C6C9D9585}.Debug|Any CPU.Build.0 = Debug|Any CPU {86A3BB43-8FA2-4CC2-BAD0-A86C6C9D9585}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -711,14 +693,6 @@ Global {7E0517E0-AE09-4E10-8469-308F065F2F43}.Debug|Any CPU.Build.0 = Debug|Any CPU {7E0517E0-AE09-4E10-8469-308F065F2F43}.Release|Any CPU.ActiveCfg = Release|Any CPU {7E0517E0-AE09-4E10-8469-308F065F2F43}.Release|Any CPU.Build.0 = Release|Any CPU - {57E29185-6DAF-4A41-8CE0-3F07EE3E289A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {57E29185-6DAF-4A41-8CE0-3F07EE3E289A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {57E29185-6DAF-4A41-8CE0-3F07EE3E289A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {57E29185-6DAF-4A41-8CE0-3F07EE3E289A}.Release|Any CPU.Build.0 = Release|Any CPU - {869F7453-7DDC-4915-B92C-7861466AB68B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {869F7453-7DDC-4915-B92C-7861466AB68B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {869F7453-7DDC-4915-B92C-7861466AB68B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {869F7453-7DDC-4915-B92C-7861466AB68B}.Release|Any CPU.Build.0 = Release|Any CPU {8B1CB44B-BA40-4C78-9447-A7864126D7C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8B1CB44B-BA40-4C78-9447-A7864126D7C3}.Debug|Any CPU.Build.0 = Debug|Any CPU {8B1CB44B-BA40-4C78-9447-A7864126D7C3}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -931,10 +905,6 @@ Global {29E42ADB-85F8-44AE-A9B0-078F84C1B866}.Debug|Any CPU.Build.0 = Debug|Any CPU {29E42ADB-85F8-44AE-A9B0-078F84C1B866}.Release|Any CPU.ActiveCfg = Release|Any CPU {29E42ADB-85F8-44AE-A9B0-078F84C1B866}.Release|Any CPU.Build.0 = Release|Any CPU - {0C498CF2-D052-4BF7-AD35-509A90F69707}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0C498CF2-D052-4BF7-AD35-509A90F69707}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0C498CF2-D052-4BF7-AD35-509A90F69707}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0C498CF2-D052-4BF7-AD35-509A90F69707}.Release|Any CPU.Build.0 = Release|Any CPU {E1963439-2BE5-4DB5-8438-2A9A792A1ADA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E1963439-2BE5-4DB5-8438-2A9A792A1ADA}.Debug|Any CPU.Build.0 = Debug|Any CPU {E1963439-2BE5-4DB5-8438-2A9A792A1ADA}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -1075,10 +1045,6 @@ Global {4EBDDB1B-D6C5-4FAE-B5A7-2171B18CDFA5}.Debug|Any CPU.Build.0 = Debug|Any CPU {4EBDDB1B-D6C5-4FAE-B5A7-2171B18CDFA5}.Release|Any CPU.ActiveCfg = Release|Any CPU {4EBDDB1B-D6C5-4FAE-B5A7-2171B18CDFA5}.Release|Any CPU.Build.0 = Release|Any CPU - {ABC27C10-C0FF-44CB-B4FF-A09C0B79F695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ABC27C10-C0FF-44CB-B4FF-A09C0B79F695}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ABC27C10-C0FF-44CB-B4FF-A09C0B79F695}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ABC27C10-C0FF-44CB-B4FF-A09C0B79F695}.Release|Any CPU.Build.0 = Release|Any CPU {29CA7471-4E3E-4E75-8B33-001DDF682F01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {29CA7471-4E3E-4E75-8B33-001DDF682F01}.Debug|Any CPU.Build.0 = Debug|Any CPU {29CA7471-4E3E-4E75-8B33-001DDF682F01}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -1119,10 +1085,6 @@ Global {F03A1CEA-FA44-4F30-BFC2-00BC2EAAB4E2}.Debug|Any CPU.Build.0 = Debug|Any CPU {F03A1CEA-FA44-4F30-BFC2-00BC2EAAB4E2}.Release|Any CPU.ActiveCfg = Release|Any CPU {F03A1CEA-FA44-4F30-BFC2-00BC2EAAB4E2}.Release|Any CPU.Build.0 = Release|Any CPU - {5AD34048-5DAA-4067-9C7D-09295617A057}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5AD34048-5DAA-4067-9C7D-09295617A057}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5AD34048-5DAA-4067-9C7D-09295617A057}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5AD34048-5DAA-4067-9C7D-09295617A057}.Release|Any CPU.Build.0 = Release|Any CPU {B9133C38-AC24-4E2F-B581-D124CF410CDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B9133C38-AC24-4E2F-B581-D124CF410CDF}.Debug|Any CPU.Build.0 = Debug|Any CPU {B9133C38-AC24-4E2F-B581-D124CF410CDF}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -1131,10 +1093,6 @@ Global {8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Debug|Any CPU.Build.0 = Debug|Any CPU {8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Release|Any CPU.ActiveCfg = Release|Any CPU {8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE}.Release|Any CPU.Build.0 = Release|Any CPU - {F35E5CFC-569F-4D7D-A30F-DD8AE97FEC5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F35E5CFC-569F-4D7D-A30F-DD8AE97FEC5A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F35E5CFC-569F-4D7D-A30F-DD8AE97FEC5A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F35E5CFC-569F-4D7D-A30F-DD8AE97FEC5A}.Release|Any CPU.Build.0 = Release|Any CPU {ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Debug|Any CPU.Build.0 = Debug|Any CPU {ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -1262,11 +1220,8 @@ Global {82ED4DD2-DEF8-40D5-9BF9-663AFD35B06D} = {447C8A77-E5F0-4538-8687-7383196D04EA} {6EABA98D-0B71-4ED7-A939-AFDA106D1151} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {468C3DCB-8C00-40E7-AE51-0738EAAB312A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} - {2F5EE6D9-511B-4998-BD62-0B9F03E02432} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {86A3BB43-8FA2-4CC2-BAD0-A86C6C9D9585} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {7E0517E0-AE09-4E10-8469-308F065F2F43} = {447C8A77-E5F0-4538-8687-7383196D04EA} - {57E29185-6DAF-4A41-8CE0-3F07EE3E289A} = {447C8A77-E5F0-4538-8687-7383196D04EA} - {869F7453-7DDC-4915-B92C-7861466AB68B} = {447C8A77-E5F0-4538-8687-7383196D04EA} {8B1CB44B-BA40-4C78-9447-A7864126D7C3} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {8BB10746-8BAD-4317-8EE5-A36805DB93F6} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {EC71FBDD-A6BD-4B5D-92FE-E108FE12CE8B} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} @@ -1320,7 +1275,6 @@ Global {9467418B-4A9B-4093-9B31-01A9DEF5B372} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {CD5770BB-2E0C-4B3C-80E0-21B8CC43DBA9} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {29E42ADB-85F8-44AE-A9B0-078F84C1B866} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} - {0C498CF2-D052-4BF7-AD35-509A90F69707} = {447C8A77-E5F0-4538-8687-7383196D04EA} {E1963439-2BE5-4DB5-8438-2A9A792A1ADA} = {447C8A77-E5F0-4538-8687-7383196D04EA} {D1815C77-16D6-4F99-8814-69065CD89FB3} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {17F8CA89-D9A2-4863-A5BD-B8E4D2901FD5} = {447C8A77-E5F0-4538-8687-7383196D04EA} @@ -1356,7 +1310,6 @@ Global {8A22D962-016E-474A-8BB7-F831F0ABF3AC} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {E1A62D10-F2FB-4040-BD60-11A3934058DF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {4EBDDB1B-D6C5-4FAE-B5A7-2171B18CDFA5} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} - {ABC27C10-C0FF-44CB-B4FF-A09C0B79F695} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {29CA7471-4E3E-4E75-8B33-001DDF682F01} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {37F89B0B-1C6B-426F-A5EE-676D1956D9E9} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {DEFE3DB2-EA4F-4F90-87FC-B25D64427BC5} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} @@ -1367,10 +1320,8 @@ Global {00D07595-993C-40FC-BD90-0DD6331414D3} = {447C8A77-E5F0-4538-8687-7383196D04EA} {A37BFEB5-7C57-4CDC-93B8-B5CE4BB9ACE1} = {447C8A77-E5F0-4538-8687-7383196D04EA} {F03A1CEA-FA44-4F30-BFC2-00BC2EAAB4E2} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} - {5AD34048-5DAA-4067-9C7D-09295617A057} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {B9133C38-AC24-4E2F-B581-D124CF410CDF} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {8FDB3BF7-AD89-43F6-8DEB-C3E29B8801FE} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} - {F35E5CFC-569F-4D7D-A30F-DD8AE97FEC5A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {ACFBA3FB-18CE-4655-9D14-1F1F5C3DFC30} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {DADEA538-3CA1-4ADE-A7E6-EF77A0CE4401} = {447C8A77-E5F0-4538-8687-7383196D04EA} {863C18F9-2407-49F9-9ADC-F6229AF3B385} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Server.BasicTheme/Volo.Abp.AspNetCore.Components.Server.BasicTheme.csproj b/framework/src/Volo.Abp.AspNetCore.Components.Server.BasicTheme/Volo.Abp.AspNetCore.Components.Server.BasicTheme.csproj deleted file mode 100644 index 73374aff94..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Components.Server.BasicTheme/Volo.Abp.AspNetCore.Components.Server.BasicTheme.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - net5.0 - - - - - - - - - - - - diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Volo.Abp.AspNetCore.Components.Web.BasicTheme.csproj b/framework/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Volo.Abp.AspNetCore.Components.Web.BasicTheme.csproj deleted file mode 100644 index 4f3c306eab..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Volo.Abp.AspNetCore.Components.Web.BasicTheme.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - net5.0 - - - - - - - diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj deleted file mode 100644 index 9f456a72c2..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - net5.0 - Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme - - - - - - - - - diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Table/AbpTableTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Table/AbpTableTagHelperService.cs index 86bfd43744..8f84a04bbe 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Table/AbpTableTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Table/AbpTableTagHelperService.cs @@ -9,6 +9,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Table { output.TagName = "table"; output.Attributes.AddClass("table"); + output.TagMode = TagMode.StartTagAndEndTag; SetResponsiveness(context, output); SetTheme(context, output); @@ -95,4 +96,4 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Table } } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/fi.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/fi.json index d6fb04eb4c..0547630188 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/fi.json +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/fi.json @@ -10,4 +10,4 @@ "SwitchTenant": "Vaihda vuokralainen", "NotSelected": "Ei valittu" } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj deleted file mode 100644 index b421036ab0..0000000000 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - net5.0 - true - Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic - Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic - $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; - false - false - false - true - Library - - - - - - - - - - - - - - - - diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js index 8023b59be1..6ae24f20dd 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js @@ -236,9 +236,11 @@ var abp = abp || {}; var $actionContainer = _createRowAction(aData, column.rowAction, tableInstance); hideEmptyColumn($actionContainer, tableInstance, colIndex); - var $actionButton = $(cells[colIndex]).find(".abp-action-button"); - if ($actionButton.length === 0) { - $(cells[colIndex]).empty().append($actionContainer); + if ($actionContainer) { + var $actionButton = $(cells[colIndex]).find(".abp-action-button"); + if ($actionButton.length === 0) { + $(cells[colIndex]).empty().append($actionContainer); + } } } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs index ff7f4913a8..ca1ebef793 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Reflection; using System.Text; using JetBrains.Annotations; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.ApiExplorer; @@ -102,6 +103,16 @@ namespace Volo.Abp.AspNetCore.Mvc Logger.LogDebug($"ActionApiDescriptionModel.Create: {controllerModel.ControllerName}.{uniqueMethodName}"); + bool? allowAnonymous = null; + if (apiDescription.ActionDescriptor.EndpointMetadata.Any(x => x is IAllowAnonymous)) + { + allowAnonymous = true; + } + else if (apiDescription.ActionDescriptor.EndpointMetadata.Any(x => x is IAuthorizeData)) + { + allowAnonymous = false; + } + var actionModel = controllerModel.AddAction( uniqueMethodName, ActionApiDescriptionModel.Create( @@ -109,7 +120,8 @@ namespace Volo.Abp.AspNetCore.Mvc method, apiDescription.RelativePath, apiDescription.HttpMethod, - GetSupportedVersions(controllerType, method, setting) + GetSupportedVersions(controllerType, method, setting), + allowAnonymous ) ); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpMvcAttributeValidationResultProvider.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpMvcAttributeValidationResultProvider.cs new file mode 100644 index 0000000000..c6a280cca3 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpMvcAttributeValidationResultProvider.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Mvc.Validation; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Validation; + +namespace Volo.Abp.AspNetCore.Mvc.Localization +{ + [Dependency(ReplaceServices = true)] + public class AbpMvcAttributeValidationResultProvider : DefaultAttributeValidationResultProvider + { + private readonly AbpMvcDataAnnotationsLocalizationOptions _abpMvcDataAnnotationsLocalizationOptions; + private readonly IStringLocalizerFactory _stringLocalizerFactory; + + public AbpMvcAttributeValidationResultProvider( + IOptions abpMvcDataAnnotationsLocalizationOptions, + IStringLocalizerFactory stringLocalizerFactory) + { + _abpMvcDataAnnotationsLocalizationOptions = abpMvcDataAnnotationsLocalizationOptions.Value; + _stringLocalizerFactory = stringLocalizerFactory; + } + + public override ValidationResult GetOrDefault(ValidationAttribute validationAttribute, object validatingObject, ValidationContext validationContext) + { + var resourceSource = _abpMvcDataAnnotationsLocalizationOptions.AssemblyResources.GetOrDefault(validationContext.ObjectType.Assembly); + if (resourceSource == null) + { + return base.GetOrDefault(validationAttribute, validatingObject, validationContext); + } + + if (validationAttribute.ErrorMessage == null) + { + ValidationAttributeHelper.SetDefaultErrorMessage(validationAttribute); + } + + if (validationAttribute.ErrorMessage != null) + { + validationAttribute.ErrorMessage = _stringLocalizerFactory.Create(resourceSource)[validationAttribute.ErrorMessage]; + } + + return base.GetOrDefault(validationAttribute, validatingObject, validationContext); + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs index 6b559f4d3e..23fece372f 100644 --- a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.Auditing; using Volo.Abp.DependencyInjection; using Volo.Abp.Modularity; @@ -30,6 +31,7 @@ namespace Volo.Abp.AspNetCore.SignalR public override void ConfigureServices(ServiceConfigurationContext context) { + var routePatterns = new List {"/signalr-hubs"}; var signalRServerBuilder = context.Services.AddSignalR(); context.Services.ExecutePreConfiguredActions(signalRServerBuilder); @@ -45,6 +47,8 @@ namespace Volo.Abp.AspNetCore.SignalR foreach (var hubConfig in signalROptions.Hubs) { + routePatterns.AddIfNotContains(hubConfig.RoutePattern); + MapHubType( hubConfig.HubType, endpointContext.Endpoints, @@ -60,6 +64,14 @@ namespace Volo.Abp.AspNetCore.SignalR } }); }); + + Configure(options => + { + foreach (var routePattern in routePatterns) + { + options.IgnoredUrls.AddIfNotContains(x => routePattern.StartsWith(x), () => routePattern); + } + }); } private void AutoAddHubTypes(IServiceCollection services) diff --git a/framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj b/framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj index 7e742c0467..036144e8c6 100644 --- a/framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj +++ b/framework/src/Volo.Abp.Castle.Core/Volo.Abp.Castle.Core.csproj @@ -16,7 +16,7 @@ - + diff --git a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj index 1b7603194a..4f28bad500 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj +++ b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj @@ -13,6 +13,7 @@ + diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs index b3de9d71ff..08da2e3d00 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs @@ -2,9 +2,11 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Cli.Commands; using Volo.Abp.Cli.Http; +using Volo.Abp.Cli.LIbs; using Volo.Abp.Domain; using Volo.Abp.IdentityModel; using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson; using Volo.Abp.Minify; using Volo.Abp.Modularity; @@ -25,6 +27,11 @@ namespace Volo.Abp.Cli Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + Configure(options => + { + options.UnsupportedTypes.Add(typeof(ResourceMapping)); + }); + Configure(options => { //TODO: Define constants like done for GenerateProxyCommand.Name. @@ -49,6 +56,7 @@ namespace Volo.Abp.Cli options.Commands["build"] = typeof(BuildCommand); options.Commands["bundle"] = typeof(BundleCommand); options.Commands["create-migration-and-run-migrator"] = typeof(CreateMigrationAndRunMigratorCommand); + options.Commands["install-libs"] = typeof(InstallLibsCommand); }); } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/InstallLibsCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/InstallLibsCommand.cs new file mode 100644 index 0000000000..dc3e67fe29 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/InstallLibsCommand.cs @@ -0,0 +1,78 @@ +using System; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.LIbs; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Cli.Commands +{ + public class InstallLibsCommand : IConsoleCommand, ITransientDependency + { + public ILogger Logger { get; set; } + + protected IInstallLibsService InstallLibsService { get; } + + public InstallLibsCommand(IInstallLibsService installLibsService) + { + InstallLibsService = installLibsService; + Logger = NullLogger.Instance; + } + + public async Task ExecuteAsync(CommandLineArgs commandLineArgs) + { + var workingDirectoryArg = commandLineArgs.Options.GetOrNull( + Options.WorkingDirectory.Short, + Options.WorkingDirectory.Long + ); + + var workingDirectory = workingDirectoryArg ?? Directory.GetCurrentDirectory(); + + if (!Directory.Exists(workingDirectory)) + { + throw new CliUsageException( + "Specified directory does not exist." + + Environment.NewLine + Environment.NewLine + + GetUsageInfo() + ); + } + + await InstallLibsService.InstallLibsAsync(workingDirectory); + } + + public string GetUsageInfo() + { + var sb = new StringBuilder(); + + sb.AppendLine(""); + sb.AppendLine("Usage:"); + sb.AppendLine(""); + sb.AppendLine(" abp install-libs"); + sb.AppendLine(""); + sb.AppendLine("Options:"); + sb.AppendLine(""); + sb.AppendLine("-wd|--working-directory (default: empty)"); + sb.AppendLine(""); + sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); + + return sb.ToString(); + } + + public string GetShortDescription() + { + return "Install NPM Packages for MVC / Razor Pages and Blazor Server UI types."; + } + + public static class Options + { + public static class WorkingDirectory + { + public const string Short = "wd"; + public const string Long = "working-directory"; + } + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/FileMatchResult.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/FileMatchResult.cs new file mode 100644 index 0000000000..cbaf9c52da --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/FileMatchResult.cs @@ -0,0 +1,15 @@ +namespace Volo.Abp.Cli.LIbs +{ + public class FileMatchResult + { + public string Path { get; } + + public string Stem { get; } + + public FileMatchResult(string path, string stem) + { + Path = path; + Stem = stem; + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/IInstallLibsService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/IInstallLibsService.cs new file mode 100644 index 0000000000..b0b05f35da --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/IInstallLibsService.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.Cli.LIbs +{ + public interface IInstallLibsService + { + Task InstallLibsAsync(string directory); + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs new file mode 100644 index 0000000000..5379c62aed --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs @@ -0,0 +1,230 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.FileSystemGlobbing; +using Microsoft.Extensions.FileSystemGlobbing.Abstractions; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using NuGet.Versioning; +using Volo.Abp.Cli.Utils; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Json; + +namespace Volo.Abp.Cli.LIbs +{ + public class InstallLibsService : IInstallLibsService, ITransientDependency + { + public const string LibsDirectory = "./wwwroot/libs"; + + public ILogger Logger { get; set; } + + private readonly IJsonSerializer _jsonSerializer; + + public InstallLibsService(IJsonSerializer jsonSerializer) + { + _jsonSerializer = jsonSerializer; + Logger = NullLogger.Instance; + } + + public async Task InstallLibsAsync(string directory) + { + var projectFiles = Directory.GetFiles(directory, "*.csproj"); + if (!projectFiles.Any()) + { + Logger.LogError("No project file found in the directory."); + return; + } + + if (!await CanInstallLibs(directory)) + { + Logger.LogWarning( + "abp install-libs command is available for MVC, Razor Page, and Blazor-Server UI types"); + return; + } + + if (!IsNpmInstalled()) + { + Logger.LogWarning("NPM is not installed, visit https://nodejs.org/en/download/ and install NPM"); + return; + } + + if (IsYarnAvailable()) + { + RunYarn(directory); + } + else + { + RunNpmInstall(directory); + } + + await CleanAndCopyResources(directory); + } + + private async Task CleanAndCopyResources(string fileDirectory) + { + var mappingFiles = Directory.GetFiles(fileDirectory, "abp.resourcemapping.js", SearchOption.AllDirectories); + var resourceMapping = new ResourceMapping + { + Clean = new List {LibsDirectory} + }; + + foreach (var mappingFile in mappingFiles) + { + using (var reader = File.OpenText(mappingFile)) + { + var mappingFileContent = await reader.ReadToEndAsync(); + + var mapping = _jsonSerializer.Deserialize(mappingFileContent + .Replace("module.exports", string.Empty) + .Replace("=", string.Empty).Trim().TrimEnd(';')); + + mapping.ReplaceAliases(); + + mapping.Clean.ForEach(c => resourceMapping.Clean.AddIfNotContains(c)); + mapping.Aliases.ToList().ForEach(x => + { + resourceMapping.Aliases.AddIfNotContains(new KeyValuePair(x.Key, x.Value)); + }); + mapping.Mappings.ToList().ForEach(x => + { + resourceMapping.Mappings.AddIfNotContains(new KeyValuePair(x.Key, x.Value)); + }); + } + } + + EnsureLibsFolderExists(fileDirectory, LibsDirectory); + + CleanDirsAndFiles(fileDirectory, resourceMapping); + CopyResourcesToLibs(fileDirectory, resourceMapping); + } + + private void EnsureLibsFolderExists(string fileDirectory, string libsDirectory) + { + Directory.CreateDirectory(Path.Combine(fileDirectory, libsDirectory)); + } + + private void CopyResourcesToLibs(string fileDirectory, ResourceMapping resourceMapping) + { + foreach (var mapping in resourceMapping.Mappings) + { + var destPath = Path.Combine(fileDirectory, mapping.Value); + var files = FindFiles(fileDirectory, mapping.Key); + + foreach (var file in files) + { + var destFilePath = Path.Combine(destPath, file.Stem); + if (File.Exists(destFilePath)) + { + continue; + } + + Directory.CreateDirectory(Path.GetDirectoryName(destFilePath)); + File.Copy(file.Path, destFilePath); + + } + } + } + + private async Task CanInstallLibs(string fileDirectory) + { + var projectFiles = Directory.GetFiles(fileDirectory, "*.csproj"); + + using (var reader = File.OpenText(projectFiles[0])) + { + var projectFileContent = await reader.ReadToEndAsync(); + + return projectFileContent.Contains("Microsoft.NET.Sdk.Web"); + } + } + + private void CleanDirsAndFiles(string directory, ResourceMapping resourceMapping) + { + var files = FindFiles(directory, resourceMapping.Clean.ToArray()); + + foreach (var file in files) + { + if (File.Exists(file.Path)) + { + File.Delete(file.Path); + } + } + + foreach (var directoryInfo in Directory.GetDirectories(Path.Combine(directory, resourceMapping.Clean.First()),"*", SearchOption.AllDirectories).Reverse()) + { + if (!Directory.EnumerateFileSystemEntries(directoryInfo).Any()) + { + Directory.Delete(directoryInfo); + } + } + } + + private List FindFiles(string directory, params string[] patterns) + { + var matcher = new Matcher(); + + foreach (var pattern in patterns) + { + if (pattern.StartsWith("!")) + { + matcher.AddExclude(NormalizeGlob(pattern).TrimStart('!')); + } + else + { + matcher.AddInclude(NormalizeGlob(pattern)); + } + } + + var result = matcher.Execute(new DirectoryInfoWrapper(new DirectoryInfo(directory))); + + return result.Files.Select(x => new FileMatchResult(Path.Combine(directory, x.Path), x.Stem)).ToList(); + } + + private string NormalizeGlob(string pattern) + { + pattern = pattern.Replace("//", "/"); + + if (!Path.HasExtension(pattern) && !pattern.EndsWith("*")) + { + return pattern.EnsureEndsWith('/') + "**"; + } + + return pattern; + } + + private void RunNpmInstall(string directory) + { + Logger.LogInformation($"Running npm install on {directory}"); + CmdHelper.RunCmd($"cd {directory} && npm install"); + } + + private void RunYarn(string directory) + { + Logger.LogInformation($"Running Yarn on {directory}"); + CmdHelper.RunCmd($"cd {directory} && yarn"); + } + + private bool IsNpmInstalled() + { + var output = CmdHelper.RunCmdAndGetOutput("npm -v").Trim(); + return SemanticVersion.TryParse(output, out _); + } + + private bool IsYarnAvailable() + { + var output = CmdHelper.RunCmdAndGetOutput("npm list yarn -g").Trim(); + if (output.Contains("empty")) + { + return false; + } + + if (!SemanticVersion.TryParse(output.Substring(output.IndexOf('@') + 1), out var version)) + { + return false; + } + + return version > SemanticVersion.Parse("1.20.0"); + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/ResourceMapping.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/ResourceMapping.cs new file mode 100644 index 0000000000..ed46b833ad --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/ResourceMapping.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Volo.Abp.Cli.LIbs +{ + public class ResourceMapping + { + public Dictionary Aliases { get; set; } + + public List Clean { get; set; } + + public Dictionary Mappings { get; set; } + + public ResourceMapping() + { + Aliases = new Dictionary + { + {"@node_modules", "./node_modules"}, + {"@libs", "./wwwroot/libs"}, + }; + Clean = new List(); + Mappings = new Dictionary(); + } + + public void ReplaceAliases() + { + for (var i = 0; i < Mappings.Count; i++) + { + var mapping = Mappings.ElementAt(i); + Mappings.Remove(mapping.Key); + + var key = mapping.Key; + var value = mapping.Value; + + foreach (var alias in Aliases) + { + key = key.Replace(alias.Key, alias.Value); + value = value.Replace(alias.Key, alias.Value); + } + + Mappings[key] = value; + } + + for (var i = 0; i < Clean.Count; i++) + { + foreach (var alias in Aliases) + { + Clean[i] = Clean[i].Replace(alias.Key, alias.Value); + } + } + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ProjectNameValidator.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ProjectNameValidator.cs index 8430cd79a0..4606aa59c4 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ProjectNameValidator.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Utils/ProjectNameValidator.cs @@ -17,6 +17,11 @@ namespace Volo.Abp.Cli.Utils "LPT2" }; + private static readonly string[] IllegalKeywords = new[] + { + "Blazor" + }; + private static bool HasParentDirectoryString(string projectName) { return projectName.Contains(".."); @@ -40,6 +45,19 @@ namespace Volo.Abp.Cli.Utils return false; } + private static bool HasIllegalKeywords(string projectName) + { + foreach (var illegalKeyword in IllegalKeywords) + { + if (projectName.Contains(illegalKeyword)) + { + return true; + } + } + + return false; + } + public static bool IsValid(string projectName) { if (projectName == null) @@ -62,6 +80,11 @@ namespace Volo.Abp.Cli.Utils return false; } + if (HasIllegalKeywords(projectName)) + { + return false; + } + return true; } } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs index ee172b3409..886d8e020c 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs @@ -15,7 +15,7 @@ namespace Volo.Abp.DependencyInjection public IServiceCollection Services { get; } - public List ReplacedDbContextTypes { get; } + public Dictionary ReplacedDbContextTypes { get; } public Type DefaultRepositoryDbContextType { get; protected set; } @@ -39,7 +39,7 @@ namespace Volo.Abp.DependencyInjection Services = services; DefaultRepositoryDbContextType = originalDbContextType; CustomRepositories = new Dictionary(); - ReplacedDbContextTypes = new List(); + ReplacedDbContextTypes = new Dictionary(); SpecifiedDefaultRepositories = new List(); } @@ -47,15 +47,20 @@ namespace Volo.Abp.DependencyInjection { return ReplaceDbContext(typeof(TOtherDbContext)); } + + public IAbpCommonDbContextRegistrationOptionsBuilder ReplaceDbContext() + { + return ReplaceDbContext(typeof(TOtherDbContext), typeof(TTargetDbContext)); + } - public IAbpCommonDbContextRegistrationOptionsBuilder ReplaceDbContext(Type otherDbContextType) + public IAbpCommonDbContextRegistrationOptionsBuilder ReplaceDbContext(Type otherDbContextType, Type targetDbContextType = null) { if (!otherDbContextType.IsAssignableFrom(OriginalDbContextType)) { throw new AbpException($"{OriginalDbContextType.AssemblyQualifiedName} should inherit/implement {otherDbContextType.AssemblyQualifiedName}!"); } - ReplacedDbContextTypes.AddIfNotContains(otherDbContextType); + ReplacedDbContextTypes[otherDbContextType] = targetDbContextType; return this; } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/IAbpCommonDbContextRegistrationOptionsBuilder.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/IAbpCommonDbContextRegistrationOptionsBuilder.cs index 34e74d90cd..248300ab62 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/IAbpCommonDbContextRegistrationOptionsBuilder.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/IAbpCommonDbContextRegistrationOptionsBuilder.cs @@ -75,9 +75,17 @@ namespace Volo.Abp.DependencyInjection IAbpCommonDbContextRegistrationOptionsBuilder ReplaceDbContext(); /// - /// Replaces given DbContext type with this DbContext type. + /// Replaces given DbContext type with the target DbContext type. + /// + /// The DbContext type to be replaced + /// The target DbContext type + IAbpCommonDbContextRegistrationOptionsBuilder ReplaceDbContext(); + + /// + /// Replaces given DbContext type with the given or this DbContext type. /// /// The DbContext type to be replaced - IAbpCommonDbContextRegistrationOptionsBuilder ReplaceDbContext(Type otherDbContextType); + /// The target DbContext type (optional, used this DbContext type if not provided) + IAbpCommonDbContextRegistrationOptionsBuilder ReplaceDbContext(Type otherDbContextType, Type targetDbContextType = null); } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs index a48575ddcc..658269a376 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs @@ -31,18 +31,21 @@ namespace Microsoft.Extensions.DependencyInjection services.TryAddTransient(DbContextOptionsFactory.Create); - foreach (var dbContextType in options.ReplacedDbContextTypes) + foreach (var entry in options.ReplacedDbContextTypes) { + var originalDbContextType = entry.Key; + var targetDbContextType = entry.Value ?? typeof(TDbContext); + services.Replace( ServiceDescriptor.Transient( - dbContextType, - sp => sp.GetRequiredService(typeof(TDbContext)) + originalDbContextType, + sp => sp.GetRequiredService(targetDbContextType) ) ); services.Configure(opts => { - opts.DbContextReplacements[dbContextType] = typeof(TDbContext); + opts.DbContextReplacements[originalDbContextType] = targetDbContextType; }); } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs index cda8c02416..9b488924e8 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -86,7 +86,6 @@ namespace Volo.Abp.EntityFrameworkCore protected AbpDbContext(DbContextOptions options) : base(options) { - } protected override void OnModelCreating(ModelBuilder modelBuilder) @@ -372,17 +371,20 @@ namespace Volo.Abp.EntityFrameworkCore protected virtual void ApplyAbpConceptsForModifiedEntity(EntityEntry entry, EntityChangeReport changeReport) { - UpdateConcurrencyStamp(entry); - SetModificationAuditProperties(entry); - - if (entry.Entity is ISoftDelete && entry.Entity.As().IsDeleted) - { - SetDeletionAuditProperties(entry); - changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Deleted)); - } - else + if (entry.State == EntityState.Modified && entry.Properties.Any(x => x.IsModified && x.Metadata.ValueGenerated == ValueGenerated.Never)) { - changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Updated)); + UpdateConcurrencyStamp(entry); + SetModificationAuditProperties(entry); + + if (entry.Entity is ISoftDelete && entry.Entity.As().IsDeleted) + { + SetDeletionAuditProperties(entry); + changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Deleted)); + } + else + { + changeReport.ChangedEntities.Add(new EntityChangeEntry(entry.Entity, EntityChangeType.Updated)); + } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs index a40c4d6254..44cad9c638 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpEntityTypeBuilderExtensions.cs @@ -82,6 +82,11 @@ namespace Volo.Abp.EntityFrameworkCore.Modeling } } + public static void ApplyObjectExtensionMappings(this EntityTypeBuilder b) + { + ObjectExtensionManager.Instance.ConfigureEfCoreEntity(b); + } + public static void ConfigureSoftDelete(this EntityTypeBuilder b) where T : class, ISoftDelete { diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpModelBuilderObjectExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpModelBuilderObjectExtensions.cs new file mode 100644 index 0000000000..295f6ef7cf --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/Modeling/AbpModelBuilderObjectExtensions.cs @@ -0,0 +1,14 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.ObjectExtending; + +namespace Volo.Abp.EntityFrameworkCore.Modeling +{ + public static class AbpModelBuilderObjectExtensions + { + public static void TryConfigureObjectExtensions(this ModelBuilder modelBuilder) + where TDbContext : DbContext + { + ObjectExtensionManager.Instance.ConfigureEfCoreDbContext(modelBuilder); + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/EfCoreObjectExtensionInfoExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/EfCoreObjectExtensionInfoExtensions.cs index 17b495cdad..f27fc12d64 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/EfCoreObjectExtensionInfoExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/EfCoreObjectExtensionInfoExtensions.cs @@ -1,11 +1,17 @@ using System; +using System.Collections.Generic; +using System.Linq; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace Volo.Abp.ObjectExtending { public static class EfCoreObjectExtensionInfoExtensions { + public const string EfCoreDbContextConfigurationName = "EfCoreDbContextMapping"; + public const string EfCoreEntityConfigurationName = "EfCoreEntityMapping"; + [Obsolete("Use MapEfCoreProperty with EntityTypeAndPropertyBuildAction parameters.")] public static ObjectExtensionInfo MapEfCoreProperty( [NotNull] this ObjectExtensionInfo objectExtensionInfo, @@ -71,5 +77,69 @@ namespace Volo.Abp.ObjectExtending } ); } + + public static ObjectExtensionInfo MapEfCoreEntity( + [NotNull] this ObjectExtensionInfo objectExtensionInfo, + [NotNull] Action entityTypeBuildAction) + { + Check.NotNull(objectExtensionInfo, nameof(objectExtensionInfo)); + + var mappingOptionList = new List + { + new ObjectExtensionInfoEfCoreMappingOptions( + objectExtensionInfo, + entityTypeBuildAction) + }; + + objectExtensionInfo.Configuration.AddOrUpdate(EfCoreEntityConfigurationName, mappingOptionList, + (k, v) => + { + v.As>().Add(mappingOptionList.First()); + return v; + }); + + return objectExtensionInfo; + } + + public static ObjectExtensionInfo MapEfCoreDbContext( + [NotNull] this ObjectExtensionInfo objectExtensionInfo, + [NotNull] Action modelBuildAction) + { + Check.NotNull(objectExtensionInfo, nameof(objectExtensionInfo)); + + var mappingOptionList = new List + { + new ObjectExtensionInfoEfCoreMappingOptions( + objectExtensionInfo, + modelBuildAction) + }; + + objectExtensionInfo.Configuration.AddOrUpdate(EfCoreDbContextConfigurationName, mappingOptionList, + (k, v) => + { + v.As>().Add(mappingOptionList.First()); + return v; + }); + + return objectExtensionInfo; + } + + public static List GetEfCoreEntityMappings( + [NotNull] this ObjectExtensionInfo objectExtensionInfo) + { + Check.NotNull(objectExtensionInfo, nameof(objectExtensionInfo)); + + return !objectExtensionInfo.Configuration.TryGetValue(EfCoreEntityConfigurationName, out var options) ? + new List() : options.As>(); + } + + public static List GetEfCoreDbContextMappings( + [NotNull] this ObjectExtensionInfo objectExtensionInfo) + { + Check.NotNull(objectExtensionInfo, nameof(objectExtensionInfo)); + + return !objectExtensionInfo.Configuration.TryGetValue(EfCoreDbContextConfigurationName, out var options) ? + new List() : options.As>(); + } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/EfCoreObjectExtensionManagerExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/EfCoreObjectExtensionManagerExtensions.cs index 54c1909bb3..86d4115421 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/EfCoreObjectExtensionManagerExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/EfCoreObjectExtensionManagerExtensions.cs @@ -1,5 +1,6 @@ using System; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Volo.Abp.Data; using Volo.Abp.Domain.Entities; @@ -8,6 +9,45 @@ namespace Volo.Abp.ObjectExtending { public static class EfCoreObjectExtensionManagerExtensions { + public static ObjectExtensionManager MapEfCoreDbContext( + [NotNull] this ObjectExtensionManager objectExtensionManager, + [NotNull] Action modelBuilderAction) + where TDbContext : DbContext + { + return objectExtensionManager.AddOrUpdate( + typeof(TDbContext), + options => + { + options.MapEfCoreDbContext(modelBuilderAction); + }); + } + + public static ObjectExtensionManager MapEfCoreEntity( + [NotNull] this ObjectExtensionManager objectExtensionManager, + [NotNull] Action entityTypeBuildAction) + where TEntity : IEntity + { + return MapEfCoreEntity( + objectExtensionManager, + typeof(TEntity), + entityTypeBuildAction); + } + + public static ObjectExtensionManager MapEfCoreEntity( + [NotNull] this ObjectExtensionManager objectExtensionManager, + [NotNull] Type entityType, + [NotNull] Action entityTypeBuildAction) + { + Check.NotNull(objectExtensionManager, nameof(objectExtensionManager)); + + return objectExtensionManager.AddOrUpdate( + entityType, + options => + { + options.MapEfCoreEntity(entityTypeBuildAction); + }); + } + public static ObjectExtensionManager MapEfCoreProperty( [NotNull] this ObjectExtensionManager objectExtensionManager, [NotNull] string propertyName) @@ -32,10 +72,7 @@ namespace Volo.Abp.ObjectExtending entityType, propertyType, propertyName, - options => - { - options.MapEfCore(); - } + options => { options.MapEfCore(); } ); } @@ -126,6 +163,13 @@ namespace Volo.Abp.ObjectExtending return; } + var efCoreEntityMappings = objectExtension.GetEfCoreEntityMappings(); + + foreach (var efCoreEntityMapping in efCoreEntityMappings) + { + efCoreEntityMapping.EntityTypeBuildAction?.Invoke(typeBuilder); + } + foreach (var property in objectExtension.GetProperties()) { var efCoreMapping = property.GetEfCoreMappingOrNull(); @@ -148,5 +192,27 @@ namespace Volo.Abp.ObjectExtending #pragma warning restore 618 } } + + public static void ConfigureEfCoreDbContext( + [NotNull] this ObjectExtensionManager objectExtensionManager, + [NotNull] ModelBuilder modelBuilder) + where TDbContext : DbContext + { + Check.NotNull(objectExtensionManager, nameof(objectExtensionManager)); + Check.NotNull(modelBuilder, nameof(modelBuilder)); + + var objectExtension = objectExtensionManager.GetOrNull(typeof(TDbContext)); + if (objectExtension == null) + { + return; + } + + var efCoreDbContextMappings = objectExtension.GetEfCoreDbContextMappings(); + + foreach (var efCoreDbContextMapping in efCoreDbContextMappings) + { + efCoreDbContextMapping.ModelBuildAction?.Invoke(modelBuilder); + } + } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/ObjectExtensionInfoEfCoreMappingOptions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/ObjectExtensionInfoEfCoreMappingOptions.cs new file mode 100644 index 0000000000..5510e138e4 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/ObjectExtending/ObjectExtensionInfoEfCoreMappingOptions.cs @@ -0,0 +1,39 @@ +using System; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Volo.Abp.ObjectExtending +{ + public class ObjectExtensionInfoEfCoreMappingOptions + { + [NotNull] + public ObjectExtensionInfo ObjectExtension { get; } + + [CanBeNull] + public Action EntityTypeBuildAction { get; set; } + + [CanBeNull] + public Action ModelBuildAction { get; set; } + + public ObjectExtensionInfoEfCoreMappingOptions( + [NotNull] ObjectExtensionInfo objectExtension, + [NotNull] Action entityTypeBuildAction) + { + ObjectExtension = Check.NotNull(objectExtension, nameof(objectExtension)); + EntityTypeBuildAction = Check.NotNull(entityTypeBuildAction, nameof(entityTypeBuildAction)); + + EntityTypeBuildAction = entityTypeBuildAction; + } + + public ObjectExtensionInfoEfCoreMappingOptions( + [NotNull] ObjectExtensionInfo objectExtension, + [NotNull] Action modelBuildAction) + { + ObjectExtension = Check.NotNull(objectExtension, nameof(objectExtension)); + ModelBuildAction = Check.NotNull(modelBuildAction, nameof(modelBuildAction)); + + ModelBuildAction = modelBuildAction; + } + } +} diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Domain/Entities/EntityNotFoundException.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Domain/Entities/EntityNotFoundException.cs index 85466ccf0e..c920e1e475 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Domain/Entities/EntityNotFoundException.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/Domain/Entities/EntityNotFoundException.cs @@ -49,7 +49,7 @@ namespace Volo.Abp.Domain.Entities public EntityNotFoundException(Type entityType, object id, Exception innerException) : base( id == null - ? $"There is no such an entity given given id. Entity type: {entityType.FullName}" + ? $"There is no such an entity given id. Entity type: {entityType.FullName}" : $"There is no such an entity. Entity type: {entityType.FullName}, id: {id}", innerException) { diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs index dd96ad98a2..a397f1b53e 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs @@ -156,14 +156,17 @@ namespace Volo.Abp.Http.Client.DynamicProxying AddHeaders(invocation, action, requestMessage, apiVersion); - await ClientAuthenticator.Authenticate( - new RemoteServiceHttpClientAuthenticateContext( - client, - requestMessage, - remoteServiceConfig, - clientConfig.RemoteServiceName - ) - ); + if (action.AllowAnonymous != true) + { + await ClientAuthenticator.Authenticate( + new RemoteServiceHttpClientAuthenticateContext( + client, + requestMessage, + remoteServiceConfig, + clientConfig.RemoteServiceName + ) + ); + } var response = await client.SendAsync( requestMessage, diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ActionApiDescriptionModel.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ActionApiDescriptionModel.cs index 1ca0c28aa1..2901161259 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ActionApiDescriptionModel.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ActionApiDescriptionModel.cs @@ -26,12 +26,14 @@ namespace Volo.Abp.Http.Modeling public ReturnValueApiDescriptionModel ReturnValue { get; set; } + public bool? AllowAnonymous { get; set; } + public ActionApiDescriptionModel() { } - public static ActionApiDescriptionModel Create([NotNull] string uniqueName, [NotNull] MethodInfo method, [NotNull] string url, [CanBeNull] string httpMethod, [NotNull] IList supportedVersions) + public static ActionApiDescriptionModel Create([NotNull] string uniqueName, [NotNull] MethodInfo method, [NotNull] string url, [CanBeNull] string httpMethod, [NotNull] IList supportedVersions, bool? allowAnonymous = null) { Check.NotNull(uniqueName, nameof(uniqueName)); Check.NotNull(method, nameof(method)); @@ -50,7 +52,8 @@ namespace Volo.Abp.Http.Modeling .GetParameters() .Select(MethodParameterApiDescriptionModel.Create) .ToList(), - SupportedVersions = supportedVersions + SupportedVersions = supportedVersions, + AllowAnonymous = allowAnonymous }; } diff --git a/framework/src/Volo.Abp.MemoryDb/Microsoft/Extensions/DependencyInjection/AbpMemoryDbServiceCollectionExtensions.cs b/framework/src/Volo.Abp.MemoryDb/Microsoft/Extensions/DependencyInjection/AbpMemoryDbServiceCollectionExtensions.cs index 3cab95cb03..99ef1bd445 100644 --- a/framework/src/Volo.Abp.MemoryDb/Microsoft/Extensions/DependencyInjection/AbpMemoryDbServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.MemoryDb/Microsoft/Extensions/DependencyInjection/AbpMemoryDbServiceCollectionExtensions.cs @@ -18,9 +18,17 @@ namespace Microsoft.Extensions.DependencyInjection services.TryAddSingleton(options.DefaultRepositoryDbContextType, sp => sp.GetRequiredService()); } - foreach (var dbContextType in options.ReplacedDbContextTypes) + foreach (var entry in options.ReplacedDbContextTypes) { - services.Replace(ServiceDescriptor.Singleton(dbContextType, sp => sp.GetRequiredService())); + var originalDbContextType = entry.Key; + var targetDbContextType = entry.Value ?? typeof(TMemoryDbContext); + + services.Replace( + ServiceDescriptor.Singleton( + originalDbContextType, + sp => sp.GetRequiredService(targetDbContextType) + ) + ); } new MemoryDbRepositoryRegistrar(options).AddRepositories(); diff --git a/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs b/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs index 7f9c6b8d42..c05dbe5b3a 100644 --- a/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs @@ -25,23 +25,21 @@ namespace Microsoft.Extensions.DependencyInjection optionsBuilder?.Invoke(options); - foreach (var dbContextType in options.ReplacedDbContextTypes) - { - services.Replace(ServiceDescriptor.Transient(dbContextType, typeof(TMongoDbContext))); - } - - foreach (var dbContextType in options.ReplacedDbContextTypes) + foreach (var entry in options.ReplacedDbContextTypes) { + var originalDbContextType = entry.Key; + var targetDbContextType = entry.Value ?? typeof(TMongoDbContext); + services.Replace( ServiceDescriptor.Transient( - dbContextType, - sp => sp.GetRequiredService(typeof(TMongoDbContext)) + originalDbContextType, + sp => sp.GetRequiredService(targetDbContextType) ) ); services.Configure(opts => { - opts.DbContextReplacements[dbContextType] = typeof(TMongoDbContext); + opts.DbContextReplacements[originalDbContextType] = targetDbContextType; }); } diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionInfo.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionInfo.cs index 237953db4a..7b71386474 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionInfo.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionInfo.cs @@ -24,7 +24,7 @@ namespace Volo.Abp.ObjectExtending public ObjectExtensionInfo([NotNull] Type type) { - Type = Check.AssignableTo(type, nameof(type)); + Type = Check.NotNull(type, nameof(type)); Properties = new ConcurrentDictionary(); Configuration = new ConcurrentDictionary(); Validators = new List>(); diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManager.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManager.cs index 4cbc3a3fb8..85a60a2824 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManager.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionManager.cs @@ -25,7 +25,6 @@ namespace Volo.Abp.ObjectExtending [NotNull] public virtual ObjectExtensionManager AddOrUpdate( [CanBeNull] Action configureAction = null) - where TObject : IHasExtraProperties { return AddOrUpdate(typeof(TObject), configureAction); } @@ -50,8 +49,6 @@ namespace Volo.Abp.ObjectExtending [NotNull] Type type, [CanBeNull] Action configureAction = null) { - Check.AssignableTo(type, nameof(type)); - var extensionInfo = ObjectsExtensions.GetOrAdd( type, _ => new ObjectExtensionInfo(type) @@ -64,7 +61,6 @@ namespace Volo.Abp.ObjectExtending [CanBeNull] public virtual ObjectExtensionInfo GetOrNull() - where TObject : IHasExtraProperties { return GetOrNull(typeof(TObject)); } @@ -72,8 +68,6 @@ namespace Volo.Abp.ObjectExtending [CanBeNull] public virtual ObjectExtensionInfo GetOrNull([NotNull] Type type) { - Check.AssignableTo(type, nameof(type)); - return ObjectsExtensions.GetOrDefault(type); } diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs index 878c03d629..7b4f8fda33 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs @@ -89,6 +89,11 @@ namespace Volo.Abp.Uow public virtual async Task SaveChangesAsync(CancellationToken cancellationToken = default) { + if (_isRolledback) + { + return; + } + foreach (var databaseApi in GetAllActiveDatabaseApis()) { if (databaseApi is ISupportsSavingChanges) diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs index ae016e6954..912f68e4af 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.Reflection; @@ -120,9 +121,10 @@ namespace Volo.Abp.Validation MemberName = property.Name }; + var attributeValidationResultProvider = ServiceProvider.GetRequiredService(); foreach (var attribute in validationAttributes) { - var result = attribute.GetValidationResult(property.GetValue(validatingObject), validationContext); + var result = attributeValidationResultProvider.GetOrDefault(attribute, property.GetValue(validatingObject), validationContext); if (result != null) { errors.Add(result); diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DefaultAttributeValidationResultProvider.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DefaultAttributeValidationResultProvider.cs new file mode 100644 index 0000000000..f60a695b65 --- /dev/null +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DefaultAttributeValidationResultProvider.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Validation +{ + public class DefaultAttributeValidationResultProvider : IAttributeValidationResultProvider, ITransientDependency + { + public virtual ValidationResult GetOrDefault(ValidationAttribute validationAttribute, object validatingObject, ValidationContext validationContext) + { + return validationAttribute.GetValidationResult(validatingObject, validationContext); + } + } +} diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IAttributeValidationResultProvider.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IAttributeValidationResultProvider.cs new file mode 100644 index 0000000000..a5fa367092 --- /dev/null +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IAttributeValidationResultProvider.cs @@ -0,0 +1,9 @@ +using System.ComponentModel.DataAnnotations; + +namespace Volo.Abp.Validation +{ + public interface IAttributeValidationResultProvider + { + ValidationResult GetOrDefault(ValidationAttribute validationAttribute, object validatingObject, ValidationContext validationContext); + } +} diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj deleted file mode 100644 index fcde227f3a..0000000000 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - net5.0 - $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; - Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests - Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests - true - true - true - true - - - - - - - - - - - - - - - - - - PreserveNewest - - - - - - - - - - - - - diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml deleted file mode 100644 index 779494d70f..0000000000 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml +++ /dev/null @@ -1,88 +0,0 @@ -@page -@model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.PopoversModel -@{ - ViewData["Title"] = "Popovers"; -} - -@section styles { - - - -} - -@section scripts { - - @* - *@ - -} - - - - - - -

    Popovers

    - -

    Based on Bootstrap Popovers.

    - - -

    Example

    - -
    -
    - - - Popover Default - - - Popover With Title - - - Dismissible Popover - - - Disabled Popover - - - Disabled Popover - -
    -
    - - -
    
    -<abp-button abp-popover="Hi, i'm popover content!">
    -       Popover Default
    -</abp-button>
    -<abp-button abp-popover-top="Hi, i'm popover content!" title="Popover Title">
    -       Popover With Title
    -</abp-button>
    -<abp-button abp-popover-right="Hi, i'm popover content!" title="Popover Title" dismissible="true">
    -       Dismissible Popover
    -</abp-button>
    -<abp-button abp-popover-left="Hi, i'm popover content!" title="Popover Title" disabled="true">
    -       Disabled Popover
    -</abp-button>
    -
    -
    - -
    
    -<button class="btn" type="button" data-busy-text="Processing..." data-toggle="popover" data-placement="bottom" data-content="Hi, i'm popover content!" data-original-title="" title="">
    -      Popover Default
    -</button>
    -<button title="" class="btn" type="button" data-busy-text="Processing..." data-toggle="popover" data-placement="top" data-content="Hi, i'm popover content!" data-original-title="Popover Title">
    -      Popover With Title
    -</button>
    -<button title="" class="btn" type="button" data-busy-text="Processing..." data-toggle="popover" data-placement="right" data-content="Hi, i'm popover content!" data-trigger="focus" data-original-title="Popover Title">
    -      Dismissible Popover
    -</button>
    -<span class="d-inline-block" title="" data-placement="left" data-toggle="popover" data-content="Hi, i'm popover content!" data-original-title="Popover Title"><button title="Popover Title" class="btn" type="button" data-busy-text="Processing..." style="pointer-events: none;">
    -      Disabled Popover
    -</button></span>
    -
    -
    -
    -
    -
    diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj deleted file mode 100644 index b0cd1e1aeb..0000000000 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - net5.0 - true - - - - - - - - - - - - - - diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json deleted file mode 100644 index 6ac5027054..0000000000 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "version": "1.0.0", - "name": "asp.net", - "private": true, - "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.shared": "^4.3.1", - "highlight.js": "^9.13.1" - }, - "devDependencies": {} -} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js deleted file mode 100644 index 359d2f7247..0000000000 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js +++ /dev/null @@ -1,694 +0,0 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('just-compare')) : - typeof define === 'function' && define.amd ? define('@abp/utils', ['exports', 'just-compare'], factory) : - (global = global || self, factory((global.abp = global.abp || {}, global.abp.utils = global.abp.utils || {}, global.abp.utils.common = {}), global.compare)); -}(this, (function (exports, compare) { 'use strict'; - - compare = compare && Object.prototype.hasOwnProperty.call(compare, 'default') ? compare['default'] : compare; - - /*! ***************************************************************************** - Copyright (c) Microsoft Corporation. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. - ***************************************************************************** */ - /* global Reflect, Promise */ - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) - if (b.hasOwnProperty(p)) - d[p] = b[p]; }; - return extendStatics(d, b); - }; - function __extends(d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - } - var __assign = function () { - __assign = Object.assign || function __assign(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) - if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); - }; - function __rest(s, e) { - var t = {}; - for (var p in s) - if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) - t[p] = s[p]; - if (s != null && typeof Object.getOwnPropertySymbols === "function") - for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { - if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) - t[p[i]] = s[p[i]]; - } - return t; - } - function __decorate(decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") - r = Reflect.decorate(decorators, target, key, desc); - else - for (var i = decorators.length - 1; i >= 0; i--) - if (d = decorators[i]) - r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; - } - function __param(paramIndex, decorator) { - return function (target, key) { decorator(target, key, paramIndex); }; - } - function __metadata(metadataKey, metadataValue) { - if (typeof Reflect === "object" && typeof Reflect.metadata === "function") - return Reflect.metadata(metadataKey, metadataValue); - } - function __awaiter(thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { - step(generator.next(value)); - } - catch (e) { - reject(e); - } } - function rejected(value) { try { - step(generator["throw"](value)); - } - catch (e) { - reject(e); - } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); - } - function __generator(thisArg, body) { - var _ = { label: 0, sent: function () { if (t[0] & 1) - throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) - throw new TypeError("Generator is already executing."); - while (_) - try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) - return t; - if (y = 0, t) - op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: - case 1: - t = op; - break; - case 4: - _.label++; - return { value: op[1], done: false }; - case 5: - _.label++; - y = op[1]; - op = [0]; - continue; - case 7: - op = _.ops.pop(); - _.trys.pop(); - continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { - _ = 0; - continue; - } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { - _.label = op[1]; - break; - } - if (op[0] === 6 && _.label < t[1]) { - _.label = t[1]; - t = op; - break; - } - if (t && _.label < t[2]) { - _.label = t[2]; - _.ops.push(op); - break; - } - if (t[2]) - _.ops.pop(); - _.trys.pop(); - continue; - } - op = body.call(thisArg, _); - } - catch (e) { - op = [6, e]; - y = 0; - } - finally { - f = t = 0; - } - if (op[0] & 5) - throw op[1]; - return { value: op[0] ? op[1] : void 0, done: true }; - } - } - var __createBinding = Object.create ? (function (o, m, k, k2) { - if (k2 === undefined) - k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } }); - }) : (function (o, m, k, k2) { - if (k2 === undefined) - k2 = k; - o[k2] = m[k]; - }); - function __exportStar(m, exports) { - for (var p in m) - if (p !== "default" && !exports.hasOwnProperty(p)) - __createBinding(exports, m, p); - } - function __values(o) { - var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; - if (m) - return m.call(o); - if (o && typeof o.length === "number") - return { - next: function () { - if (o && i >= o.length) - o = void 0; - return { value: o && o[i++], done: !o }; - } - }; - throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); - } - function __read(o, n) { - var m = typeof Symbol === "function" && o[Symbol.iterator]; - if (!m) - return o; - var i = m.call(o), r, ar = [], e; - try { - while ((n === void 0 || n-- > 0) && !(r = i.next()).done) - ar.push(r.value); - } - catch (error) { - e = { error: error }; - } - finally { - try { - if (r && !r.done && (m = i["return"])) - m.call(i); - } - finally { - if (e) - throw e.error; - } - } - return ar; - } - function __spread() { - for (var ar = [], i = 0; i < arguments.length; i++) - ar = ar.concat(__read(arguments[i])); - return ar; - } - function __spreadArrays() { - for (var s = 0, i = 0, il = arguments.length; i < il; i++) - s += arguments[i].length; - for (var r = Array(s), k = 0, i = 0; i < il; i++) - for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) - r[k] = a[j]; - return r; - } - ; - function __await(v) { - return this instanceof __await ? (this.v = v, this) : new __await(v); - } - function __asyncGenerator(thisArg, _arguments, generator) { - if (!Symbol.asyncIterator) - throw new TypeError("Symbol.asyncIterator is not defined."); - var g = generator.apply(thisArg, _arguments || []), i, q = []; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; - function verb(n) { if (g[n]) - i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } - function resume(n, v) { try { - step(g[n](v)); - } - catch (e) { - settle(q[0][3], e); - } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } - function fulfill(value) { resume("next", value); } - function reject(value) { resume("throw", value); } - function settle(f, v) { if (f(v), q.shift(), q.length) - resume(q[0][0], q[0][1]); } - } - function __asyncDelegator(o) { - var i, p; - return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; - function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; } - } - function __asyncValues(o) { - if (!Symbol.asyncIterator) - throw new TypeError("Symbol.asyncIterator is not defined."); - var m = o[Symbol.asyncIterator], i; - return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); - function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } - function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); } - } - function __makeTemplateObject(cooked, raw) { - if (Object.defineProperty) { - Object.defineProperty(cooked, "raw", { value: raw }); - } - else { - cooked.raw = raw; - } - return cooked; - } - ; - var __setModuleDefault = Object.create ? (function (o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); - }) : function (o, v) { - o["default"] = v; - }; - function __importStar(mod) { - if (mod && mod.__esModule) - return mod; - var result = {}; - if (mod != null) - for (var k in mod) - if (Object.hasOwnProperty.call(mod, k)) - __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; - } - function __importDefault(mod) { - return (mod && mod.__esModule) ? mod : { default: mod }; - } - function __classPrivateFieldGet(receiver, privateMap) { - if (!privateMap.has(receiver)) { - throw new TypeError("attempted to get private field on non-instance"); - } - return privateMap.get(receiver); - } - function __classPrivateFieldSet(receiver, privateMap, value) { - if (!privateMap.has(receiver)) { - throw new TypeError("attempted to set private field on non-instance"); - } - privateMap.set(receiver, value); - return value; - } - - var ListNode = /** @class */ (function () { - function ListNode(value) { - this.value = value; - } - return ListNode; - }()); - var LinkedList = /** @class */ (function () { - function LinkedList() { - this.size = 0; - } - Object.defineProperty(LinkedList.prototype, "head", { - get: function () { - return this.first; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(LinkedList.prototype, "tail", { - get: function () { - return this.last; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(LinkedList.prototype, "length", { - get: function () { - return this.size; - }, - enumerable: false, - configurable: true - }); - LinkedList.prototype.attach = function (value, previousNode, nextNode) { - if (!previousNode) - return this.addHead(value); - if (!nextNode) - return this.addTail(value); - var node = new ListNode(value); - node.previous = previousNode; - previousNode.next = node; - node.next = nextNode; - nextNode.previous = node; - this.size++; - return node; - }; - LinkedList.prototype.attachMany = function (values, previousNode, nextNode) { - if (!values.length) - return []; - if (!previousNode) - return this.addManyHead(values); - if (!nextNode) - return this.addManyTail(values); - var list = new LinkedList(); - list.addManyTail(values); - list.first.previous = previousNode; - previousNode.next = list.first; - list.last.next = nextNode; - nextNode.previous = list.last; - this.size += values.length; - return list.toNodeArray(); - }; - LinkedList.prototype.detach = function (node) { - if (!node.previous) - return this.dropHead(); - if (!node.next) - return this.dropTail(); - node.previous.next = node.next; - node.next.previous = node.previous; - this.size--; - return node; - }; - LinkedList.prototype.add = function (value) { - var _this = this; - return { - after: function () { - var _a; - var params = []; - for (var _i = 0; _i < arguments.length; _i++) { - params[_i] = arguments[_i]; - } - return (_a = _this.addAfter).call.apply(_a, __spread([_this, value], params)); - }, - before: function () { - var _a; - var params = []; - for (var _i = 0; _i < arguments.length; _i++) { - params[_i] = arguments[_i]; - } - return (_a = _this.addBefore).call.apply(_a, __spread([_this, value], params)); - }, - byIndex: function (position) { return _this.addByIndex(value, position); }, - head: function () { return _this.addHead(value); }, - tail: function () { return _this.addTail(value); }, - }; - }; - LinkedList.prototype.addMany = function (values) { - var _this = this; - return { - after: function () { - var _a; - var params = []; - for (var _i = 0; _i < arguments.length; _i++) { - params[_i] = arguments[_i]; - } - return (_a = _this.addManyAfter).call.apply(_a, __spread([_this, values], params)); - }, - before: function () { - var _a; - var params = []; - for (var _i = 0; _i < arguments.length; _i++) { - params[_i] = arguments[_i]; - } - return (_a = _this.addManyBefore).call.apply(_a, __spread([_this, values], params)); - }, - byIndex: function (position) { return _this.addManyByIndex(values, position); }, - head: function () { return _this.addManyHead(values); }, - tail: function () { return _this.addManyTail(values); }, - }; - }; - LinkedList.prototype.addAfter = function (value, previousValue, compareFn) { - if (compareFn === void 0) { compareFn = compare; } - var previous = this.find(function (node) { return compareFn(node.value, previousValue); }); - return previous ? this.attach(value, previous, previous.next) : this.addTail(value); - }; - LinkedList.prototype.addBefore = function (value, nextValue, compareFn) { - if (compareFn === void 0) { compareFn = compare; } - var next = this.find(function (node) { return compareFn(node.value, nextValue); }); - return next ? this.attach(value, next.previous, next) : this.addHead(value); - }; - LinkedList.prototype.addByIndex = function (value, position) { - if (position < 0) - position += this.size; - else if (position >= this.size) - return this.addTail(value); - if (position <= 0) - return this.addHead(value); - var next = this.get(position); - return this.attach(value, next.previous, next); - }; - LinkedList.prototype.addHead = function (value) { - var node = new ListNode(value); - node.next = this.first; - if (this.first) - this.first.previous = node; - else - this.last = node; - this.first = node; - this.size++; - return node; - }; - LinkedList.prototype.addTail = function (value) { - var node = new ListNode(value); - if (this.first) { - node.previous = this.last; - this.last.next = node; - this.last = node; - } - else { - this.first = node; - this.last = node; - } - this.size++; - return node; - }; - LinkedList.prototype.addManyAfter = function (values, previousValue, compareFn) { - if (compareFn === void 0) { compareFn = compare; } - var previous = this.find(function (node) { return compareFn(node.value, previousValue); }); - return previous ? this.attachMany(values, previous, previous.next) : this.addManyTail(values); - }; - LinkedList.prototype.addManyBefore = function (values, nextValue, compareFn) { - if (compareFn === void 0) { compareFn = compare; } - var next = this.find(function (node) { return compareFn(node.value, nextValue); }); - return next ? this.attachMany(values, next.previous, next) : this.addManyHead(values); - }; - LinkedList.prototype.addManyByIndex = function (values, position) { - if (position < 0) - position += this.size; - if (position <= 0) - return this.addManyHead(values); - if (position >= this.size) - return this.addManyTail(values); - var next = this.get(position); - return this.attachMany(values, next.previous, next); - }; - LinkedList.prototype.addManyHead = function (values) { - var _this = this; - return values.reduceRight(function (nodes, value) { - nodes.unshift(_this.addHead(value)); - return nodes; - }, []); - }; - LinkedList.prototype.addManyTail = function (values) { - var _this = this; - return values.map(function (value) { return _this.addTail(value); }); - }; - LinkedList.prototype.drop = function () { - var _this = this; - return { - byIndex: function (position) { return _this.dropByIndex(position); }, - byValue: function () { - var params = []; - for (var _i = 0; _i < arguments.length; _i++) { - params[_i] = arguments[_i]; - } - return _this.dropByValue.apply(_this, params); - }, - byValueAll: function () { - var params = []; - for (var _i = 0; _i < arguments.length; _i++) { - params[_i] = arguments[_i]; - } - return _this.dropByValueAll.apply(_this, params); - }, - head: function () { return _this.dropHead(); }, - tail: function () { return _this.dropTail(); }, - }; - }; - LinkedList.prototype.dropMany = function (count) { - var _this = this; - return { - byIndex: function (position) { return _this.dropManyByIndex(count, position); }, - head: function () { return _this.dropManyHead(count); }, - tail: function () { return _this.dropManyTail(count); }, - }; - }; - LinkedList.prototype.dropByIndex = function (position) { - if (position < 0) - position += this.size; - var current = this.get(position); - return current ? this.detach(current) : undefined; - }; - LinkedList.prototype.dropByValue = function (value, compareFn) { - if (compareFn === void 0) { compareFn = compare; } - var position = this.findIndex(function (node) { return compareFn(node.value, value); }); - return position < 0 ? undefined : this.dropByIndex(position); - }; - LinkedList.prototype.dropByValueAll = function (value, compareFn) { - if (compareFn === void 0) { compareFn = compare; } - var dropped = []; - for (var current = this.first, position = 0; current; position++, current = current.next) { - if (compareFn(current.value, value)) { - dropped.push(this.dropByIndex(position - dropped.length)); - } - } - return dropped; - }; - LinkedList.prototype.dropHead = function () { - var head = this.first; - if (head) { - this.first = head.next; - if (this.first) - this.first.previous = undefined; - else - this.last = undefined; - this.size--; - return head; - } - return undefined; - }; - LinkedList.prototype.dropTail = function () { - var tail = this.last; - if (tail) { - this.last = tail.previous; - if (this.last) - this.last.next = undefined; - else - this.first = undefined; - this.size--; - return tail; - } - return undefined; - }; - LinkedList.prototype.dropManyByIndex = function (count, position) { - if (count <= 0) - return []; - if (position < 0) - position = Math.max(position + this.size, 0); - else if (position >= this.size) - return []; - count = Math.min(count, this.size - position); - var dropped = []; - while (count--) { - var current = this.get(position); - dropped.push(this.detach(current)); - } - return dropped; - }; - LinkedList.prototype.dropManyHead = function (count) { - if (count <= 0) - return []; - count = Math.min(count, this.size); - var dropped = []; - while (count--) - dropped.unshift(this.dropHead()); - return dropped; - }; - LinkedList.prototype.dropManyTail = function (count) { - if (count <= 0) - return []; - count = Math.min(count, this.size); - var dropped = []; - while (count--) - dropped.push(this.dropTail()); - return dropped; - }; - LinkedList.prototype.find = function (predicate) { - for (var current = this.first, position = 0; current; position++, current = current.next) { - if (predicate(current, position, this)) - return current; - } - return undefined; - }; - LinkedList.prototype.findIndex = function (predicate) { - for (var current = this.first, position = 0; current; position++, current = current.next) { - if (predicate(current, position, this)) - return position; - } - return -1; - }; - LinkedList.prototype.forEach = function (iteratorFn) { - for (var node = this.first, position = 0; node; position++, node = node.next) { - iteratorFn(node, position, this); - } - }; - LinkedList.prototype.get = function (position) { - return this.find(function (_, index) { return position === index; }); - }; - LinkedList.prototype.indexOf = function (value, compareFn) { - if (compareFn === void 0) { compareFn = compare; } - return this.findIndex(function (node) { return compareFn(node.value, value); }); - }; - LinkedList.prototype.toArray = function () { - var array = new Array(this.size); - this.forEach(function (node, index) { return (array[index] = node.value); }); - return array; - }; - LinkedList.prototype.toNodeArray = function () { - var array = new Array(this.size); - this.forEach(function (node, index) { return (array[index] = node); }); - return array; - }; - LinkedList.prototype.toString = function (mapperFn) { - if (mapperFn === void 0) { mapperFn = JSON.stringify; } - return this.toArray() - .map(function (value) { return mapperFn(value); }) - .join(' <-> '); - }; - // Cannot use Generator type because of ng-packagr - LinkedList.prototype[Symbol.iterator] = function () { - var node, position; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - node = this.first, position = 0; - _a.label = 1; - case 1: - if (!node) return [3 /*break*/, 4]; - return [4 /*yield*/, node.value]; - case 2: - _a.sent(); - _a.label = 3; - case 3: - position++, node = node.next; - return [3 /*break*/, 1]; - case 4: return [2 /*return*/]; - } - }); - }; - return LinkedList; - }()); - - /* - * Public API Surface of utils - */ - - /** - * Generated bundle index. Do not edit. - */ - - exports.LinkedList = LinkedList; - exports.ListNode = ListNode; - - Object.defineProperty(exports, '__esModule', { value: true }); - -}))); -//# sourceMappingURL=abp-utils.umd.js.map diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/jquery.validate.js b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/jquery.validate.js deleted file mode 100644 index abc357d190..0000000000 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/jquery.validate.js +++ /dev/null @@ -1,1601 +0,0 @@ -/*! - * jQuery Validation Plugin v1.17.0 - * - * https://jqueryvalidation.org/ - * - * Copyright (c) 2017 Jörn Zaefferer - * Released under the MIT license - */ -(function( factory ) { - if ( typeof define === "function" && define.amd ) { - define( ["jquery"], factory ); - } else if (typeof module === "object" && module.exports) { - module.exports = factory( require( "jquery" ) ); - } else { - factory( jQuery ); - } -}(function( $ ) { - -$.extend( $.fn, { - - // https://jqueryvalidation.org/validate/ - validate: function( options ) { - - // If nothing is selected, return nothing; can't chain anyway - if ( !this.length ) { - if ( options && options.debug && window.console ) { - console.warn( "Nothing selected, can't validate, returning nothing." ); - } - return; - } - - // Check if a validator for this form was already created - var validator = $.data( this[ 0 ], "validator" ); - if ( validator ) { - return validator; - } - - // Add novalidate tag if HTML5. - this.attr( "novalidate", "novalidate" ); - - validator = new $.validator( options, this[ 0 ] ); - $.data( this[ 0 ], "validator", validator ); - - if ( validator.settings.onsubmit ) { - - this.on( "click.validate", ":submit", function( event ) { - - // Track the used submit button to properly handle scripted - // submits later. - validator.submitButton = event.currentTarget; - - // Allow suppressing validation by adding a cancel class to the submit button - if ( $( this ).hasClass( "cancel" ) ) { - validator.cancelSubmit = true; - } - - // Allow suppressing validation by adding the html5 formnovalidate attribute to the submit button - if ( $( this ).attr( "formnovalidate" ) !== undefined ) { - validator.cancelSubmit = true; - } - } ); - - // Validate the form on submit - this.on( "submit.validate", function( event ) { - if ( validator.settings.debug ) { - - // Prevent form submit to be able to see console output - event.preventDefault(); - } - function handle() { - var hidden, result; - - // Insert a hidden input as a replacement for the missing submit button - // The hidden input is inserted in two cases: - // - A user defined a `submitHandler` - // - There was a pending request due to `remote` method and `stopRequest()` - // was called to submit the form in case it's valid - if ( validator.submitButton && ( validator.settings.submitHandler || validator.formSubmitted ) ) { - hidden = $( "" ) - .attr( "name", validator.submitButton.name ) - .val( $( validator.submitButton ).val() ) - .appendTo( validator.currentForm ); - } - - if ( validator.settings.submitHandler ) { - result = validator.settings.submitHandler.call( validator, validator.currentForm, event ); - if ( hidden ) { - - // And clean up afterwards; thanks to no-block-scope, hidden can be referenced - hidden.remove(); - } - if ( result !== undefined ) { - return result; - } - return false; - } - return true; - } - - // Prevent submit for invalid forms or custom submit handlers - if ( validator.cancelSubmit ) { - validator.cancelSubmit = false; - return handle(); - } - if ( validator.form() ) { - if ( validator.pendingRequest ) { - validator.formSubmitted = true; - return false; - } - return handle(); - } else { - validator.focusInvalid(); - return false; - } - } ); - } - - return validator; - }, - - // https://jqueryvalidation.org/valid/ - valid: function() { - var valid, validator, errorList; - - if ( $( this[ 0 ] ).is( "form" ) ) { - valid = this.validate().form(); - } else { - errorList = []; - valid = true; - validator = $( this[ 0 ].form ).validate(); - this.each( function() { - valid = validator.element( this ) && valid; - if ( !valid ) { - errorList = errorList.concat( validator.errorList ); - } - } ); - validator.errorList = errorList; - } - return valid; - }, - - // https://jqueryvalidation.org/rules/ - rules: function( command, argument ) { - var element = this[ 0 ], - settings, staticRules, existingRules, data, param, filtered; - - // If nothing is selected, return empty object; can't chain anyway - if ( element == null ) { - return; - } - - if ( !element.form && element.hasAttribute( "contenteditable" ) ) { - element.form = this.closest( "form" )[ 0 ]; - element.name = this.attr( "name" ); - } - - if ( element.form == null ) { - return; - } - - if ( command ) { - settings = $.data( element.form, "validator" ).settings; - staticRules = settings.rules; - existingRules = $.validator.staticRules( element ); - switch ( command ) { - case "add": - $.extend( existingRules, $.validator.normalizeRule( argument ) ); - - // Remove messages from rules, but allow them to be set separately - delete existingRules.messages; - staticRules[ element.name ] = existingRules; - if ( argument.messages ) { - settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages ); - } - break; - case "remove": - if ( !argument ) { - delete staticRules[ element.name ]; - return existingRules; - } - filtered = {}; - $.each( argument.split( /\s/ ), function( index, method ) { - filtered[ method ] = existingRules[ method ]; - delete existingRules[ method ]; - } ); - return filtered; - } - } - - data = $.validator.normalizeRules( - $.extend( - {}, - $.validator.classRules( element ), - $.validator.attributeRules( element ), - $.validator.dataRules( element ), - $.validator.staticRules( element ) - ), element ); - - // Make sure required is at front - if ( data.required ) { - param = data.required; - delete data.required; - data = $.extend( { required: param }, data ); - } - - // Make sure remote is at back - if ( data.remote ) { - param = data.remote; - delete data.remote; - data = $.extend( data, { remote: param } ); - } - - return data; - } -} ); - -// Custom selectors -$.extend( $.expr.pseudos || $.expr[ ":" ], { // '|| $.expr[ ":" ]' here enables backwards compatibility to jQuery 1.7. Can be removed when dropping jQ 1.7.x support - - // https://jqueryvalidation.org/blank-selector/ - blank: function( a ) { - return !$.trim( "" + $( a ).val() ); - }, - - // https://jqueryvalidation.org/filled-selector/ - filled: function( a ) { - var val = $( a ).val(); - return val !== null && !!$.trim( "" + val ); - }, - - // https://jqueryvalidation.org/unchecked-selector/ - unchecked: function( a ) { - return !$( a ).prop( "checked" ); - } -} ); - -// Constructor for validator -$.validator = function( options, form ) { - this.settings = $.extend( true, {}, $.validator.defaults, options ); - this.currentForm = form; - this.init(); -}; - -// https://jqueryvalidation.org/jQuery.validator.format/ -$.validator.format = function( source, params ) { - if ( arguments.length === 1 ) { - return function() { - var args = $.makeArray( arguments ); - args.unshift( source ); - return $.validator.format.apply( this, args ); - }; - } - if ( params === undefined ) { - return source; - } - if ( arguments.length > 2 && params.constructor !== Array ) { - params = $.makeArray( arguments ).slice( 1 ); - } - if ( params.constructor !== Array ) { - params = [ params ]; - } - $.each( params, function( i, n ) { - source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() { - return n; - } ); - } ); - return source; -}; - -$.extend( $.validator, { - - defaults: { - messages: {}, - groups: {}, - rules: {}, - errorClass: "error", - pendingClass: "pending", - validClass: "valid", - errorElement: "label", - focusCleanup: false, - focusInvalid: true, - errorContainer: $( [] ), - errorLabelContainer: $( [] ), - onsubmit: true, - ignore: ":hidden", - ignoreTitle: false, - onfocusin: function( element ) { - this.lastActive = element; - - // Hide error label and remove error class on focus if enabled - if ( this.settings.focusCleanup ) { - if ( this.settings.unhighlight ) { - this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); - } - this.hideThese( this.errorsFor( element ) ); - } - }, - onfocusout: function( element ) { - if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) { - this.element( element ); - } - }, - onkeyup: function( element, event ) { - - // Avoid revalidate the field when pressing one of the following keys - // Shift => 16 - // Ctrl => 17 - // Alt => 18 - // Caps lock => 20 - // End => 35 - // Home => 36 - // Left arrow => 37 - // Up arrow => 38 - // Right arrow => 39 - // Down arrow => 40 - // Insert => 45 - // Num lock => 144 - // AltGr key => 225 - var excludedKeys = [ - 16, 17, 18, 20, 35, 36, 37, - 38, 39, 40, 45, 144, 225 - ]; - - if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) { - return; - } else if ( element.name in this.submitted || element.name in this.invalid ) { - this.element( element ); - } - }, - onclick: function( element ) { - - // Click on selects, radiobuttons and checkboxes - if ( element.name in this.submitted ) { - this.element( element ); - - // Or option elements, check parent select in that case - } else if ( element.parentNode.name in this.submitted ) { - this.element( element.parentNode ); - } - }, - highlight: function( element, errorClass, validClass ) { - if ( element.type === "radio" ) { - this.findByName( element.name ).addClass( errorClass ).removeClass( validClass ); - } else { - $( element ).addClass( errorClass ).removeClass( validClass ); - } - }, - unhighlight: function( element, errorClass, validClass ) { - if ( element.type === "radio" ) { - this.findByName( element.name ).removeClass( errorClass ).addClass( validClass ); - } else { - $( element ).removeClass( errorClass ).addClass( validClass ); - } - } - }, - - // https://jqueryvalidation.org/jQuery.validator.setDefaults/ - setDefaults: function( settings ) { - $.extend( $.validator.defaults, settings ); - }, - - messages: { - required: "This field is required.", - remote: "Please fix this field.", - email: "Please enter a valid email address.", - url: "Please enter a valid URL.", - date: "Please enter a valid date.", - dateISO: "Please enter a valid date (ISO).", - number: "Please enter a valid number.", - digits: "Please enter only digits.", - equalTo: "Please enter the same value again.", - maxlength: $.validator.format( "Please enter no more than {0} characters." ), - minlength: $.validator.format( "Please enter at least {0} characters." ), - rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ), - range: $.validator.format( "Please enter a value between {0} and {1}." ), - max: $.validator.format( "Please enter a value less than or equal to {0}." ), - min: $.validator.format( "Please enter a value greater than or equal to {0}." ), - step: $.validator.format( "Please enter a multiple of {0}." ) - }, - - autoCreateRanges: false, - - prototype: { - - init: function() { - this.labelContainer = $( this.settings.errorLabelContainer ); - this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm ); - this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer ); - this.submitted = {}; - this.valueCache = {}; - this.pendingRequest = 0; - this.pending = {}; - this.invalid = {}; - this.reset(); - - var groups = ( this.groups = {} ), - rules; - $.each( this.settings.groups, function( key, value ) { - if ( typeof value === "string" ) { - value = value.split( /\s/ ); - } - $.each( value, function( index, name ) { - groups[ name ] = key; - } ); - } ); - rules = this.settings.rules; - $.each( rules, function( key, value ) { - rules[ key ] = $.validator.normalizeRule( value ); - } ); - - function delegate( event ) { - - // Set form expando on contenteditable - if ( !this.form && this.hasAttribute( "contenteditable" ) ) { - this.form = $( this ).closest( "form" )[ 0 ]; - this.name = $( this ).attr( "name" ); - } - - var validator = $.data( this.form, "validator" ), - eventType = "on" + event.type.replace( /^validate/, "" ), - settings = validator.settings; - if ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) { - settings[ eventType ].call( validator, this, event ); - } - } - - $( this.currentForm ) - .on( "focusin.validate focusout.validate keyup.validate", - ":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " + - "[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " + - "[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " + - "[type='radio'], [type='checkbox'], [contenteditable], [type='button']", delegate ) - - // Support: Chrome, oldIE - // "select" is provided as event.target when clicking a option - .on( "click.validate", "select, option, [type='radio'], [type='checkbox']", delegate ); - - if ( this.settings.invalidHandler ) { - $( this.currentForm ).on( "invalid-form.validate", this.settings.invalidHandler ); - } - }, - - // https://jqueryvalidation.org/Validator.form/ - form: function() { - this.checkForm(); - $.extend( this.submitted, this.errorMap ); - this.invalid = $.extend( {}, this.errorMap ); - if ( !this.valid() ) { - $( this.currentForm ).triggerHandler( "invalid-form", [ this ] ); - } - this.showErrors(); - return this.valid(); - }, - - checkForm: function() { - this.prepareForm(); - for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) { - this.check( elements[ i ] ); - } - return this.valid(); - }, - - // https://jqueryvalidation.org/Validator.element/ - element: function( element ) { - var cleanElement = this.clean( element ), - checkElement = this.validationTargetFor( cleanElement ), - v = this, - result = true, - rs, group; - - if ( checkElement === undefined ) { - delete this.invalid[ cleanElement.name ]; - } else { - this.prepareElement( checkElement ); - this.currentElements = $( checkElement ); - - // If this element is grouped, then validate all group elements already - // containing a value - group = this.groups[ checkElement.name ]; - if ( group ) { - $.each( this.groups, function( name, testgroup ) { - if ( testgroup === group && name !== checkElement.name ) { - cleanElement = v.validationTargetFor( v.clean( v.findByName( name ) ) ); - if ( cleanElement && cleanElement.name in v.invalid ) { - v.currentElements.push( cleanElement ); - result = v.check( cleanElement ) && result; - } - } - } ); - } - - rs = this.check( checkElement ) !== false; - result = result && rs; - if ( rs ) { - this.invalid[ checkElement.name ] = false; - } else { - this.invalid[ checkElement.name ] = true; - } - - if ( !this.numberOfInvalids() ) { - - // Hide error containers on last error - this.toHide = this.toHide.add( this.containers ); - } - this.showErrors(); - - // Add aria-invalid status for screen readers - $( element ).attr( "aria-invalid", !rs ); - } - - return result; - }, - - // https://jqueryvalidation.org/Validator.showErrors/ - showErrors: function( errors ) { - if ( errors ) { - var validator = this; - - // Add items to error list and map - $.extend( this.errorMap, errors ); - this.errorList = $.map( this.errorMap, function( message, name ) { - return { - message: message, - element: validator.findByName( name )[ 0 ] - }; - } ); - - // Remove items from success list - this.successList = $.grep( this.successList, function( element ) { - return !( element.name in errors ); - } ); - } - if ( this.settings.showErrors ) { - this.settings.showErrors.call( this, this.errorMap, this.errorList ); - } else { - this.defaultShowErrors(); - } - }, - - // https://jqueryvalidation.org/Validator.resetForm/ - resetForm: function() { - if ( $.fn.resetForm ) { - $( this.currentForm ).resetForm(); - } - this.invalid = {}; - this.submitted = {}; - this.prepareForm(); - this.hideErrors(); - var elements = this.elements() - .removeData( "previousValue" ) - .removeAttr( "aria-invalid" ); - - this.resetElements( elements ); - }, - - resetElements: function( elements ) { - var i; - - if ( this.settings.unhighlight ) { - for ( i = 0; elements[ i ]; i++ ) { - this.settings.unhighlight.call( this, elements[ i ], - this.settings.errorClass, "" ); - this.findByName( elements[ i ].name ).removeClass( this.settings.validClass ); - } - } else { - elements - .removeClass( this.settings.errorClass ) - .removeClass( this.settings.validClass ); - } - }, - - numberOfInvalids: function() { - return this.objectLength( this.invalid ); - }, - - objectLength: function( obj ) { - /* jshint unused: false */ - var count = 0, - i; - for ( i in obj ) { - - // This check allows counting elements with empty error - // message as invalid elements - if ( obj[ i ] !== undefined && obj[ i ] !== null && obj[ i ] !== false ) { - count++; - } - } - return count; - }, - - hideErrors: function() { - this.hideThese( this.toHide ); - }, - - hideThese: function( errors ) { - errors.not( this.containers ).text( "" ); - this.addWrapper( errors ).hide(); - }, - - valid: function() { - return this.size() === 0; - }, - - size: function() { - return this.errorList.length; - }, - - focusInvalid: function() { - if ( this.settings.focusInvalid ) { - try { - $( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [] ) - .filter( ":visible" ) - .focus() - - // Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find - .trigger( "focusin" ); - } catch ( e ) { - - // Ignore IE throwing errors when focusing hidden elements - } - } - }, - - findLastActive: function() { - var lastActive = this.lastActive; - return lastActive && $.grep( this.errorList, function( n ) { - return n.element.name === lastActive.name; - } ).length === 1 && lastActive; - }, - - elements: function() { - var validator = this, - rulesCache = {}; - - // Select all valid inputs inside the form (no submit or reset buttons) - return $( this.currentForm ) - .find( "input, select, textarea, [contenteditable]" ) - .not( ":submit, :reset, :image, :disabled" ) - .not( this.settings.ignore ) - .filter( function() { - var name = this.name || $( this ).attr( "name" ); // For contenteditable - if ( !name && validator.settings.debug && window.console ) { - console.error( "%o has no name assigned", this ); - } - - // Set form expando on contenteditable - if ( this.hasAttribute( "contenteditable" ) ) { - this.form = $( this ).closest( "form" )[ 0 ]; - this.name = name; - } - - // Select only the first element for each name, and only those with rules specified - if ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) { - return false; - } - - rulesCache[ name ] = true; - return true; - } ); - }, - - clean: function( selector ) { - return $( selector )[ 0 ]; - }, - - errors: function() { - var errorClass = this.settings.errorClass.split( " " ).join( "." ); - return $( this.settings.errorElement + "." + errorClass, this.errorContext ); - }, - - resetInternals: function() { - this.successList = []; - this.errorList = []; - this.errorMap = {}; - this.toShow = $( [] ); - this.toHide = $( [] ); - }, - - reset: function() { - this.resetInternals(); - this.currentElements = $( [] ); - }, - - prepareForm: function() { - this.reset(); - this.toHide = this.errors().add( this.containers ); - }, - - prepareElement: function( element ) { - this.reset(); - this.toHide = this.errorsFor( element ); - }, - - elementValue: function( element ) { - var $element = $( element ), - type = element.type, - val, idx; - - if ( type === "radio" || type === "checkbox" ) { - return this.findByName( element.name ).filter( ":checked" ).val(); - } else if ( type === "number" && typeof element.validity !== "undefined" ) { - return element.validity.badInput ? "NaN" : $element.val(); - } - - if ( element.hasAttribute( "contenteditable" ) ) { - val = $element.text(); - } else { - val = $element.val(); - } - - if ( type === "file" ) { - - // Modern browser (chrome & safari) - if ( val.substr( 0, 12 ) === "C:\\fakepath\\" ) { - return val.substr( 12 ); - } - - // Legacy browsers - // Unix-based path - idx = val.lastIndexOf( "/" ); - if ( idx >= 0 ) { - return val.substr( idx + 1 ); - } - - // Windows-based path - idx = val.lastIndexOf( "\\" ); - if ( idx >= 0 ) { - return val.substr( idx + 1 ); - } - - // Just the file name - return val; - } - - if ( typeof val === "string" ) { - return val.replace( /\r/g, "" ); - } - return val; - }, - - check: function( element ) { - element = this.validationTargetFor( this.clean( element ) ); - - var rules = $( element ).rules(), - rulesCount = $.map( rules, function( n, i ) { - return i; - } ).length, - dependencyMismatch = false, - val = this.elementValue( element ), - result, method, rule, normalizer; - - // Prioritize the local normalizer defined for this element over the global one - // if the former exists, otherwise user the global one in case it exists. - if ( typeof rules.normalizer === "function" ) { - normalizer = rules.normalizer; - } else if ( typeof this.settings.normalizer === "function" ) { - normalizer = this.settings.normalizer; - } - - // If normalizer is defined, then call it to retreive the changed value instead - // of using the real one. - // Note that `this` in the normalizer is `element`. - if ( normalizer ) { - val = normalizer.call( element, val ); - - if ( typeof val !== "string" ) { - throw new TypeError( "The normalizer should return a string value." ); - } - - // Delete the normalizer from rules to avoid treating it as a pre-defined method. - delete rules.normalizer; - } - - for ( method in rules ) { - rule = { method: method, parameters: rules[ method ] }; - try { - result = $.validator.methods[ method ].call( this, val, element, rule.parameters ); - - // If a method indicates that the field is optional and therefore valid, - // don't mark it as valid when there are no other rules - if ( result === "dependency-mismatch" && rulesCount === 1 ) { - dependencyMismatch = true; - continue; - } - dependencyMismatch = false; - - if ( result === "pending" ) { - this.toHide = this.toHide.not( this.errorsFor( element ) ); - return; - } - - if ( !result ) { - this.formatAndAdd( element, rule ); - return false; - } - } catch ( e ) { - if ( this.settings.debug && window.console ) { - console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e ); - } - if ( e instanceof TypeError ) { - e.message += ". Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method."; - } - - throw e; - } - } - if ( dependencyMismatch ) { - return; - } - if ( this.objectLength( rules ) ) { - this.successList.push( element ); - } - return true; - }, - - // Return the custom message for the given element and validation method - // specified in the element's HTML5 data attribute - // return the generic message if present and no method specific message is present - customDataMessage: function( element, method ) { - return $( element ).data( "msg" + method.charAt( 0 ).toUpperCase() + - method.substring( 1 ).toLowerCase() ) || $( element ).data( "msg" ); - }, - - // Return the custom message for the given element name and validation method - customMessage: function( name, method ) { - var m = this.settings.messages[ name ]; - return m && ( m.constructor === String ? m : m[ method ] ); - }, - - // Return the first defined argument, allowing empty strings - findDefined: function() { - for ( var i = 0; i < arguments.length; i++ ) { - if ( arguments[ i ] !== undefined ) { - return arguments[ i ]; - } - } - return undefined; - }, - - // The second parameter 'rule' used to be a string, and extended to an object literal - // of the following form: - // rule = { - // method: "method name", - // parameters: "the given method parameters" - // } - // - // The old behavior still supported, kept to maintain backward compatibility with - // old code, and will be removed in the next major release. - defaultMessage: function( element, rule ) { - if ( typeof rule === "string" ) { - rule = { method: rule }; - } - - var message = this.findDefined( - this.customMessage( element.name, rule.method ), - this.customDataMessage( element, rule.method ), - - // 'title' is never undefined, so handle empty string as undefined - !this.settings.ignoreTitle && element.title || undefined, - $.validator.messages[ rule.method ], - "Warning: No message defined for " + element.name + "" - ), - theregex = /\$?\{(\d+)\}/g; - if ( typeof message === "function" ) { - message = message.call( this, rule.parameters, element ); - } else if ( theregex.test( message ) ) { - message = $.validator.format( message.replace( theregex, "{$1}" ), rule.parameters ); - } - - return message; - }, - - formatAndAdd: function( element, rule ) { - var message = this.defaultMessage( element, rule ); - - this.errorList.push( { - message: message, - element: element, - method: rule.method - } ); - - this.errorMap[ element.name ] = message; - this.submitted[ element.name ] = message; - }, - - addWrapper: function( toToggle ) { - if ( this.settings.wrapper ) { - toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); - } - return toToggle; - }, - - defaultShowErrors: function() { - var i, elements, error; - for ( i = 0; this.errorList[ i ]; i++ ) { - error = this.errorList[ i ]; - if ( this.settings.highlight ) { - this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass ); - } - this.showLabel( error.element, error.message ); - } - if ( this.errorList.length ) { - this.toShow = this.toShow.add( this.containers ); - } - if ( this.settings.success ) { - for ( i = 0; this.successList[ i ]; i++ ) { - this.showLabel( this.successList[ i ] ); - } - } - if ( this.settings.unhighlight ) { - for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) { - this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass ); - } - } - this.toHide = this.toHide.not( this.toShow ); - this.hideErrors(); - this.addWrapper( this.toShow ).show(); - }, - - validElements: function() { - return this.currentElements.not( this.invalidElements() ); - }, - - invalidElements: function() { - return $( this.errorList ).map( function() { - return this.element; - } ); - }, - - showLabel: function( element, message ) { - var place, group, errorID, v, - error = this.errorsFor( element ), - elementID = this.idOrName( element ), - describedBy = $( element ).attr( "aria-describedby" ); - - if ( error.length ) { - - // Refresh error/success class - error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass ); - - // Replace message on existing label - error.html( message ); - } else { - - // Create error element - error = $( "<" + this.settings.errorElement + ">" ) - .attr( "id", elementID + "-error" ) - .addClass( this.settings.errorClass ) - .html( message || "" ); - - // Maintain reference to the element to be placed into the DOM - place = error; - if ( this.settings.wrapper ) { - - // Make sure the element is visible, even in IE - // actually showing the wrapped element is handled elsewhere - place = error.hide().show().wrap( "<" + this.settings.wrapper + "/>" ).parent(); - } - if ( this.labelContainer.length ) { - this.labelContainer.append( place ); - } else if ( this.settings.errorPlacement ) { - this.settings.errorPlacement.call( this, place, $( element ) ); - } else { - place.insertAfter( element ); - } - - // Link error back to the element - if ( error.is( "label" ) ) { - - // If the error is a label, then associate using 'for' - error.attr( "for", elementID ); - - // If the element is not a child of an associated label, then it's necessary - // to explicitly apply aria-describedby - } else if ( error.parents( "label[for='" + this.escapeCssMeta( elementID ) + "']" ).length === 0 ) { - errorID = error.attr( "id" ); - - // Respect existing non-error aria-describedby - if ( !describedBy ) { - describedBy = errorID; - } else if ( !describedBy.match( new RegExp( "\\b" + this.escapeCssMeta( errorID ) + "\\b" ) ) ) { - - // Add to end of list if not already present - describedBy += " " + errorID; - } - $( element ).attr( "aria-describedby", describedBy ); - - // If this element is grouped, then assign to all elements in the same group - group = this.groups[ element.name ]; - if ( group ) { - v = this; - $.each( v.groups, function( name, testgroup ) { - if ( testgroup === group ) { - $( "[name='" + v.escapeCssMeta( name ) + "']", v.currentForm ) - .attr( "aria-describedby", error.attr( "id" ) ); - } - } ); - } - } - } - if ( !message && this.settings.success ) { - error.text( "" ); - if ( typeof this.settings.success === "string" ) { - error.addClass( this.settings.success ); - } else { - this.settings.success( error, element ); - } - } - this.toShow = this.toShow.add( error ); - }, - - errorsFor: function( element ) { - var name = this.escapeCssMeta( this.idOrName( element ) ), - describer = $( element ).attr( "aria-describedby" ), - selector = "label[for='" + name + "'], label[for='" + name + "'] *"; - - // 'aria-describedby' should directly reference the error element - if ( describer ) { - selector = selector + ", #" + this.escapeCssMeta( describer ) - .replace( /\s+/g, ", #" ); - } - - return this - .errors() - .filter( selector ); - }, - - // See https://api.jquery.com/category/selectors/, for CSS - // meta-characters that should be escaped in order to be used with JQuery - // as a literal part of a name/id or any selector. - escapeCssMeta: function( string ) { - return string.replace( /([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g, "\\$1" ); - }, - - idOrName: function( element ) { - return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name ); - }, - - validationTargetFor: function( element ) { - - // If radio/checkbox, validate first element in group instead - if ( this.checkable( element ) ) { - element = this.findByName( element.name ); - } - - // Always apply ignore filter - return $( element ).not( this.settings.ignore )[ 0 ]; - }, - - checkable: function( element ) { - return ( /radio|checkbox/i ).test( element.type ); - }, - - findByName: function( name ) { - return $( this.currentForm ).find( "[name='" + this.escapeCssMeta( name ) + "']" ); - }, - - getLength: function( value, element ) { - switch ( element.nodeName.toLowerCase() ) { - case "select": - return $( "option:selected", element ).length; - case "input": - if ( this.checkable( element ) ) { - return this.findByName( element.name ).filter( ":checked" ).length; - } - } - return value.length; - }, - - depend: function( param, element ) { - return this.dependTypes[ typeof param ] ? this.dependTypes[ typeof param ]( param, element ) : true; - }, - - dependTypes: { - "boolean": function( param ) { - return param; - }, - "string": function( param, element ) { - return !!$( param, element.form ).length; - }, - "function": function( param, element ) { - return param( element ); - } - }, - - optional: function( element ) { - var val = this.elementValue( element ); - return !$.validator.methods.required.call( this, val, element ) && "dependency-mismatch"; - }, - - startRequest: function( element ) { - if ( !this.pending[ element.name ] ) { - this.pendingRequest++; - $( element ).addClass( this.settings.pendingClass ); - this.pending[ element.name ] = true; - } - }, - - stopRequest: function( element, valid ) { - this.pendingRequest--; - - // Sometimes synchronization fails, make sure pendingRequest is never < 0 - if ( this.pendingRequest < 0 ) { - this.pendingRequest = 0; - } - delete this.pending[ element.name ]; - $( element ).removeClass( this.settings.pendingClass ); - if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) { - $( this.currentForm ).submit(); - - // Remove the hidden input that was used as a replacement for the - // missing submit button. The hidden input is added by `handle()` - // to ensure that the value of the used submit button is passed on - // for scripted submits triggered by this method - if ( this.submitButton ) { - $( "input:hidden[name='" + this.submitButton.name + "']", this.currentForm ).remove(); - } - - this.formSubmitted = false; - } else if ( !valid && this.pendingRequest === 0 && this.formSubmitted ) { - $( this.currentForm ).triggerHandler( "invalid-form", [ this ] ); - this.formSubmitted = false; - } - }, - - previousValue: function( element, method ) { - method = typeof method === "string" && method || "remote"; - - return $.data( element, "previousValue" ) || $.data( element, "previousValue", { - old: null, - valid: true, - message: this.defaultMessage( element, { method: method } ) - } ); - }, - - // Cleans up all forms and elements, removes validator-specific events - destroy: function() { - this.resetForm(); - - $( this.currentForm ) - .off( ".validate" ) - .removeData( "validator" ) - .find( ".validate-equalTo-blur" ) - .off( ".validate-equalTo" ) - .removeClass( "validate-equalTo-blur" ); - } - - }, - - classRuleSettings: { - required: { required: true }, - email: { email: true }, - url: { url: true }, - date: { date: true }, - dateISO: { dateISO: true }, - number: { number: true }, - digits: { digits: true }, - creditcard: { creditcard: true } - }, - - addClassRules: function( className, rules ) { - if ( className.constructor === String ) { - this.classRuleSettings[ className ] = rules; - } else { - $.extend( this.classRuleSettings, className ); - } - }, - - classRules: function( element ) { - var rules = {}, - classes = $( element ).attr( "class" ); - - if ( classes ) { - $.each( classes.split( " " ), function() { - if ( this in $.validator.classRuleSettings ) { - $.extend( rules, $.validator.classRuleSettings[ this ] ); - } - } ); - } - return rules; - }, - - normalizeAttributeRule: function( rules, type, method, value ) { - - // Convert the value to a number for number inputs, and for text for backwards compability - // allows type="date" and others to be compared as strings - if ( /min|max|step/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) { - value = Number( value ); - - // Support Opera Mini, which returns NaN for undefined minlength - if ( isNaN( value ) ) { - value = undefined; - } - } - - if ( value || value === 0 ) { - rules[ method ] = value; - } else if ( type === method && type !== "range" ) { - - // Exception: the jquery validate 'range' method - // does not test for the html5 'range' type - rules[ method ] = true; - } - }, - - attributeRules: function( element ) { - var rules = {}, - $element = $( element ), - type = element.getAttribute( "type" ), - method, value; - - for ( method in $.validator.methods ) { - - // Support for in both html5 and older browsers - if ( method === "required" ) { - value = element.getAttribute( method ); - - // Some browsers return an empty string for the required attribute - // and non-HTML5 browsers might have required="" markup - if ( value === "" ) { - value = true; - } - - // Force non-HTML5 browsers to return bool - value = !!value; - } else { - value = $element.attr( method ); - } - - this.normalizeAttributeRule( rules, type, method, value ); - } - - // 'maxlength' may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs - if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) { - delete rules.maxlength; - } - - return rules; - }, - - dataRules: function( element ) { - var rules = {}, - $element = $( element ), - type = element.getAttribute( "type" ), - method, value; - - for ( method in $.validator.methods ) { - value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() ); - this.normalizeAttributeRule( rules, type, method, value ); - } - return rules; - }, - - staticRules: function( element ) { - var rules = {}, - validator = $.data( element.form, "validator" ); - - if ( validator.settings.rules ) { - rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {}; - } - return rules; - }, - - normalizeRules: function( rules, element ) { - - // Handle dependency check - $.each( rules, function( prop, val ) { - - // Ignore rule when param is explicitly false, eg. required:false - if ( val === false ) { - delete rules[ prop ]; - return; - } - if ( val.param || val.depends ) { - var keepRule = true; - switch ( typeof val.depends ) { - case "string": - keepRule = !!$( val.depends, element.form ).length; - break; - case "function": - keepRule = val.depends.call( element, element ); - break; - } - if ( keepRule ) { - rules[ prop ] = val.param !== undefined ? val.param : true; - } else { - $.data( element.form, "validator" ).resetElements( $( element ) ); - delete rules[ prop ]; - } - } - } ); - - // Evaluate parameters - $.each( rules, function( rule, parameter ) { - rules[ rule ] = $.isFunction( parameter ) && rule !== "normalizer" ? parameter( element ) : parameter; - } ); - - // Clean number parameters - $.each( [ "minlength", "maxlength" ], function() { - if ( rules[ this ] ) { - rules[ this ] = Number( rules[ this ] ); - } - } ); - $.each( [ "rangelength", "range" ], function() { - var parts; - if ( rules[ this ] ) { - if ( $.isArray( rules[ this ] ) ) { - rules[ this ] = [ Number( rules[ this ][ 0 ] ), Number( rules[ this ][ 1 ] ) ]; - } else if ( typeof rules[ this ] === "string" ) { - parts = rules[ this ].replace( /[\[\]]/g, "" ).split( /[\s,]+/ ); - rules[ this ] = [ Number( parts[ 0 ] ), Number( parts[ 1 ] ) ]; - } - } - } ); - - if ( $.validator.autoCreateRanges ) { - - // Auto-create ranges - if ( rules.min != null && rules.max != null ) { - rules.range = [ rules.min, rules.max ]; - delete rules.min; - delete rules.max; - } - if ( rules.minlength != null && rules.maxlength != null ) { - rules.rangelength = [ rules.minlength, rules.maxlength ]; - delete rules.minlength; - delete rules.maxlength; - } - } - - return rules; - }, - - // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} - normalizeRule: function( data ) { - if ( typeof data === "string" ) { - var transformed = {}; - $.each( data.split( /\s/ ), function() { - transformed[ this ] = true; - } ); - data = transformed; - } - return data; - }, - - // https://jqueryvalidation.org/jQuery.validator.addMethod/ - addMethod: function( name, method, message ) { - $.validator.methods[ name ] = method; - $.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ]; - if ( method.length < 3 ) { - $.validator.addClassRules( name, $.validator.normalizeRule( name ) ); - } - }, - - // https://jqueryvalidation.org/jQuery.validator.methods/ - methods: { - - // https://jqueryvalidation.org/required-method/ - required: function( value, element, param ) { - - // Check if dependency is met - if ( !this.depend( param, element ) ) { - return "dependency-mismatch"; - } - if ( element.nodeName.toLowerCase() === "select" ) { - - // Could be an array for select-multiple or a string, both are fine this way - var val = $( element ).val(); - return val && val.length > 0; - } - if ( this.checkable( element ) ) { - return this.getLength( value, element ) > 0; - } - return value.length > 0; - }, - - // https://jqueryvalidation.org/email-method/ - email: function( value, element ) { - - // From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address - // Retrieved 2014-01-14 - // If you have a problem with this implementation, report a bug against the above spec - // Or use custom methods to implement your own email validation - return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value ); - }, - - // https://jqueryvalidation.org/url-method/ - url: function( value, element ) { - - // Copyright (c) 2010-2013 Diego Perini, MIT licensed - // https://gist.github.com/dperini/729294 - // see also https://mathiasbynens.be/demo/url-regex - // modified to allow protocol-relative URLs - return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value ); - }, - - // https://jqueryvalidation.org/date-method/ - date: function( value, element ) { - return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() ); - }, - - // https://jqueryvalidation.org/dateISO-method/ - dateISO: function( value, element ) { - return this.optional( element ) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value ); - }, - - // https://jqueryvalidation.org/number-method/ - number: function( value, element ) { - return this.optional( element ) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value ); - }, - - // https://jqueryvalidation.org/digits-method/ - digits: function( value, element ) { - return this.optional( element ) || /^\d+$/.test( value ); - }, - - // https://jqueryvalidation.org/minlength-method/ - minlength: function( value, element, param ) { - var length = $.isArray( value ) ? value.length : this.getLength( value, element ); - return this.optional( element ) || length >= param; - }, - - // https://jqueryvalidation.org/maxlength-method/ - maxlength: function( value, element, param ) { - var length = $.isArray( value ) ? value.length : this.getLength( value, element ); - return this.optional( element ) || length <= param; - }, - - // https://jqueryvalidation.org/rangelength-method/ - rangelength: function( value, element, param ) { - var length = $.isArray( value ) ? value.length : this.getLength( value, element ); - return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] ); - }, - - // https://jqueryvalidation.org/min-method/ - min: function( value, element, param ) { - return this.optional( element ) || value >= param; - }, - - // https://jqueryvalidation.org/max-method/ - max: function( value, element, param ) { - return this.optional( element ) || value <= param; - }, - - // https://jqueryvalidation.org/range-method/ - range: function( value, element, param ) { - return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] ); - }, - - // https://jqueryvalidation.org/step-method/ - step: function( value, element, param ) { - var type = $( element ).attr( "type" ), - errorMessage = "Step attribute on input type " + type + " is not supported.", - supportedTypes = [ "text", "number", "range" ], - re = new RegExp( "\\b" + type + "\\b" ), - notSupported = type && !re.test( supportedTypes.join() ), - decimalPlaces = function( num ) { - var match = ( "" + num ).match( /(?:\.(\d+))?$/ ); - if ( !match ) { - return 0; - } - - // Number of digits right of decimal point. - return match[ 1 ] ? match[ 1 ].length : 0; - }, - toInt = function( num ) { - return Math.round( num * Math.pow( 10, decimals ) ); - }, - valid = true, - decimals; - - // Works only for text, number and range input types - // TODO find a way to support input types date, datetime, datetime-local, month, time and week - if ( notSupported ) { - throw new Error( errorMessage ); - } - - decimals = decimalPlaces( param ); - - // Value can't have too many decimals - if ( decimalPlaces( value ) > decimals || toInt( value ) % toInt( param ) !== 0 ) { - valid = false; - } - - return this.optional( element ) || valid; - }, - - // https://jqueryvalidation.org/equalTo-method/ - equalTo: function( value, element, param ) { - - // Bind to the blur event of the target in order to revalidate whenever the target field is updated - var target = $( param ); - if ( this.settings.onfocusout && target.not( ".validate-equalTo-blur" ).length ) { - target.addClass( "validate-equalTo-blur" ).on( "blur.validate-equalTo", function() { - $( element ).valid(); - } ); - } - return value === target.val(); - }, - - // https://jqueryvalidation.org/remote-method/ - remote: function( value, element, param, method ) { - if ( this.optional( element ) ) { - return "dependency-mismatch"; - } - - method = typeof method === "string" && method || "remote"; - - var previous = this.previousValue( element, method ), - validator, data, optionDataString; - - if ( !this.settings.messages[ element.name ] ) { - this.settings.messages[ element.name ] = {}; - } - previous.originalMessage = previous.originalMessage || this.settings.messages[ element.name ][ method ]; - this.settings.messages[ element.name ][ method ] = previous.message; - - param = typeof param === "string" && { url: param } || param; - optionDataString = $.param( $.extend( { data: value }, param.data ) ); - if ( previous.old === optionDataString ) { - return previous.valid; - } - - previous.old = optionDataString; - validator = this; - this.startRequest( element ); - data = {}; - data[ element.name ] = value; - $.ajax( $.extend( true, { - mode: "abort", - port: "validate" + element.name, - dataType: "json", - data: data, - context: validator.currentForm, - success: function( response ) { - var valid = response === true || response === "true", - errors, message, submitted; - - validator.settings.messages[ element.name ][ method ] = previous.originalMessage; - if ( valid ) { - submitted = validator.formSubmitted; - validator.resetInternals(); - validator.toHide = validator.errorsFor( element ); - validator.formSubmitted = submitted; - validator.successList.push( element ); - validator.invalid[ element.name ] = false; - validator.showErrors(); - } else { - errors = {}; - message = response || validator.defaultMessage( element, { method: method, parameters: value } ); - errors[ element.name ] = previous.message = message; - validator.invalid[ element.name ] = true; - validator.showErrors( errors ); - } - previous.valid = valid; - validator.stopRequest( element, valid ); - } - }, param ) ); - return "pending"; - } - } - -} ); - -// Ajax mode: abort -// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); -// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() - -var pendingRequests = {}, - ajax; - -// Use a prefilter if available (1.5+) -if ( $.ajaxPrefilter ) { - $.ajaxPrefilter( function( settings, _, xhr ) { - var port = settings.port; - if ( settings.mode === "abort" ) { - if ( pendingRequests[ port ] ) { - pendingRequests[ port ].abort(); - } - pendingRequests[ port ] = xhr; - } - } ); -} else { - - // Proxy ajax - ajax = $.ajax; - $.ajax = function( settings ) { - var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode, - port = ( "port" in settings ? settings : $.ajaxSettings ).port; - if ( mode === "abort" ) { - if ( pendingRequests[ port ] ) { - pendingRequests[ port ].abort(); - } - pendingRequests[ port ] = ajax.apply( this, arguments ); - return pendingRequests[ port ]; - } - return ajax.apply( this, arguments ); - }; -} -return $; -})); \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js deleted file mode 100644 index 8d13c0a985..0000000000 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js +++ /dev/null @@ -1,5 +0,0 @@ -/* == jquery mousewheel plugin == Version: 3.1.13, License: MIT License (MIT) */ -!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})}); -/* == malihu jquery custom scrollbar plugin == Version: 3.1.5, License: MIT License (MIT) */ -!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"undefined"!=typeof module&&module.exports?module.exports=e:e(jQuery,window,document)}(function(e){!function(t){var o="function"==typeof define&&define.amd,a="undefined"!=typeof module&&module.exports,n="https:"==document.location.protocol?"https:":"http:",i="cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js";o||(a?require("jquery-mousewheel")(e):e.event.special.mousewheel||e("head").append(decodeURI("%3Cscript src="+n+"//"+i+"%3E%3C/script%3E"))),t()}(function(){var t,o="mCustomScrollbar",a="mCS",n=".mCustomScrollbar",i={setTop:0,setLeft:0,axis:"y",scrollbarPosition:"inside",scrollInertia:950,autoDraggerLength:!0,alwaysShowScrollbar:0,snapOffset:0,mouseWheel:{enable:!0,scrollAmount:"auto",axis:"y",deltaFactor:"auto",disableOver:["select","option","keygen","datalist","textarea"]},scrollButtons:{scrollType:"stepless",scrollAmount:"auto"},keyboard:{enable:!0,scrollType:"stepless",scrollAmount:"auto"},contentTouchScroll:25,documentTouchScroll:!0,advanced:{autoScrollOnFocus:"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']",updateOnContentResize:!0,updateOnImageLoad:"auto",autoUpdateTimeout:60},theme:"light",callbacks:{onTotalScrollOffset:0,onTotalScrollBackOffset:0,alwaysTriggerOffsets:!0}},r=0,l={},s=window.attachEvent&&!window.addEventListener?1:0,c=!1,d=["mCSB_dragger_onDrag","mCSB_scrollTools_onDrag","mCS_img_loaded","mCS_disabled","mCS_destroyed","mCS_no_scrollbar","mCS-autoHide","mCS-dir-rtl","mCS_no_scrollbar_y","mCS_no_scrollbar_x","mCS_y_hidden","mCS_x_hidden","mCSB_draggerContainer","mCSB_buttonUp","mCSB_buttonDown","mCSB_buttonLeft","mCSB_buttonRight"],u={init:function(t){var t=e.extend(!0,{},i,t),o=f.call(this);if(t.live){var s=t.liveSelector||this.selector||n,c=e(s);if("off"===t.live)return void m(s);l[s]=setTimeout(function(){c.mCustomScrollbar(t),"once"===t.live&&c.length&&m(s)},500)}else m(s);return t.setWidth=t.set_width?t.set_width:t.setWidth,t.setHeight=t.set_height?t.set_height:t.setHeight,t.axis=t.horizontalScroll?"x":p(t.axis),t.scrollInertia=t.scrollInertia>0&&t.scrollInertia<17?17:t.scrollInertia,"object"!=typeof t.mouseWheel&&1==t.mouseWheel&&(t.mouseWheel={enable:!0,scrollAmount:"auto",axis:"y",preventDefault:!1,deltaFactor:"auto",normalizeDelta:!1,invert:!1}),t.mouseWheel.scrollAmount=t.mouseWheelPixels?t.mouseWheelPixels:t.mouseWheel.scrollAmount,t.mouseWheel.normalizeDelta=t.advanced.normalizeMouseWheelDelta?t.advanced.normalizeMouseWheelDelta:t.mouseWheel.normalizeDelta,t.scrollButtons.scrollType=g(t.scrollButtons.scrollType),h(t),e(o).each(function(){var o=e(this);if(!o.data(a)){o.data(a,{idx:++r,opt:t,scrollRatio:{y:null,x:null},overflowed:null,contentReset:{y:null,x:null},bindEvents:!1,tweenRunning:!1,sequential:{},langDir:o.css("direction"),cbOffsets:null,trigger:null,poll:{size:{o:0,n:0},img:{o:0,n:0},change:{o:0,n:0}}});var n=o.data(a),i=n.opt,l=o.data("mcs-axis"),s=o.data("mcs-scrollbar-position"),c=o.data("mcs-theme");l&&(i.axis=l),s&&(i.scrollbarPosition=s),c&&(i.theme=c,h(i)),v.call(this),n&&i.callbacks.onCreate&&"function"==typeof i.callbacks.onCreate&&i.callbacks.onCreate.call(this),e("#mCSB_"+n.idx+"_container img:not(."+d[2]+")").addClass(d[2]),u.update.call(null,o)}})},update:function(t,o){var n=t||f.call(this);return e(n).each(function(){var t=e(this);if(t.data(a)){var n=t.data(a),i=n.opt,r=e("#mCSB_"+n.idx+"_container"),l=e("#mCSB_"+n.idx),s=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")];if(!r.length)return;n.tweenRunning&&Q(t),o&&n&&i.callbacks.onBeforeUpdate&&"function"==typeof i.callbacks.onBeforeUpdate&&i.callbacks.onBeforeUpdate.call(this),t.hasClass(d[3])&&t.removeClass(d[3]),t.hasClass(d[4])&&t.removeClass(d[4]),l.css("max-height","none"),l.height()!==t.height()&&l.css("max-height",t.height()),_.call(this),"y"===i.axis||i.advanced.autoExpandHorizontalScroll||r.css("width",x(r)),n.overflowed=y.call(this),M.call(this),i.autoDraggerLength&&S.call(this),b.call(this),T.call(this);var c=[Math.abs(r[0].offsetTop),Math.abs(r[0].offsetLeft)];"x"!==i.axis&&(n.overflowed[0]?s[0].height()>s[0].parent().height()?B.call(this):(G(t,c[0].toString(),{dir:"y",dur:0,overwrite:"none"}),n.contentReset.y=null):(B.call(this),"y"===i.axis?k.call(this):"yx"===i.axis&&n.overflowed[1]&&G(t,c[1].toString(),{dir:"x",dur:0,overwrite:"none"}))),"y"!==i.axis&&(n.overflowed[1]?s[1].width()>s[1].parent().width()?B.call(this):(G(t,c[1].toString(),{dir:"x",dur:0,overwrite:"none"}),n.contentReset.x=null):(B.call(this),"x"===i.axis?k.call(this):"yx"===i.axis&&n.overflowed[0]&&G(t,c[0].toString(),{dir:"y",dur:0,overwrite:"none"}))),o&&n&&(2===o&&i.callbacks.onImageLoad&&"function"==typeof i.callbacks.onImageLoad?i.callbacks.onImageLoad.call(this):3===o&&i.callbacks.onSelectorChange&&"function"==typeof i.callbacks.onSelectorChange?i.callbacks.onSelectorChange.call(this):i.callbacks.onUpdate&&"function"==typeof i.callbacks.onUpdate&&i.callbacks.onUpdate.call(this)),N.call(this)}})},scrollTo:function(t,o){if("undefined"!=typeof t&&null!=t){var n=f.call(this);return e(n).each(function(){var n=e(this);if(n.data(a)){var i=n.data(a),r=i.opt,l={trigger:"external",scrollInertia:r.scrollInertia,scrollEasing:"mcsEaseInOut",moveDragger:!1,timeout:60,callbacks:!0,onStart:!0,onUpdate:!0,onComplete:!0},s=e.extend(!0,{},l,o),c=Y.call(this,t),d=s.scrollInertia>0&&s.scrollInertia<17?17:s.scrollInertia;c[0]=X.call(this,c[0],"y"),c[1]=X.call(this,c[1],"x"),s.moveDragger&&(c[0]*=i.scrollRatio.y,c[1]*=i.scrollRatio.x),s.dur=ne()?0:d,setTimeout(function(){null!==c[0]&&"undefined"!=typeof c[0]&&"x"!==r.axis&&i.overflowed[0]&&(s.dir="y",s.overwrite="all",G(n,c[0].toString(),s)),null!==c[1]&&"undefined"!=typeof c[1]&&"y"!==r.axis&&i.overflowed[1]&&(s.dir="x",s.overwrite="none",G(n,c[1].toString(),s))},s.timeout)}})}},stop:function(){var t=f.call(this);return e(t).each(function(){var t=e(this);t.data(a)&&Q(t)})},disable:function(t){var o=f.call(this);return e(o).each(function(){var o=e(this);if(o.data(a)){o.data(a);N.call(this,"remove"),k.call(this),t&&B.call(this),M.call(this,!0),o.addClass(d[3])}})},destroy:function(){var t=f.call(this);return e(t).each(function(){var n=e(this);if(n.data(a)){var i=n.data(a),r=i.opt,l=e("#mCSB_"+i.idx),s=e("#mCSB_"+i.idx+"_container"),c=e(".mCSB_"+i.idx+"_scrollbar");r.live&&m(r.liveSelector||e(t).selector),N.call(this,"remove"),k.call(this),B.call(this),n.removeData(a),$(this,"mcs"),c.remove(),s.find("img."+d[2]).removeClass(d[2]),l.replaceWith(s.contents()),n.removeClass(o+" _"+a+"_"+i.idx+" "+d[6]+" "+d[7]+" "+d[5]+" "+d[3]).addClass(d[4])}})}},f=function(){return"object"!=typeof e(this)||e(this).length<1?n:this},h=function(t){var o=["rounded","rounded-dark","rounded-dots","rounded-dots-dark"],a=["rounded-dots","rounded-dots-dark","3d","3d-dark","3d-thick","3d-thick-dark","inset","inset-dark","inset-2","inset-2-dark","inset-3","inset-3-dark"],n=["minimal","minimal-dark"],i=["minimal","minimal-dark"],r=["minimal","minimal-dark"];t.autoDraggerLength=e.inArray(t.theme,o)>-1?!1:t.autoDraggerLength,t.autoExpandScrollbar=e.inArray(t.theme,a)>-1?!1:t.autoExpandScrollbar,t.scrollButtons.enable=e.inArray(t.theme,n)>-1?!1:t.scrollButtons.enable,t.autoHideScrollbar=e.inArray(t.theme,i)>-1?!0:t.autoHideScrollbar,t.scrollbarPosition=e.inArray(t.theme,r)>-1?"outside":t.scrollbarPosition},m=function(e){l[e]&&(clearTimeout(l[e]),$(l,e))},p=function(e){return"yx"===e||"xy"===e||"auto"===e?"yx":"x"===e||"horizontal"===e?"x":"y"},g=function(e){return"stepped"===e||"pixels"===e||"step"===e||"click"===e?"stepped":"stepless"},v=function(){var t=e(this),n=t.data(a),i=n.opt,r=i.autoExpandScrollbar?" "+d[1]+"_expand":"",l=["
    ","
    "],s="yx"===i.axis?"mCSB_vertical_horizontal":"x"===i.axis?"mCSB_horizontal":"mCSB_vertical",c="yx"===i.axis?l[0]+l[1]:"x"===i.axis?l[1]:l[0],u="yx"===i.axis?"
    ":"",f=i.autoHideScrollbar?" "+d[6]:"",h="x"!==i.axis&&"rtl"===n.langDir?" "+d[7]:"";i.setWidth&&t.css("width",i.setWidth),i.setHeight&&t.css("height",i.setHeight),i.setLeft="y"!==i.axis&&"rtl"===n.langDir?"989999px":i.setLeft,t.addClass(o+" _"+a+"_"+n.idx+f+h).wrapInner("
    ");var m=e("#mCSB_"+n.idx),p=e("#mCSB_"+n.idx+"_container");"y"===i.axis||i.advanced.autoExpandHorizontalScroll||p.css("width",x(p)),"outside"===i.scrollbarPosition?("static"===t.css("position")&&t.css("position","relative"),t.css("overflow","visible"),m.addClass("mCSB_outside").after(c)):(m.addClass("mCSB_inside").append(c),p.wrap(u)),w.call(this);var g=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")];g[0].css("min-height",g[0].height()),g[1].css("min-width",g[1].width())},x=function(t){var o=[t[0].scrollWidth,Math.max.apply(Math,t.children().map(function(){return e(this).outerWidth(!0)}).get())],a=t.parent().width();return o[0]>a?o[0]:o[1]>a?o[1]:"100%"},_=function(){var t=e(this),o=t.data(a),n=o.opt,i=e("#mCSB_"+o.idx+"_container");if(n.advanced.autoExpandHorizontalScroll&&"y"!==n.axis){i.css({width:"auto","min-width":0,"overflow-x":"scroll"});var r=Math.ceil(i[0].scrollWidth);3===n.advanced.autoExpandHorizontalScroll||2!==n.advanced.autoExpandHorizontalScroll&&r>i.parent().width()?i.css({width:r,"min-width":"100%","overflow-x":"inherit"}):i.css({"overflow-x":"inherit",position:"absolute"}).wrap("
    ").css({width:Math.ceil(i[0].getBoundingClientRect().right+.4)-Math.floor(i[0].getBoundingClientRect().left),"min-width":"100%",position:"relative"}).unwrap()}},w=function(){var t=e(this),o=t.data(a),n=o.opt,i=e(".mCSB_"+o.idx+"_scrollbar:first"),r=oe(n.scrollButtons.tabindex)?"tabindex='"+n.scrollButtons.tabindex+"'":"",l=["","","",""],s=["x"===n.axis?l[2]:l[0],"x"===n.axis?l[3]:l[1],l[2],l[3]];n.scrollButtons.enable&&i.prepend(s[0]).append(s[1]).next(".mCSB_scrollTools").prepend(s[2]).append(s[3])},S=function(){var t=e(this),o=t.data(a),n=e("#mCSB_"+o.idx),i=e("#mCSB_"+o.idx+"_container"),r=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")],l=[n.height()/i.outerHeight(!1),n.width()/i.outerWidth(!1)],c=[parseInt(r[0].css("min-height")),Math.round(l[0]*r[0].parent().height()),parseInt(r[1].css("min-width")),Math.round(l[1]*r[1].parent().width())],d=s&&c[1]r&&(r=s),c>l&&(l=c),[r>n.height(),l>n.width()]},B=function(){var t=e(this),o=t.data(a),n=o.opt,i=e("#mCSB_"+o.idx),r=e("#mCSB_"+o.idx+"_container"),l=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")];if(Q(t),("x"!==n.axis&&!o.overflowed[0]||"y"===n.axis&&o.overflowed[0])&&(l[0].add(r).css("top",0),G(t,"_resetY")),"y"!==n.axis&&!o.overflowed[1]||"x"===n.axis&&o.overflowed[1]){var s=dx=0;"rtl"===o.langDir&&(s=i.width()-r.outerWidth(!1),dx=Math.abs(s/o.scrollRatio.x)),r.css("left",s),l[1].css("left",dx),G(t,"_resetX")}},T=function(){function t(){r=setTimeout(function(){e.event.special.mousewheel?(clearTimeout(r),W.call(o[0])):t()},100)}var o=e(this),n=o.data(a),i=n.opt;if(!n.bindEvents){if(I.call(this),i.contentTouchScroll&&D.call(this),E.call(this),i.mouseWheel.enable){var r;t()}P.call(this),U.call(this),i.advanced.autoScrollOnFocus&&H.call(this),i.scrollButtons.enable&&F.call(this),i.keyboard.enable&&q.call(this),n.bindEvents=!0}},k=function(){var t=e(this),o=t.data(a),n=o.opt,i=a+"_"+o.idx,r=".mCSB_"+o.idx+"_scrollbar",l=e("#mCSB_"+o.idx+",#mCSB_"+o.idx+"_container,#mCSB_"+o.idx+"_container_wrapper,"+r+" ."+d[12]+",#mCSB_"+o.idx+"_dragger_vertical,#mCSB_"+o.idx+"_dragger_horizontal,"+r+">a"),s=e("#mCSB_"+o.idx+"_container");n.advanced.releaseDraggableSelectors&&l.add(e(n.advanced.releaseDraggableSelectors)),n.advanced.extraDraggableSelectors&&l.add(e(n.advanced.extraDraggableSelectors)),o.bindEvents&&(e(document).add(e(!A()||top.document)).unbind("."+i),l.each(function(){e(this).unbind("."+i)}),clearTimeout(t[0]._focusTimeout),$(t[0],"_focusTimeout"),clearTimeout(o.sequential.step),$(o.sequential,"step"),clearTimeout(s[0].onCompleteTimeout),$(s[0],"onCompleteTimeout"),o.bindEvents=!1)},M=function(t){var o=e(this),n=o.data(a),i=n.opt,r=e("#mCSB_"+n.idx+"_container_wrapper"),l=r.length?r:e("#mCSB_"+n.idx+"_container"),s=[e("#mCSB_"+n.idx+"_scrollbar_vertical"),e("#mCSB_"+n.idx+"_scrollbar_horizontal")],c=[s[0].find(".mCSB_dragger"),s[1].find(".mCSB_dragger")];"x"!==i.axis&&(n.overflowed[0]&&!t?(s[0].add(c[0]).add(s[0].children("a")).css("display","block"),l.removeClass(d[8]+" "+d[10])):(i.alwaysShowScrollbar?(2!==i.alwaysShowScrollbar&&c[0].css("display","none"),l.removeClass(d[10])):(s[0].css("display","none"),l.addClass(d[10])),l.addClass(d[8]))),"y"!==i.axis&&(n.overflowed[1]&&!t?(s[1].add(c[1]).add(s[1].children("a")).css("display","block"),l.removeClass(d[9]+" "+d[11])):(i.alwaysShowScrollbar?(2!==i.alwaysShowScrollbar&&c[1].css("display","none"),l.removeClass(d[11])):(s[1].css("display","none"),l.addClass(d[11])),l.addClass(d[9]))),n.overflowed[0]||n.overflowed[1]?o.removeClass(d[5]):o.addClass(d[5])},O=function(t){var o=t.type,a=t.target.ownerDocument!==document&&null!==frameElement?[e(frameElement).offset().top,e(frameElement).offset().left]:null,n=A()&&t.target.ownerDocument!==top.document&&null!==frameElement?[e(t.view.frameElement).offset().top,e(t.view.frameElement).offset().left]:[0,0];switch(o){case"pointerdown":case"MSPointerDown":case"pointermove":case"MSPointerMove":case"pointerup":case"MSPointerUp":return a?[t.originalEvent.pageY-a[0]+n[0],t.originalEvent.pageX-a[1]+n[1],!1]:[t.originalEvent.pageY,t.originalEvent.pageX,!1];case"touchstart":case"touchmove":case"touchend":var i=t.originalEvent.touches[0]||t.originalEvent.changedTouches[0],r=t.originalEvent.touches.length||t.originalEvent.changedTouches.length;return t.target.ownerDocument!==document?[i.screenY,i.screenX,r>1]:[i.pageY,i.pageX,r>1];default:return a?[t.pageY-a[0]+n[0],t.pageX-a[1]+n[1],!1]:[t.pageY,t.pageX,!1]}},I=function(){function t(e,t,a,n){if(h[0].idleTimer=d.scrollInertia<233?250:0,o.attr("id")===f[1])var i="x",s=(o[0].offsetLeft-t+n)*l.scrollRatio.x;else var i="y",s=(o[0].offsetTop-e+a)*l.scrollRatio.y;G(r,s.toString(),{dir:i,drag:!0})}var o,n,i,r=e(this),l=r.data(a),d=l.opt,u=a+"_"+l.idx,f=["mCSB_"+l.idx+"_dragger_vertical","mCSB_"+l.idx+"_dragger_horizontal"],h=e("#mCSB_"+l.idx+"_container"),m=e("#"+f[0]+",#"+f[1]),p=d.advanced.releaseDraggableSelectors?m.add(e(d.advanced.releaseDraggableSelectors)):m,g=d.advanced.extraDraggableSelectors?e(!A()||top.document).add(e(d.advanced.extraDraggableSelectors)):e(!A()||top.document);m.bind("contextmenu."+u,function(e){e.preventDefault()}).bind("mousedown."+u+" touchstart."+u+" pointerdown."+u+" MSPointerDown."+u,function(t){if(t.stopImmediatePropagation(),t.preventDefault(),ee(t)){c=!0,s&&(document.onselectstart=function(){return!1}),L.call(h,!1),Q(r),o=e(this);var a=o.offset(),l=O(t)[0]-a.top,u=O(t)[1]-a.left,f=o.height()+a.top,m=o.width()+a.left;f>l&&l>0&&m>u&&u>0&&(n=l,i=u),C(o,"active",d.autoExpandScrollbar)}}).bind("touchmove."+u,function(e){e.stopImmediatePropagation(),e.preventDefault();var a=o.offset(),r=O(e)[0]-a.top,l=O(e)[1]-a.left;t(n,i,r,l)}),e(document).add(g).bind("mousemove."+u+" pointermove."+u+" MSPointerMove."+u,function(e){if(o){var a=o.offset(),r=O(e)[0]-a.top,l=O(e)[1]-a.left;if(n===r&&i===l)return;t(n,i,r,l)}}).add(p).bind("mouseup."+u+" touchend."+u+" pointerup."+u+" MSPointerUp."+u,function(){o&&(C(o,"active",d.autoExpandScrollbar),o=null),c=!1,s&&(document.onselectstart=null),L.call(h,!0)})},D=function(){function o(e){if(!te(e)||c||O(e)[2])return void(t=0);t=1,b=0,C=0,d=1,y.removeClass("mCS_touch_action");var o=I.offset();u=O(e)[0]-o.top,f=O(e)[1]-o.left,z=[O(e)[0],O(e)[1]]}function n(e){if(te(e)&&!c&&!O(e)[2]&&(T.documentTouchScroll||e.preventDefault(),e.stopImmediatePropagation(),(!C||b)&&d)){g=K();var t=M.offset(),o=O(e)[0]-t.top,a=O(e)[1]-t.left,n="mcsLinearOut";if(E.push(o),W.push(a),z[2]=Math.abs(O(e)[0]-z[0]),z[3]=Math.abs(O(e)[1]-z[1]),B.overflowed[0])var i=D[0].parent().height()-D[0].height(),r=u-o>0&&o-u>-(i*B.scrollRatio.y)&&(2*z[3]0&&a-f>-(l*B.scrollRatio.x)&&(2*z[2]30)){_=1e3/(v-p);var n="mcsEaseOut",i=2.5>_,r=i?[E[E.length-2],W[W.length-2]]:[0,0];x=i?[o-r[0],a-r[1]]:[o-h,a-m];var u=[Math.abs(x[0]),Math.abs(x[1])];_=i?[Math.abs(x[0]/4),Math.abs(x[1]/4)]:[_,_];var f=[Math.abs(I[0].offsetTop)-x[0]*l(u[0]/_[0],_[0]),Math.abs(I[0].offsetLeft)-x[1]*l(u[1]/_[1],_[1])];w="yx"===T.axis?[f[0],f[1]]:"x"===T.axis?[null,f[1]]:[f[0],null],S=[4*u[0]+T.scrollInertia,4*u[1]+T.scrollInertia];var y=parseInt(T.contentTouchScroll)||0;w[0]=u[0]>y?w[0]:0,w[1]=u[1]>y?w[1]:0,B.overflowed[0]&&s(w[0],S[0],n,"y",L,!1),B.overflowed[1]&&s(w[1],S[1],n,"x",L,!1)}}}function l(e,t){var o=[1.5*t,2*t,t/1.5,t/2];return e>90?t>4?o[0]:o[3]:e>60?t>3?o[3]:o[2]:e>30?t>8?o[1]:t>6?o[0]:t>4?t:o[2]:t>8?t:o[3]}function s(e,t,o,a,n,i){e&&G(y,e.toString(),{dur:t,scrollEasing:o,dir:a,overwrite:n,drag:i})}var d,u,f,h,m,p,g,v,x,_,w,S,b,C,y=e(this),B=y.data(a),T=B.opt,k=a+"_"+B.idx,M=e("#mCSB_"+B.idx),I=e("#mCSB_"+B.idx+"_container"),D=[e("#mCSB_"+B.idx+"_dragger_vertical"),e("#mCSB_"+B.idx+"_dragger_horizontal")],E=[],W=[],R=0,L="yx"===T.axis?"none":"all",z=[],P=I.find("iframe"),H=["touchstart."+k+" pointerdown."+k+" MSPointerDown."+k,"touchmove."+k+" pointermove."+k+" MSPointerMove."+k,"touchend."+k+" pointerup."+k+" MSPointerUp."+k],U=void 0!==document.body.style.touchAction&&""!==document.body.style.touchAction;I.bind(H[0],function(e){o(e)}).bind(H[1],function(e){n(e)}),M.bind(H[0],function(e){i(e)}).bind(H[2],function(e){r(e)}),P.length&&P.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind(H[0],function(e){o(e),i(e)}).bind(H[1],function(e){n(e)}).bind(H[2],function(e){r(e)})})})},E=function(){function o(){return window.getSelection?window.getSelection().toString():document.selection&&"Control"!=document.selection.type?document.selection.createRange().text:0}function n(e,t,o){d.type=o&&i?"stepped":"stepless",d.scrollAmount=10,j(r,e,t,"mcsLinearOut",o?60:null)}var i,r=e(this),l=r.data(a),s=l.opt,d=l.sequential,u=a+"_"+l.idx,f=e("#mCSB_"+l.idx+"_container"),h=f.parent();f.bind("mousedown."+u,function(){t||i||(i=1,c=!0)}).add(document).bind("mousemove."+u,function(e){if(!t&&i&&o()){var a=f.offset(),r=O(e)[0]-a.top+f[0].offsetTop,c=O(e)[1]-a.left+f[0].offsetLeft;r>0&&r0&&cr?n("on",38):r>h.height()&&n("on",40)),"y"!==s.axis&&l.overflowed[1]&&(0>c?n("on",37):c>h.width()&&n("on",39)))}}).bind("mouseup."+u+" dragend."+u,function(){t||(i&&(i=0,n("off",null)),c=!1)})},W=function(){function t(t,a){if(Q(o),!z(o,t.target)){var r="auto"!==i.mouseWheel.deltaFactor?parseInt(i.mouseWheel.deltaFactor):s&&t.deltaFactor<100?100:t.deltaFactor||100,d=i.scrollInertia;if("x"===i.axis||"x"===i.mouseWheel.axis)var u="x",f=[Math.round(r*n.scrollRatio.x),parseInt(i.mouseWheel.scrollAmount)],h="auto"!==i.mouseWheel.scrollAmount?f[1]:f[0]>=l.width()?.9*l.width():f[0],m=Math.abs(e("#mCSB_"+n.idx+"_container")[0].offsetLeft),p=c[1][0].offsetLeft,g=c[1].parent().width()-c[1].width(),v="y"===i.mouseWheel.axis?t.deltaY||a:t.deltaX;else var u="y",f=[Math.round(r*n.scrollRatio.y),parseInt(i.mouseWheel.scrollAmount)],h="auto"!==i.mouseWheel.scrollAmount?f[1]:f[0]>=l.height()?.9*l.height():f[0],m=Math.abs(e("#mCSB_"+n.idx+"_container")[0].offsetTop),p=c[0][0].offsetTop,g=c[0].parent().height()-c[0].height(),v=t.deltaY||a;"y"===u&&!n.overflowed[0]||"x"===u&&!n.overflowed[1]||((i.mouseWheel.invert||t.webkitDirectionInvertedFromDevice)&&(v=-v),i.mouseWheel.normalizeDelta&&(v=0>v?-1:1),(v>0&&0!==p||0>v&&p!==g||i.mouseWheel.preventDefault)&&(t.stopImmediatePropagation(),t.preventDefault()),t.deltaFactor<5&&!i.mouseWheel.normalizeDelta&&(h=t.deltaFactor,d=17),G(o,(m-v*h).toString(),{dir:u,dur:d}))}}if(e(this).data(a)){var o=e(this),n=o.data(a),i=n.opt,r=a+"_"+n.idx,l=e("#mCSB_"+n.idx),c=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")],d=e("#mCSB_"+n.idx+"_container").find("iframe");d.length&&d.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind("mousewheel."+r,function(e,o){t(e,o)})})}),l.bind("mousewheel."+r,function(e,o){t(e,o)})}},R=new Object,A=function(t){var o=!1,a=!1,n=null;if(void 0===t?a="#empty":void 0!==e(t).attr("id")&&(a=e(t).attr("id")),a!==!1&&void 0!==R[a])return R[a];if(t){try{var i=t.contentDocument||t.contentWindow.document;n=i.body.innerHTML}catch(r){}o=null!==n}else{try{var i=top.document;n=i.body.innerHTML}catch(r){}o=null!==n}return a!==!1&&(R[a]=o),o},L=function(e){var t=this.find("iframe");if(t.length){var o=e?"auto":"none";t.css("pointer-events",o)}},z=function(t,o){var n=o.nodeName.toLowerCase(),i=t.data(a).opt.mouseWheel.disableOver,r=["select","textarea"];return e.inArray(n,i)>-1&&!(e.inArray(n,r)>-1&&!e(o).is(":focus"))},P=function(){var t,o=e(this),n=o.data(a),i=a+"_"+n.idx,r=e("#mCSB_"+n.idx+"_container"),l=r.parent(),s=e(".mCSB_"+n.idx+"_scrollbar ."+d[12]);s.bind("mousedown."+i+" touchstart."+i+" pointerdown."+i+" MSPointerDown."+i,function(o){c=!0,e(o.target).hasClass("mCSB_dragger")||(t=1)}).bind("touchend."+i+" pointerup."+i+" MSPointerUp."+i,function(){c=!1}).bind("click."+i,function(a){if(t&&(t=0,e(a.target).hasClass(d[12])||e(a.target).hasClass("mCSB_draggerRail"))){Q(o);var i=e(this),s=i.find(".mCSB_dragger");if(i.parent(".mCSB_scrollTools_horizontal").length>0){if(!n.overflowed[1])return;var c="x",u=a.pageX>s.offset().left?-1:1,f=Math.abs(r[0].offsetLeft)-u*(.9*l.width())}else{if(!n.overflowed[0])return;var c="y",u=a.pageY>s.offset().top?-1:1,f=Math.abs(r[0].offsetTop)-u*(.9*l.height())}G(o,f.toString(),{dir:c,scrollEasing:"mcsEaseInOut"})}})},H=function(){var t=e(this),o=t.data(a),n=o.opt,i=a+"_"+o.idx,r=e("#mCSB_"+o.idx+"_container"),l=r.parent();r.bind("focusin."+i,function(){var o=e(document.activeElement),a=r.find(".mCustomScrollBox").length,i=0;o.is(n.advanced.autoScrollOnFocus)&&(Q(t),clearTimeout(t[0]._focusTimeout),t[0]._focusTimer=a?(i+17)*a:0,t[0]._focusTimeout=setTimeout(function(){var e=[ae(o)[0],ae(o)[1]],a=[r[0].offsetTop,r[0].offsetLeft],s=[a[0]+e[0]>=0&&a[0]+e[0]=0&&a[0]+e[1]a");s.bind("contextmenu."+r,function(e){e.preventDefault()}).bind("mousedown."+r+" touchstart."+r+" pointerdown."+r+" MSPointerDown."+r+" mouseup."+r+" touchend."+r+" pointerup."+r+" MSPointerUp."+r+" mouseout."+r+" pointerout."+r+" MSPointerOut."+r+" click."+r,function(a){function r(e,o){i.scrollAmount=n.scrollButtons.scrollAmount,j(t,e,o)}if(a.preventDefault(),ee(a)){var l=e(this).attr("class");switch(i.type=n.scrollButtons.scrollType,a.type){case"mousedown":case"touchstart":case"pointerdown":case"MSPointerDown":if("stepped"===i.type)return;c=!0,o.tweenRunning=!1,r("on",l);break;case"mouseup":case"touchend":case"pointerup":case"MSPointerUp":case"mouseout":case"pointerout":case"MSPointerOut":if("stepped"===i.type)return;c=!1,i.dir&&r("off",l);break;case"click":if("stepped"!==i.type||o.tweenRunning)return;r("on",l)}}})},q=function(){function t(t){function a(e,t){r.type=i.keyboard.scrollType,r.scrollAmount=i.keyboard.scrollAmount,"stepped"===r.type&&n.tweenRunning||j(o,e,t)}switch(t.type){case"blur":n.tweenRunning&&r.dir&&a("off",null);break;case"keydown":case"keyup":var l=t.keyCode?t.keyCode:t.which,s="on";if("x"!==i.axis&&(38===l||40===l)||"y"!==i.axis&&(37===l||39===l)){if((38===l||40===l)&&!n.overflowed[0]||(37===l||39===l)&&!n.overflowed[1])return;"keyup"===t.type&&(s="off"),e(document.activeElement).is(u)||(t.preventDefault(),t.stopImmediatePropagation(),a(s,l))}else if(33===l||34===l){if((n.overflowed[0]||n.overflowed[1])&&(t.preventDefault(),t.stopImmediatePropagation()),"keyup"===t.type){Q(o);var f=34===l?-1:1;if("x"===i.axis||"yx"===i.axis&&n.overflowed[1]&&!n.overflowed[0])var h="x",m=Math.abs(c[0].offsetLeft)-f*(.9*d.width());else var h="y",m=Math.abs(c[0].offsetTop)-f*(.9*d.height());G(o,m.toString(),{dir:h,scrollEasing:"mcsEaseInOut"})}}else if((35===l||36===l)&&!e(document.activeElement).is(u)&&((n.overflowed[0]||n.overflowed[1])&&(t.preventDefault(),t.stopImmediatePropagation()),"keyup"===t.type)){if("x"===i.axis||"yx"===i.axis&&n.overflowed[1]&&!n.overflowed[0])var h="x",m=35===l?Math.abs(d.width()-c.outerWidth(!1)):0;else var h="y",m=35===l?Math.abs(d.height()-c.outerHeight(!1)):0;G(o,m.toString(),{dir:h,scrollEasing:"mcsEaseInOut"})}}}var o=e(this),n=o.data(a),i=n.opt,r=n.sequential,l=a+"_"+n.idx,s=e("#mCSB_"+n.idx),c=e("#mCSB_"+n.idx+"_container"),d=c.parent(),u="input,textarea,select,datalist,keygen,[contenteditable='true']",f=c.find("iframe"),h=["blur."+l+" keydown."+l+" keyup."+l];f.length&&f.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind(h[0],function(e){t(e)})})}),s.attr("tabindex","0").bind(h[0],function(e){t(e)})},j=function(t,o,n,i,r){function l(e){u.snapAmount&&(f.scrollAmount=u.snapAmount instanceof Array?"x"===f.dir[0]?u.snapAmount[1]:u.snapAmount[0]:u.snapAmount);var o="stepped"!==f.type,a=r?r:e?o?p/1.5:g:1e3/60,n=e?o?7.5:40:2.5,s=[Math.abs(h[0].offsetTop),Math.abs(h[0].offsetLeft)],d=[c.scrollRatio.y>10?10:c.scrollRatio.y,c.scrollRatio.x>10?10:c.scrollRatio.x],m="x"===f.dir[0]?s[1]+f.dir[1]*(d[1]*n):s[0]+f.dir[1]*(d[0]*n),v="x"===f.dir[0]?s[1]+f.dir[1]*parseInt(f.scrollAmount):s[0]+f.dir[1]*parseInt(f.scrollAmount),x="auto"!==f.scrollAmount?v:m,_=i?i:e?o?"mcsLinearOut":"mcsEaseInOut":"mcsLinear",w=!!e;return e&&17>a&&(x="x"===f.dir[0]?s[1]:s[0]),G(t,x.toString(),{dir:f.dir[0],scrollEasing:_,dur:a,onComplete:w}),e?void(f.dir=!1):(clearTimeout(f.step),void(f.step=setTimeout(function(){l()},a)))}function s(){clearTimeout(f.step),$(f,"step"),Q(t)}var c=t.data(a),u=c.opt,f=c.sequential,h=e("#mCSB_"+c.idx+"_container"),m="stepped"===f.type,p=u.scrollInertia<26?26:u.scrollInertia,g=u.scrollInertia<1?17:u.scrollInertia;switch(o){case"on":if(f.dir=[n===d[16]||n===d[15]||39===n||37===n?"x":"y",n===d[13]||n===d[15]||38===n||37===n?-1:1],Q(t),oe(n)&&"stepped"===f.type)return;l(m);break;case"off":s(),(m||c.tweenRunning&&f.dir)&&l(!0)}},Y=function(t){var o=e(this).data(a).opt,n=[];return"function"==typeof t&&(t=t()),t instanceof Array?n=t.length>1?[t[0],t[1]]:"x"===o.axis?[null,t[0]]:[t[0],null]:(n[0]=t.y?t.y:t.x||"x"===o.axis?null:t,n[1]=t.x?t.x:t.y||"y"===o.axis?null:t),"function"==typeof n[0]&&(n[0]=n[0]()),"function"==typeof n[1]&&(n[1]=n[1]()),n},X=function(t,o){if(null!=t&&"undefined"!=typeof t){var n=e(this),i=n.data(a),r=i.opt,l=e("#mCSB_"+i.idx+"_container"),s=l.parent(),c=typeof t;o||(o="x"===r.axis?"x":"y");var d="x"===o?l.outerWidth(!1)-s.width():l.outerHeight(!1)-s.height(),f="x"===o?l[0].offsetLeft:l[0].offsetTop,h="x"===o?"left":"top";switch(c){case"function":return t();case"object":var m=t.jquery?t:e(t);if(!m.length)return;return"x"===o?ae(m)[1]:ae(m)[0];case"string":case"number":if(oe(t))return Math.abs(t);if(-1!==t.indexOf("%"))return Math.abs(d*parseInt(t)/100);if(-1!==t.indexOf("-="))return Math.abs(f-parseInt(t.split("-=")[1]));if(-1!==t.indexOf("+=")){var p=f+parseInt(t.split("+=")[1]);return p>=0?0:Math.abs(p)}if(-1!==t.indexOf("px")&&oe(t.split("px")[0]))return Math.abs(t.split("px")[0]);if("top"===t||"left"===t)return 0;if("bottom"===t)return Math.abs(s.height()-l.outerHeight(!1));if("right"===t)return Math.abs(s.width()-l.outerWidth(!1));if("first"===t||"last"===t){var m=l.find(":"+t);return"x"===o?ae(m)[1]:ae(m)[0]}return e(t).length?"x"===o?ae(e(t))[1]:ae(e(t))[0]:(l.css(h,t),void u.update.call(null,n[0]))}}},N=function(t){function o(){return clearTimeout(f[0].autoUpdate),0===l.parents("html").length?void(l=null):void(f[0].autoUpdate=setTimeout(function(){return c.advanced.updateOnSelectorChange&&(s.poll.change.n=i(),s.poll.change.n!==s.poll.change.o)?(s.poll.change.o=s.poll.change.n,void r(3)):c.advanced.updateOnContentResize&&(s.poll.size.n=l[0].scrollHeight+l[0].scrollWidth+f[0].offsetHeight+l[0].offsetHeight+l[0].offsetWidth,s.poll.size.n!==s.poll.size.o)?(s.poll.size.o=s.poll.size.n,void r(1)):!c.advanced.updateOnImageLoad||"auto"===c.advanced.updateOnImageLoad&&"y"===c.axis||(s.poll.img.n=f.find("img").length,s.poll.img.n===s.poll.img.o)?void((c.advanced.updateOnSelectorChange||c.advanced.updateOnContentResize||c.advanced.updateOnImageLoad)&&o()):(s.poll.img.o=s.poll.img.n,void f.find("img").each(function(){n(this)}))},c.advanced.autoUpdateTimeout))}function n(t){function o(e,t){return function(){ -return t.apply(e,arguments)}}function a(){this.onload=null,e(t).addClass(d[2]),r(2)}if(e(t).hasClass(d[2]))return void r();var n=new Image;n.onload=o(n,a),n.src=t.src}function i(){c.advanced.updateOnSelectorChange===!0&&(c.advanced.updateOnSelectorChange="*");var e=0,t=f.find(c.advanced.updateOnSelectorChange);return c.advanced.updateOnSelectorChange&&t.length>0&&t.each(function(){e+=this.offsetHeight+this.offsetWidth}),e}function r(e){clearTimeout(f[0].autoUpdate),u.update.call(null,l[0],e)}var l=e(this),s=l.data(a),c=s.opt,f=e("#mCSB_"+s.idx+"_container");return t?(clearTimeout(f[0].autoUpdate),void $(f[0],"autoUpdate")):void o()},V=function(e,t,o){return Math.round(e/t)*t-o},Q=function(t){var o=t.data(a),n=e("#mCSB_"+o.idx+"_container,#mCSB_"+o.idx+"_container_wrapper,#mCSB_"+o.idx+"_dragger_vertical,#mCSB_"+o.idx+"_dragger_horizontal");n.each(function(){Z.call(this)})},G=function(t,o,n){function i(e){return s&&c.callbacks[e]&&"function"==typeof c.callbacks[e]}function r(){return[c.callbacks.alwaysTriggerOffsets||w>=S[0]+y,c.callbacks.alwaysTriggerOffsets||-B>=w]}function l(){var e=[h[0].offsetTop,h[0].offsetLeft],o=[x[0].offsetTop,x[0].offsetLeft],a=[h.outerHeight(!1),h.outerWidth(!1)],i=[f.height(),f.width()];t[0].mcs={content:h,top:e[0],left:e[1],draggerTop:o[0],draggerLeft:o[1],topPct:Math.round(100*Math.abs(e[0])/(Math.abs(a[0])-i[0])),leftPct:Math.round(100*Math.abs(e[1])/(Math.abs(a[1])-i[1])),direction:n.dir}}var s=t.data(a),c=s.opt,d={trigger:"internal",dir:"y",scrollEasing:"mcsEaseOut",drag:!1,dur:c.scrollInertia,overwrite:"all",callbacks:!0,onStart:!0,onUpdate:!0,onComplete:!0},n=e.extend(d,n),u=[n.dur,n.drag?0:n.dur],f=e("#mCSB_"+s.idx),h=e("#mCSB_"+s.idx+"_container"),m=h.parent(),p=c.callbacks.onTotalScrollOffset?Y.call(t,c.callbacks.onTotalScrollOffset):[0,0],g=c.callbacks.onTotalScrollBackOffset?Y.call(t,c.callbacks.onTotalScrollBackOffset):[0,0];if(s.trigger=n.trigger,0===m.scrollTop()&&0===m.scrollLeft()||(e(".mCSB_"+s.idx+"_scrollbar").css("visibility","visible"),m.scrollTop(0).scrollLeft(0)),"_resetY"!==o||s.contentReset.y||(i("onOverflowYNone")&&c.callbacks.onOverflowYNone.call(t[0]),s.contentReset.y=1),"_resetX"!==o||s.contentReset.x||(i("onOverflowXNone")&&c.callbacks.onOverflowXNone.call(t[0]),s.contentReset.x=1),"_resetY"!==o&&"_resetX"!==o){if(!s.contentReset.y&&t[0].mcs||!s.overflowed[0]||(i("onOverflowY")&&c.callbacks.onOverflowY.call(t[0]),s.contentReset.x=null),!s.contentReset.x&&t[0].mcs||!s.overflowed[1]||(i("onOverflowX")&&c.callbacks.onOverflowX.call(t[0]),s.contentReset.x=null),c.snapAmount){var v=c.snapAmount instanceof Array?"x"===n.dir?c.snapAmount[1]:c.snapAmount[0]:c.snapAmount;o=V(o,v,c.snapOffset)}switch(n.dir){case"x":var x=e("#mCSB_"+s.idx+"_dragger_horizontal"),_="left",w=h[0].offsetLeft,S=[f.width()-h.outerWidth(!1),x.parent().width()-x.width()],b=[o,0===o?0:o/s.scrollRatio.x],y=p[1],B=g[1],T=y>0?y/s.scrollRatio.x:0,k=B>0?B/s.scrollRatio.x:0;break;case"y":var x=e("#mCSB_"+s.idx+"_dragger_vertical"),_="top",w=h[0].offsetTop,S=[f.height()-h.outerHeight(!1),x.parent().height()-x.height()],b=[o,0===o?0:o/s.scrollRatio.y],y=p[0],B=g[0],T=y>0?y/s.scrollRatio.y:0,k=B>0?B/s.scrollRatio.y:0}b[1]<0||0===b[0]&&0===b[1]?b=[0,0]:b[1]>=S[1]?b=[S[0],S[1]]:b[0]=-b[0],t[0].mcs||(l(),i("onInit")&&c.callbacks.onInit.call(t[0])),clearTimeout(h[0].onCompleteTimeout),J(x[0],_,Math.round(b[1]),u[1],n.scrollEasing),!s.tweenRunning&&(0===w&&b[0]>=0||w===S[0]&&b[0]<=S[0])||J(h[0],_,Math.round(b[0]),u[0],n.scrollEasing,n.overwrite,{onStart:function(){n.callbacks&&n.onStart&&!s.tweenRunning&&(i("onScrollStart")&&(l(),c.callbacks.onScrollStart.call(t[0])),s.tweenRunning=!0,C(x),s.cbOffsets=r())},onUpdate:function(){n.callbacks&&n.onUpdate&&i("whileScrolling")&&(l(),c.callbacks.whileScrolling.call(t[0]))},onComplete:function(){if(n.callbacks&&n.onComplete){"yx"===c.axis&&clearTimeout(h[0].onCompleteTimeout);var e=h[0].idleTimer||0;h[0].onCompleteTimeout=setTimeout(function(){i("onScroll")&&(l(),c.callbacks.onScroll.call(t[0])),i("onTotalScroll")&&b[1]>=S[1]-T&&s.cbOffsets[0]&&(l(),c.callbacks.onTotalScroll.call(t[0])),i("onTotalScrollBack")&&b[1]<=k&&s.cbOffsets[1]&&(l(),c.callbacks.onTotalScrollBack.call(t[0])),s.tweenRunning=!1,h[0].idleTimer=0,C(x,"hide")},e)}}})}},J=function(e,t,o,a,n,i,r){function l(){S.stop||(x||m.call(),x=K()-v,s(),x>=S.time&&(S.time=x>S.time?x+f-(x-S.time):x+f-1,S.time0?(S.currVal=u(S.time,_,b,a,n),w[t]=Math.round(S.currVal)+"px"):w[t]=o+"px",p.call()}function c(){f=1e3/60,S.time=x+f,h=window.requestAnimationFrame?window.requestAnimationFrame:function(e){return s(),setTimeout(e,.01)},S.id=h(l)}function d(){null!=S.id&&(window.requestAnimationFrame?window.cancelAnimationFrame(S.id):clearTimeout(S.id),S.id=null)}function u(e,t,o,a,n){switch(n){case"linear":case"mcsLinear":return o*e/a+t;case"mcsLinearOut":return e/=a,e--,o*Math.sqrt(1-e*e)+t;case"easeInOutSmooth":return e/=a/2,1>e?o/2*e*e+t:(e--,-o/2*(e*(e-2)-1)+t);case"easeInOutStrong":return e/=a/2,1>e?o/2*Math.pow(2,10*(e-1))+t:(e--,o/2*(-Math.pow(2,-10*e)+2)+t);case"easeInOut":case"mcsEaseInOut":return e/=a/2,1>e?o/2*e*e*e+t:(e-=2,o/2*(e*e*e+2)+t);case"easeOutSmooth":return e/=a,e--,-o*(e*e*e*e-1)+t;case"easeOutStrong":return o*(-Math.pow(2,-10*e/a)+1)+t;case"easeOut":case"mcsEaseOut":default:var i=(e/=a)*e,r=i*e;return t+o*(.499999999999997*r*i+-2.5*i*i+5.5*r+-6.5*i+4*e)}}e._mTween||(e._mTween={top:{},left:{}});var f,h,r=r||{},m=r.onStart||function(){},p=r.onUpdate||function(){},g=r.onComplete||function(){},v=K(),x=0,_=e.offsetTop,w=e.style,S=e._mTween[t];"left"===t&&(_=e.offsetLeft);var b=o-_;S.stop=0,"none"!==i&&d(),c()},K=function(){return window.performance&&window.performance.now?window.performance.now():window.performance&&window.performance.webkitNow?window.performance.webkitNow():Date.now?Date.now():(new Date).getTime()},Z=function(){var e=this;e._mTween||(e._mTween={top:{},left:{}});for(var t=["top","left"],o=0;o=0&&a[0]+ae(n)[0]=0&&a[1]+ae(n)[1]=0&&r[1]-i[1]*l[1][0]<0&&r[1]+n[1]-i[1]*l[1][1]>=0},mcsOverflow:e.expr[":"].mcsOverflow||function(t){var o=e(t).data(a);if(o)return o.overflowed[0]||o.overflowed[1]}})})})}); \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css deleted file mode 100644 index 8f013dafa3..0000000000 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css +++ /dev/null @@ -1,1267 +0,0 @@ -/* -== malihu jquery custom scrollbar plugin == -Plugin URI: http://manos.malihu.gr/jquery-custom-content-scroller -*/ - - - -/* -CONTENTS: - 1. BASIC STYLE - Plugin's basic/essential CSS properties (normally, should not be edited). - 2. VERTICAL SCROLLBAR - Positioning and dimensions of vertical scrollbar. - 3. HORIZONTAL SCROLLBAR - Positioning and dimensions of horizontal scrollbar. - 4. VERTICAL AND HORIZONTAL SCROLLBARS - Positioning and dimensions of 2-axis scrollbars. - 5. TRANSITIONS - CSS3 transitions for hover events, auto-expanded and auto-hidden scrollbars. - 6. SCROLLBAR COLORS, OPACITY AND BACKGROUNDS - 6.1 THEMES - Scrollbar colors, opacity, dimensions, backgrounds etc. via ready-to-use themes. -*/ - - - -/* ------------------------------------------------------------------------------------------------------------------------- -1. BASIC STYLE ------------------------------------------------------------------------------------------------------------------------- -*/ - - .mCustomScrollbar{ -ms-touch-action: pinch-zoom; touch-action: pinch-zoom; /* direct pointer events to js */ } - .mCustomScrollbar.mCS_no_scrollbar, .mCustomScrollbar.mCS_touch_action{ -ms-touch-action: auto; touch-action: auto; } - - .mCustomScrollBox{ /* contains plugin's markup */ - position: relative; - overflow: hidden; - height: 100%; - max-width: 100%; - outline: none; - direction: ltr; - } - - .mCSB_container{ /* contains the original content */ - overflow: hidden; - width: auto; - height: auto; - } - - - -/* ------------------------------------------------------------------------------------------------------------------------- -2. VERTICAL SCROLLBAR -y-axis ------------------------------------------------------------------------------------------------------------------------- -*/ - - .mCSB_inside > .mCSB_container{ margin-right: 30px; } - - .mCSB_container.mCS_no_scrollbar_y.mCS_y_hidden{ margin-right: 0; } /* non-visible scrollbar */ - - .mCS-dir-rtl > .mCSB_inside > .mCSB_container{ /* RTL direction/left-side scrollbar */ - margin-right: 0; - margin-left: 30px; - } - - .mCS-dir-rtl > .mCSB_inside > .mCSB_container.mCS_no_scrollbar_y.mCS_y_hidden{ margin-left: 0; } /* RTL direction/left-side scrollbar */ - - .mCSB_scrollTools{ /* contains scrollbar markup (draggable element, dragger rail, buttons etc.) */ - position: absolute; - width: 16px; - height: auto; - left: auto; - top: 0; - right: 0; - bottom: 0; - } - - .mCSB_outside + .mCSB_scrollTools{ right: -26px; } /* scrollbar position: outside */ - - .mCS-dir-rtl > .mCSB_inside > .mCSB_scrollTools, - .mCS-dir-rtl > .mCSB_outside + .mCSB_scrollTools{ /* RTL direction/left-side scrollbar */ - right: auto; - left: 0; - } - - .mCS-dir-rtl > .mCSB_outside + .mCSB_scrollTools{ left: -26px; } /* RTL direction/left-side scrollbar (scrollbar position: outside) */ - - .mCSB_scrollTools .mCSB_draggerContainer{ /* contains the draggable element and dragger rail markup */ - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - height: auto; - } - - .mCSB_scrollTools a + .mCSB_draggerContainer{ margin: 20px 0; } - - .mCSB_scrollTools .mCSB_draggerRail{ - width: 2px; - height: 100%; - margin: 0 auto; - -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; - } - - .mCSB_scrollTools .mCSB_dragger{ /* the draggable element */ - cursor: pointer; - width: 100%; - height: 30px; /* minimum dragger height */ - z-index: 1; - } - - .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ /* the dragger element */ - position: relative; - width: 4px; - height: 100%; - margin: 0 auto; - -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; - text-align: center; - } - - .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, - .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ width: 12px; /* auto-expanded scrollbar */ } - - .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ width: 8px; /* auto-expanded scrollbar */ } - - .mCSB_scrollTools .mCSB_buttonUp, - .mCSB_scrollTools .mCSB_buttonDown{ - display: block; - position: absolute; - height: 20px; - width: 100%; - overflow: hidden; - margin: 0 auto; - cursor: pointer; - } - - .mCSB_scrollTools .mCSB_buttonDown{ bottom: 0; } - - - -/* ------------------------------------------------------------------------------------------------------------------------- -3. HORIZONTAL SCROLLBAR -x-axis ------------------------------------------------------------------------------------------------------------------------- -*/ - - .mCSB_horizontal.mCSB_inside > .mCSB_container{ - margin-right: 0; - margin-bottom: 30px; - } - - .mCSB_horizontal.mCSB_outside > .mCSB_container{ min-height: 100%; } - - .mCSB_horizontal > .mCSB_container.mCS_no_scrollbar_x.mCS_x_hidden{ margin-bottom: 0; } /* non-visible scrollbar */ - - .mCSB_scrollTools.mCSB_scrollTools_horizontal{ - width: auto; - height: 16px; - top: auto; - right: 0; - bottom: 0; - left: 0; - } - - .mCustomScrollBox + .mCSB_scrollTools.mCSB_scrollTools_horizontal, - .mCustomScrollBox + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal{ bottom: -26px; } /* scrollbar position: outside */ - - .mCSB_scrollTools.mCSB_scrollTools_horizontal a + .mCSB_draggerContainer{ margin: 0 20px; } - - .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_draggerRail{ - width: 100%; - height: 2px; - margin: 7px 0; - } - - .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_dragger{ - width: 30px; /* minimum dragger width */ - height: 100%; - left: 0; - } - - .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - width: 100%; - height: 4px; - margin: 6px auto; - } - - .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, - .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ - height: 12px; /* auto-expanded scrollbar */ - margin: 2px auto; - } - - .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ - height: 8px; /* auto-expanded scrollbar */ - margin: 4px 0; - } - - .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonLeft, - .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonRight{ - display: block; - position: absolute; - width: 20px; - height: 100%; - overflow: hidden; - margin: 0 auto; - cursor: pointer; - } - - .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonLeft{ left: 0; } - - .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonRight{ right: 0; } - - - -/* ------------------------------------------------------------------------------------------------------------------------- -4. VERTICAL AND HORIZONTAL SCROLLBARS -yx-axis ------------------------------------------------------------------------------------------------------------------------- -*/ - - .mCSB_container_wrapper{ - position: absolute; - height: auto; - width: auto; - overflow: hidden; - top: 0; - left: 0; - right: 0; - bottom: 0; - margin-right: 30px; - margin-bottom: 30px; - } - - .mCSB_container_wrapper > .mCSB_container{ - padding-right: 30px; - padding-bottom: 30px; - -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; - } - - .mCSB_vertical_horizontal > .mCSB_scrollTools.mCSB_scrollTools_vertical{ bottom: 20px; } - - .mCSB_vertical_horizontal > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ right: 20px; } - - /* non-visible horizontal scrollbar */ - .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden + .mCSB_scrollTools.mCSB_scrollTools_vertical{ bottom: 0; } - - /* non-visible vertical scrollbar/RTL direction/left-side scrollbar */ - .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden + .mCSB_scrollTools ~ .mCSB_scrollTools.mCSB_scrollTools_horizontal, - .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ right: 0; } - - /* RTL direction/left-side scrollbar */ - .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ left: 20px; } - - /* non-visible scrollbar/RTL direction/left-side scrollbar */ - .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden + .mCSB_scrollTools ~ .mCSB_scrollTools.mCSB_scrollTools_horizontal{ left: 0; } - - .mCS-dir-rtl > .mCSB_inside > .mCSB_container_wrapper{ /* RTL direction/left-side scrollbar */ - margin-right: 0; - margin-left: 30px; - } - - .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden > .mCSB_container{ padding-right: 0; } - - .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden > .mCSB_container{ padding-bottom: 0; } - - .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden{ - margin-right: 0; /* non-visible scrollbar */ - margin-left: 0; - } - - /* non-visible horizontal scrollbar */ - .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden{ margin-bottom: 0; } - - - -/* ------------------------------------------------------------------------------------------------------------------------- -5. TRANSITIONS ------------------------------------------------------------------------------------------------------------------------- -*/ - - .mCSB_scrollTools, - .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCSB_scrollTools .mCSB_buttonUp, - .mCSB_scrollTools .mCSB_buttonDown, - .mCSB_scrollTools .mCSB_buttonLeft, - .mCSB_scrollTools .mCSB_buttonRight{ - -webkit-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; - -moz-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; - -o-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; - transition: opacity .2s ease-in-out, background-color .2s ease-in-out; - } - - .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger_bar, /* auto-expanded scrollbar */ - .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerRail, - .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger_bar, - .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerRail{ - -webkit-transition: width .2s ease-out .2s, height .2s ease-out .2s, - margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, - margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, - opacity .2s ease-in-out, background-color .2s ease-in-out; - -moz-transition: width .2s ease-out .2s, height .2s ease-out .2s, - margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, - margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, - opacity .2s ease-in-out, background-color .2s ease-in-out; - -o-transition: width .2s ease-out .2s, height .2s ease-out .2s, - margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, - margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, - opacity .2s ease-in-out, background-color .2s ease-in-out; - transition: width .2s ease-out .2s, height .2s ease-out .2s, - margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, - margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, - opacity .2s ease-in-out, background-color .2s ease-in-out; - } - - - -/* ------------------------------------------------------------------------------------------------------------------------- -6. SCROLLBAR COLORS, OPACITY AND BACKGROUNDS ------------------------------------------------------------------------------------------------------------------------- -*/ - - /* - ---------------------------------------- - 6.1 THEMES - ---------------------------------------- - */ - - /* default theme ("light") */ - - .mCSB_scrollTools{ opacity: 0.75; filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; } - - .mCS-autoHide > .mCustomScrollBox > .mCSB_scrollTools, - .mCS-autoHide > .mCustomScrollBox ~ .mCSB_scrollTools{ opacity: 0; filter: "alpha(opacity=0)"; -ms-filter: "alpha(opacity=0)"; } - - .mCustomScrollbar > .mCustomScrollBox > .mCSB_scrollTools.mCSB_scrollTools_onDrag, - .mCustomScrollbar > .mCustomScrollBox ~ .mCSB_scrollTools.mCSB_scrollTools_onDrag, - .mCustomScrollBox:hover > .mCSB_scrollTools, - .mCustomScrollBox:hover ~ .mCSB_scrollTools, - .mCS-autoHide:hover > .mCustomScrollBox > .mCSB_scrollTools, - .mCS-autoHide:hover > .mCustomScrollBox ~ .mCSB_scrollTools{ opacity: 1; filter: "alpha(opacity=100)"; -ms-filter: "alpha(opacity=100)"; } - - .mCSB_scrollTools .mCSB_draggerRail{ - background-color: #000; background-color: rgba(0,0,0,0.4); - filter: "alpha(opacity=40)"; -ms-filter: "alpha(opacity=40)"; - } - - .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - background-color: #fff; background-color: rgba(255,255,255,0.75); - filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; - } - - .mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ - background-color: #fff; background-color: rgba(255,255,255,0.85); - filter: "alpha(opacity=85)"; -ms-filter: "alpha(opacity=85)"; - } - .mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ - background-color: #fff; background-color: rgba(255,255,255,0.9); - filter: "alpha(opacity=90)"; -ms-filter: "alpha(opacity=90)"; - } - - .mCSB_scrollTools .mCSB_buttonUp, - .mCSB_scrollTools .mCSB_buttonDown, - .mCSB_scrollTools .mCSB_buttonLeft, - .mCSB_scrollTools .mCSB_buttonRight{ - background-image: url(mCSB_buttons.png); /* css sprites */ - background-repeat: no-repeat; - opacity: 0.4; filter: "alpha(opacity=40)"; -ms-filter: "alpha(opacity=40)"; - } - - .mCSB_scrollTools .mCSB_buttonUp{ - background-position: 0 0; - /* - sprites locations - light: 0 0, -16px 0, -32px 0, -48px 0, 0 -72px, -16px -72px, -32px -72px - dark: -80px 0, -96px 0, -112px 0, -128px 0, -80px -72px, -96px -72px, -112px -72px - */ - } - - .mCSB_scrollTools .mCSB_buttonDown{ - background-position: 0 -20px; - /* - sprites locations - light: 0 -20px, -16px -20px, -32px -20px, -48px -20px, 0 -92px, -16px -92px, -32px -92px - dark: -80px -20px, -96px -20px, -112px -20px, -128px -20px, -80px -92px, -96px -92px, -112 -92px - */ - } - - .mCSB_scrollTools .mCSB_buttonLeft{ - background-position: 0 -40px; - /* - sprites locations - light: 0 -40px, -20px -40px, -40px -40px, -60px -40px, 0 -112px, -20px -112px, -40px -112px - dark: -80px -40px, -100px -40px, -120px -40px, -140px -40px, -80px -112px, -100px -112px, -120px -112px - */ - } - - .mCSB_scrollTools .mCSB_buttonRight{ - background-position: 0 -56px; - /* - sprites locations - light: 0 -56px, -20px -56px, -40px -56px, -60px -56px, 0 -128px, -20px -128px, -40px -128px - dark: -80px -56px, -100px -56px, -120px -56px, -140px -56px, -80px -128px, -100px -128px, -120px -128px - */ - } - - .mCSB_scrollTools .mCSB_buttonUp:hover, - .mCSB_scrollTools .mCSB_buttonDown:hover, - .mCSB_scrollTools .mCSB_buttonLeft:hover, - .mCSB_scrollTools .mCSB_buttonRight:hover{ opacity: 0.75; filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; } - - .mCSB_scrollTools .mCSB_buttonUp:active, - .mCSB_scrollTools .mCSB_buttonDown:active, - .mCSB_scrollTools .mCSB_buttonLeft:active, - .mCSB_scrollTools .mCSB_buttonRight:active{ opacity: 0.9; filter: "alpha(opacity=90)"; -ms-filter: "alpha(opacity=90)"; } - - - /* theme: "dark" */ - - .mCS-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } - - .mCS-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } - - .mCS-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: rgba(0,0,0,0.85); } - - .mCS-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: rgba(0,0,0,0.9); } - - .mCS-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px 0; } - - .mCS-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -20px; } - - .mCS-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -40px; } - - .mCS-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -56px; } - - /* ---------------------------------------- */ - - - - /* theme: "light-2", "dark-2" */ - - .mCS-light-2.mCSB_scrollTools .mCSB_draggerRail, - .mCS-dark-2.mCSB_scrollTools .mCSB_draggerRail{ - width: 4px; - background-color: #fff; background-color: rgba(255,255,255,0.1); - -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; - } - - .mCS-light-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - width: 4px; - background-color: #fff; background-color: rgba(255,255,255,0.75); - -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; - } - - .mCS-light-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-dark-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-light-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - width: 100%; - height: 4px; - margin: 6px auto; - } - - .mCS-light-2.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } - - .mCS-light-2.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-light-2.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } - - .mCS-light-2.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px 0; } - - .mCS-light-2.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -20px; } - - .mCS-light-2.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -40px; } - - .mCS-light-2.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -56px; } - - - /* theme: "dark-2" */ - - .mCS-dark-2.mCSB_scrollTools .mCSB_draggerRail{ - background-color: #000; background-color: rgba(0,0,0,0.1); - -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; - } - - .mCS-dark-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - background-color: #000; background-color: rgba(0,0,0,0.75); - -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; - } - - .mCS-dark-2.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } - - .mCS-dark-2.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-dark-2.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } - - .mCS-dark-2.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px 0; } - - .mCS-dark-2.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -20px; } - - .mCS-dark-2.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -40px; } - - .mCS-dark-2.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -56px; } - - /* ---------------------------------------- */ - - - - /* theme: "light-thick", "dark-thick" */ - - .mCS-light-thick.mCSB_scrollTools .mCSB_draggerRail, - .mCS-dark-thick.mCSB_scrollTools .mCSB_draggerRail{ - width: 4px; - background-color: #fff; background-color: rgba(255,255,255,0.1); - -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; - } - - .mCS-light-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - width: 6px; - background-color: #fff; background-color: rgba(255,255,255,0.75); - -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; - } - - .mCS-light-thick.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-dark-thick.mCSB_scrollTools_horizontal .mCSB_draggerRail{ - width: 100%; - height: 4px; - margin: 6px 0; - } - - .mCS-light-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - width: 100%; - height: 6px; - margin: 5px auto; - } - - .mCS-light-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } - - .mCS-light-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-light-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } - - .mCS-light-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -16px 0; } - - .mCS-light-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -16px -20px; } - - .mCS-light-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -20px -40px; } - - .mCS-light-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -20px -56px; } - - - /* theme: "dark-thick" */ - - .mCS-dark-thick.mCSB_scrollTools .mCSB_draggerRail{ - background-color: #000; background-color: rgba(0,0,0,0.1); - -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; - } - - .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - background-color: #000; background-color: rgba(0,0,0,0.75); - -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; - } - - .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } - - .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } - - .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -96px 0; } - - .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -96px -20px; } - - .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -100px -40px; } - - .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -100px -56px; } - - /* ---------------------------------------- */ - - - - /* theme: "light-thin", "dark-thin" */ - - .mCS-light-thin.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.1); } - - .mCS-light-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 2px; } - - .mCS-light-thin.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-dark-thin.mCSB_scrollTools_horizontal .mCSB_draggerRail{ width: 100%; } - - .mCS-light-thin.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-thin.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - width: 100%; - height: 2px; - margin: 7px auto; - } - - - /* theme "dark-thin" */ - - .mCS-dark-thin.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } - - .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } - - .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } - - .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } - - .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px 0; } - - .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -20px; } - - .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -40px; } - - .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -56px; } - - /* ---------------------------------------- */ - - - - /* theme "rounded", "rounded-dark", "rounded-dots", "rounded-dots-dark" */ - - .mCS-rounded.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.15); } - - .mCS-rounded.mCSB_scrollTools .mCSB_dragger, - .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger, - .mCS-rounded-dots.mCSB_scrollTools .mCSB_dragger, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger{ height: 14px; } - - .mCS-rounded.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dots.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - width: 14px; - margin: 0 1px; - } - - .mCS-rounded.mCSB_scrollTools_horizontal .mCSB_dragger, - .mCS-rounded-dark.mCSB_scrollTools_horizontal .mCSB_dragger, - .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_dragger, - .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 14px; } - - .mCS-rounded.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - height: 14px; - margin: 1px 0; - } - - .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, - .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, - .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ - width: 16px; /* auto-expanded scrollbar */ - height: 16px; - margin: -1px 0; - } - - .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, - .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ width: 4px; /* auto-expanded scrollbar */ } - - .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, - .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, - .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ - height: 16px; /* auto-expanded scrollbar */ - width: 16px; - margin: 0 -1px; - } - - .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, - .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ - height: 4px; /* auto-expanded scrollbar */ - margin: 6px 0; - } - - .mCS-rounded.mCSB_scrollTools .mCSB_buttonUp{ background-position: 0 -72px; } - - .mCS-rounded.mCSB_scrollTools .mCSB_buttonDown{ background-position: 0 -92px; } - - .mCS-rounded.mCSB_scrollTools .mCSB_buttonLeft{ background-position: 0 -112px; } - - .mCS-rounded.mCSB_scrollTools .mCSB_buttonRight{ background-position: 0 -128px; } - - - /* theme "rounded-dark", "rounded-dots-dark" */ - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px -72px; } - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -92px; } - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -112px; } - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -128px; } - - - /* theme "rounded-dots", "rounded-dots-dark" */ - - .mCS-rounded-dots.mCSB_scrollTools_vertical .mCSB_draggerRail, - .mCS-rounded-dots-dark.mCSB_scrollTools_vertical .mCSB_draggerRail{ width: 4px; } - - .mCS-rounded-dots.mCSB_scrollTools .mCSB_draggerRail, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail, - .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ - background-color: transparent; - background-position: center; - } - - .mCS-rounded-dots.mCSB_scrollTools .mCSB_draggerRail, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail{ - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAANElEQVQYV2NkIAAYiVbw//9/Y6DiM1ANJoyMjGdBbLgJQAX/kU0DKgDLkaQAvxW4HEvQFwCRcxIJK1XznAAAAABJRU5ErkJggg=="); - background-repeat: repeat-y; - opacity: 0.3; - filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; - } - - .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ - height: 4px; - margin: 6px 0; - background-repeat: repeat-x; - } - - .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonUp{ background-position: -16px -72px; } - - .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonDown{ background-position: -16px -92px; } - - .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -20px -112px; } - - .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonRight{ background-position: -20px -128px; } - - - /* theme "rounded-dots-dark" */ - - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail{ - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAALElEQVQYV2NkIAAYSVFgDFR8BqrBBEifBbGRTfiPZhpYjiQFBK3A6l6CvgAAE9kGCd1mvgEAAAAASUVORK5CYII="); - } - - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -96px -72px; } - - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -96px -92px; } - - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -100px -112px; } - - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -100px -128px; } - - /* ---------------------------------------- */ - - - - /* theme "3d", "3d-dark", "3d-thick", "3d-thick-dark" */ - - .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - background-repeat: repeat-y; - background-image: -moz-linear-gradient(left, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 100%); - background-image: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(255,255,255,0.5)), color-stop(100%,rgba(255,255,255,0))); - background-image: -webkit-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - background-image: -o-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - background-image: -ms-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - background-image: linear-gradient(to right, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - } - - .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - background-repeat: repeat-x; - background-image: -moz-linear-gradient(top, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 100%); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,0.5)), color-stop(100%,rgba(255,255,255,0))); - background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - background-image: -o-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - background-image: -ms-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - background-image: linear-gradient(to bottom, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - } - - - /* theme "3d", "3d-dark" */ - - .mCS-3d.mCSB_scrollTools_vertical .mCSB_dragger, - .mCS-3d-dark.mCSB_scrollTools_vertical .mCSB_dragger{ height: 70px; } - - .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger, - .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 70px; } - - .mCS-3d.mCSB_scrollTools, - .mCS-3d-dark.mCSB_scrollTools{ - opacity: 1; - filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; - } - - .mCS-3d.mCSB_scrollTools .mCSB_draggerRail, - .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail, - .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; } - - .mCS-3d.mCSB_scrollTools .mCSB_draggerRail, - .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail{ - width: 8px; - background-color: #000; background-color: rgba(0,0,0,0.2); - box-shadow: inset 1px 0 1px rgba(0,0,0,0.5), inset -1px 0 1px rgba(255,255,255,0.2); - } - - .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, - .mCS-3d.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-3d.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #555; } - - .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 8px; } - - .mCS-3d.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ - width: 100%; - height: 8px; - margin: 4px 0; - box-shadow: inset 0 1px 1px rgba(0,0,0,0.5), inset 0 -1px 1px rgba(255,255,255,0.2); - } - - .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - width: 100%; - height: 8px; - margin: 4px auto; - } - - .mCS-3d.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } - - .mCS-3d.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } - - .mCS-3d.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } - - .mCS-3d.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } - - - /* theme "3d-dark" */ - - .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail{ - background-color: #000; background-color: rgba(0,0,0,0.1); - box-shadow: inset 1px 0 1px rgba(0,0,0,0.1); - } - - .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ box-shadow: inset 0 1px 1px rgba(0,0,0,0.1); } - - .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } - - .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } - - .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } - - .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } - - /* ---------------------------------------- */ - - - - /* theme: "3d-thick", "3d-thick-dark" */ - - .mCS-3d-thick.mCSB_scrollTools, - .mCS-3d-thick-dark.mCSB_scrollTools{ - opacity: 1; - filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; - } - - .mCS-3d-thick.mCSB_scrollTools, - .mCS-3d-thick-dark.mCSB_scrollTools, - .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerContainer, - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerContainer{ -webkit-border-radius: 7px; -moz-border-radius: 7px; border-radius: 7px; } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } - - .mCSB_inside + .mCS-3d-thick.mCSB_scrollTools_vertical, - .mCSB_inside + .mCS-3d-thick-dark.mCSB_scrollTools_vertical{ right: 1px; } - - .mCS-3d-thick.mCSB_scrollTools_vertical, - .mCS-3d-thick-dark.mCSB_scrollTools_vertical{ box-shadow: inset 1px 0 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.5); } - - .mCS-3d-thick.mCSB_scrollTools_horizontal, - .mCS-3d-thick-dark.mCSB_scrollTools_horizontal{ - bottom: 1px; - box-shadow: inset 0 1px 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.5); - } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - box-shadow: inset 1px 0 0 rgba(255,255,255,0.4); - width: 12px; - margin: 2px; - position: absolute; - height: auto; - top: 0; - bottom: 0; - left: 0; - right: 0; - } - - .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 0 1px 0 rgba(255,255,255,0.4); } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, - .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #555; } - - .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - height: 12px; - width: auto; - } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerContainer{ - background-color: #000; background-color: rgba(0,0,0,0.05); - box-shadow: inset 1px 1px 16px rgba(0,0,0,0.1); - } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } - - - /* theme: "3d-thick-dark" */ - - .mCS-3d-thick-dark.mCSB_scrollTools{ box-shadow: inset 0 0 14px rgba(0,0,0,0.2); } - - .mCS-3d-thick-dark.mCSB_scrollTools_horizontal{ box-shadow: inset 0 1px 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.2); } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 1px 0 0 rgba(255,255,255,0.4), inset -1px 0 0 rgba(0,0,0,0.2); } - - .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 0 1px 0 rgba(255,255,255,0.4), inset 0 -1px 0 rgba(0,0,0,0.2); } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #777; } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerContainer{ - background-color: #fff; background-color: rgba(0,0,0,0.05); - box-shadow: inset 1px 1px 16px rgba(0,0,0,0.1); - } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } - - /* ---------------------------------------- */ - - - - /* theme: "minimal", "minimal-dark" */ - - .mCSB_outside + .mCS-minimal.mCSB_scrollTools_vertical, - .mCSB_outside + .mCS-minimal-dark.mCSB_scrollTools_vertical{ - right: 0; - margin: 12px 0; - } - - .mCustomScrollBox.mCS-minimal + .mCSB_scrollTools.mCSB_scrollTools_horizontal, - .mCustomScrollBox.mCS-minimal + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal, - .mCustomScrollBox.mCS-minimal-dark + .mCSB_scrollTools.mCSB_scrollTools_horizontal, - .mCustomScrollBox.mCS-minimal-dark + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal{ - bottom: 0; - margin: 0 12px; - } - - /* RTL direction/left-side scrollbar */ - .mCS-dir-rtl > .mCSB_outside + .mCS-minimal.mCSB_scrollTools_vertical, - .mCS-dir-rtl > .mCSB_outside + .mCS-minimal-dark.mCSB_scrollTools_vertical{ - left: 0; - right: auto; - } - - .mCS-minimal.mCSB_scrollTools .mCSB_draggerRail, - .mCS-minimal-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } - - .mCS-minimal.mCSB_scrollTools_vertical .mCSB_dragger, - .mCS-minimal-dark.mCSB_scrollTools_vertical .mCSB_dragger{ height: 50px; } - - .mCS-minimal.mCSB_scrollTools_horizontal .mCSB_dragger, - .mCS-minimal-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 50px; } - - .mCS-minimal.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - background-color: #fff; background-color: rgba(255,255,255,0.2); - filter: "alpha(opacity=20)"; -ms-filter: "alpha(opacity=20)"; - } - - .mCS-minimal.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-minimal.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ - background-color: #fff; background-color: rgba(255,255,255,0.5); - filter: "alpha(opacity=50)"; -ms-filter: "alpha(opacity=50)"; - } - - - /* theme: "minimal-dark" */ - - .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - background-color: #000; background-color: rgba(0,0,0,0.2); - filter: "alpha(opacity=20)"; -ms-filter: "alpha(opacity=20)"; - } - - .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ - background-color: #000; background-color: rgba(0,0,0,0.5); - filter: "alpha(opacity=50)"; -ms-filter: "alpha(opacity=50)"; - } - - /* ---------------------------------------- */ - - - - /* theme "light-3", "dark-3" */ - - .mCS-light-3.mCSB_scrollTools .mCSB_draggerRail, - .mCS-dark-3.mCSB_scrollTools .mCSB_draggerRail{ - width: 6px; - background-color: #000; background-color: rgba(0,0,0,0.2); - } - - .mCS-light-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 6px; } - - .mCS-light-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-light-3.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-dark-3.mCSB_scrollTools_horizontal .mCSB_draggerRail{ - width: 100%; - height: 6px; - margin: 5px 0; - } - - .mCS-light-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-light-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, - .mCS-dark-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-dark-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ - width: 12px; - } - - .mCS-light-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-light-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, - .mCS-dark-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-dark-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ - height: 12px; - margin: 2px 0; - } - - .mCS-light-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } - - .mCS-light-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } - - .mCS-light-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } - - .mCS-light-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } - - - /* theme "dark-3" */ - - .mCS-dark-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } - - .mCS-dark-3.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } - - .mCS-dark-3.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-dark-3.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } - - .mCS-dark-3.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.1); } - - .mCS-dark-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } - - .mCS-dark-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } - - .mCS-dark-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } - - .mCS-dark-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } - - /* ---------------------------------------- */ - - - - /* theme "inset", "inset-dark", "inset-2", "inset-2-dark", "inset-3", "inset-3-dark" */ - - .mCS-inset.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-dark.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-2.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-3.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ - width: 12px; - background-color: #000; background-color: rgba(0,0,0,0.2); - } - - .mCS-inset.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - width: 6px; - margin: 3px 5px; - position: absolute; - height: auto; - top: 0; - bottom: 0; - left: 0; - right: 0; - } - - .mCS-inset.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-2-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-3-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - height: 6px; - margin: 5px 3px; - position: absolute; - width: auto; - top: 0; - bottom: 0; - left: 0; - right: 0; - } - - .mCS-inset.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-inset-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-inset-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-inset-2-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-inset-3.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-inset-3-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ - width: 100%; - height: 12px; - margin: 2px 0; - } - - .mCS-inset.mCSB_scrollTools .mCSB_buttonUp, - .mCS-inset-2.mCSB_scrollTools .mCSB_buttonUp, - .mCS-inset-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } - - .mCS-inset.mCSB_scrollTools .mCSB_buttonDown, - .mCS-inset-2.mCSB_scrollTools .mCSB_buttonDown, - .mCS-inset-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } - - .mCS-inset.mCSB_scrollTools .mCSB_buttonLeft, - .mCS-inset-2.mCSB_scrollTools .mCSB_buttonLeft, - .mCS-inset-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } - - .mCS-inset.mCSB_scrollTools .mCSB_buttonRight, - .mCS-inset-2.mCSB_scrollTools .mCSB_buttonRight, - .mCS-inset-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } - - - /* theme "inset-dark", "inset-2-dark", "inset-3-dark" */ - - .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } - - .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } - - .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } - - .mCS-inset-dark.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.1); } - - .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonUp, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonUp, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } - - .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonDown, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonDown, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } - - .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonLeft, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonLeft, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } - - .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonRight, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonRight, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } - - - /* theme "inset-2", "inset-2-dark" */ - - .mCS-inset-2.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail{ - background-color: transparent; - border-width: 1px; - border-style: solid; - border-color: #fff; - border-color: rgba(255,255,255,0.2); - -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; - } - - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail{ border-color: #000; border-color: rgba(0,0,0,0.2); } - - - /* theme "inset-3", "inset-3-dark" */ - - .mCS-inset-3.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.6); } - - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.6); } - - .mCS-inset-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } - - .mCS-inset-3.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } - - .mCS-inset-3.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-inset-3.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } - - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.75); } - - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } - - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } - - /* ---------------------------------------- */ diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js deleted file mode 100644 index ff7a7263f8..0000000000 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js +++ /dev/null @@ -1,2458 +0,0 @@ -/* -== malihu jquery custom scrollbar plugin == -Version: 3.1.5 -Plugin URI: http://manos.malihu.gr/jquery-custom-content-scroller -Author: malihu -Author URI: http://manos.malihu.gr -License: MIT License (MIT) -*/ - -/* -Copyright Manos Malihutsakis (email: manos@malihu.gr) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -/* -The code below is fairly long, fully commented and should be normally used in development. -For production, use either the minified jquery.mCustomScrollbar.min.js script or -the production-ready jquery.mCustomScrollbar.concat.min.js which contains the plugin -and dependencies (minified). -*/ - -(function(factory){ - if(typeof define==="function" && define.amd){ - define(["jquery"],factory); - }else if(typeof module!=="undefined" && module.exports){ - module.exports=factory; - }else{ - factory(jQuery,window,document); - } -}(function($){ -(function(init){ - var _rjs=typeof define==="function" && define.amd, /* RequireJS */ - _njs=typeof module !== "undefined" && module.exports, /* NodeJS */ - _dlp=("https:"==document.location.protocol) ? "https:" : "http:", /* location protocol */ - _url="cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js"; - if(!_rjs){ - if(_njs){ - require("jquery-mousewheel")($); - }else{ - /* load jquery-mousewheel plugin (via CDN) if it's not present or not loaded via RequireJS - (works when mCustomScrollbar fn is called on window load) */ - $.event.special.mousewheel || $("head").append(decodeURI("%3Cscript src="+_dlp+"//"+_url+"%3E%3C/script%3E")); - } - } - init(); -}(function(){ - - /* - ---------------------------------------- - PLUGIN NAMESPACE, PREFIX, DEFAULT SELECTOR(S) - ---------------------------------------- - */ - - var pluginNS="mCustomScrollbar", - pluginPfx="mCS", - defaultSelector=".mCustomScrollbar", - - - - - - /* - ---------------------------------------- - DEFAULT OPTIONS - ---------------------------------------- - */ - - defaults={ - /* - set element/content width/height programmatically - values: boolean, pixels, percentage - option default - ------------------------------------- - setWidth false - setHeight false - */ - /* - set the initial css top property of content - values: string (e.g. "-100px", "10%" etc.) - */ - setTop:0, - /* - set the initial css left property of content - values: string (e.g. "-100px", "10%" etc.) - */ - setLeft:0, - /* - scrollbar axis (vertical and/or horizontal scrollbars) - values (string): "y", "x", "yx" - */ - axis:"y", - /* - position of scrollbar relative to content - values (string): "inside", "outside" ("outside" requires elements with position:relative) - */ - scrollbarPosition:"inside", - /* - scrolling inertia - values: integer (milliseconds) - */ - scrollInertia:950, - /* - auto-adjust scrollbar dragger length - values: boolean - */ - autoDraggerLength:true, - /* - auto-hide scrollbar when idle - values: boolean - option default - ------------------------------------- - autoHideScrollbar false - */ - /* - auto-expands scrollbar on mouse-over and dragging - values: boolean - option default - ------------------------------------- - autoExpandScrollbar false - */ - /* - always show scrollbar, even when there's nothing to scroll - values: integer (0=disable, 1=always show dragger rail and buttons, 2=always show dragger rail, dragger and buttons), boolean - */ - alwaysShowScrollbar:0, - /* - scrolling always snaps to a multiple of this number in pixels - values: integer, array ([y,x]) - option default - ------------------------------------- - snapAmount null - */ - /* - when snapping, snap with this number in pixels as an offset - values: integer - */ - snapOffset:0, - /* - mouse-wheel scrolling - */ - mouseWheel:{ - /* - enable mouse-wheel scrolling - values: boolean - */ - enable:true, - /* - scrolling amount in pixels - values: "auto", integer - */ - scrollAmount:"auto", - /* - mouse-wheel scrolling axis - the default scrolling direction when both vertical and horizontal scrollbars are present - values (string): "y", "x" - */ - axis:"y", - /* - prevent the default behaviour which automatically scrolls the parent element(s) when end of scrolling is reached - values: boolean - option default - ------------------------------------- - preventDefault null - */ - /* - the reported mouse-wheel delta value. The number of lines (translated to pixels) one wheel notch scrolls. - values: "auto", integer - "auto" uses the default OS/browser value - */ - deltaFactor:"auto", - /* - normalize mouse-wheel delta to -1 or 1 (disables mouse-wheel acceleration) - values: boolean - option default - ------------------------------------- - normalizeDelta null - */ - /* - invert mouse-wheel scrolling direction - values: boolean - option default - ------------------------------------- - invert null - */ - /* - the tags that disable mouse-wheel when cursor is over them - */ - disableOver:["select","option","keygen","datalist","textarea"] - }, - /* - scrollbar buttons - */ - scrollButtons:{ - /* - enable scrollbar buttons - values: boolean - option default - ------------------------------------- - enable null - */ - /* - scrollbar buttons scrolling type - values (string): "stepless", "stepped" - */ - scrollType:"stepless", - /* - scrolling amount in pixels - values: "auto", integer - */ - scrollAmount:"auto" - /* - tabindex of the scrollbar buttons - values: false, integer - option default - ------------------------------------- - tabindex null - */ - }, - /* - keyboard scrolling - */ - keyboard:{ - /* - enable scrolling via keyboard - values: boolean - */ - enable:true, - /* - keyboard scrolling type - values (string): "stepless", "stepped" - */ - scrollType:"stepless", - /* - scrolling amount in pixels - values: "auto", integer - */ - scrollAmount:"auto" - }, - /* - enable content touch-swipe scrolling - values: boolean, integer, string (number) - integer values define the axis-specific minimum amount required for scrolling momentum - */ - contentTouchScroll:25, - /* - enable/disable document (default) touch-swipe scrolling - */ - documentTouchScroll:true, - /* - advanced option parameters - */ - advanced:{ - /* - auto-expand content horizontally (for "x" or "yx" axis) - values: boolean, integer (the value 2 forces the non scrollHeight/scrollWidth method, the value 3 forces the scrollHeight/scrollWidth method) - option default - ------------------------------------- - autoExpandHorizontalScroll null - */ - /* - auto-scroll to elements with focus - */ - autoScrollOnFocus:"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']", - /* - auto-update scrollbars on content, element or viewport resize - should be true for fluid layouts/elements, adding/removing content dynamically, hiding/showing elements, content with images etc. - values: boolean - */ - updateOnContentResize:true, - /* - auto-update scrollbars each time each image inside the element is fully loaded - values: "auto", boolean - */ - updateOnImageLoad:"auto", - /* - auto-update scrollbars based on the amount and size changes of specific selectors - useful when you need to update the scrollbar(s) automatically, each time a type of element is added, removed or changes its size - values: boolean, string (e.g. "ul li" will auto-update scrollbars each time list-items inside the element are changed) - a value of true (boolean) will auto-update scrollbars each time any element is changed - option default - ------------------------------------- - updateOnSelectorChange null - */ - /* - extra selectors that'll allow scrollbar dragging upon mousemove/up, pointermove/up, touchend etc. (e.g. "selector-1, selector-2") - option default - ------------------------------------- - extraDraggableSelectors null - */ - /* - extra selectors that'll release scrollbar dragging upon mouseup, pointerup, touchend etc. (e.g. "selector-1, selector-2") - option default - ------------------------------------- - releaseDraggableSelectors null - */ - /* - auto-update timeout - values: integer (milliseconds) - */ - autoUpdateTimeout:60 - }, - /* - scrollbar theme - values: string (see CSS/plugin URI for a list of ready-to-use themes) - */ - theme:"light", - /* - user defined callback functions - */ - callbacks:{ - /* - Available callbacks: - callback default - ------------------------------------- - onCreate null - onInit null - onScrollStart null - onScroll null - onTotalScroll null - onTotalScrollBack null - whileScrolling null - onOverflowY null - onOverflowX null - onOverflowYNone null - onOverflowXNone null - onImageLoad null - onSelectorChange null - onBeforeUpdate null - onUpdate null - */ - onTotalScrollOffset:0, - onTotalScrollBackOffset:0, - alwaysTriggerOffsets:true - } - /* - add scrollbar(s) on all elements matching the current selector, now and in the future - values: boolean, string - string values: "on" (enable), "once" (disable after first invocation), "off" (disable) - liveSelector values: string (selector) - option default - ------------------------------------- - live false - liveSelector null - */ - }, - - - - - - /* - ---------------------------------------- - VARS, CONSTANTS - ---------------------------------------- - */ - - totalInstances=0, /* plugin instances amount */ - liveTimers={}, /* live option timers */ - oldIE=(window.attachEvent && !window.addEventListener) ? 1 : 0, /* detect IE < 9 */ - touchActive=false,touchable, /* global touch vars (for touch and pointer events) */ - /* general plugin classes */ - classes=[ - "mCSB_dragger_onDrag","mCSB_scrollTools_onDrag","mCS_img_loaded","mCS_disabled","mCS_destroyed","mCS_no_scrollbar", - "mCS-autoHide","mCS-dir-rtl","mCS_no_scrollbar_y","mCS_no_scrollbar_x","mCS_y_hidden","mCS_x_hidden","mCSB_draggerContainer", - "mCSB_buttonUp","mCSB_buttonDown","mCSB_buttonLeft","mCSB_buttonRight" - ], - - - - - - /* - ---------------------------------------- - METHODS - ---------------------------------------- - */ - - methods={ - - /* - plugin initialization method - creates the scrollbar(s), plugin data object and options - ---------------------------------------- - */ - - init:function(options){ - - var options=$.extend(true,{},defaults,options), - selector=_selector.call(this); /* validate selector */ - - /* - if live option is enabled, monitor for elements matching the current selector and - apply scrollbar(s) when found (now and in the future) - */ - if(options.live){ - var liveSelector=options.liveSelector || this.selector || defaultSelector, /* live selector(s) */ - $liveSelector=$(liveSelector); /* live selector(s) as jquery object */ - if(options.live==="off"){ - /* - disable live if requested - usage: $(selector).mCustomScrollbar({live:"off"}); - */ - removeLiveTimers(liveSelector); - return; - } - liveTimers[liveSelector]=setTimeout(function(){ - /* call mCustomScrollbar fn on live selector(s) every half-second */ - $liveSelector.mCustomScrollbar(options); - if(options.live==="once" && $liveSelector.length){ - /* disable live after first invocation */ - removeLiveTimers(liveSelector); - } - },500); - }else{ - removeLiveTimers(liveSelector); - } - - /* options backward compatibility (for versions < 3.0.0) and normalization */ - options.setWidth=(options.set_width) ? options.set_width : options.setWidth; - options.setHeight=(options.set_height) ? options.set_height : options.setHeight; - options.axis=(options.horizontalScroll) ? "x" : _findAxis(options.axis); - options.scrollInertia=options.scrollInertia>0 && options.scrollInertia<17 ? 17 : options.scrollInertia; - if(typeof options.mouseWheel!=="object" && options.mouseWheel==true){ /* old school mouseWheel option (non-object) */ - options.mouseWheel={enable:true,scrollAmount:"auto",axis:"y",preventDefault:false,deltaFactor:"auto",normalizeDelta:false,invert:false} - } - options.mouseWheel.scrollAmount=!options.mouseWheelPixels ? options.mouseWheel.scrollAmount : options.mouseWheelPixels; - options.mouseWheel.normalizeDelta=!options.advanced.normalizeMouseWheelDelta ? options.mouseWheel.normalizeDelta : options.advanced.normalizeMouseWheelDelta; - options.scrollButtons.scrollType=_findScrollButtonsType(options.scrollButtons.scrollType); - - _theme(options); /* theme-specific options */ - - /* plugin constructor */ - return $(selector).each(function(){ - - var $this=$(this); - - if(!$this.data(pluginPfx)){ /* prevent multiple instantiations */ - - /* store options and create objects in jquery data */ - $this.data(pluginPfx,{ - idx:++totalInstances, /* instance index */ - opt:options, /* options */ - scrollRatio:{y:null,x:null}, /* scrollbar to content ratio */ - overflowed:null, /* overflowed axis */ - contentReset:{y:null,x:null}, /* object to check when content resets */ - bindEvents:false, /* object to check if events are bound */ - tweenRunning:false, /* object to check if tween is running */ - sequential:{}, /* sequential scrolling object */ - langDir:$this.css("direction"), /* detect/store direction (ltr or rtl) */ - cbOffsets:null, /* object to check whether callback offsets always trigger */ - /* - object to check how scrolling events where last triggered - "internal" (default - triggered by this script), "external" (triggered by other scripts, e.g. via scrollTo method) - usage: object.data("mCS").trigger - */ - trigger:null, - /* - object to check for changes in elements in order to call the update method automatically - */ - poll:{size:{o:0,n:0},img:{o:0,n:0},change:{o:0,n:0}} - }); - - var d=$this.data(pluginPfx),o=d.opt, - /* HTML data attributes */ - htmlDataAxis=$this.data("mcs-axis"),htmlDataSbPos=$this.data("mcs-scrollbar-position"),htmlDataTheme=$this.data("mcs-theme"); - - if(htmlDataAxis){o.axis=htmlDataAxis;} /* usage example: data-mcs-axis="y" */ - if(htmlDataSbPos){o.scrollbarPosition=htmlDataSbPos;} /* usage example: data-mcs-scrollbar-position="outside" */ - if(htmlDataTheme){ /* usage example: data-mcs-theme="minimal" */ - o.theme=htmlDataTheme; - _theme(o); /* theme-specific options */ - } - - _pluginMarkup.call(this); /* add plugin markup */ - - if(d && o.callbacks.onCreate && typeof o.callbacks.onCreate==="function"){o.callbacks.onCreate.call(this);} /* callbacks: onCreate */ - - $("#mCSB_"+d.idx+"_container img:not(."+classes[2]+")").addClass(classes[2]); /* flag loaded images */ - - methods.update.call(null,$this); /* call the update method */ - - } - - }); - - }, - /* ---------------------------------------- */ - - - - /* - plugin update method - updates content and scrollbar(s) values, events and status - ---------------------------------------- - usage: $(selector).mCustomScrollbar("update"); - */ - - update:function(el,cb){ - - var selector=el || _selector.call(this); /* validate selector */ - - return $(selector).each(function(){ - - var $this=$(this); - - if($this.data(pluginPfx)){ /* check if plugin has initialized */ - - var d=$this.data(pluginPfx),o=d.opt, - mCSB_container=$("#mCSB_"+d.idx+"_container"), - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; - - if(!mCSB_container.length){return;} - - if(d.tweenRunning){_stop($this);} /* stop any running tweens while updating */ - - if(cb && d && o.callbacks.onBeforeUpdate && typeof o.callbacks.onBeforeUpdate==="function"){o.callbacks.onBeforeUpdate.call(this);} /* callbacks: onBeforeUpdate */ - - /* if element was disabled or destroyed, remove class(es) */ - if($this.hasClass(classes[3])){$this.removeClass(classes[3]);} - if($this.hasClass(classes[4])){$this.removeClass(classes[4]);} - - /* css flexbox fix, detect/set max-height */ - mCustomScrollBox.css("max-height","none"); - if(mCustomScrollBox.height()!==$this.height()){mCustomScrollBox.css("max-height",$this.height());} - - _expandContentHorizontally.call(this); /* expand content horizontally */ - - if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){ - mCSB_container.css("width",_contentWidth(mCSB_container)); - } - - d.overflowed=_overflowed.call(this); /* determine if scrolling is required */ - - _scrollbarVisibility.call(this); /* show/hide scrollbar(s) */ - - /* auto-adjust scrollbar dragger length analogous to content */ - if(o.autoDraggerLength){_setDraggerLength.call(this);} - - _scrollRatio.call(this); /* calculate and store scrollbar to content ratio */ - - _bindEvents.call(this); /* bind scrollbar events */ - - /* reset scrolling position and/or events */ - var to=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)]; - if(o.axis!=="x"){ /* y/yx axis */ - if(!d.overflowed[0]){ /* y scrolling is not required */ - _resetContentPosition.call(this); /* reset content position */ - if(o.axis==="y"){ - _unbindEvents.call(this); - }else if(o.axis==="yx" && d.overflowed[1]){ - _scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"}); - } - }else if(mCSB_dragger[0].height()>mCSB_dragger[0].parent().height()){ - _resetContentPosition.call(this); /* reset content position */ - }else{ /* y scrolling is required */ - _scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"}); - d.contentReset.y=null; - } - } - if(o.axis!=="y"){ /* x/yx axis */ - if(!d.overflowed[1]){ /* x scrolling is not required */ - _resetContentPosition.call(this); /* reset content position */ - if(o.axis==="x"){ - _unbindEvents.call(this); - }else if(o.axis==="yx" && d.overflowed[0]){ - _scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"}); - } - }else if(mCSB_dragger[1].width()>mCSB_dragger[1].parent().width()){ - _resetContentPosition.call(this); /* reset content position */ - }else{ /* x scrolling is required */ - _scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"}); - d.contentReset.x=null; - } - } - - /* callbacks: onImageLoad, onSelectorChange, onUpdate */ - if(cb && d){ - if(cb===2 && o.callbacks.onImageLoad && typeof o.callbacks.onImageLoad==="function"){ - o.callbacks.onImageLoad.call(this); - }else if(cb===3 && o.callbacks.onSelectorChange && typeof o.callbacks.onSelectorChange==="function"){ - o.callbacks.onSelectorChange.call(this); - }else if(o.callbacks.onUpdate && typeof o.callbacks.onUpdate==="function"){ - o.callbacks.onUpdate.call(this); - } - } - - _autoUpdate.call(this); /* initialize automatic updating (for dynamic content, fluid layouts etc.) */ - - } - - }); - - }, - /* ---------------------------------------- */ - - - - /* - plugin scrollTo method - triggers a scrolling event to a specific value - ---------------------------------------- - usage: $(selector).mCustomScrollbar("scrollTo",value,options); - */ - - scrollTo:function(val,options){ - - /* prevent silly things like $(selector).mCustomScrollbar("scrollTo",undefined); */ - if(typeof val=="undefined" || val==null){return;} - - var selector=_selector.call(this); /* validate selector */ - - return $(selector).each(function(){ - - var $this=$(this); - - if($this.data(pluginPfx)){ /* check if plugin has initialized */ - - var d=$this.data(pluginPfx),o=d.opt, - /* method default options */ - methodDefaults={ - trigger:"external", /* method is by default triggered externally (e.g. from other scripts) */ - scrollInertia:o.scrollInertia, /* scrolling inertia (animation duration) */ - scrollEasing:"mcsEaseInOut", /* animation easing */ - moveDragger:false, /* move dragger instead of content */ - timeout:60, /* scroll-to delay */ - callbacks:true, /* enable/disable callbacks */ - onStart:true, - onUpdate:true, - onComplete:true - }, - methodOptions=$.extend(true,{},methodDefaults,options), - to=_arr.call(this,val),dur=methodOptions.scrollInertia>0 && methodOptions.scrollInertia<17 ? 17 : methodOptions.scrollInertia; - - /* translate yx values to actual scroll-to positions */ - to[0]=_to.call(this,to[0],"y"); - to[1]=_to.call(this,to[1],"x"); - - /* - check if scroll-to value moves the dragger instead of content. - Only pixel values apply on dragger (e.g. 100, "100px", "-=100" etc.) - */ - if(methodOptions.moveDragger){ - to[0]*=d.scrollRatio.y; - to[1]*=d.scrollRatio.x; - } - - methodOptions.dur=_isTabHidden() ? 0 : dur; //skip animations if browser tab is hidden - - setTimeout(function(){ - /* do the scrolling */ - if(to[0]!==null && typeof to[0]!=="undefined" && o.axis!=="x" && d.overflowed[0]){ /* scroll y */ - methodOptions.dir="y"; - methodOptions.overwrite="all"; - _scrollTo($this,to[0].toString(),methodOptions); - } - if(to[1]!==null && typeof to[1]!=="undefined" && o.axis!=="y" && d.overflowed[1]){ /* scroll x */ - methodOptions.dir="x"; - methodOptions.overwrite="none"; - _scrollTo($this,to[1].toString(),methodOptions); - } - },methodOptions.timeout); - - } - - }); - - }, - /* ---------------------------------------- */ - - - - /* - plugin stop method - stops scrolling animation - ---------------------------------------- - usage: $(selector).mCustomScrollbar("stop"); - */ - stop:function(){ - - var selector=_selector.call(this); /* validate selector */ - - return $(selector).each(function(){ - - var $this=$(this); - - if($this.data(pluginPfx)){ /* check if plugin has initialized */ - - _stop($this); - - } - - }); - - }, - /* ---------------------------------------- */ - - - - /* - plugin disable method - temporarily disables the scrollbar(s) - ---------------------------------------- - usage: $(selector).mCustomScrollbar("disable",reset); - reset (boolean): resets content position to 0 - */ - disable:function(r){ - - var selector=_selector.call(this); /* validate selector */ - - return $(selector).each(function(){ - - var $this=$(this); - - if($this.data(pluginPfx)){ /* check if plugin has initialized */ - - var d=$this.data(pluginPfx); - - _autoUpdate.call(this,"remove"); /* remove automatic updating */ - - _unbindEvents.call(this); /* unbind events */ - - if(r){_resetContentPosition.call(this);} /* reset content position */ - - _scrollbarVisibility.call(this,true); /* show/hide scrollbar(s) */ - - $this.addClass(classes[3]); /* add disable class */ - - } - - }); - - }, - /* ---------------------------------------- */ - - - - /* - plugin destroy method - completely removes the scrollbar(s) and returns the element to its original state - ---------------------------------------- - usage: $(selector).mCustomScrollbar("destroy"); - */ - destroy:function(){ - - var selector=_selector.call(this); /* validate selector */ - - return $(selector).each(function(){ - - var $this=$(this); - - if($this.data(pluginPfx)){ /* check if plugin has initialized */ - - var d=$this.data(pluginPfx),o=d.opt, - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_container=$("#mCSB_"+d.idx+"_container"), - scrollbar=$(".mCSB_"+d.idx+"_scrollbar"); - - if(o.live){removeLiveTimers(o.liveSelector || $(selector).selector);} /* remove live timers */ - - _autoUpdate.call(this,"remove"); /* remove automatic updating */ - - _unbindEvents.call(this); /* unbind events */ - - _resetContentPosition.call(this); /* reset content position */ - - $this.removeData(pluginPfx); /* remove plugin data object */ - - _delete(this,"mcs"); /* delete callbacks object */ - - /* remove plugin markup */ - scrollbar.remove(); /* remove scrollbar(s) first (those can be either inside or outside plugin's inner wrapper) */ - mCSB_container.find("img."+classes[2]).removeClass(classes[2]); /* remove loaded images flag */ - mCustomScrollBox.replaceWith(mCSB_container.contents()); /* replace plugin's inner wrapper with the original content */ - /* remove plugin classes from the element and add destroy class */ - $this.removeClass(pluginNS+" _"+pluginPfx+"_"+d.idx+" "+classes[6]+" "+classes[7]+" "+classes[5]+" "+classes[3]).addClass(classes[4]); - - } - - }); - - } - /* ---------------------------------------- */ - - }, - - - - - - /* - ---------------------------------------- - FUNCTIONS - ---------------------------------------- - */ - - /* validates selector (if selector is invalid or undefined uses the default one) */ - _selector=function(){ - return (typeof $(this)!=="object" || $(this).length<1) ? defaultSelector : this; - }, - /* -------------------- */ - - - /* changes options according to theme */ - _theme=function(obj){ - var fixedSizeScrollbarThemes=["rounded","rounded-dark","rounded-dots","rounded-dots-dark"], - nonExpandedScrollbarThemes=["rounded-dots","rounded-dots-dark","3d","3d-dark","3d-thick","3d-thick-dark","inset","inset-dark","inset-2","inset-2-dark","inset-3","inset-3-dark"], - disabledScrollButtonsThemes=["minimal","minimal-dark"], - enabledAutoHideScrollbarThemes=["minimal","minimal-dark"], - scrollbarPositionOutsideThemes=["minimal","minimal-dark"]; - obj.autoDraggerLength=$.inArray(obj.theme,fixedSizeScrollbarThemes) > -1 ? false : obj.autoDraggerLength; - obj.autoExpandScrollbar=$.inArray(obj.theme,nonExpandedScrollbarThemes) > -1 ? false : obj.autoExpandScrollbar; - obj.scrollButtons.enable=$.inArray(obj.theme,disabledScrollButtonsThemes) > -1 ? false : obj.scrollButtons.enable; - obj.autoHideScrollbar=$.inArray(obj.theme,enabledAutoHideScrollbarThemes) > -1 ? true : obj.autoHideScrollbar; - obj.scrollbarPosition=$.inArray(obj.theme,scrollbarPositionOutsideThemes) > -1 ? "outside" : obj.scrollbarPosition; - }, - /* -------------------- */ - - - /* live option timers removal */ - removeLiveTimers=function(selector){ - if(liveTimers[selector]){ - clearTimeout(liveTimers[selector]); - _delete(liveTimers,selector); - } - }, - /* -------------------- */ - - - /* normalizes axis option to valid values: "y", "x", "yx" */ - _findAxis=function(val){ - return (val==="yx" || val==="xy" || val==="auto") ? "yx" : (val==="x" || val==="horizontal") ? "x" : "y"; - }, - /* -------------------- */ - - - /* normalizes scrollButtons.scrollType option to valid values: "stepless", "stepped" */ - _findScrollButtonsType=function(val){ - return (val==="stepped" || val==="pixels" || val==="step" || val==="click") ? "stepped" : "stepless"; - }, - /* -------------------- */ - - - /* generates plugin markup */ - _pluginMarkup=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - expandClass=o.autoExpandScrollbar ? " "+classes[1]+"_expand" : "", - scrollbar=["
    ","
    "], - wrapperClass=o.axis==="yx" ? "mCSB_vertical_horizontal" : o.axis==="x" ? "mCSB_horizontal" : "mCSB_vertical", - scrollbars=o.axis==="yx" ? scrollbar[0]+scrollbar[1] : o.axis==="x" ? scrollbar[1] : scrollbar[0], - contentWrapper=o.axis==="yx" ? "
    " : "", - autoHideClass=o.autoHideScrollbar ? " "+classes[6] : "", - scrollbarDirClass=(o.axis!=="x" && d.langDir==="rtl") ? " "+classes[7] : ""; - if(o.setWidth){$this.css("width",o.setWidth);} /* set element width */ - if(o.setHeight){$this.css("height",o.setHeight);} /* set element height */ - o.setLeft=(o.axis!=="y" && d.langDir==="rtl") ? "989999px" : o.setLeft; /* adjust left position for rtl direction */ - $this.addClass(pluginNS+" _"+pluginPfx+"_"+d.idx+autoHideClass+scrollbarDirClass).wrapInner("
    "); - var mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_container=$("#mCSB_"+d.idx+"_container"); - if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){ - mCSB_container.css("width",_contentWidth(mCSB_container)); - } - if(o.scrollbarPosition==="outside"){ - if($this.css("position")==="static"){ /* requires elements with non-static position */ - $this.css("position","relative"); - } - $this.css("overflow","visible"); - mCustomScrollBox.addClass("mCSB_outside").after(scrollbars); - }else{ - mCustomScrollBox.addClass("mCSB_inside").append(scrollbars); - mCSB_container.wrap(contentWrapper); - } - _scrollButtons.call(this); /* add scrollbar buttons */ - /* minimum dragger length */ - var mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; - mCSB_dragger[0].css("min-height",mCSB_dragger[0].height()); - mCSB_dragger[1].css("min-width",mCSB_dragger[1].width()); - }, - /* -------------------- */ - - - /* calculates content width */ - _contentWidth=function(el){ - var val=[el[0].scrollWidth,Math.max.apply(Math,el.children().map(function(){return $(this).outerWidth(true);}).get())],w=el.parent().width(); - return val[0]>w ? val[0] : val[1]>w ? val[1] : "100%"; - }, - /* -------------------- */ - - - /* expands content horizontally */ - _expandContentHorizontally=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - mCSB_container=$("#mCSB_"+d.idx+"_container"); - if(o.advanced.autoExpandHorizontalScroll && o.axis!=="y"){ - /* calculate scrollWidth */ - mCSB_container.css({"width":"auto","min-width":0,"overflow-x":"scroll"}); - var w=Math.ceil(mCSB_container[0].scrollWidth); - if(o.advanced.autoExpandHorizontalScroll===3 || (o.advanced.autoExpandHorizontalScroll!==2 && w>mCSB_container.parent().width())){ - mCSB_container.css({"width":w,"min-width":"100%","overflow-x":"inherit"}); - }else{ - /* - wrap content with an infinite width div and set its position to absolute and width to auto. - Setting width to auto before calculating the actual width is important! - We must let the browser set the width as browser zoom values are impossible to calculate. - */ - mCSB_container.css({"overflow-x":"inherit","position":"absolute"}) - .wrap("
    ") - .css({ /* set actual width, original position and un-wrap */ - /* - get the exact width (with decimals) and then round-up. - Using jquery outerWidth() will round the width value which will mess up with inner elements that have non-integer width - */ - "width":(Math.ceil(mCSB_container[0].getBoundingClientRect().right+0.4)-Math.floor(mCSB_container[0].getBoundingClientRect().left)), - "min-width":"100%", - "position":"relative" - }).unwrap(); - } - } - }, - /* -------------------- */ - - - /* adds scrollbar buttons */ - _scrollButtons=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - mCSB_scrollTools=$(".mCSB_"+d.idx+"_scrollbar:first"), - tabindex=!_isNumeric(o.scrollButtons.tabindex) ? "" : "tabindex='"+o.scrollButtons.tabindex+"'", - btnHTML=[ - "", - "", - "", - "" - ], - btn=[(o.axis==="x" ? btnHTML[2] : btnHTML[0]),(o.axis==="x" ? btnHTML[3] : btnHTML[1]),btnHTML[2],btnHTML[3]]; - if(o.scrollButtons.enable){ - mCSB_scrollTools.prepend(btn[0]).append(btn[1]).next(".mCSB_scrollTools").prepend(btn[2]).append(btn[3]); - } - }, - /* -------------------- */ - - - /* auto-adjusts scrollbar dragger length */ - _setDraggerLength=function(){ - var $this=$(this),d=$this.data(pluginPfx), - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_container=$("#mCSB_"+d.idx+"_container"), - mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], - ratio=[mCustomScrollBox.height()/mCSB_container.outerHeight(false),mCustomScrollBox.width()/mCSB_container.outerWidth(false)], - l=[ - parseInt(mCSB_dragger[0].css("min-height")),Math.round(ratio[0]*mCSB_dragger[0].parent().height()), - parseInt(mCSB_dragger[1].css("min-width")),Math.round(ratio[1]*mCSB_dragger[1].parent().width()) - ], - h=oldIE && (l[1]contentHeight){contentHeight=h;} - if(w>contentWidth){contentWidth=w;} - return [contentHeight>mCustomScrollBox.height(),contentWidth>mCustomScrollBox.width()]; - }, - /* -------------------- */ - - - /* resets content position to 0 */ - _resetContentPosition=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_container=$("#mCSB_"+d.idx+"_container"), - mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; - _stop($this); /* stop any current scrolling before resetting */ - if((o.axis!=="x" && !d.overflowed[0]) || (o.axis==="y" && d.overflowed[0])){ /* reset y */ - mCSB_dragger[0].add(mCSB_container).css("top",0); - _scrollTo($this,"_resetY"); - } - if((o.axis!=="y" && !d.overflowed[1]) || (o.axis==="x" && d.overflowed[1])){ /* reset x */ - var cx=dx=0; - if(d.langDir==="rtl"){ /* adjust left position for rtl direction */ - cx=mCustomScrollBox.width()-mCSB_container.outerWidth(false); - dx=Math.abs(cx/d.scrollRatio.x); - } - mCSB_container.css("left",cx); - mCSB_dragger[1].css("left",dx); - _scrollTo($this,"_resetX"); - } - }, - /* -------------------- */ - - - /* binds scrollbar events */ - _bindEvents=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt; - if(!d.bindEvents){ /* check if events are already bound */ - _draggable.call(this); - if(o.contentTouchScroll){_contentDraggable.call(this);} - _selectable.call(this); - if(o.mouseWheel.enable){ /* bind mousewheel fn when plugin is available */ - function _mwt(){ - mousewheelTimeout=setTimeout(function(){ - if(!$.event.special.mousewheel){ - _mwt(); - }else{ - clearTimeout(mousewheelTimeout); - _mousewheel.call($this[0]); - } - },100); - } - var mousewheelTimeout; - _mwt(); - } - _draggerRail.call(this); - _wrapperScroll.call(this); - if(o.advanced.autoScrollOnFocus){_focus.call(this);} - if(o.scrollButtons.enable){_buttons.call(this);} - if(o.keyboard.enable){_keyboard.call(this);} - d.bindEvents=true; - } - }, - /* -------------------- */ - - - /* unbinds scrollbar events */ - _unbindEvents=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - namespace=pluginPfx+"_"+d.idx, - sb=".mCSB_"+d.idx+"_scrollbar", - sel=$("#mCSB_"+d.idx+",#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,"+sb+" ."+classes[12]+",#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal,"+sb+">a"), - mCSB_container=$("#mCSB_"+d.idx+"_container"); - if(o.advanced.releaseDraggableSelectors){sel.add($(o.advanced.releaseDraggableSelectors));} - if(o.advanced.extraDraggableSelectors){sel.add($(o.advanced.extraDraggableSelectors));} - if(d.bindEvents){ /* check if events are bound */ - /* unbind namespaced events from document/selectors */ - $(document).add($(!_canAccessIFrame() || top.document)).unbind("."+namespace); - sel.each(function(){ - $(this).unbind("."+namespace); - }); - /* clear and delete timeouts/objects */ - clearTimeout($this[0]._focusTimeout); _delete($this[0],"_focusTimeout"); - clearTimeout(d.sequential.step); _delete(d.sequential,"step"); - clearTimeout(mCSB_container[0].onCompleteTimeout); _delete(mCSB_container[0],"onCompleteTimeout"); - d.bindEvents=false; - } - }, - /* -------------------- */ - - - /* toggles scrollbar visibility */ - _scrollbarVisibility=function(disabled){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - contentWrapper=$("#mCSB_"+d.idx+"_container_wrapper"), - content=contentWrapper.length ? contentWrapper : $("#mCSB_"+d.idx+"_container"), - scrollbar=[$("#mCSB_"+d.idx+"_scrollbar_vertical"),$("#mCSB_"+d.idx+"_scrollbar_horizontal")], - mCSB_dragger=[scrollbar[0].find(".mCSB_dragger"),scrollbar[1].find(".mCSB_dragger")]; - if(o.axis!=="x"){ - if(d.overflowed[0] && !disabled){ - scrollbar[0].add(mCSB_dragger[0]).add(scrollbar[0].children("a")).css("display","block"); - content.removeClass(classes[8]+" "+classes[10]); - }else{ - if(o.alwaysShowScrollbar){ - if(o.alwaysShowScrollbar!==2){mCSB_dragger[0].css("display","none");} - content.removeClass(classes[10]); - }else{ - scrollbar[0].css("display","none"); - content.addClass(classes[10]); - } - content.addClass(classes[8]); - } - } - if(o.axis!=="y"){ - if(d.overflowed[1] && !disabled){ - scrollbar[1].add(mCSB_dragger[1]).add(scrollbar[1].children("a")).css("display","block"); - content.removeClass(classes[9]+" "+classes[11]); - }else{ - if(o.alwaysShowScrollbar){ - if(o.alwaysShowScrollbar!==2){mCSB_dragger[1].css("display","none");} - content.removeClass(classes[11]); - }else{ - scrollbar[1].css("display","none"); - content.addClass(classes[11]); - } - content.addClass(classes[9]); - } - } - if(!d.overflowed[0] && !d.overflowed[1]){ - $this.addClass(classes[5]); - }else{ - $this.removeClass(classes[5]); - } - }, - /* -------------------- */ - - - /* returns input coordinates of pointer, touch and mouse events (relative to document) */ - _coordinates=function(e){ - var t=e.type,o=e.target.ownerDocument!==document && frameElement!==null ? [$(frameElement).offset().top,$(frameElement).offset().left] : null, - io=_canAccessIFrame() && e.target.ownerDocument!==top.document && frameElement!==null ? [$(e.view.frameElement).offset().top,$(e.view.frameElement).offset().left] : [0,0]; - switch(t){ - case "pointerdown": case "MSPointerDown": case "pointermove": case "MSPointerMove": case "pointerup": case "MSPointerUp": - return o ? [e.originalEvent.pageY-o[0]+io[0],e.originalEvent.pageX-o[1]+io[1],false] : [e.originalEvent.pageY,e.originalEvent.pageX,false]; - break; - case "touchstart": case "touchmove": case "touchend": - var touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0], - touches=e.originalEvent.touches.length || e.originalEvent.changedTouches.length; - return e.target.ownerDocument!==document ? [touch.screenY,touch.screenX,touches>1] : [touch.pageY,touch.pageX,touches>1]; - break; - default: - return o ? [e.pageY-o[0]+io[0],e.pageX-o[1]+io[1],false] : [e.pageY,e.pageX,false]; - } - }, - /* -------------------- */ - - - /* - SCROLLBAR DRAG EVENTS - scrolls content via scrollbar dragging - */ - _draggable=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - namespace=pluginPfx+"_"+d.idx, - draggerId=["mCSB_"+d.idx+"_dragger_vertical","mCSB_"+d.idx+"_dragger_horizontal"], - mCSB_container=$("#mCSB_"+d.idx+"_container"), - mCSB_dragger=$("#"+draggerId[0]+",#"+draggerId[1]), - draggable,dragY,dragX, - rds=o.advanced.releaseDraggableSelectors ? mCSB_dragger.add($(o.advanced.releaseDraggableSelectors)) : mCSB_dragger, - eds=o.advanced.extraDraggableSelectors ? $(!_canAccessIFrame() || top.document).add($(o.advanced.extraDraggableSelectors)) : $(!_canAccessIFrame() || top.document); - mCSB_dragger.bind("contextmenu."+namespace,function(e){ - e.preventDefault(); //prevent right click - }).bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){ - e.stopImmediatePropagation(); - e.preventDefault(); - if(!_mouseBtnLeft(e)){return;} /* left mouse button only */ - touchActive=true; - if(oldIE){document.onselectstart=function(){return false;}} /* disable text selection for IE < 9 */ - _iframe.call(mCSB_container,false); /* enable scrollbar dragging over iframes by disabling their events */ - _stop($this); - draggable=$(this); - var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left, - h=draggable.height()+offset.top,w=draggable.width()+offset.left; - if(y0 && x0){ - dragY=y; - dragX=x; - } - _onDragClasses(draggable,"active",o.autoExpandScrollbar); - }).bind("touchmove."+namespace,function(e){ - e.stopImmediatePropagation(); - e.preventDefault(); - var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left; - _drag(dragY,dragX,y,x); - }); - $(document).add(eds).bind("mousemove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace,function(e){ - if(draggable){ - var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left; - if(dragY===y && dragX===x){return;} /* has it really moved? */ - _drag(dragY,dragX,y,x); - } - }).add(rds).bind("mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){ - if(draggable){ - _onDragClasses(draggable,"active",o.autoExpandScrollbar); - draggable=null; - } - touchActive=false; - if(oldIE){document.onselectstart=null;} /* enable text selection for IE < 9 */ - _iframe.call(mCSB_container,true); /* enable iframes events */ - }); - function _drag(dragY,dragX,y,x){ - mCSB_container[0].idleTimer=o.scrollInertia<233 ? 250 : 0; - if(draggable.attr("id")===draggerId[1]){ - var dir="x",to=((draggable[0].offsetLeft-dragX)+x)*d.scrollRatio.x; - }else{ - var dir="y",to=((draggable[0].offsetTop-dragY)+y)*d.scrollRatio.y; - } - _scrollTo($this,to.toString(),{dir:dir,drag:true}); - } - }, - /* -------------------- */ - - - /* - TOUCH SWIPE EVENTS - scrolls content via touch swipe - Emulates the native touch-swipe scrolling with momentum found in iOS, Android and WP devices - */ - _contentDraggable=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - namespace=pluginPfx+"_"+d.idx, - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_container=$("#mCSB_"+d.idx+"_container"), - mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], - draggable,dragY,dragX,touchStartY,touchStartX,touchMoveY=[],touchMoveX=[],startTime,runningTime,endTime,distance,speed,amount, - durA=0,durB,overwrite=o.axis==="yx" ? "none" : "all",touchIntent=[],touchDrag,docDrag, - iframe=mCSB_container.find("iframe"), - events=[ - "touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace, //start - "touchmove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace, //move - "touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace //end - ], - touchAction=document.body.style.touchAction!==undefined && document.body.style.touchAction!==""; - mCSB_container.bind(events[0],function(e){ - _onTouchstart(e); - }).bind(events[1],function(e){ - _onTouchmove(e); - }); - mCustomScrollBox.bind(events[0],function(e){ - _onTouchstart2(e); - }).bind(events[2],function(e){ - _onTouchend(e); - }); - if(iframe.length){ - iframe.each(function(){ - $(this).bind("load",function(){ - /* bind events on accessible iframes */ - if(_canAccessIFrame(this)){ - $(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){ - _onTouchstart(e); - _onTouchstart2(e); - }).bind(events[1],function(e){ - _onTouchmove(e); - }).bind(events[2],function(e){ - _onTouchend(e); - }); - } - }); - }); - } - function _onTouchstart(e){ - if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){touchable=0; return;} - touchable=1; touchDrag=0; docDrag=0; draggable=1; - $this.removeClass("mCS_touch_action"); - var offset=mCSB_container.offset(); - dragY=_coordinates(e)[0]-offset.top; - dragX=_coordinates(e)[1]-offset.left; - touchIntent=[_coordinates(e)[0],_coordinates(e)[1]]; - } - function _onTouchmove(e){ - if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){return;} - if(!o.documentTouchScroll){e.preventDefault();} - e.stopImmediatePropagation(); - if(docDrag && !touchDrag){return;} - if(draggable){ - runningTime=_getTime(); - var offset=mCustomScrollBox.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left, - easing="mcsLinearOut"; - touchMoveY.push(y); - touchMoveX.push(x); - touchIntent[2]=Math.abs(_coordinates(e)[0]-touchIntent[0]); touchIntent[3]=Math.abs(_coordinates(e)[1]-touchIntent[1]); - if(d.overflowed[0]){ - var limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(), - prevent=((dragY-y)>0 && (y-dragY)>-(limit*d.scrollRatio.y) && (touchIntent[3]*20 && (x-dragX)>-(limitX*d.scrollRatio.x) && (touchIntent[2]*230){return;} - speed=1000/(endTime-startTime); - var easing="mcsEaseOut",slow=speed<2.5, - diff=slow ? [touchMoveY[touchMoveY.length-2],touchMoveX[touchMoveX.length-2]] : [0,0]; - distance=slow ? [(y-diff[0]),(x-diff[1])] : [y-touchStartY,x-touchStartX]; - var absDistance=[Math.abs(distance[0]),Math.abs(distance[1])]; - speed=slow ? [Math.abs(distance[0]/4),Math.abs(distance[1]/4)] : [speed,speed]; - var a=[ - Math.abs(mCSB_container[0].offsetTop)-(distance[0]*_m((absDistance[0]/speed[0]),speed[0])), - Math.abs(mCSB_container[0].offsetLeft)-(distance[1]*_m((absDistance[1]/speed[1]),speed[1])) - ]; - amount=o.axis==="yx" ? [a[0],a[1]] : o.axis==="x" ? [null,a[1]] : [a[0],null]; - durB=[(absDistance[0]*4)+o.scrollInertia,(absDistance[1]*4)+o.scrollInertia]; - var md=parseInt(o.contentTouchScroll) || 0; /* absolute minimum distance required */ - amount[0]=absDistance[0]>md ? amount[0] : 0; - amount[1]=absDistance[1]>md ? amount[1] : 0; - if(d.overflowed[0]){_drag(amount[0],durB[0],easing,"y",overwrite,false);} - if(d.overflowed[1]){_drag(amount[1],durB[1],easing,"x",overwrite,false);} - } - function _m(ds,s){ - var r=[s*1.5,s*2,s/1.5,s/2]; - if(ds>90){ - return s>4 ? r[0] : r[3]; - }else if(ds>60){ - return s>3 ? r[3] : r[2]; - }else if(ds>30){ - return s>8 ? r[1] : s>6 ? r[0] : s>4 ? s : r[2]; - }else{ - return s>8 ? s : r[3]; - } - } - function _drag(amount,dur,easing,dir,overwrite,drag){ - if(!amount){return;} - _scrollTo($this,amount.toString(),{dur:dur,scrollEasing:easing,dir:dir,overwrite:overwrite,drag:drag}); - } - }, - /* -------------------- */ - - - /* - SELECT TEXT EVENTS - scrolls content when text is selected - */ - _selectable=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential, - namespace=pluginPfx+"_"+d.idx, - mCSB_container=$("#mCSB_"+d.idx+"_container"), - wrapper=mCSB_container.parent(), - action; - mCSB_container.bind("mousedown."+namespace,function(e){ - if(touchable){return;} - if(!action){action=1; touchActive=true;} - }).add(document).bind("mousemove."+namespace,function(e){ - if(!touchable && action && _sel()){ - var offset=mCSB_container.offset(), - y=_coordinates(e)[0]-offset.top+mCSB_container[0].offsetTop,x=_coordinates(e)[1]-offset.left+mCSB_container[0].offsetLeft; - if(y>0 && y0 && xwrapper.height()){ - _seq("on",40); - } - } - if(o.axis!=="y" && d.overflowed[1]){ - if(x<0){ - _seq("on",37); - }else if(x>wrapper.width()){ - _seq("on",39); - } - } - } - } - }).bind("mouseup."+namespace+" dragend."+namespace,function(e){ - if(touchable){return;} - if(action){action=0; _seq("off",null);} - touchActive=false; - }); - function _sel(){ - return window.getSelection ? window.getSelection().toString() : - document.selection && document.selection.type!="Control" ? document.selection.createRange().text : 0; - } - function _seq(a,c,s){ - seq.type=s && action ? "stepped" : "stepless"; - seq.scrollAmount=10; - _sequentialScroll($this,a,c,"mcsLinearOut",s ? 60 : null); - } - }, - /* -------------------- */ - - - /* - MOUSE WHEEL EVENT - scrolls content via mouse-wheel - via mouse-wheel plugin (https://github.com/brandonaaron/jquery-mousewheel) - */ - _mousewheel=function(){ - if(!$(this).data(pluginPfx)){return;} /* Check if the scrollbar is ready to use mousewheel events (issue: #185) */ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - namespace=pluginPfx+"_"+d.idx, - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], - iframe=$("#mCSB_"+d.idx+"_container").find("iframe"); - if(iframe.length){ - iframe.each(function(){ - $(this).bind("load",function(){ - /* bind events on accessible iframes */ - if(_canAccessIFrame(this)){ - $(this.contentDocument || this.contentWindow.document).bind("mousewheel."+namespace,function(e,delta){ - _onMousewheel(e,delta); - }); - } - }); - }); - } - mCustomScrollBox.bind("mousewheel."+namespace,function(e,delta){ - _onMousewheel(e,delta); - }); - function _onMousewheel(e,delta){ - _stop($this); - if(_disableMousewheel($this,e.target)){return;} /* disables mouse-wheel when hovering specific elements */ - var deltaFactor=o.mouseWheel.deltaFactor!=="auto" ? parseInt(o.mouseWheel.deltaFactor) : (oldIE && e.deltaFactor<100) ? 100 : e.deltaFactor || 100, - dur=o.scrollInertia; - if(o.axis==="x" || o.mouseWheel.axis==="x"){ - var dir="x", - px=[Math.round(deltaFactor*d.scrollRatio.x),parseInt(o.mouseWheel.scrollAmount)], - amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.width() ? mCustomScrollBox.width()*0.9 : px[0], - contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetLeft), - draggerPos=mCSB_dragger[1][0].offsetLeft, - limit=mCSB_dragger[1].parent().width()-mCSB_dragger[1].width(), - dlt=o.mouseWheel.axis==="y" ? (e.deltaY || delta) : e.deltaX; - }else{ - var dir="y", - px=[Math.round(deltaFactor*d.scrollRatio.y),parseInt(o.mouseWheel.scrollAmount)], - amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.height() ? mCustomScrollBox.height()*0.9 : px[0], - contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetTop), - draggerPos=mCSB_dragger[0][0].offsetTop, - limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(), - dlt=e.deltaY || delta; - } - if((dir==="y" && !d.overflowed[0]) || (dir==="x" && !d.overflowed[1])){return;} - if(o.mouseWheel.invert || e.webkitDirectionInvertedFromDevice){dlt=-dlt;} - if(o.mouseWheel.normalizeDelta){dlt=dlt<0 ? -1 : 1;} - if((dlt>0 && draggerPos!==0) || (dlt<0 && draggerPos!==limit) || o.mouseWheel.preventDefault){ - e.stopImmediatePropagation(); - e.preventDefault(); - } - if(e.deltaFactor<5 && !o.mouseWheel.normalizeDelta){ - //very low deltaFactor values mean some kind of delta acceleration (e.g. osx trackpad), so adjusting scrolling accordingly - amount=e.deltaFactor; dur=17; - } - _scrollTo($this,(contentPos-(dlt*amount)).toString(),{dir:dir,dur:dur}); - } - }, - /* -------------------- */ - - - /* checks if iframe can be accessed */ - _canAccessIFrameCache=new Object(), - _canAccessIFrame=function(iframe){ - var result=false,cacheKey=false,html=null; - if(iframe===undefined){ - cacheKey="#empty"; - }else if($(iframe).attr("id")!==undefined){ - cacheKey=$(iframe).attr("id"); - } - if(cacheKey!==false && _canAccessIFrameCache[cacheKey]!==undefined){ - return _canAccessIFrameCache[cacheKey]; - } - if(!iframe){ - try{ - var doc=top.document; - html=doc.body.innerHTML; - }catch(err){/* do nothing */} - result=(html!==null); - }else{ - try{ - var doc=iframe.contentDocument || iframe.contentWindow.document; - html=doc.body.innerHTML; - }catch(err){/* do nothing */} - result=(html!==null); - } - if(cacheKey!==false){_canAccessIFrameCache[cacheKey]=result;} - return result; - }, - /* -------------------- */ - - - /* switches iframe's pointer-events property (drag, mousewheel etc. over cross-domain iframes) */ - _iframe=function(evt){ - var el=this.find("iframe"); - if(!el.length){return;} /* check if content contains iframes */ - var val=!evt ? "none" : "auto"; - el.css("pointer-events",val); /* for IE11, iframe's display property should not be "block" */ - }, - /* -------------------- */ - - - /* disables mouse-wheel when hovering specific elements like select, datalist etc. */ - _disableMousewheel=function(el,target){ - var tag=target.nodeName.toLowerCase(), - tags=el.data(pluginPfx).opt.mouseWheel.disableOver, - /* elements that require focus */ - focusTags=["select","textarea"]; - return $.inArray(tag,tags) > -1 && !($.inArray(tag,focusTags) > -1 && !$(target).is(":focus")); - }, - /* -------------------- */ - - - /* - DRAGGER RAIL CLICK EVENT - scrolls content via dragger rail - */ - _draggerRail=function(){ - var $this=$(this),d=$this.data(pluginPfx), - namespace=pluginPfx+"_"+d.idx, - mCSB_container=$("#mCSB_"+d.idx+"_container"), - wrapper=mCSB_container.parent(), - mCSB_draggerContainer=$(".mCSB_"+d.idx+"_scrollbar ."+classes[12]), - clickable; - mCSB_draggerContainer.bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){ - touchActive=true; - if(!$(e.target).hasClass("mCSB_dragger")){clickable=1;} - }).bind("touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){ - touchActive=false; - }).bind("click."+namespace,function(e){ - if(!clickable){return;} - clickable=0; - if($(e.target).hasClass(classes[12]) || $(e.target).hasClass("mCSB_draggerRail")){ - _stop($this); - var el=$(this),mCSB_dragger=el.find(".mCSB_dragger"); - if(el.parent(".mCSB_scrollTools_horizontal").length>0){ - if(!d.overflowed[1]){return;} - var dir="x", - clickDir=e.pageX>mCSB_dragger.offset().left ? -1 : 1, - to=Math.abs(mCSB_container[0].offsetLeft)-(clickDir*(wrapper.width()*0.9)); - }else{ - if(!d.overflowed[0]){return;} - var dir="y", - clickDir=e.pageY>mCSB_dragger.offset().top ? -1 : 1, - to=Math.abs(mCSB_container[0].offsetTop)-(clickDir*(wrapper.height()*0.9)); - } - _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); - } - }); - }, - /* -------------------- */ - - - /* - FOCUS EVENT - scrolls content via element focus (e.g. clicking an input, pressing TAB key etc.) - */ - _focus=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - namespace=pluginPfx+"_"+d.idx, - mCSB_container=$("#mCSB_"+d.idx+"_container"), - wrapper=mCSB_container.parent(); - mCSB_container.bind("focusin."+namespace,function(e){ - var el=$(document.activeElement), - nested=mCSB_container.find(".mCustomScrollBox").length, - dur=0; - if(!el.is(o.advanced.autoScrollOnFocus)){return;} - _stop($this); - clearTimeout($this[0]._focusTimeout); - $this[0]._focusTimer=nested ? (dur+17)*nested : 0; - $this[0]._focusTimeout=setTimeout(function(){ - var to=[_childPos(el)[0],_childPos(el)[1]], - contentPos=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft], - isVisible=[ - (contentPos[0]+to[0]>=0 && contentPos[0]+to[0]=0 && contentPos[0]+to[1]a"); - btn.bind("contextmenu."+namespace,function(e){ - e.preventDefault(); //prevent right click - }).bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace+" mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace+" mouseout."+namespace+" pointerout."+namespace+" MSPointerOut."+namespace+" click."+namespace,function(e){ - e.preventDefault(); - if(!_mouseBtnLeft(e)){return;} /* left mouse button only */ - var btnClass=$(this).attr("class"); - seq.type=o.scrollButtons.scrollType; - switch(e.type){ - case "mousedown": case "touchstart": case "pointerdown": case "MSPointerDown": - if(seq.type==="stepped"){return;} - touchActive=true; - d.tweenRunning=false; - _seq("on",btnClass); - break; - case "mouseup": case "touchend": case "pointerup": case "MSPointerUp": - case "mouseout": case "pointerout": case "MSPointerOut": - if(seq.type==="stepped"){return;} - touchActive=false; - if(seq.dir){_seq("off",btnClass);} - break; - case "click": - if(seq.type!=="stepped" || d.tweenRunning){return;} - _seq("on",btnClass); - break; - } - function _seq(a,c){ - seq.scrollAmount=o.scrollButtons.scrollAmount; - _sequentialScroll($this,a,c); - } - }); - }, - /* -------------------- */ - - - /* - KEYBOARD EVENTS - scrolls content via keyboard - Keys: up arrow, down arrow, left arrow, right arrow, PgUp, PgDn, Home, End - */ - _keyboard=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential, - namespace=pluginPfx+"_"+d.idx, - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_container=$("#mCSB_"+d.idx+"_container"), - wrapper=mCSB_container.parent(), - editables="input,textarea,select,datalist,keygen,[contenteditable='true']", - iframe=mCSB_container.find("iframe"), - events=["blur."+namespace+" keydown."+namespace+" keyup."+namespace]; - if(iframe.length){ - iframe.each(function(){ - $(this).bind("load",function(){ - /* bind events on accessible iframes */ - if(_canAccessIFrame(this)){ - $(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){ - _onKeyboard(e); - }); - } - }); - }); - } - mCustomScrollBox.attr("tabindex","0").bind(events[0],function(e){ - _onKeyboard(e); - }); - function _onKeyboard(e){ - switch(e.type){ - case "blur": - if(d.tweenRunning && seq.dir){_seq("off",null);} - break; - case "keydown": case "keyup": - var code=e.keyCode ? e.keyCode : e.which,action="on"; - if((o.axis!=="x" && (code===38 || code===40)) || (o.axis!=="y" && (code===37 || code===39))){ - /* up (38), down (40), left (37), right (39) arrows */ - if(((code===38 || code===40) && !d.overflowed[0]) || ((code===37 || code===39) && !d.overflowed[1])){return;} - if(e.type==="keyup"){action="off";} - if(!$(document.activeElement).is(editables)){ - e.preventDefault(); - e.stopImmediatePropagation(); - _seq(action,code); - } - }else if(code===33 || code===34){ - /* PgUp (33), PgDn (34) */ - if(d.overflowed[0] || d.overflowed[1]){ - e.preventDefault(); - e.stopImmediatePropagation(); - } - if(e.type==="keyup"){ - _stop($this); - var keyboardDir=code===34 ? -1 : 1; - if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){ - var dir="x",to=Math.abs(mCSB_container[0].offsetLeft)-(keyboardDir*(wrapper.width()*0.9)); - }else{ - var dir="y",to=Math.abs(mCSB_container[0].offsetTop)-(keyboardDir*(wrapper.height()*0.9)); - } - _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); - } - }else if(code===35 || code===36){ - /* End (35), Home (36) */ - if(!$(document.activeElement).is(editables)){ - if(d.overflowed[0] || d.overflowed[1]){ - e.preventDefault(); - e.stopImmediatePropagation(); - } - if(e.type==="keyup"){ - if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){ - var dir="x",to=code===35 ? Math.abs(wrapper.width()-mCSB_container.outerWidth(false)) : 0; - }else{ - var dir="y",to=code===35 ? Math.abs(wrapper.height()-mCSB_container.outerHeight(false)) : 0; - } - _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); - } - } - } - break; - } - function _seq(a,c){ - seq.type=o.keyboard.scrollType; - seq.scrollAmount=o.keyboard.scrollAmount; - if(seq.type==="stepped" && d.tweenRunning){return;} - _sequentialScroll($this,a,c); - } - } - }, - /* -------------------- */ - - - /* scrolls content sequentially (used when scrolling via buttons, keyboard arrows etc.) */ - _sequentialScroll=function(el,action,trigger,e,s){ - var d=el.data(pluginPfx),o=d.opt,seq=d.sequential, - mCSB_container=$("#mCSB_"+d.idx+"_container"), - once=seq.type==="stepped" ? true : false, - steplessSpeed=o.scrollInertia < 26 ? 26 : o.scrollInertia, /* 26/1.5=17 */ - steppedSpeed=o.scrollInertia < 1 ? 17 : o.scrollInertia; - switch(action){ - case "on": - seq.dir=[ - (trigger===classes[16] || trigger===classes[15] || trigger===39 || trigger===37 ? "x" : "y"), - (trigger===classes[13] || trigger===classes[15] || trigger===38 || trigger===37 ? -1 : 1) - ]; - _stop(el); - if(_isNumeric(trigger) && seq.type==="stepped"){return;} - _on(once); - break; - case "off": - _off(); - if(once || (d.tweenRunning && seq.dir)){ - _on(true); - } - break; - } - - /* starts sequence */ - function _on(once){ - if(o.snapAmount){seq.scrollAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : seq.dir[0]==="x" ? o.snapAmount[1] : o.snapAmount[0];} /* scrolling snapping */ - var c=seq.type!=="stepped", /* continuous scrolling */ - t=s ? s : !once ? 1000/60 : c ? steplessSpeed/1.5 : steppedSpeed, /* timer */ - m=!once ? 2.5 : c ? 7.5 : 40, /* multiplier */ - contentPos=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)], - ratio=[d.scrollRatio.y>10 ? 10 : d.scrollRatio.y,d.scrollRatio.x>10 ? 10 : d.scrollRatio.x], - amount=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*(ratio[1]*m)) : contentPos[0]+(seq.dir[1]*(ratio[0]*m)), - px=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*parseInt(seq.scrollAmount)) : contentPos[0]+(seq.dir[1]*parseInt(seq.scrollAmount)), - to=seq.scrollAmount!=="auto" ? px : amount, - easing=e ? e : !once ? "mcsLinear" : c ? "mcsLinearOut" : "mcsEaseInOut", - onComplete=!once ? false : true; - if(once && t<17){ - to=seq.dir[0]==="x" ? contentPos[1] : contentPos[0]; - } - _scrollTo(el,to.toString(),{dir:seq.dir[0],scrollEasing:easing,dur:t,onComplete:onComplete}); - if(once){ - seq.dir=false; - return; - } - clearTimeout(seq.step); - seq.step=setTimeout(function(){ - _on(); - },t); - } - /* stops sequence */ - function _off(){ - clearTimeout(seq.step); - _delete(seq,"step"); - _stop(el); - } - }, - /* -------------------- */ - - - /* returns a yx array from value */ - _arr=function(val){ - var o=$(this).data(pluginPfx).opt,vals=[]; - if(typeof val==="function"){val=val();} /* check if the value is a single anonymous function */ - /* check if value is object or array, its length and create an array with yx values */ - if(!(val instanceof Array)){ /* object value (e.g. {y:"100",x:"100"}, 100 etc.) */ - vals[0]=val.y ? val.y : val.x || o.axis==="x" ? null : val; - vals[1]=val.x ? val.x : val.y || o.axis==="y" ? null : val; - }else{ /* array value (e.g. [100,100]) */ - vals=val.length>1 ? [val[0],val[1]] : o.axis==="x" ? [null,val[0]] : [val[0],null]; - } - /* check if array values are anonymous functions */ - if(typeof vals[0]==="function"){vals[0]=vals[0]();} - if(typeof vals[1]==="function"){vals[1]=vals[1]();} - return vals; - }, - /* -------------------- */ - - - /* translates values (e.g. "top", 100, "100px", "#id") to actual scroll-to positions */ - _to=function(val,dir){ - if(val==null || typeof val=="undefined"){return;} - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - mCSB_container=$("#mCSB_"+d.idx+"_container"), - wrapper=mCSB_container.parent(), - t=typeof val; - if(!dir){dir=o.axis==="x" ? "x" : "y";} - var contentLength=dir==="x" ? mCSB_container.outerWidth(false)-wrapper.width() : mCSB_container.outerHeight(false)-wrapper.height(), - contentPos=dir==="x" ? mCSB_container[0].offsetLeft : mCSB_container[0].offsetTop, - cssProp=dir==="x" ? "left" : "top"; - switch(t){ - case "function": /* this currently is not used. Consider removing it */ - return val(); - break; - case "object": /* js/jquery object */ - var obj=val.jquery ? val : $(val); - if(!obj.length){return;} - return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0]; - break; - case "string": case "number": - if(_isNumeric(val)){ /* numeric value */ - return Math.abs(val); - }else if(val.indexOf("%")!==-1){ /* percentage value */ - return Math.abs(contentLength*parseInt(val)/100); - }else if(val.indexOf("-=")!==-1){ /* decrease value */ - return Math.abs(contentPos-parseInt(val.split("-=")[1])); - }else if(val.indexOf("+=")!==-1){ /* inrease value */ - var p=(contentPos+parseInt(val.split("+=")[1])); - return p>=0 ? 0 : Math.abs(p); - }else if(val.indexOf("px")!==-1 && _isNumeric(val.split("px")[0])){ /* pixels string value (e.g. "100px") */ - return Math.abs(val.split("px")[0]); - }else{ - if(val==="top" || val==="left"){ /* special strings */ - return 0; - }else if(val==="bottom"){ - return Math.abs(wrapper.height()-mCSB_container.outerHeight(false)); - }else if(val==="right"){ - return Math.abs(wrapper.width()-mCSB_container.outerWidth(false)); - }else if(val==="first" || val==="last"){ - var obj=mCSB_container.find(":"+val); - return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0]; - }else{ - if($(val).length){ /* jquery selector */ - return dir==="x" ? _childPos($(val))[1] : _childPos($(val))[0]; - }else{ /* other values (e.g. "100em") */ - mCSB_container.css(cssProp,val); - methods.update.call(null,$this[0]); - return; - } - } - } - break; - } - }, - /* -------------------- */ - - - /* calls the update method automatically */ - _autoUpdate=function(rem){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - mCSB_container=$("#mCSB_"+d.idx+"_container"); - if(rem){ - /* - removes autoUpdate timer - usage: _autoUpdate.call(this,"remove"); - */ - clearTimeout(mCSB_container[0].autoUpdate); - _delete(mCSB_container[0],"autoUpdate"); - return; - } - upd(); - function upd(){ - clearTimeout(mCSB_container[0].autoUpdate); - if($this.parents("html").length===0){ - /* check element in dom tree */ - $this=null; - return; - } - mCSB_container[0].autoUpdate=setTimeout(function(){ - /* update on specific selector(s) length and size change */ - if(o.advanced.updateOnSelectorChange){ - d.poll.change.n=sizesSum(); - if(d.poll.change.n!==d.poll.change.o){ - d.poll.change.o=d.poll.change.n; - doUpd(3); - return; - } - } - /* update on main element and scrollbar size changes */ - if(o.advanced.updateOnContentResize){ - d.poll.size.n=$this[0].scrollHeight+$this[0].scrollWidth+mCSB_container[0].offsetHeight+$this[0].offsetHeight+$this[0].offsetWidth; - if(d.poll.size.n!==d.poll.size.o){ - d.poll.size.o=d.poll.size.n; - doUpd(1); - return; - } - } - /* update on image load */ - if(o.advanced.updateOnImageLoad){ - if(!(o.advanced.updateOnImageLoad==="auto" && o.axis==="y")){ //by default, it doesn't run on vertical content - d.poll.img.n=mCSB_container.find("img").length; - if(d.poll.img.n!==d.poll.img.o){ - d.poll.img.o=d.poll.img.n; - mCSB_container.find("img").each(function(){ - imgLoader(this); - }); - return; - } - } - } - if(o.advanced.updateOnSelectorChange || o.advanced.updateOnContentResize || o.advanced.updateOnImageLoad){upd();} - },o.advanced.autoUpdateTimeout); - } - /* a tiny image loader */ - function imgLoader(el){ - if($(el).hasClass(classes[2])){doUpd(); return;} - var img=new Image(); - function createDelegate(contextObject,delegateMethod){ - return function(){return delegateMethod.apply(contextObject,arguments);} - } - function imgOnLoad(){ - this.onload=null; - $(el).addClass(classes[2]); - doUpd(2); - } - img.onload=createDelegate(img,imgOnLoad); - img.src=el.src; - } - /* returns the total height and width sum of all elements matching the selector */ - function sizesSum(){ - if(o.advanced.updateOnSelectorChange===true){o.advanced.updateOnSelectorChange="*";} - var total=0,sel=mCSB_container.find(o.advanced.updateOnSelectorChange); - if(o.advanced.updateOnSelectorChange && sel.length>0){sel.each(function(){total+=this.offsetHeight+this.offsetWidth;});} - return total; - } - /* calls the update method */ - function doUpd(cb){ - clearTimeout(mCSB_container[0].autoUpdate); - methods.update.call(null,$this[0],cb); - } - }, - /* -------------------- */ - - - /* snaps scrolling to a multiple of a pixels number */ - _snapAmount=function(to,amount,offset){ - return (Math.round(to/amount)*amount-offset); - }, - /* -------------------- */ - - - /* stops content and scrollbar animations */ - _stop=function(el){ - var d=el.data(pluginPfx), - sel=$("#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal"); - sel.each(function(){ - _stopTween.call(this); - }); - }, - /* -------------------- */ - - - /* - ANIMATES CONTENT - This is where the actual scrolling happens - */ - _scrollTo=function(el,to,options){ - var d=el.data(pluginPfx),o=d.opt, - defaults={ - trigger:"internal", - dir:"y", - scrollEasing:"mcsEaseOut", - drag:false, - dur:o.scrollInertia, - overwrite:"all", - callbacks:true, - onStart:true, - onUpdate:true, - onComplete:true - }, - options=$.extend(defaults,options), - dur=[options.dur,(options.drag ? 0 : options.dur)], - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_container=$("#mCSB_"+d.idx+"_container"), - wrapper=mCSB_container.parent(), - totalScrollOffsets=o.callbacks.onTotalScrollOffset ? _arr.call(el,o.callbacks.onTotalScrollOffset) : [0,0], - totalScrollBackOffsets=o.callbacks.onTotalScrollBackOffset ? _arr.call(el,o.callbacks.onTotalScrollBackOffset) : [0,0]; - d.trigger=options.trigger; - if(wrapper.scrollTop()!==0 || wrapper.scrollLeft()!==0){ /* always reset scrollTop/Left */ - $(".mCSB_"+d.idx+"_scrollbar").css("visibility","visible"); - wrapper.scrollTop(0).scrollLeft(0); - } - if(to==="_resetY" && !d.contentReset.y){ - /* callbacks: onOverflowYNone */ - if(_cb("onOverflowYNone")){o.callbacks.onOverflowYNone.call(el[0]);} - d.contentReset.y=1; - } - if(to==="_resetX" && !d.contentReset.x){ - /* callbacks: onOverflowXNone */ - if(_cb("onOverflowXNone")){o.callbacks.onOverflowXNone.call(el[0]);} - d.contentReset.x=1; - } - if(to==="_resetY" || to==="_resetX"){return;} - if((d.contentReset.y || !el[0].mcs) && d.overflowed[0]){ - /* callbacks: onOverflowY */ - if(_cb("onOverflowY")){o.callbacks.onOverflowY.call(el[0]);} - d.contentReset.x=null; - } - if((d.contentReset.x || !el[0].mcs) && d.overflowed[1]){ - /* callbacks: onOverflowX */ - if(_cb("onOverflowX")){o.callbacks.onOverflowX.call(el[0]);} - d.contentReset.x=null; - } - if(o.snapAmount){ /* scrolling snapping */ - var snapAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : options.dir==="x" ? o.snapAmount[1] : o.snapAmount[0]; - to=_snapAmount(to,snapAmount,o.snapOffset); - } - switch(options.dir){ - case "x": - var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_horizontal"), - property="left", - contentPos=mCSB_container[0].offsetLeft, - limit=[ - mCustomScrollBox.width()-mCSB_container.outerWidth(false), - mCSB_dragger.parent().width()-mCSB_dragger.width() - ], - scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.x)], - tso=totalScrollOffsets[1], - tsbo=totalScrollBackOffsets[1], - totalScrollOffset=tso>0 ? tso/d.scrollRatio.x : 0, - totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.x : 0; - break; - case "y": - var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_vertical"), - property="top", - contentPos=mCSB_container[0].offsetTop, - limit=[ - mCustomScrollBox.height()-mCSB_container.outerHeight(false), - mCSB_dragger.parent().height()-mCSB_dragger.height() - ], - scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.y)], - tso=totalScrollOffsets[0], - tsbo=totalScrollBackOffsets[0], - totalScrollOffset=tso>0 ? tso/d.scrollRatio.y : 0, - totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.y : 0; - break; - } - if(scrollTo[1]<0 || (scrollTo[0]===0 && scrollTo[1]===0)){ - scrollTo=[0,0]; - }else if(scrollTo[1]>=limit[1]){ - scrollTo=[limit[0],limit[1]]; - }else{ - scrollTo[0]=-scrollTo[0]; - } - if(!el[0].mcs){ - _mcs(); /* init mcs object (once) to make it available before callbacks */ - if(_cb("onInit")){o.callbacks.onInit.call(el[0]);} /* callbacks: onInit */ - } - clearTimeout(mCSB_container[0].onCompleteTimeout); - _tweenTo(mCSB_dragger[0],property,Math.round(scrollTo[1]),dur[1],options.scrollEasing); - if(!d.tweenRunning && ((contentPos===0 && scrollTo[0]>=0) || (contentPos===limit[0] && scrollTo[0]<=limit[0]))){return;} - _tweenTo(mCSB_container[0],property,Math.round(scrollTo[0]),dur[0],options.scrollEasing,options.overwrite,{ - onStart:function(){ - if(options.callbacks && options.onStart && !d.tweenRunning){ - /* callbacks: onScrollStart */ - if(_cb("onScrollStart")){_mcs(); o.callbacks.onScrollStart.call(el[0]);} - d.tweenRunning=true; - _onDragClasses(mCSB_dragger); - d.cbOffsets=_cbOffsets(); - } - },onUpdate:function(){ - if(options.callbacks && options.onUpdate){ - /* callbacks: whileScrolling */ - if(_cb("whileScrolling")){_mcs(); o.callbacks.whileScrolling.call(el[0]);} - } - },onComplete:function(){ - if(options.callbacks && options.onComplete){ - if(o.axis==="yx"){clearTimeout(mCSB_container[0].onCompleteTimeout);} - var t=mCSB_container[0].idleTimer || 0; - mCSB_container[0].onCompleteTimeout=setTimeout(function(){ - /* callbacks: onScroll, onTotalScroll, onTotalScrollBack */ - if(_cb("onScroll")){_mcs(); o.callbacks.onScroll.call(el[0]);} - if(_cb("onTotalScroll") && scrollTo[1]>=limit[1]-totalScrollOffset && d.cbOffsets[0]){_mcs(); o.callbacks.onTotalScroll.call(el[0]);} - if(_cb("onTotalScrollBack") && scrollTo[1]<=totalScrollBackOffset && d.cbOffsets[1]){_mcs(); o.callbacks.onTotalScrollBack.call(el[0]);} - d.tweenRunning=false; - mCSB_container[0].idleTimer=0; - _onDragClasses(mCSB_dragger,"hide"); - },t); - } - } - }); - /* checks if callback function exists */ - function _cb(cb){ - return d && o.callbacks[cb] && typeof o.callbacks[cb]==="function"; - } - /* checks whether callback offsets always trigger */ - function _cbOffsets(){ - return [o.callbacks.alwaysTriggerOffsets || contentPos>=limit[0]+tso,o.callbacks.alwaysTriggerOffsets || contentPos<=-tsbo]; - } - /* - populates object with useful values for the user - values: - content: this.mcs.content - content top position: this.mcs.top - content left position: this.mcs.left - dragger top position: this.mcs.draggerTop - dragger left position: this.mcs.draggerLeft - scrolling y percentage: this.mcs.topPct - scrolling x percentage: this.mcs.leftPct - scrolling direction: this.mcs.direction - */ - function _mcs(){ - var cp=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft], /* content position */ - dp=[mCSB_dragger[0].offsetTop,mCSB_dragger[0].offsetLeft], /* dragger position */ - cl=[mCSB_container.outerHeight(false),mCSB_container.outerWidth(false)], /* content length */ - pl=[mCustomScrollBox.height(),mCustomScrollBox.width()]; /* content parent length */ - el[0].mcs={ - content:mCSB_container, /* original content wrapper as jquery object */ - top:cp[0],left:cp[1],draggerTop:dp[0],draggerLeft:dp[1], - topPct:Math.round((100*Math.abs(cp[0]))/(Math.abs(cl[0])-pl[0])),leftPct:Math.round((100*Math.abs(cp[1]))/(Math.abs(cl[1])-pl[1])), - direction:options.dir - }; - /* - this refers to the original element containing the scrollbar(s) - usage: this.mcs.top, this.mcs.leftPct etc. - */ - } - }, - /* -------------------- */ - - - /* - CUSTOM JAVASCRIPT ANIMATION TWEEN - Lighter and faster than jquery animate() and css transitions - Animates top/left properties and includes easings - */ - _tweenTo=function(el,prop,to,duration,easing,overwrite,callbacks){ - if(!el._mTween){el._mTween={top:{},left:{}};} - var callbacks=callbacks || {}, - onStart=callbacks.onStart || function(){},onUpdate=callbacks.onUpdate || function(){},onComplete=callbacks.onComplete || function(){}, - startTime=_getTime(),_delay,progress=0,from=el.offsetTop,elStyle=el.style,_request,tobj=el._mTween[prop]; - if(prop==="left"){from=el.offsetLeft;} - var diff=to-from; - tobj.stop=0; - if(overwrite!=="none"){_cancelTween();} - _startTween(); - function _step(){ - if(tobj.stop){return;} - if(!progress){onStart.call();} - progress=_getTime()-startTime; - _tween(); - if(progress>=tobj.time){ - tobj.time=(progress>tobj.time) ? progress+_delay-(progress-tobj.time) : progress+_delay-1; - if(tobj.time0){ - tobj.currVal=_ease(tobj.time,from,diff,duration,easing); - elStyle[prop]=Math.round(tobj.currVal)+"px"; - }else{ - elStyle[prop]=to+"px"; - } - onUpdate.call(); - } - function _startTween(){ - _delay=1000/60; - tobj.time=progress+_delay; - _request=(!window.requestAnimationFrame) ? function(f){_tween(); return setTimeout(f,0.01);} : window.requestAnimationFrame; - tobj.id=_request(_step); - } - function _cancelTween(){ - if(tobj.id==null){return;} - if(!window.requestAnimationFrame){clearTimeout(tobj.id); - }else{window.cancelAnimationFrame(tobj.id);} - tobj.id=null; - } - function _ease(t,b,c,d,type){ - switch(type){ - case "linear": case "mcsLinear": - return c*t/d + b; - break; - case "mcsLinearOut": - t/=d; t--; return c * Math.sqrt(1 - t*t) + b; - break; - case "easeInOutSmooth": - t/=d/2; - if(t<1) return c/2*t*t + b; - t--; - return -c/2 * (t*(t-2) - 1) + b; - break; - case "easeInOutStrong": - t/=d/2; - if(t<1) return c/2 * Math.pow( 2, 10 * (t - 1) ) + b; - t--; - return c/2 * ( -Math.pow( 2, -10 * t) + 2 ) + b; - break; - case "easeInOut": case "mcsEaseInOut": - t/=d/2; - if(t<1) return c/2*t*t*t + b; - t-=2; - return c/2*(t*t*t + 2) + b; - break; - case "easeOutSmooth": - t/=d; t--; - return -c * (t*t*t*t - 1) + b; - break; - case "easeOutStrong": - return c * ( -Math.pow( 2, -10 * t/d ) + 1 ) + b; - break; - case "easeOut": case "mcsEaseOut": default: - var ts=(t/=d)*t,tc=ts*t; - return b+c*(0.499999999999997*tc*ts + -2.5*ts*ts + 5.5*tc + -6.5*ts + 4*t); - } - } - }, - /* -------------------- */ - - - /* returns current time */ - _getTime=function(){ - if(window.performance && window.performance.now){ - return window.performance.now(); - }else{ - if(window.performance && window.performance.webkitNow){ - return window.performance.webkitNow(); - }else{ - if(Date.now){return Date.now();}else{return new Date().getTime();} - } - } - }, - /* -------------------- */ - - - /* stops a tween */ - _stopTween=function(){ - var el=this; - if(!el._mTween){el._mTween={top:{},left:{}};} - var props=["top","left"]; - for(var i=0; i
    ","
    "],s="yx"===i.axis?"mCSB_vertical_horizontal":"x"===i.axis?"mCSB_horizontal":"mCSB_vertical",c="yx"===i.axis?l[0]+l[1]:"x"===i.axis?l[1]:l[0],u="yx"===i.axis?"
    ":"",f=i.autoHideScrollbar?" "+d[6]:"",h="x"!==i.axis&&"rtl"===n.langDir?" "+d[7]:"";i.setWidth&&t.css("width",i.setWidth),i.setHeight&&t.css("height",i.setHeight),i.setLeft="y"!==i.axis&&"rtl"===n.langDir?"989999px":i.setLeft,t.addClass(o+" _"+a+"_"+n.idx+f+h).wrapInner("
    ");var m=e("#mCSB_"+n.idx),p=e("#mCSB_"+n.idx+"_container");"y"===i.axis||i.advanced.autoExpandHorizontalScroll||p.css("width",x(p)),"outside"===i.scrollbarPosition?("static"===t.css("position")&&t.css("position","relative"),t.css("overflow","visible"),m.addClass("mCSB_outside").after(c)):(m.addClass("mCSB_inside").append(c),p.wrap(u)),w.call(this);var g=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")];g[0].css("min-height",g[0].height()),g[1].css("min-width",g[1].width())},x=function(t){var o=[t[0].scrollWidth,Math.max.apply(Math,t.children().map(function(){return e(this).outerWidth(!0)}).get())],a=t.parent().width();return o[0]>a?o[0]:o[1]>a?o[1]:"100%"},_=function(){var t=e(this),o=t.data(a),n=o.opt,i=e("#mCSB_"+o.idx+"_container");if(n.advanced.autoExpandHorizontalScroll&&"y"!==n.axis){i.css({width:"auto","min-width":0,"overflow-x":"scroll"});var r=Math.ceil(i[0].scrollWidth);3===n.advanced.autoExpandHorizontalScroll||2!==n.advanced.autoExpandHorizontalScroll&&r>i.parent().width()?i.css({width:r,"min-width":"100%","overflow-x":"inherit"}):i.css({"overflow-x":"inherit",position:"absolute"}).wrap("
    ").css({width:Math.ceil(i[0].getBoundingClientRect().right+.4)-Math.floor(i[0].getBoundingClientRect().left),"min-width":"100%",position:"relative"}).unwrap()}},w=function(){var t=e(this),o=t.data(a),n=o.opt,i=e(".mCSB_"+o.idx+"_scrollbar:first"),r=oe(n.scrollButtons.tabindex)?"tabindex='"+n.scrollButtons.tabindex+"'":"",l=["","","",""],s=["x"===n.axis?l[2]:l[0],"x"===n.axis?l[3]:l[1],l[2],l[3]];n.scrollButtons.enable&&i.prepend(s[0]).append(s[1]).next(".mCSB_scrollTools").prepend(s[2]).append(s[3])},S=function(){var t=e(this),o=t.data(a),n=e("#mCSB_"+o.idx),i=e("#mCSB_"+o.idx+"_container"),r=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")],l=[n.height()/i.outerHeight(!1),n.width()/i.outerWidth(!1)],c=[parseInt(r[0].css("min-height")),Math.round(l[0]*r[0].parent().height()),parseInt(r[1].css("min-width")),Math.round(l[1]*r[1].parent().width())],d=s&&c[1]r&&(r=s),c>l&&(l=c),[r>n.height(),l>n.width()]},B=function(){var t=e(this),o=t.data(a),n=o.opt,i=e("#mCSB_"+o.idx),r=e("#mCSB_"+o.idx+"_container"),l=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")];if(Q(t),("x"!==n.axis&&!o.overflowed[0]||"y"===n.axis&&o.overflowed[0])&&(l[0].add(r).css("top",0),G(t,"_resetY")),"y"!==n.axis&&!o.overflowed[1]||"x"===n.axis&&o.overflowed[1]){var s=dx=0;"rtl"===o.langDir&&(s=i.width()-r.outerWidth(!1),dx=Math.abs(s/o.scrollRatio.x)),r.css("left",s),l[1].css("left",dx),G(t,"_resetX")}},T=function(){function t(){r=setTimeout(function(){e.event.special.mousewheel?(clearTimeout(r),W.call(o[0])):t()},100)}var o=e(this),n=o.data(a),i=n.opt;if(!n.bindEvents){if(I.call(this),i.contentTouchScroll&&D.call(this),E.call(this),i.mouseWheel.enable){var r;t()}P.call(this),U.call(this),i.advanced.autoScrollOnFocus&&H.call(this),i.scrollButtons.enable&&F.call(this),i.keyboard.enable&&q.call(this),n.bindEvents=!0}},k=function(){var t=e(this),o=t.data(a),n=o.opt,i=a+"_"+o.idx,r=".mCSB_"+o.idx+"_scrollbar",l=e("#mCSB_"+o.idx+",#mCSB_"+o.idx+"_container,#mCSB_"+o.idx+"_container_wrapper,"+r+" ."+d[12]+",#mCSB_"+o.idx+"_dragger_vertical,#mCSB_"+o.idx+"_dragger_horizontal,"+r+">a"),s=e("#mCSB_"+o.idx+"_container");n.advanced.releaseDraggableSelectors&&l.add(e(n.advanced.releaseDraggableSelectors)),n.advanced.extraDraggableSelectors&&l.add(e(n.advanced.extraDraggableSelectors)),o.bindEvents&&(e(document).add(e(!A()||top.document)).unbind("."+i),l.each(function(){e(this).unbind("."+i)}),clearTimeout(t[0]._focusTimeout),$(t[0],"_focusTimeout"),clearTimeout(o.sequential.step),$(o.sequential,"step"),clearTimeout(s[0].onCompleteTimeout),$(s[0],"onCompleteTimeout"),o.bindEvents=!1)},M=function(t){var o=e(this),n=o.data(a),i=n.opt,r=e("#mCSB_"+n.idx+"_container_wrapper"),l=r.length?r:e("#mCSB_"+n.idx+"_container"),s=[e("#mCSB_"+n.idx+"_scrollbar_vertical"),e("#mCSB_"+n.idx+"_scrollbar_horizontal")],c=[s[0].find(".mCSB_dragger"),s[1].find(".mCSB_dragger")];"x"!==i.axis&&(n.overflowed[0]&&!t?(s[0].add(c[0]).add(s[0].children("a")).css("display","block"),l.removeClass(d[8]+" "+d[10])):(i.alwaysShowScrollbar?(2!==i.alwaysShowScrollbar&&c[0].css("display","none"),l.removeClass(d[10])):(s[0].css("display","none"),l.addClass(d[10])),l.addClass(d[8]))),"y"!==i.axis&&(n.overflowed[1]&&!t?(s[1].add(c[1]).add(s[1].children("a")).css("display","block"),l.removeClass(d[9]+" "+d[11])):(i.alwaysShowScrollbar?(2!==i.alwaysShowScrollbar&&c[1].css("display","none"),l.removeClass(d[11])):(s[1].css("display","none"),l.addClass(d[11])),l.addClass(d[9]))),n.overflowed[0]||n.overflowed[1]?o.removeClass(d[5]):o.addClass(d[5])},O=function(t){var o=t.type,a=t.target.ownerDocument!==document&&null!==frameElement?[e(frameElement).offset().top,e(frameElement).offset().left]:null,n=A()&&t.target.ownerDocument!==top.document&&null!==frameElement?[e(t.view.frameElement).offset().top,e(t.view.frameElement).offset().left]:[0,0];switch(o){case"pointerdown":case"MSPointerDown":case"pointermove":case"MSPointerMove":case"pointerup":case"MSPointerUp":return a?[t.originalEvent.pageY-a[0]+n[0],t.originalEvent.pageX-a[1]+n[1],!1]:[t.originalEvent.pageY,t.originalEvent.pageX,!1];case"touchstart":case"touchmove":case"touchend":var i=t.originalEvent.touches[0]||t.originalEvent.changedTouches[0],r=t.originalEvent.touches.length||t.originalEvent.changedTouches.length;return t.target.ownerDocument!==document?[i.screenY,i.screenX,r>1]:[i.pageY,i.pageX,r>1];default:return a?[t.pageY-a[0]+n[0],t.pageX-a[1]+n[1],!1]:[t.pageY,t.pageX,!1]}},I=function(){function t(e,t,a,n){if(h[0].idleTimer=d.scrollInertia<233?250:0,o.attr("id")===f[1])var i="x",s=(o[0].offsetLeft-t+n)*l.scrollRatio.x;else var i="y",s=(o[0].offsetTop-e+a)*l.scrollRatio.y;G(r,s.toString(),{dir:i,drag:!0})}var o,n,i,r=e(this),l=r.data(a),d=l.opt,u=a+"_"+l.idx,f=["mCSB_"+l.idx+"_dragger_vertical","mCSB_"+l.idx+"_dragger_horizontal"],h=e("#mCSB_"+l.idx+"_container"),m=e("#"+f[0]+",#"+f[1]),p=d.advanced.releaseDraggableSelectors?m.add(e(d.advanced.releaseDraggableSelectors)):m,g=d.advanced.extraDraggableSelectors?e(!A()||top.document).add(e(d.advanced.extraDraggableSelectors)):e(!A()||top.document);m.bind("contextmenu."+u,function(e){e.preventDefault()}).bind("mousedown."+u+" touchstart."+u+" pointerdown."+u+" MSPointerDown."+u,function(t){if(t.stopImmediatePropagation(),t.preventDefault(),ee(t)){c=!0,s&&(document.onselectstart=function(){return!1}),L.call(h,!1),Q(r),o=e(this);var a=o.offset(),l=O(t)[0]-a.top,u=O(t)[1]-a.left,f=o.height()+a.top,m=o.width()+a.left;f>l&&l>0&&m>u&&u>0&&(n=l,i=u),C(o,"active",d.autoExpandScrollbar)}}).bind("touchmove."+u,function(e){e.stopImmediatePropagation(),e.preventDefault();var a=o.offset(),r=O(e)[0]-a.top,l=O(e)[1]-a.left;t(n,i,r,l)}),e(document).add(g).bind("mousemove."+u+" pointermove."+u+" MSPointerMove."+u,function(e){if(o){var a=o.offset(),r=O(e)[0]-a.top,l=O(e)[1]-a.left;if(n===r&&i===l)return;t(n,i,r,l)}}).add(p).bind("mouseup."+u+" touchend."+u+" pointerup."+u+" MSPointerUp."+u,function(){o&&(C(o,"active",d.autoExpandScrollbar),o=null),c=!1,s&&(document.onselectstart=null),L.call(h,!0)})},D=function(){function o(e){if(!te(e)||c||O(e)[2])return void(t=0);t=1,b=0,C=0,d=1,y.removeClass("mCS_touch_action");var o=I.offset();u=O(e)[0]-o.top,f=O(e)[1]-o.left,z=[O(e)[0],O(e)[1]]}function n(e){if(te(e)&&!c&&!O(e)[2]&&(T.documentTouchScroll||e.preventDefault(),e.stopImmediatePropagation(),(!C||b)&&d)){g=K();var t=M.offset(),o=O(e)[0]-t.top,a=O(e)[1]-t.left,n="mcsLinearOut";if(E.push(o),W.push(a),z[2]=Math.abs(O(e)[0]-z[0]),z[3]=Math.abs(O(e)[1]-z[1]),B.overflowed[0])var i=D[0].parent().height()-D[0].height(),r=u-o>0&&o-u>-(i*B.scrollRatio.y)&&(2*z[3]0&&a-f>-(l*B.scrollRatio.x)&&(2*z[2]30)){_=1e3/(v-p);var n="mcsEaseOut",i=2.5>_,r=i?[E[E.length-2],W[W.length-2]]:[0,0];x=i?[o-r[0],a-r[1]]:[o-h,a-m];var u=[Math.abs(x[0]),Math.abs(x[1])];_=i?[Math.abs(x[0]/4),Math.abs(x[1]/4)]:[_,_];var f=[Math.abs(I[0].offsetTop)-x[0]*l(u[0]/_[0],_[0]),Math.abs(I[0].offsetLeft)-x[1]*l(u[1]/_[1],_[1])];w="yx"===T.axis?[f[0],f[1]]:"x"===T.axis?[null,f[1]]:[f[0],null],S=[4*u[0]+T.scrollInertia,4*u[1]+T.scrollInertia];var y=parseInt(T.contentTouchScroll)||0;w[0]=u[0]>y?w[0]:0,w[1]=u[1]>y?w[1]:0,B.overflowed[0]&&s(w[0],S[0],n,"y",L,!1),B.overflowed[1]&&s(w[1],S[1],n,"x",L,!1)}}}function l(e,t){var o=[1.5*t,2*t,t/1.5,t/2];return e>90?t>4?o[0]:o[3]:e>60?t>3?o[3]:o[2]:e>30?t>8?o[1]:t>6?o[0]:t>4?t:o[2]:t>8?t:o[3]}function s(e,t,o,a,n,i){e&&G(y,e.toString(),{dur:t,scrollEasing:o,dir:a,overwrite:n,drag:i})}var d,u,f,h,m,p,g,v,x,_,w,S,b,C,y=e(this),B=y.data(a),T=B.opt,k=a+"_"+B.idx,M=e("#mCSB_"+B.idx),I=e("#mCSB_"+B.idx+"_container"),D=[e("#mCSB_"+B.idx+"_dragger_vertical"),e("#mCSB_"+B.idx+"_dragger_horizontal")],E=[],W=[],R=0,L="yx"===T.axis?"none":"all",z=[],P=I.find("iframe"),H=["touchstart."+k+" pointerdown."+k+" MSPointerDown."+k,"touchmove."+k+" pointermove."+k+" MSPointerMove."+k,"touchend."+k+" pointerup."+k+" MSPointerUp."+k],U=void 0!==document.body.style.touchAction&&""!==document.body.style.touchAction;I.bind(H[0],function(e){o(e)}).bind(H[1],function(e){n(e)}),M.bind(H[0],function(e){i(e)}).bind(H[2],function(e){r(e)}),P.length&&P.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind(H[0],function(e){o(e),i(e)}).bind(H[1],function(e){n(e)}).bind(H[2],function(e){r(e)})})})},E=function(){function o(){return window.getSelection?window.getSelection().toString():document.selection&&"Control"!=document.selection.type?document.selection.createRange().text:0}function n(e,t,o){d.type=o&&i?"stepped":"stepless",d.scrollAmount=10,j(r,e,t,"mcsLinearOut",o?60:null)}var i,r=e(this),l=r.data(a),s=l.opt,d=l.sequential,u=a+"_"+l.idx,f=e("#mCSB_"+l.idx+"_container"),h=f.parent();f.bind("mousedown."+u,function(){t||i||(i=1,c=!0)}).add(document).bind("mousemove."+u,function(e){if(!t&&i&&o()){var a=f.offset(),r=O(e)[0]-a.top+f[0].offsetTop,c=O(e)[1]-a.left+f[0].offsetLeft;r>0&&r0&&cr?n("on",38):r>h.height()&&n("on",40)),"y"!==s.axis&&l.overflowed[1]&&(0>c?n("on",37):c>h.width()&&n("on",39)))}}).bind("mouseup."+u+" dragend."+u,function(){t||(i&&(i=0,n("off",null)),c=!1)})},W=function(){function t(t,a){if(Q(o),!z(o,t.target)){var r="auto"!==i.mouseWheel.deltaFactor?parseInt(i.mouseWheel.deltaFactor):s&&t.deltaFactor<100?100:t.deltaFactor||100,d=i.scrollInertia;if("x"===i.axis||"x"===i.mouseWheel.axis)var u="x",f=[Math.round(r*n.scrollRatio.x),parseInt(i.mouseWheel.scrollAmount)],h="auto"!==i.mouseWheel.scrollAmount?f[1]:f[0]>=l.width()?.9*l.width():f[0],m=Math.abs(e("#mCSB_"+n.idx+"_container")[0].offsetLeft),p=c[1][0].offsetLeft,g=c[1].parent().width()-c[1].width(),v="y"===i.mouseWheel.axis?t.deltaY||a:t.deltaX;else var u="y",f=[Math.round(r*n.scrollRatio.y),parseInt(i.mouseWheel.scrollAmount)],h="auto"!==i.mouseWheel.scrollAmount?f[1]:f[0]>=l.height()?.9*l.height():f[0],m=Math.abs(e("#mCSB_"+n.idx+"_container")[0].offsetTop),p=c[0][0].offsetTop,g=c[0].parent().height()-c[0].height(),v=t.deltaY||a;"y"===u&&!n.overflowed[0]||"x"===u&&!n.overflowed[1]||((i.mouseWheel.invert||t.webkitDirectionInvertedFromDevice)&&(v=-v),i.mouseWheel.normalizeDelta&&(v=0>v?-1:1),(v>0&&0!==p||0>v&&p!==g||i.mouseWheel.preventDefault)&&(t.stopImmediatePropagation(),t.preventDefault()),t.deltaFactor<5&&!i.mouseWheel.normalizeDelta&&(h=t.deltaFactor,d=17),G(o,(m-v*h).toString(),{dir:u,dur:d}))}}if(e(this).data(a)){var o=e(this),n=o.data(a),i=n.opt,r=a+"_"+n.idx,l=e("#mCSB_"+n.idx),c=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")],d=e("#mCSB_"+n.idx+"_container").find("iframe");d.length&&d.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind("mousewheel."+r,function(e,o){t(e,o)})})}),l.bind("mousewheel."+r,function(e,o){t(e,o)})}},R=new Object,A=function(t){var o=!1,a=!1,n=null;if(void 0===t?a="#empty":void 0!==e(t).attr("id")&&(a=e(t).attr("id")),a!==!1&&void 0!==R[a])return R[a];if(t){try{var i=t.contentDocument||t.contentWindow.document;n=i.body.innerHTML}catch(r){}o=null!==n}else{try{var i=top.document;n=i.body.innerHTML}catch(r){}o=null!==n}return a!==!1&&(R[a]=o),o},L=function(e){var t=this.find("iframe");if(t.length){var o=e?"auto":"none";t.css("pointer-events",o)}},z=function(t,o){var n=o.nodeName.toLowerCase(),i=t.data(a).opt.mouseWheel.disableOver,r=["select","textarea"];return e.inArray(n,i)>-1&&!(e.inArray(n,r)>-1&&!e(o).is(":focus"))},P=function(){var t,o=e(this),n=o.data(a),i=a+"_"+n.idx,r=e("#mCSB_"+n.idx+"_container"),l=r.parent(),s=e(".mCSB_"+n.idx+"_scrollbar ."+d[12]);s.bind("mousedown."+i+" touchstart."+i+" pointerdown."+i+" MSPointerDown."+i,function(o){c=!0,e(o.target).hasClass("mCSB_dragger")||(t=1)}).bind("touchend."+i+" pointerup."+i+" MSPointerUp."+i,function(){c=!1}).bind("click."+i,function(a){if(t&&(t=0,e(a.target).hasClass(d[12])||e(a.target).hasClass("mCSB_draggerRail"))){Q(o);var i=e(this),s=i.find(".mCSB_dragger");if(i.parent(".mCSB_scrollTools_horizontal").length>0){if(!n.overflowed[1])return;var c="x",u=a.pageX>s.offset().left?-1:1,f=Math.abs(r[0].offsetLeft)-u*(.9*l.width())}else{if(!n.overflowed[0])return;var c="y",u=a.pageY>s.offset().top?-1:1,f=Math.abs(r[0].offsetTop)-u*(.9*l.height())}G(o,f.toString(),{dir:c,scrollEasing:"mcsEaseInOut"})}})},H=function(){var t=e(this),o=t.data(a),n=o.opt,i=a+"_"+o.idx,r=e("#mCSB_"+o.idx+"_container"),l=r.parent();r.bind("focusin."+i,function(){var o=e(document.activeElement),a=r.find(".mCustomScrollBox").length,i=0;o.is(n.advanced.autoScrollOnFocus)&&(Q(t),clearTimeout(t[0]._focusTimeout),t[0]._focusTimer=a?(i+17)*a:0,t[0]._focusTimeout=setTimeout(function(){var e=[ae(o)[0],ae(o)[1]],a=[r[0].offsetTop,r[0].offsetLeft],s=[a[0]+e[0]>=0&&a[0]+e[0]=0&&a[0]+e[1]a");s.bind("contextmenu."+r,function(e){e.preventDefault()}).bind("mousedown."+r+" touchstart."+r+" pointerdown."+r+" MSPointerDown."+r+" mouseup."+r+" touchend."+r+" pointerup."+r+" MSPointerUp."+r+" mouseout."+r+" pointerout."+r+" MSPointerOut."+r+" click."+r,function(a){function r(e,o){i.scrollAmount=n.scrollButtons.scrollAmount,j(t,e,o)}if(a.preventDefault(),ee(a)){var l=e(this).attr("class");switch(i.type=n.scrollButtons.scrollType,a.type){case"mousedown":case"touchstart":case"pointerdown":case"MSPointerDown":if("stepped"===i.type)return;c=!0,o.tweenRunning=!1,r("on",l);break;case"mouseup":case"touchend":case"pointerup":case"MSPointerUp":case"mouseout":case"pointerout":case"MSPointerOut":if("stepped"===i.type)return;c=!1,i.dir&&r("off",l);break;case"click":if("stepped"!==i.type||o.tweenRunning)return;r("on",l)}}})},q=function(){function t(t){function a(e,t){r.type=i.keyboard.scrollType,r.scrollAmount=i.keyboard.scrollAmount,"stepped"===r.type&&n.tweenRunning||j(o,e,t)}switch(t.type){case"blur":n.tweenRunning&&r.dir&&a("off",null);break;case"keydown":case"keyup":var l=t.keyCode?t.keyCode:t.which,s="on";if("x"!==i.axis&&(38===l||40===l)||"y"!==i.axis&&(37===l||39===l)){if((38===l||40===l)&&!n.overflowed[0]||(37===l||39===l)&&!n.overflowed[1])return;"keyup"===t.type&&(s="off"),e(document.activeElement).is(u)||(t.preventDefault(),t.stopImmediatePropagation(),a(s,l))}else if(33===l||34===l){if((n.overflowed[0]||n.overflowed[1])&&(t.preventDefault(),t.stopImmediatePropagation()),"keyup"===t.type){Q(o);var f=34===l?-1:1;if("x"===i.axis||"yx"===i.axis&&n.overflowed[1]&&!n.overflowed[0])var h="x",m=Math.abs(c[0].offsetLeft)-f*(.9*d.width());else var h="y",m=Math.abs(c[0].offsetTop)-f*(.9*d.height());G(o,m.toString(),{dir:h,scrollEasing:"mcsEaseInOut"})}}else if((35===l||36===l)&&!e(document.activeElement).is(u)&&((n.overflowed[0]||n.overflowed[1])&&(t.preventDefault(),t.stopImmediatePropagation()),"keyup"===t.type)){if("x"===i.axis||"yx"===i.axis&&n.overflowed[1]&&!n.overflowed[0])var h="x",m=35===l?Math.abs(d.width()-c.outerWidth(!1)):0;else var h="y",m=35===l?Math.abs(d.height()-c.outerHeight(!1)):0;G(o,m.toString(),{dir:h,scrollEasing:"mcsEaseInOut"})}}}var o=e(this),n=o.data(a),i=n.opt,r=n.sequential,l=a+"_"+n.idx,s=e("#mCSB_"+n.idx),c=e("#mCSB_"+n.idx+"_container"),d=c.parent(),u="input,textarea,select,datalist,keygen,[contenteditable='true']",f=c.find("iframe"),h=["blur."+l+" keydown."+l+" keyup."+l];f.length&&f.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind(h[0],function(e){t(e)})})}),s.attr("tabindex","0").bind(h[0],function(e){t(e)})},j=function(t,o,n,i,r){function l(e){u.snapAmount&&(f.scrollAmount=u.snapAmount instanceof Array?"x"===f.dir[0]?u.snapAmount[1]:u.snapAmount[0]:u.snapAmount);var o="stepped"!==f.type,a=r?r:e?o?p/1.5:g:1e3/60,n=e?o?7.5:40:2.5,s=[Math.abs(h[0].offsetTop),Math.abs(h[0].offsetLeft)],d=[c.scrollRatio.y>10?10:c.scrollRatio.y,c.scrollRatio.x>10?10:c.scrollRatio.x],m="x"===f.dir[0]?s[1]+f.dir[1]*(d[1]*n):s[0]+f.dir[1]*(d[0]*n),v="x"===f.dir[0]?s[1]+f.dir[1]*parseInt(f.scrollAmount):s[0]+f.dir[1]*parseInt(f.scrollAmount),x="auto"!==f.scrollAmount?v:m,_=i?i:e?o?"mcsLinearOut":"mcsEaseInOut":"mcsLinear",w=!!e;return e&&17>a&&(x="x"===f.dir[0]?s[1]:s[0]),G(t,x.toString(),{dir:f.dir[0],scrollEasing:_,dur:a,onComplete:w}),e?void(f.dir=!1):(clearTimeout(f.step),void(f.step=setTimeout(function(){l()},a)))}function s(){clearTimeout(f.step),$(f,"step"),Q(t)}var c=t.data(a),u=c.opt,f=c.sequential,h=e("#mCSB_"+c.idx+"_container"),m="stepped"===f.type,p=u.scrollInertia<26?26:u.scrollInertia,g=u.scrollInertia<1?17:u.scrollInertia;switch(o){case"on":if(f.dir=[n===d[16]||n===d[15]||39===n||37===n?"x":"y",n===d[13]||n===d[15]||38===n||37===n?-1:1],Q(t),oe(n)&&"stepped"===f.type)return;l(m);break;case"off":s(),(m||c.tweenRunning&&f.dir)&&l(!0)}},Y=function(t){var o=e(this).data(a).opt,n=[];return"function"==typeof t&&(t=t()),t instanceof Array?n=t.length>1?[t[0],t[1]]:"x"===o.axis?[null,t[0]]:[t[0],null]:(n[0]=t.y?t.y:t.x||"x"===o.axis?null:t,n[1]=t.x?t.x:t.y||"y"===o.axis?null:t),"function"==typeof n[0]&&(n[0]=n[0]()),"function"==typeof n[1]&&(n[1]=n[1]()),n},X=function(t,o){if(null!=t&&"undefined"!=typeof t){var n=e(this),i=n.data(a),r=i.opt,l=e("#mCSB_"+i.idx+"_container"),s=l.parent(),c=typeof t;o||(o="x"===r.axis?"x":"y");var d="x"===o?l.outerWidth(!1)-s.width():l.outerHeight(!1)-s.height(),f="x"===o?l[0].offsetLeft:l[0].offsetTop,h="x"===o?"left":"top";switch(c){case"function":return t();case"object":var m=t.jquery?t:e(t);if(!m.length)return;return"x"===o?ae(m)[1]:ae(m)[0];case"string":case"number":if(oe(t))return Math.abs(t);if(-1!==t.indexOf("%"))return Math.abs(d*parseInt(t)/100);if(-1!==t.indexOf("-="))return Math.abs(f-parseInt(t.split("-=")[1]));if(-1!==t.indexOf("+=")){var p=f+parseInt(t.split("+=")[1]);return p>=0?0:Math.abs(p)}if(-1!==t.indexOf("px")&&oe(t.split("px")[0]))return Math.abs(t.split("px")[0]);if("top"===t||"left"===t)return 0;if("bottom"===t)return Math.abs(s.height()-l.outerHeight(!1));if("right"===t)return Math.abs(s.width()-l.outerWidth(!1));if("first"===t||"last"===t){var m=l.find(":"+t);return"x"===o?ae(m)[1]:ae(m)[0]}return e(t).length?"x"===o?ae(e(t))[1]:ae(e(t))[0]:(l.css(h,t),void u.update.call(null,n[0]))}}},N=function(t){function o(){return clearTimeout(f[0].autoUpdate),0===l.parents("html").length?void(l=null):void(f[0].autoUpdate=setTimeout(function(){return c.advanced.updateOnSelectorChange&&(s.poll.change.n=i(),s.poll.change.n!==s.poll.change.o)?(s.poll.change.o=s.poll.change.n,void r(3)):c.advanced.updateOnContentResize&&(s.poll.size.n=l[0].scrollHeight+l[0].scrollWidth+f[0].offsetHeight+l[0].offsetHeight+l[0].offsetWidth,s.poll.size.n!==s.poll.size.o)?(s.poll.size.o=s.poll.size.n,void r(1)):!c.advanced.updateOnImageLoad||"auto"===c.advanced.updateOnImageLoad&&"y"===c.axis||(s.poll.img.n=f.find("img").length,s.poll.img.n===s.poll.img.o)?void((c.advanced.updateOnSelectorChange||c.advanced.updateOnContentResize||c.advanced.updateOnImageLoad)&&o()):(s.poll.img.o=s.poll.img.n,void f.find("img").each(function(){n(this)}))},c.advanced.autoUpdateTimeout))}function n(t){function o(e,t){return function(){ -return t.apply(e,arguments)}}function a(){this.onload=null,e(t).addClass(d[2]),r(2)}if(e(t).hasClass(d[2]))return void r();var n=new Image;n.onload=o(n,a),n.src=t.src}function i(){c.advanced.updateOnSelectorChange===!0&&(c.advanced.updateOnSelectorChange="*");var e=0,t=f.find(c.advanced.updateOnSelectorChange);return c.advanced.updateOnSelectorChange&&t.length>0&&t.each(function(){e+=this.offsetHeight+this.offsetWidth}),e}function r(e){clearTimeout(f[0].autoUpdate),u.update.call(null,l[0],e)}var l=e(this),s=l.data(a),c=s.opt,f=e("#mCSB_"+s.idx+"_container");return t?(clearTimeout(f[0].autoUpdate),void $(f[0],"autoUpdate")):void o()},V=function(e,t,o){return Math.round(e/t)*t-o},Q=function(t){var o=t.data(a),n=e("#mCSB_"+o.idx+"_container,#mCSB_"+o.idx+"_container_wrapper,#mCSB_"+o.idx+"_dragger_vertical,#mCSB_"+o.idx+"_dragger_horizontal");n.each(function(){Z.call(this)})},G=function(t,o,n){function i(e){return s&&c.callbacks[e]&&"function"==typeof c.callbacks[e]}function r(){return[c.callbacks.alwaysTriggerOffsets||w>=S[0]+y,c.callbacks.alwaysTriggerOffsets||-B>=w]}function l(){var e=[h[0].offsetTop,h[0].offsetLeft],o=[x[0].offsetTop,x[0].offsetLeft],a=[h.outerHeight(!1),h.outerWidth(!1)],i=[f.height(),f.width()];t[0].mcs={content:h,top:e[0],left:e[1],draggerTop:o[0],draggerLeft:o[1],topPct:Math.round(100*Math.abs(e[0])/(Math.abs(a[0])-i[0])),leftPct:Math.round(100*Math.abs(e[1])/(Math.abs(a[1])-i[1])),direction:n.dir}}var s=t.data(a),c=s.opt,d={trigger:"internal",dir:"y",scrollEasing:"mcsEaseOut",drag:!1,dur:c.scrollInertia,overwrite:"all",callbacks:!0,onStart:!0,onUpdate:!0,onComplete:!0},n=e.extend(d,n),u=[n.dur,n.drag?0:n.dur],f=e("#mCSB_"+s.idx),h=e("#mCSB_"+s.idx+"_container"),m=h.parent(),p=c.callbacks.onTotalScrollOffset?Y.call(t,c.callbacks.onTotalScrollOffset):[0,0],g=c.callbacks.onTotalScrollBackOffset?Y.call(t,c.callbacks.onTotalScrollBackOffset):[0,0];if(s.trigger=n.trigger,0===m.scrollTop()&&0===m.scrollLeft()||(e(".mCSB_"+s.idx+"_scrollbar").css("visibility","visible"),m.scrollTop(0).scrollLeft(0)),"_resetY"!==o||s.contentReset.y||(i("onOverflowYNone")&&c.callbacks.onOverflowYNone.call(t[0]),s.contentReset.y=1),"_resetX"!==o||s.contentReset.x||(i("onOverflowXNone")&&c.callbacks.onOverflowXNone.call(t[0]),s.contentReset.x=1),"_resetY"!==o&&"_resetX"!==o){if(!s.contentReset.y&&t[0].mcs||!s.overflowed[0]||(i("onOverflowY")&&c.callbacks.onOverflowY.call(t[0]),s.contentReset.x=null),!s.contentReset.x&&t[0].mcs||!s.overflowed[1]||(i("onOverflowX")&&c.callbacks.onOverflowX.call(t[0]),s.contentReset.x=null),c.snapAmount){var v=c.snapAmount instanceof Array?"x"===n.dir?c.snapAmount[1]:c.snapAmount[0]:c.snapAmount;o=V(o,v,c.snapOffset)}switch(n.dir){case"x":var x=e("#mCSB_"+s.idx+"_dragger_horizontal"),_="left",w=h[0].offsetLeft,S=[f.width()-h.outerWidth(!1),x.parent().width()-x.width()],b=[o,0===o?0:o/s.scrollRatio.x],y=p[1],B=g[1],T=y>0?y/s.scrollRatio.x:0,k=B>0?B/s.scrollRatio.x:0;break;case"y":var x=e("#mCSB_"+s.idx+"_dragger_vertical"),_="top",w=h[0].offsetTop,S=[f.height()-h.outerHeight(!1),x.parent().height()-x.height()],b=[o,0===o?0:o/s.scrollRatio.y],y=p[0],B=g[0],T=y>0?y/s.scrollRatio.y:0,k=B>0?B/s.scrollRatio.y:0}b[1]<0||0===b[0]&&0===b[1]?b=[0,0]:b[1]>=S[1]?b=[S[0],S[1]]:b[0]=-b[0],t[0].mcs||(l(),i("onInit")&&c.callbacks.onInit.call(t[0])),clearTimeout(h[0].onCompleteTimeout),J(x[0],_,Math.round(b[1]),u[1],n.scrollEasing),!s.tweenRunning&&(0===w&&b[0]>=0||w===S[0]&&b[0]<=S[0])||J(h[0],_,Math.round(b[0]),u[0],n.scrollEasing,n.overwrite,{onStart:function(){n.callbacks&&n.onStart&&!s.tweenRunning&&(i("onScrollStart")&&(l(),c.callbacks.onScrollStart.call(t[0])),s.tweenRunning=!0,C(x),s.cbOffsets=r())},onUpdate:function(){n.callbacks&&n.onUpdate&&i("whileScrolling")&&(l(),c.callbacks.whileScrolling.call(t[0]))},onComplete:function(){if(n.callbacks&&n.onComplete){"yx"===c.axis&&clearTimeout(h[0].onCompleteTimeout);var e=h[0].idleTimer||0;h[0].onCompleteTimeout=setTimeout(function(){i("onScroll")&&(l(),c.callbacks.onScroll.call(t[0])),i("onTotalScroll")&&b[1]>=S[1]-T&&s.cbOffsets[0]&&(l(),c.callbacks.onTotalScroll.call(t[0])),i("onTotalScrollBack")&&b[1]<=k&&s.cbOffsets[1]&&(l(),c.callbacks.onTotalScrollBack.call(t[0])),s.tweenRunning=!1,h[0].idleTimer=0,C(x,"hide")},e)}}})}},J=function(e,t,o,a,n,i,r){function l(){S.stop||(x||m.call(),x=K()-v,s(),x>=S.time&&(S.time=x>S.time?x+f-(x-S.time):x+f-1,S.time0?(S.currVal=u(S.time,_,b,a,n),w[t]=Math.round(S.currVal)+"px"):w[t]=o+"px",p.call()}function c(){f=1e3/60,S.time=x+f,h=window.requestAnimationFrame?window.requestAnimationFrame:function(e){return s(),setTimeout(e,.01)},S.id=h(l)}function d(){null!=S.id&&(window.requestAnimationFrame?window.cancelAnimationFrame(S.id):clearTimeout(S.id),S.id=null)}function u(e,t,o,a,n){switch(n){case"linear":case"mcsLinear":return o*e/a+t;case"mcsLinearOut":return e/=a,e--,o*Math.sqrt(1-e*e)+t;case"easeInOutSmooth":return e/=a/2,1>e?o/2*e*e+t:(e--,-o/2*(e*(e-2)-1)+t);case"easeInOutStrong":return e/=a/2,1>e?o/2*Math.pow(2,10*(e-1))+t:(e--,o/2*(-Math.pow(2,-10*e)+2)+t);case"easeInOut":case"mcsEaseInOut":return e/=a/2,1>e?o/2*e*e*e+t:(e-=2,o/2*(e*e*e+2)+t);case"easeOutSmooth":return e/=a,e--,-o*(e*e*e*e-1)+t;case"easeOutStrong":return o*(-Math.pow(2,-10*e/a)+1)+t;case"easeOut":case"mcsEaseOut":default:var i=(e/=a)*e,r=i*e;return t+o*(.499999999999997*r*i+-2.5*i*i+5.5*r+-6.5*i+4*e)}}e._mTween||(e._mTween={top:{},left:{}});var f,h,r=r||{},m=r.onStart||function(){},p=r.onUpdate||function(){},g=r.onComplete||function(){},v=K(),x=0,_=e.offsetTop,w=e.style,S=e._mTween[t];"left"===t&&(_=e.offsetLeft);var b=o-_;S.stop=0,"none"!==i&&d(),c()},K=function(){return window.performance&&window.performance.now?window.performance.now():window.performance&&window.performance.webkitNow?window.performance.webkitNow():Date.now?Date.now():(new Date).getTime()},Z=function(){var e=this;e._mTween||(e._mTween={top:{},left:{}});for(var t=["top","left"],o=0;o=0&&a[0]+ae(n)[0]=0&&a[1]+ae(n)[1]=0&&r[1]-i[1]*l[1][0]<0&&r[1]+n[1]-i[1]*l[1][1]>=0},mcsOverflow:e.expr[":"].mcsOverflow||function(t){var o=e(t).data(a);if(o)return o.overflowed[0]||o.overflowed[1]}})})})}); \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css deleted file mode 100644 index 8f013dafa3..0000000000 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css +++ /dev/null @@ -1,1267 +0,0 @@ -/* -== malihu jquery custom scrollbar plugin == -Plugin URI: http://manos.malihu.gr/jquery-custom-content-scroller -*/ - - - -/* -CONTENTS: - 1. BASIC STYLE - Plugin's basic/essential CSS properties (normally, should not be edited). - 2. VERTICAL SCROLLBAR - Positioning and dimensions of vertical scrollbar. - 3. HORIZONTAL SCROLLBAR - Positioning and dimensions of horizontal scrollbar. - 4. VERTICAL AND HORIZONTAL SCROLLBARS - Positioning and dimensions of 2-axis scrollbars. - 5. TRANSITIONS - CSS3 transitions for hover events, auto-expanded and auto-hidden scrollbars. - 6. SCROLLBAR COLORS, OPACITY AND BACKGROUNDS - 6.1 THEMES - Scrollbar colors, opacity, dimensions, backgrounds etc. via ready-to-use themes. -*/ - - - -/* ------------------------------------------------------------------------------------------------------------------------- -1. BASIC STYLE ------------------------------------------------------------------------------------------------------------------------- -*/ - - .mCustomScrollbar{ -ms-touch-action: pinch-zoom; touch-action: pinch-zoom; /* direct pointer events to js */ } - .mCustomScrollbar.mCS_no_scrollbar, .mCustomScrollbar.mCS_touch_action{ -ms-touch-action: auto; touch-action: auto; } - - .mCustomScrollBox{ /* contains plugin's markup */ - position: relative; - overflow: hidden; - height: 100%; - max-width: 100%; - outline: none; - direction: ltr; - } - - .mCSB_container{ /* contains the original content */ - overflow: hidden; - width: auto; - height: auto; - } - - - -/* ------------------------------------------------------------------------------------------------------------------------- -2. VERTICAL SCROLLBAR -y-axis ------------------------------------------------------------------------------------------------------------------------- -*/ - - .mCSB_inside > .mCSB_container{ margin-right: 30px; } - - .mCSB_container.mCS_no_scrollbar_y.mCS_y_hidden{ margin-right: 0; } /* non-visible scrollbar */ - - .mCS-dir-rtl > .mCSB_inside > .mCSB_container{ /* RTL direction/left-side scrollbar */ - margin-right: 0; - margin-left: 30px; - } - - .mCS-dir-rtl > .mCSB_inside > .mCSB_container.mCS_no_scrollbar_y.mCS_y_hidden{ margin-left: 0; } /* RTL direction/left-side scrollbar */ - - .mCSB_scrollTools{ /* contains scrollbar markup (draggable element, dragger rail, buttons etc.) */ - position: absolute; - width: 16px; - height: auto; - left: auto; - top: 0; - right: 0; - bottom: 0; - } - - .mCSB_outside + .mCSB_scrollTools{ right: -26px; } /* scrollbar position: outside */ - - .mCS-dir-rtl > .mCSB_inside > .mCSB_scrollTools, - .mCS-dir-rtl > .mCSB_outside + .mCSB_scrollTools{ /* RTL direction/left-side scrollbar */ - right: auto; - left: 0; - } - - .mCS-dir-rtl > .mCSB_outside + .mCSB_scrollTools{ left: -26px; } /* RTL direction/left-side scrollbar (scrollbar position: outside) */ - - .mCSB_scrollTools .mCSB_draggerContainer{ /* contains the draggable element and dragger rail markup */ - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - height: auto; - } - - .mCSB_scrollTools a + .mCSB_draggerContainer{ margin: 20px 0; } - - .mCSB_scrollTools .mCSB_draggerRail{ - width: 2px; - height: 100%; - margin: 0 auto; - -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; - } - - .mCSB_scrollTools .mCSB_dragger{ /* the draggable element */ - cursor: pointer; - width: 100%; - height: 30px; /* minimum dragger height */ - z-index: 1; - } - - .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ /* the dragger element */ - position: relative; - width: 4px; - height: 100%; - margin: 0 auto; - -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; - text-align: center; - } - - .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, - .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ width: 12px; /* auto-expanded scrollbar */ } - - .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ width: 8px; /* auto-expanded scrollbar */ } - - .mCSB_scrollTools .mCSB_buttonUp, - .mCSB_scrollTools .mCSB_buttonDown{ - display: block; - position: absolute; - height: 20px; - width: 100%; - overflow: hidden; - margin: 0 auto; - cursor: pointer; - } - - .mCSB_scrollTools .mCSB_buttonDown{ bottom: 0; } - - - -/* ------------------------------------------------------------------------------------------------------------------------- -3. HORIZONTAL SCROLLBAR -x-axis ------------------------------------------------------------------------------------------------------------------------- -*/ - - .mCSB_horizontal.mCSB_inside > .mCSB_container{ - margin-right: 0; - margin-bottom: 30px; - } - - .mCSB_horizontal.mCSB_outside > .mCSB_container{ min-height: 100%; } - - .mCSB_horizontal > .mCSB_container.mCS_no_scrollbar_x.mCS_x_hidden{ margin-bottom: 0; } /* non-visible scrollbar */ - - .mCSB_scrollTools.mCSB_scrollTools_horizontal{ - width: auto; - height: 16px; - top: auto; - right: 0; - bottom: 0; - left: 0; - } - - .mCustomScrollBox + .mCSB_scrollTools.mCSB_scrollTools_horizontal, - .mCustomScrollBox + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal{ bottom: -26px; } /* scrollbar position: outside */ - - .mCSB_scrollTools.mCSB_scrollTools_horizontal a + .mCSB_draggerContainer{ margin: 0 20px; } - - .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_draggerRail{ - width: 100%; - height: 2px; - margin: 7px 0; - } - - .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_dragger{ - width: 30px; /* minimum dragger width */ - height: 100%; - left: 0; - } - - .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - width: 100%; - height: 4px; - margin: 6px auto; - } - - .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, - .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ - height: 12px; /* auto-expanded scrollbar */ - margin: 2px auto; - } - - .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ - height: 8px; /* auto-expanded scrollbar */ - margin: 4px 0; - } - - .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonLeft, - .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonRight{ - display: block; - position: absolute; - width: 20px; - height: 100%; - overflow: hidden; - margin: 0 auto; - cursor: pointer; - } - - .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonLeft{ left: 0; } - - .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonRight{ right: 0; } - - - -/* ------------------------------------------------------------------------------------------------------------------------- -4. VERTICAL AND HORIZONTAL SCROLLBARS -yx-axis ------------------------------------------------------------------------------------------------------------------------- -*/ - - .mCSB_container_wrapper{ - position: absolute; - height: auto; - width: auto; - overflow: hidden; - top: 0; - left: 0; - right: 0; - bottom: 0; - margin-right: 30px; - margin-bottom: 30px; - } - - .mCSB_container_wrapper > .mCSB_container{ - padding-right: 30px; - padding-bottom: 30px; - -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; - } - - .mCSB_vertical_horizontal > .mCSB_scrollTools.mCSB_scrollTools_vertical{ bottom: 20px; } - - .mCSB_vertical_horizontal > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ right: 20px; } - - /* non-visible horizontal scrollbar */ - .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden + .mCSB_scrollTools.mCSB_scrollTools_vertical{ bottom: 0; } - - /* non-visible vertical scrollbar/RTL direction/left-side scrollbar */ - .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden + .mCSB_scrollTools ~ .mCSB_scrollTools.mCSB_scrollTools_horizontal, - .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ right: 0; } - - /* RTL direction/left-side scrollbar */ - .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ left: 20px; } - - /* non-visible scrollbar/RTL direction/left-side scrollbar */ - .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden + .mCSB_scrollTools ~ .mCSB_scrollTools.mCSB_scrollTools_horizontal{ left: 0; } - - .mCS-dir-rtl > .mCSB_inside > .mCSB_container_wrapper{ /* RTL direction/left-side scrollbar */ - margin-right: 0; - margin-left: 30px; - } - - .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden > .mCSB_container{ padding-right: 0; } - - .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden > .mCSB_container{ padding-bottom: 0; } - - .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden{ - margin-right: 0; /* non-visible scrollbar */ - margin-left: 0; - } - - /* non-visible horizontal scrollbar */ - .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden{ margin-bottom: 0; } - - - -/* ------------------------------------------------------------------------------------------------------------------------- -5. TRANSITIONS ------------------------------------------------------------------------------------------------------------------------- -*/ - - .mCSB_scrollTools, - .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCSB_scrollTools .mCSB_buttonUp, - .mCSB_scrollTools .mCSB_buttonDown, - .mCSB_scrollTools .mCSB_buttonLeft, - .mCSB_scrollTools .mCSB_buttonRight{ - -webkit-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; - -moz-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; - -o-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; - transition: opacity .2s ease-in-out, background-color .2s ease-in-out; - } - - .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger_bar, /* auto-expanded scrollbar */ - .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerRail, - .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger_bar, - .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerRail{ - -webkit-transition: width .2s ease-out .2s, height .2s ease-out .2s, - margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, - margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, - opacity .2s ease-in-out, background-color .2s ease-in-out; - -moz-transition: width .2s ease-out .2s, height .2s ease-out .2s, - margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, - margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, - opacity .2s ease-in-out, background-color .2s ease-in-out; - -o-transition: width .2s ease-out .2s, height .2s ease-out .2s, - margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, - margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, - opacity .2s ease-in-out, background-color .2s ease-in-out; - transition: width .2s ease-out .2s, height .2s ease-out .2s, - margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, - margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, - opacity .2s ease-in-out, background-color .2s ease-in-out; - } - - - -/* ------------------------------------------------------------------------------------------------------------------------- -6. SCROLLBAR COLORS, OPACITY AND BACKGROUNDS ------------------------------------------------------------------------------------------------------------------------- -*/ - - /* - ---------------------------------------- - 6.1 THEMES - ---------------------------------------- - */ - - /* default theme ("light") */ - - .mCSB_scrollTools{ opacity: 0.75; filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; } - - .mCS-autoHide > .mCustomScrollBox > .mCSB_scrollTools, - .mCS-autoHide > .mCustomScrollBox ~ .mCSB_scrollTools{ opacity: 0; filter: "alpha(opacity=0)"; -ms-filter: "alpha(opacity=0)"; } - - .mCustomScrollbar > .mCustomScrollBox > .mCSB_scrollTools.mCSB_scrollTools_onDrag, - .mCustomScrollbar > .mCustomScrollBox ~ .mCSB_scrollTools.mCSB_scrollTools_onDrag, - .mCustomScrollBox:hover > .mCSB_scrollTools, - .mCustomScrollBox:hover ~ .mCSB_scrollTools, - .mCS-autoHide:hover > .mCustomScrollBox > .mCSB_scrollTools, - .mCS-autoHide:hover > .mCustomScrollBox ~ .mCSB_scrollTools{ opacity: 1; filter: "alpha(opacity=100)"; -ms-filter: "alpha(opacity=100)"; } - - .mCSB_scrollTools .mCSB_draggerRail{ - background-color: #000; background-color: rgba(0,0,0,0.4); - filter: "alpha(opacity=40)"; -ms-filter: "alpha(opacity=40)"; - } - - .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - background-color: #fff; background-color: rgba(255,255,255,0.75); - filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; - } - - .mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ - background-color: #fff; background-color: rgba(255,255,255,0.85); - filter: "alpha(opacity=85)"; -ms-filter: "alpha(opacity=85)"; - } - .mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ - background-color: #fff; background-color: rgba(255,255,255,0.9); - filter: "alpha(opacity=90)"; -ms-filter: "alpha(opacity=90)"; - } - - .mCSB_scrollTools .mCSB_buttonUp, - .mCSB_scrollTools .mCSB_buttonDown, - .mCSB_scrollTools .mCSB_buttonLeft, - .mCSB_scrollTools .mCSB_buttonRight{ - background-image: url(mCSB_buttons.png); /* css sprites */ - background-repeat: no-repeat; - opacity: 0.4; filter: "alpha(opacity=40)"; -ms-filter: "alpha(opacity=40)"; - } - - .mCSB_scrollTools .mCSB_buttonUp{ - background-position: 0 0; - /* - sprites locations - light: 0 0, -16px 0, -32px 0, -48px 0, 0 -72px, -16px -72px, -32px -72px - dark: -80px 0, -96px 0, -112px 0, -128px 0, -80px -72px, -96px -72px, -112px -72px - */ - } - - .mCSB_scrollTools .mCSB_buttonDown{ - background-position: 0 -20px; - /* - sprites locations - light: 0 -20px, -16px -20px, -32px -20px, -48px -20px, 0 -92px, -16px -92px, -32px -92px - dark: -80px -20px, -96px -20px, -112px -20px, -128px -20px, -80px -92px, -96px -92px, -112 -92px - */ - } - - .mCSB_scrollTools .mCSB_buttonLeft{ - background-position: 0 -40px; - /* - sprites locations - light: 0 -40px, -20px -40px, -40px -40px, -60px -40px, 0 -112px, -20px -112px, -40px -112px - dark: -80px -40px, -100px -40px, -120px -40px, -140px -40px, -80px -112px, -100px -112px, -120px -112px - */ - } - - .mCSB_scrollTools .mCSB_buttonRight{ - background-position: 0 -56px; - /* - sprites locations - light: 0 -56px, -20px -56px, -40px -56px, -60px -56px, 0 -128px, -20px -128px, -40px -128px - dark: -80px -56px, -100px -56px, -120px -56px, -140px -56px, -80px -128px, -100px -128px, -120px -128px - */ - } - - .mCSB_scrollTools .mCSB_buttonUp:hover, - .mCSB_scrollTools .mCSB_buttonDown:hover, - .mCSB_scrollTools .mCSB_buttonLeft:hover, - .mCSB_scrollTools .mCSB_buttonRight:hover{ opacity: 0.75; filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; } - - .mCSB_scrollTools .mCSB_buttonUp:active, - .mCSB_scrollTools .mCSB_buttonDown:active, - .mCSB_scrollTools .mCSB_buttonLeft:active, - .mCSB_scrollTools .mCSB_buttonRight:active{ opacity: 0.9; filter: "alpha(opacity=90)"; -ms-filter: "alpha(opacity=90)"; } - - - /* theme: "dark" */ - - .mCS-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } - - .mCS-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } - - .mCS-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: rgba(0,0,0,0.85); } - - .mCS-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: rgba(0,0,0,0.9); } - - .mCS-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px 0; } - - .mCS-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -20px; } - - .mCS-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -40px; } - - .mCS-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -56px; } - - /* ---------------------------------------- */ - - - - /* theme: "light-2", "dark-2" */ - - .mCS-light-2.mCSB_scrollTools .mCSB_draggerRail, - .mCS-dark-2.mCSB_scrollTools .mCSB_draggerRail{ - width: 4px; - background-color: #fff; background-color: rgba(255,255,255,0.1); - -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; - } - - .mCS-light-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - width: 4px; - background-color: #fff; background-color: rgba(255,255,255,0.75); - -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; - } - - .mCS-light-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-dark-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-light-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - width: 100%; - height: 4px; - margin: 6px auto; - } - - .mCS-light-2.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } - - .mCS-light-2.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-light-2.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } - - .mCS-light-2.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px 0; } - - .mCS-light-2.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -20px; } - - .mCS-light-2.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -40px; } - - .mCS-light-2.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -56px; } - - - /* theme: "dark-2" */ - - .mCS-dark-2.mCSB_scrollTools .mCSB_draggerRail{ - background-color: #000; background-color: rgba(0,0,0,0.1); - -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; - } - - .mCS-dark-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - background-color: #000; background-color: rgba(0,0,0,0.75); - -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; - } - - .mCS-dark-2.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } - - .mCS-dark-2.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-dark-2.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } - - .mCS-dark-2.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px 0; } - - .mCS-dark-2.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -20px; } - - .mCS-dark-2.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -40px; } - - .mCS-dark-2.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -56px; } - - /* ---------------------------------------- */ - - - - /* theme: "light-thick", "dark-thick" */ - - .mCS-light-thick.mCSB_scrollTools .mCSB_draggerRail, - .mCS-dark-thick.mCSB_scrollTools .mCSB_draggerRail{ - width: 4px; - background-color: #fff; background-color: rgba(255,255,255,0.1); - -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; - } - - .mCS-light-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - width: 6px; - background-color: #fff; background-color: rgba(255,255,255,0.75); - -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; - } - - .mCS-light-thick.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-dark-thick.mCSB_scrollTools_horizontal .mCSB_draggerRail{ - width: 100%; - height: 4px; - margin: 6px 0; - } - - .mCS-light-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - width: 100%; - height: 6px; - margin: 5px auto; - } - - .mCS-light-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } - - .mCS-light-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-light-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } - - .mCS-light-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -16px 0; } - - .mCS-light-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -16px -20px; } - - .mCS-light-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -20px -40px; } - - .mCS-light-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -20px -56px; } - - - /* theme: "dark-thick" */ - - .mCS-dark-thick.mCSB_scrollTools .mCSB_draggerRail{ - background-color: #000; background-color: rgba(0,0,0,0.1); - -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; - } - - .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - background-color: #000; background-color: rgba(0,0,0,0.75); - -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; - } - - .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } - - .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } - - .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -96px 0; } - - .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -96px -20px; } - - .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -100px -40px; } - - .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -100px -56px; } - - /* ---------------------------------------- */ - - - - /* theme: "light-thin", "dark-thin" */ - - .mCS-light-thin.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.1); } - - .mCS-light-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 2px; } - - .mCS-light-thin.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-dark-thin.mCSB_scrollTools_horizontal .mCSB_draggerRail{ width: 100%; } - - .mCS-light-thin.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-thin.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - width: 100%; - height: 2px; - margin: 7px auto; - } - - - /* theme "dark-thin" */ - - .mCS-dark-thin.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } - - .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } - - .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } - - .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } - - .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px 0; } - - .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -20px; } - - .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -40px; } - - .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -56px; } - - /* ---------------------------------------- */ - - - - /* theme "rounded", "rounded-dark", "rounded-dots", "rounded-dots-dark" */ - - .mCS-rounded.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.15); } - - .mCS-rounded.mCSB_scrollTools .mCSB_dragger, - .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger, - .mCS-rounded-dots.mCSB_scrollTools .mCSB_dragger, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger{ height: 14px; } - - .mCS-rounded.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dots.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - width: 14px; - margin: 0 1px; - } - - .mCS-rounded.mCSB_scrollTools_horizontal .mCSB_dragger, - .mCS-rounded-dark.mCSB_scrollTools_horizontal .mCSB_dragger, - .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_dragger, - .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 14px; } - - .mCS-rounded.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - height: 14px; - margin: 1px 0; - } - - .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, - .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, - .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ - width: 16px; /* auto-expanded scrollbar */ - height: 16px; - margin: -1px 0; - } - - .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, - .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ width: 4px; /* auto-expanded scrollbar */ } - - .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, - .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, - .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ - height: 16px; /* auto-expanded scrollbar */ - width: 16px; - margin: 0 -1px; - } - - .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, - .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ - height: 4px; /* auto-expanded scrollbar */ - margin: 6px 0; - } - - .mCS-rounded.mCSB_scrollTools .mCSB_buttonUp{ background-position: 0 -72px; } - - .mCS-rounded.mCSB_scrollTools .mCSB_buttonDown{ background-position: 0 -92px; } - - .mCS-rounded.mCSB_scrollTools .mCSB_buttonLeft{ background-position: 0 -112px; } - - .mCS-rounded.mCSB_scrollTools .mCSB_buttonRight{ background-position: 0 -128px; } - - - /* theme "rounded-dark", "rounded-dots-dark" */ - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px -72px; } - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -92px; } - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -112px; } - - .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -128px; } - - - /* theme "rounded-dots", "rounded-dots-dark" */ - - .mCS-rounded-dots.mCSB_scrollTools_vertical .mCSB_draggerRail, - .mCS-rounded-dots-dark.mCSB_scrollTools_vertical .mCSB_draggerRail{ width: 4px; } - - .mCS-rounded-dots.mCSB_scrollTools .mCSB_draggerRail, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail, - .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ - background-color: transparent; - background-position: center; - } - - .mCS-rounded-dots.mCSB_scrollTools .mCSB_draggerRail, - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail{ - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAANElEQVQYV2NkIAAYiVbw//9/Y6DiM1ANJoyMjGdBbLgJQAX/kU0DKgDLkaQAvxW4HEvQFwCRcxIJK1XznAAAAABJRU5ErkJggg=="); - background-repeat: repeat-y; - opacity: 0.3; - filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; - } - - .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ - height: 4px; - margin: 6px 0; - background-repeat: repeat-x; - } - - .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonUp{ background-position: -16px -72px; } - - .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonDown{ background-position: -16px -92px; } - - .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -20px -112px; } - - .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonRight{ background-position: -20px -128px; } - - - /* theme "rounded-dots-dark" */ - - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail{ - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAALElEQVQYV2NkIAAYSVFgDFR8BqrBBEifBbGRTfiPZhpYjiQFBK3A6l6CvgAAE9kGCd1mvgEAAAAASUVORK5CYII="); - } - - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -96px -72px; } - - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -96px -92px; } - - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -100px -112px; } - - .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -100px -128px; } - - /* ---------------------------------------- */ - - - - /* theme "3d", "3d-dark", "3d-thick", "3d-thick-dark" */ - - .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - background-repeat: repeat-y; - background-image: -moz-linear-gradient(left, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 100%); - background-image: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(255,255,255,0.5)), color-stop(100%,rgba(255,255,255,0))); - background-image: -webkit-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - background-image: -o-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - background-image: -ms-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - background-image: linear-gradient(to right, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - } - - .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - background-repeat: repeat-x; - background-image: -moz-linear-gradient(top, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 100%); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,0.5)), color-stop(100%,rgba(255,255,255,0))); - background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - background-image: -o-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - background-image: -ms-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - background-image: linear-gradient(to bottom, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); - } - - - /* theme "3d", "3d-dark" */ - - .mCS-3d.mCSB_scrollTools_vertical .mCSB_dragger, - .mCS-3d-dark.mCSB_scrollTools_vertical .mCSB_dragger{ height: 70px; } - - .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger, - .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 70px; } - - .mCS-3d.mCSB_scrollTools, - .mCS-3d-dark.mCSB_scrollTools{ - opacity: 1; - filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; - } - - .mCS-3d.mCSB_scrollTools .mCSB_draggerRail, - .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail, - .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; } - - .mCS-3d.mCSB_scrollTools .mCSB_draggerRail, - .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail{ - width: 8px; - background-color: #000; background-color: rgba(0,0,0,0.2); - box-shadow: inset 1px 0 1px rgba(0,0,0,0.5), inset -1px 0 1px rgba(255,255,255,0.2); - } - - .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, - .mCS-3d.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-3d.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #555; } - - .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 8px; } - - .mCS-3d.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ - width: 100%; - height: 8px; - margin: 4px 0; - box-shadow: inset 0 1px 1px rgba(0,0,0,0.5), inset 0 -1px 1px rgba(255,255,255,0.2); - } - - .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - width: 100%; - height: 8px; - margin: 4px auto; - } - - .mCS-3d.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } - - .mCS-3d.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } - - .mCS-3d.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } - - .mCS-3d.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } - - - /* theme "3d-dark" */ - - .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail{ - background-color: #000; background-color: rgba(0,0,0,0.1); - box-shadow: inset 1px 0 1px rgba(0,0,0,0.1); - } - - .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ box-shadow: inset 0 1px 1px rgba(0,0,0,0.1); } - - .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } - - .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } - - .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } - - .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } - - /* ---------------------------------------- */ - - - - /* theme: "3d-thick", "3d-thick-dark" */ - - .mCS-3d-thick.mCSB_scrollTools, - .mCS-3d-thick-dark.mCSB_scrollTools{ - opacity: 1; - filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; - } - - .mCS-3d-thick.mCSB_scrollTools, - .mCS-3d-thick-dark.mCSB_scrollTools, - .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerContainer, - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerContainer{ -webkit-border-radius: 7px; -moz-border-radius: 7px; border-radius: 7px; } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } - - .mCSB_inside + .mCS-3d-thick.mCSB_scrollTools_vertical, - .mCSB_inside + .mCS-3d-thick-dark.mCSB_scrollTools_vertical{ right: 1px; } - - .mCS-3d-thick.mCSB_scrollTools_vertical, - .mCS-3d-thick-dark.mCSB_scrollTools_vertical{ box-shadow: inset 1px 0 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.5); } - - .mCS-3d-thick.mCSB_scrollTools_horizontal, - .mCS-3d-thick-dark.mCSB_scrollTools_horizontal{ - bottom: 1px; - box-shadow: inset 0 1px 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.5); - } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - box-shadow: inset 1px 0 0 rgba(255,255,255,0.4); - width: 12px; - margin: 2px; - position: absolute; - height: auto; - top: 0; - bottom: 0; - left: 0; - right: 0; - } - - .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 0 1px 0 rgba(255,255,255,0.4); } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, - .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #555; } - - .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - height: 12px; - width: auto; - } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerContainer{ - background-color: #000; background-color: rgba(0,0,0,0.05); - box-shadow: inset 1px 1px 16px rgba(0,0,0,0.1); - } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } - - .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } - - - /* theme: "3d-thick-dark" */ - - .mCS-3d-thick-dark.mCSB_scrollTools{ box-shadow: inset 0 0 14px rgba(0,0,0,0.2); } - - .mCS-3d-thick-dark.mCSB_scrollTools_horizontal{ box-shadow: inset 0 1px 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.2); } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 1px 0 0 rgba(255,255,255,0.4), inset -1px 0 0 rgba(0,0,0,0.2); } - - .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 0 1px 0 rgba(255,255,255,0.4), inset 0 -1px 0 rgba(0,0,0,0.2); } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #777; } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerContainer{ - background-color: #fff; background-color: rgba(0,0,0,0.05); - box-shadow: inset 1px 1px 16px rgba(0,0,0,0.1); - } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } - - .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } - - /* ---------------------------------------- */ - - - - /* theme: "minimal", "minimal-dark" */ - - .mCSB_outside + .mCS-minimal.mCSB_scrollTools_vertical, - .mCSB_outside + .mCS-minimal-dark.mCSB_scrollTools_vertical{ - right: 0; - margin: 12px 0; - } - - .mCustomScrollBox.mCS-minimal + .mCSB_scrollTools.mCSB_scrollTools_horizontal, - .mCustomScrollBox.mCS-minimal + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal, - .mCustomScrollBox.mCS-minimal-dark + .mCSB_scrollTools.mCSB_scrollTools_horizontal, - .mCustomScrollBox.mCS-minimal-dark + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal{ - bottom: 0; - margin: 0 12px; - } - - /* RTL direction/left-side scrollbar */ - .mCS-dir-rtl > .mCSB_outside + .mCS-minimal.mCSB_scrollTools_vertical, - .mCS-dir-rtl > .mCSB_outside + .mCS-minimal-dark.mCSB_scrollTools_vertical{ - left: 0; - right: auto; - } - - .mCS-minimal.mCSB_scrollTools .mCSB_draggerRail, - .mCS-minimal-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } - - .mCS-minimal.mCSB_scrollTools_vertical .mCSB_dragger, - .mCS-minimal-dark.mCSB_scrollTools_vertical .mCSB_dragger{ height: 50px; } - - .mCS-minimal.mCSB_scrollTools_horizontal .mCSB_dragger, - .mCS-minimal-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 50px; } - - .mCS-minimal.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - background-color: #fff; background-color: rgba(255,255,255,0.2); - filter: "alpha(opacity=20)"; -ms-filter: "alpha(opacity=20)"; - } - - .mCS-minimal.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-minimal.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ - background-color: #fff; background-color: rgba(255,255,255,0.5); - filter: "alpha(opacity=50)"; -ms-filter: "alpha(opacity=50)"; - } - - - /* theme: "minimal-dark" */ - - .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - background-color: #000; background-color: rgba(0,0,0,0.2); - filter: "alpha(opacity=20)"; -ms-filter: "alpha(opacity=20)"; - } - - .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ - background-color: #000; background-color: rgba(0,0,0,0.5); - filter: "alpha(opacity=50)"; -ms-filter: "alpha(opacity=50)"; - } - - /* ---------------------------------------- */ - - - - /* theme "light-3", "dark-3" */ - - .mCS-light-3.mCSB_scrollTools .mCSB_draggerRail, - .mCS-dark-3.mCSB_scrollTools .mCSB_draggerRail{ - width: 6px; - background-color: #000; background-color: rgba(0,0,0,0.2); - } - - .mCS-light-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 6px; } - - .mCS-light-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-dark-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-light-3.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-dark-3.mCSB_scrollTools_horizontal .mCSB_draggerRail{ - width: 100%; - height: 6px; - margin: 5px 0; - } - - .mCS-light-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-light-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, - .mCS-dark-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-dark-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ - width: 12px; - } - - .mCS-light-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-light-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, - .mCS-dark-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, - .mCS-dark-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ - height: 12px; - margin: 2px 0; - } - - .mCS-light-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } - - .mCS-light-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } - - .mCS-light-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } - - .mCS-light-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } - - - /* theme "dark-3" */ - - .mCS-dark-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } - - .mCS-dark-3.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } - - .mCS-dark-3.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-dark-3.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } - - .mCS-dark-3.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.1); } - - .mCS-dark-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } - - .mCS-dark-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } - - .mCS-dark-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } - - .mCS-dark-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } - - /* ---------------------------------------- */ - - - - /* theme "inset", "inset-dark", "inset-2", "inset-2-dark", "inset-3", "inset-3-dark" */ - - .mCS-inset.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-dark.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-2.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-3.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ - width: 12px; - background-color: #000; background-color: rgba(0,0,0,0.2); - } - - .mCS-inset.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ - width: 6px; - margin: 3px 5px; - position: absolute; - height: auto; - top: 0; - bottom: 0; - left: 0; - right: 0; - } - - .mCS-inset.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-2-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-3-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ - height: 6px; - margin: 5px 3px; - position: absolute; - width: auto; - top: 0; - bottom: 0; - left: 0; - right: 0; - } - - .mCS-inset.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-inset-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-inset-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-inset-2-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-inset-3.mCSB_scrollTools_horizontal .mCSB_draggerRail, - .mCS-inset-3-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ - width: 100%; - height: 12px; - margin: 2px 0; - } - - .mCS-inset.mCSB_scrollTools .mCSB_buttonUp, - .mCS-inset-2.mCSB_scrollTools .mCSB_buttonUp, - .mCS-inset-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } - - .mCS-inset.mCSB_scrollTools .mCSB_buttonDown, - .mCS-inset-2.mCSB_scrollTools .mCSB_buttonDown, - .mCS-inset-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } - - .mCS-inset.mCSB_scrollTools .mCSB_buttonLeft, - .mCS-inset-2.mCSB_scrollTools .mCSB_buttonLeft, - .mCS-inset-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } - - .mCS-inset.mCSB_scrollTools .mCSB_buttonRight, - .mCS-inset-2.mCSB_scrollTools .mCSB_buttonRight, - .mCS-inset-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } - - - /* theme "inset-dark", "inset-2-dark", "inset-3-dark" */ - - .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } - - .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } - - .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } - - .mCS-inset-dark.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.1); } - - .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonUp, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonUp, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } - - .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonDown, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonDown, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } - - .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonLeft, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonLeft, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } - - .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonRight, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonRight, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } - - - /* theme "inset-2", "inset-2-dark" */ - - .mCS-inset-2.mCSB_scrollTools .mCSB_draggerRail, - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail{ - background-color: transparent; - border-width: 1px; - border-style: solid; - border-color: #fff; - border-color: rgba(255,255,255,0.2); - -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; - } - - .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail{ border-color: #000; border-color: rgba(0,0,0,0.2); } - - - /* theme "inset-3", "inset-3-dark" */ - - .mCS-inset-3.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.6); } - - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.6); } - - .mCS-inset-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } - - .mCS-inset-3.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } - - .mCS-inset-3.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-inset-3.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } - - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.75); } - - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } - - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, - .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } - - /* ---------------------------------------- */ diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js b/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js deleted file mode 100644 index ff7a7263f8..0000000000 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js +++ /dev/null @@ -1,2458 +0,0 @@ -/* -== malihu jquery custom scrollbar plugin == -Version: 3.1.5 -Plugin URI: http://manos.malihu.gr/jquery-custom-content-scroller -Author: malihu -Author URI: http://manos.malihu.gr -License: MIT License (MIT) -*/ - -/* -Copyright Manos Malihutsakis (email: manos@malihu.gr) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -/* -The code below is fairly long, fully commented and should be normally used in development. -For production, use either the minified jquery.mCustomScrollbar.min.js script or -the production-ready jquery.mCustomScrollbar.concat.min.js which contains the plugin -and dependencies (minified). -*/ - -(function(factory){ - if(typeof define==="function" && define.amd){ - define(["jquery"],factory); - }else if(typeof module!=="undefined" && module.exports){ - module.exports=factory; - }else{ - factory(jQuery,window,document); - } -}(function($){ -(function(init){ - var _rjs=typeof define==="function" && define.amd, /* RequireJS */ - _njs=typeof module !== "undefined" && module.exports, /* NodeJS */ - _dlp=("https:"==document.location.protocol) ? "https:" : "http:", /* location protocol */ - _url="cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js"; - if(!_rjs){ - if(_njs){ - require("jquery-mousewheel")($); - }else{ - /* load jquery-mousewheel plugin (via CDN) if it's not present or not loaded via RequireJS - (works when mCustomScrollbar fn is called on window load) */ - $.event.special.mousewheel || $("head").append(decodeURI("%3Cscript src="+_dlp+"//"+_url+"%3E%3C/script%3E")); - } - } - init(); -}(function(){ - - /* - ---------------------------------------- - PLUGIN NAMESPACE, PREFIX, DEFAULT SELECTOR(S) - ---------------------------------------- - */ - - var pluginNS="mCustomScrollbar", - pluginPfx="mCS", - defaultSelector=".mCustomScrollbar", - - - - - - /* - ---------------------------------------- - DEFAULT OPTIONS - ---------------------------------------- - */ - - defaults={ - /* - set element/content width/height programmatically - values: boolean, pixels, percentage - option default - ------------------------------------- - setWidth false - setHeight false - */ - /* - set the initial css top property of content - values: string (e.g. "-100px", "10%" etc.) - */ - setTop:0, - /* - set the initial css left property of content - values: string (e.g. "-100px", "10%" etc.) - */ - setLeft:0, - /* - scrollbar axis (vertical and/or horizontal scrollbars) - values (string): "y", "x", "yx" - */ - axis:"y", - /* - position of scrollbar relative to content - values (string): "inside", "outside" ("outside" requires elements with position:relative) - */ - scrollbarPosition:"inside", - /* - scrolling inertia - values: integer (milliseconds) - */ - scrollInertia:950, - /* - auto-adjust scrollbar dragger length - values: boolean - */ - autoDraggerLength:true, - /* - auto-hide scrollbar when idle - values: boolean - option default - ------------------------------------- - autoHideScrollbar false - */ - /* - auto-expands scrollbar on mouse-over and dragging - values: boolean - option default - ------------------------------------- - autoExpandScrollbar false - */ - /* - always show scrollbar, even when there's nothing to scroll - values: integer (0=disable, 1=always show dragger rail and buttons, 2=always show dragger rail, dragger and buttons), boolean - */ - alwaysShowScrollbar:0, - /* - scrolling always snaps to a multiple of this number in pixels - values: integer, array ([y,x]) - option default - ------------------------------------- - snapAmount null - */ - /* - when snapping, snap with this number in pixels as an offset - values: integer - */ - snapOffset:0, - /* - mouse-wheel scrolling - */ - mouseWheel:{ - /* - enable mouse-wheel scrolling - values: boolean - */ - enable:true, - /* - scrolling amount in pixels - values: "auto", integer - */ - scrollAmount:"auto", - /* - mouse-wheel scrolling axis - the default scrolling direction when both vertical and horizontal scrollbars are present - values (string): "y", "x" - */ - axis:"y", - /* - prevent the default behaviour which automatically scrolls the parent element(s) when end of scrolling is reached - values: boolean - option default - ------------------------------------- - preventDefault null - */ - /* - the reported mouse-wheel delta value. The number of lines (translated to pixels) one wheel notch scrolls. - values: "auto", integer - "auto" uses the default OS/browser value - */ - deltaFactor:"auto", - /* - normalize mouse-wheel delta to -1 or 1 (disables mouse-wheel acceleration) - values: boolean - option default - ------------------------------------- - normalizeDelta null - */ - /* - invert mouse-wheel scrolling direction - values: boolean - option default - ------------------------------------- - invert null - */ - /* - the tags that disable mouse-wheel when cursor is over them - */ - disableOver:["select","option","keygen","datalist","textarea"] - }, - /* - scrollbar buttons - */ - scrollButtons:{ - /* - enable scrollbar buttons - values: boolean - option default - ------------------------------------- - enable null - */ - /* - scrollbar buttons scrolling type - values (string): "stepless", "stepped" - */ - scrollType:"stepless", - /* - scrolling amount in pixels - values: "auto", integer - */ - scrollAmount:"auto" - /* - tabindex of the scrollbar buttons - values: false, integer - option default - ------------------------------------- - tabindex null - */ - }, - /* - keyboard scrolling - */ - keyboard:{ - /* - enable scrolling via keyboard - values: boolean - */ - enable:true, - /* - keyboard scrolling type - values (string): "stepless", "stepped" - */ - scrollType:"stepless", - /* - scrolling amount in pixels - values: "auto", integer - */ - scrollAmount:"auto" - }, - /* - enable content touch-swipe scrolling - values: boolean, integer, string (number) - integer values define the axis-specific minimum amount required for scrolling momentum - */ - contentTouchScroll:25, - /* - enable/disable document (default) touch-swipe scrolling - */ - documentTouchScroll:true, - /* - advanced option parameters - */ - advanced:{ - /* - auto-expand content horizontally (for "x" or "yx" axis) - values: boolean, integer (the value 2 forces the non scrollHeight/scrollWidth method, the value 3 forces the scrollHeight/scrollWidth method) - option default - ------------------------------------- - autoExpandHorizontalScroll null - */ - /* - auto-scroll to elements with focus - */ - autoScrollOnFocus:"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']", - /* - auto-update scrollbars on content, element or viewport resize - should be true for fluid layouts/elements, adding/removing content dynamically, hiding/showing elements, content with images etc. - values: boolean - */ - updateOnContentResize:true, - /* - auto-update scrollbars each time each image inside the element is fully loaded - values: "auto", boolean - */ - updateOnImageLoad:"auto", - /* - auto-update scrollbars based on the amount and size changes of specific selectors - useful when you need to update the scrollbar(s) automatically, each time a type of element is added, removed or changes its size - values: boolean, string (e.g. "ul li" will auto-update scrollbars each time list-items inside the element are changed) - a value of true (boolean) will auto-update scrollbars each time any element is changed - option default - ------------------------------------- - updateOnSelectorChange null - */ - /* - extra selectors that'll allow scrollbar dragging upon mousemove/up, pointermove/up, touchend etc. (e.g. "selector-1, selector-2") - option default - ------------------------------------- - extraDraggableSelectors null - */ - /* - extra selectors that'll release scrollbar dragging upon mouseup, pointerup, touchend etc. (e.g. "selector-1, selector-2") - option default - ------------------------------------- - releaseDraggableSelectors null - */ - /* - auto-update timeout - values: integer (milliseconds) - */ - autoUpdateTimeout:60 - }, - /* - scrollbar theme - values: string (see CSS/plugin URI for a list of ready-to-use themes) - */ - theme:"light", - /* - user defined callback functions - */ - callbacks:{ - /* - Available callbacks: - callback default - ------------------------------------- - onCreate null - onInit null - onScrollStart null - onScroll null - onTotalScroll null - onTotalScrollBack null - whileScrolling null - onOverflowY null - onOverflowX null - onOverflowYNone null - onOverflowXNone null - onImageLoad null - onSelectorChange null - onBeforeUpdate null - onUpdate null - */ - onTotalScrollOffset:0, - onTotalScrollBackOffset:0, - alwaysTriggerOffsets:true - } - /* - add scrollbar(s) on all elements matching the current selector, now and in the future - values: boolean, string - string values: "on" (enable), "once" (disable after first invocation), "off" (disable) - liveSelector values: string (selector) - option default - ------------------------------------- - live false - liveSelector null - */ - }, - - - - - - /* - ---------------------------------------- - VARS, CONSTANTS - ---------------------------------------- - */ - - totalInstances=0, /* plugin instances amount */ - liveTimers={}, /* live option timers */ - oldIE=(window.attachEvent && !window.addEventListener) ? 1 : 0, /* detect IE < 9 */ - touchActive=false,touchable, /* global touch vars (for touch and pointer events) */ - /* general plugin classes */ - classes=[ - "mCSB_dragger_onDrag","mCSB_scrollTools_onDrag","mCS_img_loaded","mCS_disabled","mCS_destroyed","mCS_no_scrollbar", - "mCS-autoHide","mCS-dir-rtl","mCS_no_scrollbar_y","mCS_no_scrollbar_x","mCS_y_hidden","mCS_x_hidden","mCSB_draggerContainer", - "mCSB_buttonUp","mCSB_buttonDown","mCSB_buttonLeft","mCSB_buttonRight" - ], - - - - - - /* - ---------------------------------------- - METHODS - ---------------------------------------- - */ - - methods={ - - /* - plugin initialization method - creates the scrollbar(s), plugin data object and options - ---------------------------------------- - */ - - init:function(options){ - - var options=$.extend(true,{},defaults,options), - selector=_selector.call(this); /* validate selector */ - - /* - if live option is enabled, monitor for elements matching the current selector and - apply scrollbar(s) when found (now and in the future) - */ - if(options.live){ - var liveSelector=options.liveSelector || this.selector || defaultSelector, /* live selector(s) */ - $liveSelector=$(liveSelector); /* live selector(s) as jquery object */ - if(options.live==="off"){ - /* - disable live if requested - usage: $(selector).mCustomScrollbar({live:"off"}); - */ - removeLiveTimers(liveSelector); - return; - } - liveTimers[liveSelector]=setTimeout(function(){ - /* call mCustomScrollbar fn on live selector(s) every half-second */ - $liveSelector.mCustomScrollbar(options); - if(options.live==="once" && $liveSelector.length){ - /* disable live after first invocation */ - removeLiveTimers(liveSelector); - } - },500); - }else{ - removeLiveTimers(liveSelector); - } - - /* options backward compatibility (for versions < 3.0.0) and normalization */ - options.setWidth=(options.set_width) ? options.set_width : options.setWidth; - options.setHeight=(options.set_height) ? options.set_height : options.setHeight; - options.axis=(options.horizontalScroll) ? "x" : _findAxis(options.axis); - options.scrollInertia=options.scrollInertia>0 && options.scrollInertia<17 ? 17 : options.scrollInertia; - if(typeof options.mouseWheel!=="object" && options.mouseWheel==true){ /* old school mouseWheel option (non-object) */ - options.mouseWheel={enable:true,scrollAmount:"auto",axis:"y",preventDefault:false,deltaFactor:"auto",normalizeDelta:false,invert:false} - } - options.mouseWheel.scrollAmount=!options.mouseWheelPixels ? options.mouseWheel.scrollAmount : options.mouseWheelPixels; - options.mouseWheel.normalizeDelta=!options.advanced.normalizeMouseWheelDelta ? options.mouseWheel.normalizeDelta : options.advanced.normalizeMouseWheelDelta; - options.scrollButtons.scrollType=_findScrollButtonsType(options.scrollButtons.scrollType); - - _theme(options); /* theme-specific options */ - - /* plugin constructor */ - return $(selector).each(function(){ - - var $this=$(this); - - if(!$this.data(pluginPfx)){ /* prevent multiple instantiations */ - - /* store options and create objects in jquery data */ - $this.data(pluginPfx,{ - idx:++totalInstances, /* instance index */ - opt:options, /* options */ - scrollRatio:{y:null,x:null}, /* scrollbar to content ratio */ - overflowed:null, /* overflowed axis */ - contentReset:{y:null,x:null}, /* object to check when content resets */ - bindEvents:false, /* object to check if events are bound */ - tweenRunning:false, /* object to check if tween is running */ - sequential:{}, /* sequential scrolling object */ - langDir:$this.css("direction"), /* detect/store direction (ltr or rtl) */ - cbOffsets:null, /* object to check whether callback offsets always trigger */ - /* - object to check how scrolling events where last triggered - "internal" (default - triggered by this script), "external" (triggered by other scripts, e.g. via scrollTo method) - usage: object.data("mCS").trigger - */ - trigger:null, - /* - object to check for changes in elements in order to call the update method automatically - */ - poll:{size:{o:0,n:0},img:{o:0,n:0},change:{o:0,n:0}} - }); - - var d=$this.data(pluginPfx),o=d.opt, - /* HTML data attributes */ - htmlDataAxis=$this.data("mcs-axis"),htmlDataSbPos=$this.data("mcs-scrollbar-position"),htmlDataTheme=$this.data("mcs-theme"); - - if(htmlDataAxis){o.axis=htmlDataAxis;} /* usage example: data-mcs-axis="y" */ - if(htmlDataSbPos){o.scrollbarPosition=htmlDataSbPos;} /* usage example: data-mcs-scrollbar-position="outside" */ - if(htmlDataTheme){ /* usage example: data-mcs-theme="minimal" */ - o.theme=htmlDataTheme; - _theme(o); /* theme-specific options */ - } - - _pluginMarkup.call(this); /* add plugin markup */ - - if(d && o.callbacks.onCreate && typeof o.callbacks.onCreate==="function"){o.callbacks.onCreate.call(this);} /* callbacks: onCreate */ - - $("#mCSB_"+d.idx+"_container img:not(."+classes[2]+")").addClass(classes[2]); /* flag loaded images */ - - methods.update.call(null,$this); /* call the update method */ - - } - - }); - - }, - /* ---------------------------------------- */ - - - - /* - plugin update method - updates content and scrollbar(s) values, events and status - ---------------------------------------- - usage: $(selector).mCustomScrollbar("update"); - */ - - update:function(el,cb){ - - var selector=el || _selector.call(this); /* validate selector */ - - return $(selector).each(function(){ - - var $this=$(this); - - if($this.data(pluginPfx)){ /* check if plugin has initialized */ - - var d=$this.data(pluginPfx),o=d.opt, - mCSB_container=$("#mCSB_"+d.idx+"_container"), - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; - - if(!mCSB_container.length){return;} - - if(d.tweenRunning){_stop($this);} /* stop any running tweens while updating */ - - if(cb && d && o.callbacks.onBeforeUpdate && typeof o.callbacks.onBeforeUpdate==="function"){o.callbacks.onBeforeUpdate.call(this);} /* callbacks: onBeforeUpdate */ - - /* if element was disabled or destroyed, remove class(es) */ - if($this.hasClass(classes[3])){$this.removeClass(classes[3]);} - if($this.hasClass(classes[4])){$this.removeClass(classes[4]);} - - /* css flexbox fix, detect/set max-height */ - mCustomScrollBox.css("max-height","none"); - if(mCustomScrollBox.height()!==$this.height()){mCustomScrollBox.css("max-height",$this.height());} - - _expandContentHorizontally.call(this); /* expand content horizontally */ - - if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){ - mCSB_container.css("width",_contentWidth(mCSB_container)); - } - - d.overflowed=_overflowed.call(this); /* determine if scrolling is required */ - - _scrollbarVisibility.call(this); /* show/hide scrollbar(s) */ - - /* auto-adjust scrollbar dragger length analogous to content */ - if(o.autoDraggerLength){_setDraggerLength.call(this);} - - _scrollRatio.call(this); /* calculate and store scrollbar to content ratio */ - - _bindEvents.call(this); /* bind scrollbar events */ - - /* reset scrolling position and/or events */ - var to=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)]; - if(o.axis!=="x"){ /* y/yx axis */ - if(!d.overflowed[0]){ /* y scrolling is not required */ - _resetContentPosition.call(this); /* reset content position */ - if(o.axis==="y"){ - _unbindEvents.call(this); - }else if(o.axis==="yx" && d.overflowed[1]){ - _scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"}); - } - }else if(mCSB_dragger[0].height()>mCSB_dragger[0].parent().height()){ - _resetContentPosition.call(this); /* reset content position */ - }else{ /* y scrolling is required */ - _scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"}); - d.contentReset.y=null; - } - } - if(o.axis!=="y"){ /* x/yx axis */ - if(!d.overflowed[1]){ /* x scrolling is not required */ - _resetContentPosition.call(this); /* reset content position */ - if(o.axis==="x"){ - _unbindEvents.call(this); - }else if(o.axis==="yx" && d.overflowed[0]){ - _scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"}); - } - }else if(mCSB_dragger[1].width()>mCSB_dragger[1].parent().width()){ - _resetContentPosition.call(this); /* reset content position */ - }else{ /* x scrolling is required */ - _scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"}); - d.contentReset.x=null; - } - } - - /* callbacks: onImageLoad, onSelectorChange, onUpdate */ - if(cb && d){ - if(cb===2 && o.callbacks.onImageLoad && typeof o.callbacks.onImageLoad==="function"){ - o.callbacks.onImageLoad.call(this); - }else if(cb===3 && o.callbacks.onSelectorChange && typeof o.callbacks.onSelectorChange==="function"){ - o.callbacks.onSelectorChange.call(this); - }else if(o.callbacks.onUpdate && typeof o.callbacks.onUpdate==="function"){ - o.callbacks.onUpdate.call(this); - } - } - - _autoUpdate.call(this); /* initialize automatic updating (for dynamic content, fluid layouts etc.) */ - - } - - }); - - }, - /* ---------------------------------------- */ - - - - /* - plugin scrollTo method - triggers a scrolling event to a specific value - ---------------------------------------- - usage: $(selector).mCustomScrollbar("scrollTo",value,options); - */ - - scrollTo:function(val,options){ - - /* prevent silly things like $(selector).mCustomScrollbar("scrollTo",undefined); */ - if(typeof val=="undefined" || val==null){return;} - - var selector=_selector.call(this); /* validate selector */ - - return $(selector).each(function(){ - - var $this=$(this); - - if($this.data(pluginPfx)){ /* check if plugin has initialized */ - - var d=$this.data(pluginPfx),o=d.opt, - /* method default options */ - methodDefaults={ - trigger:"external", /* method is by default triggered externally (e.g. from other scripts) */ - scrollInertia:o.scrollInertia, /* scrolling inertia (animation duration) */ - scrollEasing:"mcsEaseInOut", /* animation easing */ - moveDragger:false, /* move dragger instead of content */ - timeout:60, /* scroll-to delay */ - callbacks:true, /* enable/disable callbacks */ - onStart:true, - onUpdate:true, - onComplete:true - }, - methodOptions=$.extend(true,{},methodDefaults,options), - to=_arr.call(this,val),dur=methodOptions.scrollInertia>0 && methodOptions.scrollInertia<17 ? 17 : methodOptions.scrollInertia; - - /* translate yx values to actual scroll-to positions */ - to[0]=_to.call(this,to[0],"y"); - to[1]=_to.call(this,to[1],"x"); - - /* - check if scroll-to value moves the dragger instead of content. - Only pixel values apply on dragger (e.g. 100, "100px", "-=100" etc.) - */ - if(methodOptions.moveDragger){ - to[0]*=d.scrollRatio.y; - to[1]*=d.scrollRatio.x; - } - - methodOptions.dur=_isTabHidden() ? 0 : dur; //skip animations if browser tab is hidden - - setTimeout(function(){ - /* do the scrolling */ - if(to[0]!==null && typeof to[0]!=="undefined" && o.axis!=="x" && d.overflowed[0]){ /* scroll y */ - methodOptions.dir="y"; - methodOptions.overwrite="all"; - _scrollTo($this,to[0].toString(),methodOptions); - } - if(to[1]!==null && typeof to[1]!=="undefined" && o.axis!=="y" && d.overflowed[1]){ /* scroll x */ - methodOptions.dir="x"; - methodOptions.overwrite="none"; - _scrollTo($this,to[1].toString(),methodOptions); - } - },methodOptions.timeout); - - } - - }); - - }, - /* ---------------------------------------- */ - - - - /* - plugin stop method - stops scrolling animation - ---------------------------------------- - usage: $(selector).mCustomScrollbar("stop"); - */ - stop:function(){ - - var selector=_selector.call(this); /* validate selector */ - - return $(selector).each(function(){ - - var $this=$(this); - - if($this.data(pluginPfx)){ /* check if plugin has initialized */ - - _stop($this); - - } - - }); - - }, - /* ---------------------------------------- */ - - - - /* - plugin disable method - temporarily disables the scrollbar(s) - ---------------------------------------- - usage: $(selector).mCustomScrollbar("disable",reset); - reset (boolean): resets content position to 0 - */ - disable:function(r){ - - var selector=_selector.call(this); /* validate selector */ - - return $(selector).each(function(){ - - var $this=$(this); - - if($this.data(pluginPfx)){ /* check if plugin has initialized */ - - var d=$this.data(pluginPfx); - - _autoUpdate.call(this,"remove"); /* remove automatic updating */ - - _unbindEvents.call(this); /* unbind events */ - - if(r){_resetContentPosition.call(this);} /* reset content position */ - - _scrollbarVisibility.call(this,true); /* show/hide scrollbar(s) */ - - $this.addClass(classes[3]); /* add disable class */ - - } - - }); - - }, - /* ---------------------------------------- */ - - - - /* - plugin destroy method - completely removes the scrollbar(s) and returns the element to its original state - ---------------------------------------- - usage: $(selector).mCustomScrollbar("destroy"); - */ - destroy:function(){ - - var selector=_selector.call(this); /* validate selector */ - - return $(selector).each(function(){ - - var $this=$(this); - - if($this.data(pluginPfx)){ /* check if plugin has initialized */ - - var d=$this.data(pluginPfx),o=d.opt, - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_container=$("#mCSB_"+d.idx+"_container"), - scrollbar=$(".mCSB_"+d.idx+"_scrollbar"); - - if(o.live){removeLiveTimers(o.liveSelector || $(selector).selector);} /* remove live timers */ - - _autoUpdate.call(this,"remove"); /* remove automatic updating */ - - _unbindEvents.call(this); /* unbind events */ - - _resetContentPosition.call(this); /* reset content position */ - - $this.removeData(pluginPfx); /* remove plugin data object */ - - _delete(this,"mcs"); /* delete callbacks object */ - - /* remove plugin markup */ - scrollbar.remove(); /* remove scrollbar(s) first (those can be either inside or outside plugin's inner wrapper) */ - mCSB_container.find("img."+classes[2]).removeClass(classes[2]); /* remove loaded images flag */ - mCustomScrollBox.replaceWith(mCSB_container.contents()); /* replace plugin's inner wrapper with the original content */ - /* remove plugin classes from the element and add destroy class */ - $this.removeClass(pluginNS+" _"+pluginPfx+"_"+d.idx+" "+classes[6]+" "+classes[7]+" "+classes[5]+" "+classes[3]).addClass(classes[4]); - - } - - }); - - } - /* ---------------------------------------- */ - - }, - - - - - - /* - ---------------------------------------- - FUNCTIONS - ---------------------------------------- - */ - - /* validates selector (if selector is invalid or undefined uses the default one) */ - _selector=function(){ - return (typeof $(this)!=="object" || $(this).length<1) ? defaultSelector : this; - }, - /* -------------------- */ - - - /* changes options according to theme */ - _theme=function(obj){ - var fixedSizeScrollbarThemes=["rounded","rounded-dark","rounded-dots","rounded-dots-dark"], - nonExpandedScrollbarThemes=["rounded-dots","rounded-dots-dark","3d","3d-dark","3d-thick","3d-thick-dark","inset","inset-dark","inset-2","inset-2-dark","inset-3","inset-3-dark"], - disabledScrollButtonsThemes=["minimal","minimal-dark"], - enabledAutoHideScrollbarThemes=["minimal","minimal-dark"], - scrollbarPositionOutsideThemes=["minimal","minimal-dark"]; - obj.autoDraggerLength=$.inArray(obj.theme,fixedSizeScrollbarThemes) > -1 ? false : obj.autoDraggerLength; - obj.autoExpandScrollbar=$.inArray(obj.theme,nonExpandedScrollbarThemes) > -1 ? false : obj.autoExpandScrollbar; - obj.scrollButtons.enable=$.inArray(obj.theme,disabledScrollButtonsThemes) > -1 ? false : obj.scrollButtons.enable; - obj.autoHideScrollbar=$.inArray(obj.theme,enabledAutoHideScrollbarThemes) > -1 ? true : obj.autoHideScrollbar; - obj.scrollbarPosition=$.inArray(obj.theme,scrollbarPositionOutsideThemes) > -1 ? "outside" : obj.scrollbarPosition; - }, - /* -------------------- */ - - - /* live option timers removal */ - removeLiveTimers=function(selector){ - if(liveTimers[selector]){ - clearTimeout(liveTimers[selector]); - _delete(liveTimers,selector); - } - }, - /* -------------------- */ - - - /* normalizes axis option to valid values: "y", "x", "yx" */ - _findAxis=function(val){ - return (val==="yx" || val==="xy" || val==="auto") ? "yx" : (val==="x" || val==="horizontal") ? "x" : "y"; - }, - /* -------------------- */ - - - /* normalizes scrollButtons.scrollType option to valid values: "stepless", "stepped" */ - _findScrollButtonsType=function(val){ - return (val==="stepped" || val==="pixels" || val==="step" || val==="click") ? "stepped" : "stepless"; - }, - /* -------------------- */ - - - /* generates plugin markup */ - _pluginMarkup=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - expandClass=o.autoExpandScrollbar ? " "+classes[1]+"_expand" : "", - scrollbar=["
    ","
    "], - wrapperClass=o.axis==="yx" ? "mCSB_vertical_horizontal" : o.axis==="x" ? "mCSB_horizontal" : "mCSB_vertical", - scrollbars=o.axis==="yx" ? scrollbar[0]+scrollbar[1] : o.axis==="x" ? scrollbar[1] : scrollbar[0], - contentWrapper=o.axis==="yx" ? "
    " : "", - autoHideClass=o.autoHideScrollbar ? " "+classes[6] : "", - scrollbarDirClass=(o.axis!=="x" && d.langDir==="rtl") ? " "+classes[7] : ""; - if(o.setWidth){$this.css("width",o.setWidth);} /* set element width */ - if(o.setHeight){$this.css("height",o.setHeight);} /* set element height */ - o.setLeft=(o.axis!=="y" && d.langDir==="rtl") ? "989999px" : o.setLeft; /* adjust left position for rtl direction */ - $this.addClass(pluginNS+" _"+pluginPfx+"_"+d.idx+autoHideClass+scrollbarDirClass).wrapInner("
    "); - var mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_container=$("#mCSB_"+d.idx+"_container"); - if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){ - mCSB_container.css("width",_contentWidth(mCSB_container)); - } - if(o.scrollbarPosition==="outside"){ - if($this.css("position")==="static"){ /* requires elements with non-static position */ - $this.css("position","relative"); - } - $this.css("overflow","visible"); - mCustomScrollBox.addClass("mCSB_outside").after(scrollbars); - }else{ - mCustomScrollBox.addClass("mCSB_inside").append(scrollbars); - mCSB_container.wrap(contentWrapper); - } - _scrollButtons.call(this); /* add scrollbar buttons */ - /* minimum dragger length */ - var mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; - mCSB_dragger[0].css("min-height",mCSB_dragger[0].height()); - mCSB_dragger[1].css("min-width",mCSB_dragger[1].width()); - }, - /* -------------------- */ - - - /* calculates content width */ - _contentWidth=function(el){ - var val=[el[0].scrollWidth,Math.max.apply(Math,el.children().map(function(){return $(this).outerWidth(true);}).get())],w=el.parent().width(); - return val[0]>w ? val[0] : val[1]>w ? val[1] : "100%"; - }, - /* -------------------- */ - - - /* expands content horizontally */ - _expandContentHorizontally=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - mCSB_container=$("#mCSB_"+d.idx+"_container"); - if(o.advanced.autoExpandHorizontalScroll && o.axis!=="y"){ - /* calculate scrollWidth */ - mCSB_container.css({"width":"auto","min-width":0,"overflow-x":"scroll"}); - var w=Math.ceil(mCSB_container[0].scrollWidth); - if(o.advanced.autoExpandHorizontalScroll===3 || (o.advanced.autoExpandHorizontalScroll!==2 && w>mCSB_container.parent().width())){ - mCSB_container.css({"width":w,"min-width":"100%","overflow-x":"inherit"}); - }else{ - /* - wrap content with an infinite width div and set its position to absolute and width to auto. - Setting width to auto before calculating the actual width is important! - We must let the browser set the width as browser zoom values are impossible to calculate. - */ - mCSB_container.css({"overflow-x":"inherit","position":"absolute"}) - .wrap("
    ") - .css({ /* set actual width, original position and un-wrap */ - /* - get the exact width (with decimals) and then round-up. - Using jquery outerWidth() will round the width value which will mess up with inner elements that have non-integer width - */ - "width":(Math.ceil(mCSB_container[0].getBoundingClientRect().right+0.4)-Math.floor(mCSB_container[0].getBoundingClientRect().left)), - "min-width":"100%", - "position":"relative" - }).unwrap(); - } - } - }, - /* -------------------- */ - - - /* adds scrollbar buttons */ - _scrollButtons=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - mCSB_scrollTools=$(".mCSB_"+d.idx+"_scrollbar:first"), - tabindex=!_isNumeric(o.scrollButtons.tabindex) ? "" : "tabindex='"+o.scrollButtons.tabindex+"'", - btnHTML=[ - "", - "", - "", - "" - ], - btn=[(o.axis==="x" ? btnHTML[2] : btnHTML[0]),(o.axis==="x" ? btnHTML[3] : btnHTML[1]),btnHTML[2],btnHTML[3]]; - if(o.scrollButtons.enable){ - mCSB_scrollTools.prepend(btn[0]).append(btn[1]).next(".mCSB_scrollTools").prepend(btn[2]).append(btn[3]); - } - }, - /* -------------------- */ - - - /* auto-adjusts scrollbar dragger length */ - _setDraggerLength=function(){ - var $this=$(this),d=$this.data(pluginPfx), - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_container=$("#mCSB_"+d.idx+"_container"), - mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], - ratio=[mCustomScrollBox.height()/mCSB_container.outerHeight(false),mCustomScrollBox.width()/mCSB_container.outerWidth(false)], - l=[ - parseInt(mCSB_dragger[0].css("min-height")),Math.round(ratio[0]*mCSB_dragger[0].parent().height()), - parseInt(mCSB_dragger[1].css("min-width")),Math.round(ratio[1]*mCSB_dragger[1].parent().width()) - ], - h=oldIE && (l[1]contentHeight){contentHeight=h;} - if(w>contentWidth){contentWidth=w;} - return [contentHeight>mCustomScrollBox.height(),contentWidth>mCustomScrollBox.width()]; - }, - /* -------------------- */ - - - /* resets content position to 0 */ - _resetContentPosition=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_container=$("#mCSB_"+d.idx+"_container"), - mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; - _stop($this); /* stop any current scrolling before resetting */ - if((o.axis!=="x" && !d.overflowed[0]) || (o.axis==="y" && d.overflowed[0])){ /* reset y */ - mCSB_dragger[0].add(mCSB_container).css("top",0); - _scrollTo($this,"_resetY"); - } - if((o.axis!=="y" && !d.overflowed[1]) || (o.axis==="x" && d.overflowed[1])){ /* reset x */ - var cx=dx=0; - if(d.langDir==="rtl"){ /* adjust left position for rtl direction */ - cx=mCustomScrollBox.width()-mCSB_container.outerWidth(false); - dx=Math.abs(cx/d.scrollRatio.x); - } - mCSB_container.css("left",cx); - mCSB_dragger[1].css("left",dx); - _scrollTo($this,"_resetX"); - } - }, - /* -------------------- */ - - - /* binds scrollbar events */ - _bindEvents=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt; - if(!d.bindEvents){ /* check if events are already bound */ - _draggable.call(this); - if(o.contentTouchScroll){_contentDraggable.call(this);} - _selectable.call(this); - if(o.mouseWheel.enable){ /* bind mousewheel fn when plugin is available */ - function _mwt(){ - mousewheelTimeout=setTimeout(function(){ - if(!$.event.special.mousewheel){ - _mwt(); - }else{ - clearTimeout(mousewheelTimeout); - _mousewheel.call($this[0]); - } - },100); - } - var mousewheelTimeout; - _mwt(); - } - _draggerRail.call(this); - _wrapperScroll.call(this); - if(o.advanced.autoScrollOnFocus){_focus.call(this);} - if(o.scrollButtons.enable){_buttons.call(this);} - if(o.keyboard.enable){_keyboard.call(this);} - d.bindEvents=true; - } - }, - /* -------------------- */ - - - /* unbinds scrollbar events */ - _unbindEvents=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - namespace=pluginPfx+"_"+d.idx, - sb=".mCSB_"+d.idx+"_scrollbar", - sel=$("#mCSB_"+d.idx+",#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,"+sb+" ."+classes[12]+",#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal,"+sb+">a"), - mCSB_container=$("#mCSB_"+d.idx+"_container"); - if(o.advanced.releaseDraggableSelectors){sel.add($(o.advanced.releaseDraggableSelectors));} - if(o.advanced.extraDraggableSelectors){sel.add($(o.advanced.extraDraggableSelectors));} - if(d.bindEvents){ /* check if events are bound */ - /* unbind namespaced events from document/selectors */ - $(document).add($(!_canAccessIFrame() || top.document)).unbind("."+namespace); - sel.each(function(){ - $(this).unbind("."+namespace); - }); - /* clear and delete timeouts/objects */ - clearTimeout($this[0]._focusTimeout); _delete($this[0],"_focusTimeout"); - clearTimeout(d.sequential.step); _delete(d.sequential,"step"); - clearTimeout(mCSB_container[0].onCompleteTimeout); _delete(mCSB_container[0],"onCompleteTimeout"); - d.bindEvents=false; - } - }, - /* -------------------- */ - - - /* toggles scrollbar visibility */ - _scrollbarVisibility=function(disabled){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - contentWrapper=$("#mCSB_"+d.idx+"_container_wrapper"), - content=contentWrapper.length ? contentWrapper : $("#mCSB_"+d.idx+"_container"), - scrollbar=[$("#mCSB_"+d.idx+"_scrollbar_vertical"),$("#mCSB_"+d.idx+"_scrollbar_horizontal")], - mCSB_dragger=[scrollbar[0].find(".mCSB_dragger"),scrollbar[1].find(".mCSB_dragger")]; - if(o.axis!=="x"){ - if(d.overflowed[0] && !disabled){ - scrollbar[0].add(mCSB_dragger[0]).add(scrollbar[0].children("a")).css("display","block"); - content.removeClass(classes[8]+" "+classes[10]); - }else{ - if(o.alwaysShowScrollbar){ - if(o.alwaysShowScrollbar!==2){mCSB_dragger[0].css("display","none");} - content.removeClass(classes[10]); - }else{ - scrollbar[0].css("display","none"); - content.addClass(classes[10]); - } - content.addClass(classes[8]); - } - } - if(o.axis!=="y"){ - if(d.overflowed[1] && !disabled){ - scrollbar[1].add(mCSB_dragger[1]).add(scrollbar[1].children("a")).css("display","block"); - content.removeClass(classes[9]+" "+classes[11]); - }else{ - if(o.alwaysShowScrollbar){ - if(o.alwaysShowScrollbar!==2){mCSB_dragger[1].css("display","none");} - content.removeClass(classes[11]); - }else{ - scrollbar[1].css("display","none"); - content.addClass(classes[11]); - } - content.addClass(classes[9]); - } - } - if(!d.overflowed[0] && !d.overflowed[1]){ - $this.addClass(classes[5]); - }else{ - $this.removeClass(classes[5]); - } - }, - /* -------------------- */ - - - /* returns input coordinates of pointer, touch and mouse events (relative to document) */ - _coordinates=function(e){ - var t=e.type,o=e.target.ownerDocument!==document && frameElement!==null ? [$(frameElement).offset().top,$(frameElement).offset().left] : null, - io=_canAccessIFrame() && e.target.ownerDocument!==top.document && frameElement!==null ? [$(e.view.frameElement).offset().top,$(e.view.frameElement).offset().left] : [0,0]; - switch(t){ - case "pointerdown": case "MSPointerDown": case "pointermove": case "MSPointerMove": case "pointerup": case "MSPointerUp": - return o ? [e.originalEvent.pageY-o[0]+io[0],e.originalEvent.pageX-o[1]+io[1],false] : [e.originalEvent.pageY,e.originalEvent.pageX,false]; - break; - case "touchstart": case "touchmove": case "touchend": - var touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0], - touches=e.originalEvent.touches.length || e.originalEvent.changedTouches.length; - return e.target.ownerDocument!==document ? [touch.screenY,touch.screenX,touches>1] : [touch.pageY,touch.pageX,touches>1]; - break; - default: - return o ? [e.pageY-o[0]+io[0],e.pageX-o[1]+io[1],false] : [e.pageY,e.pageX,false]; - } - }, - /* -------------------- */ - - - /* - SCROLLBAR DRAG EVENTS - scrolls content via scrollbar dragging - */ - _draggable=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - namespace=pluginPfx+"_"+d.idx, - draggerId=["mCSB_"+d.idx+"_dragger_vertical","mCSB_"+d.idx+"_dragger_horizontal"], - mCSB_container=$("#mCSB_"+d.idx+"_container"), - mCSB_dragger=$("#"+draggerId[0]+",#"+draggerId[1]), - draggable,dragY,dragX, - rds=o.advanced.releaseDraggableSelectors ? mCSB_dragger.add($(o.advanced.releaseDraggableSelectors)) : mCSB_dragger, - eds=o.advanced.extraDraggableSelectors ? $(!_canAccessIFrame() || top.document).add($(o.advanced.extraDraggableSelectors)) : $(!_canAccessIFrame() || top.document); - mCSB_dragger.bind("contextmenu."+namespace,function(e){ - e.preventDefault(); //prevent right click - }).bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){ - e.stopImmediatePropagation(); - e.preventDefault(); - if(!_mouseBtnLeft(e)){return;} /* left mouse button only */ - touchActive=true; - if(oldIE){document.onselectstart=function(){return false;}} /* disable text selection for IE < 9 */ - _iframe.call(mCSB_container,false); /* enable scrollbar dragging over iframes by disabling their events */ - _stop($this); - draggable=$(this); - var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left, - h=draggable.height()+offset.top,w=draggable.width()+offset.left; - if(y0 && x0){ - dragY=y; - dragX=x; - } - _onDragClasses(draggable,"active",o.autoExpandScrollbar); - }).bind("touchmove."+namespace,function(e){ - e.stopImmediatePropagation(); - e.preventDefault(); - var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left; - _drag(dragY,dragX,y,x); - }); - $(document).add(eds).bind("mousemove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace,function(e){ - if(draggable){ - var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left; - if(dragY===y && dragX===x){return;} /* has it really moved? */ - _drag(dragY,dragX,y,x); - } - }).add(rds).bind("mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){ - if(draggable){ - _onDragClasses(draggable,"active",o.autoExpandScrollbar); - draggable=null; - } - touchActive=false; - if(oldIE){document.onselectstart=null;} /* enable text selection for IE < 9 */ - _iframe.call(mCSB_container,true); /* enable iframes events */ - }); - function _drag(dragY,dragX,y,x){ - mCSB_container[0].idleTimer=o.scrollInertia<233 ? 250 : 0; - if(draggable.attr("id")===draggerId[1]){ - var dir="x",to=((draggable[0].offsetLeft-dragX)+x)*d.scrollRatio.x; - }else{ - var dir="y",to=((draggable[0].offsetTop-dragY)+y)*d.scrollRatio.y; - } - _scrollTo($this,to.toString(),{dir:dir,drag:true}); - } - }, - /* -------------------- */ - - - /* - TOUCH SWIPE EVENTS - scrolls content via touch swipe - Emulates the native touch-swipe scrolling with momentum found in iOS, Android and WP devices - */ - _contentDraggable=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - namespace=pluginPfx+"_"+d.idx, - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_container=$("#mCSB_"+d.idx+"_container"), - mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], - draggable,dragY,dragX,touchStartY,touchStartX,touchMoveY=[],touchMoveX=[],startTime,runningTime,endTime,distance,speed,amount, - durA=0,durB,overwrite=o.axis==="yx" ? "none" : "all",touchIntent=[],touchDrag,docDrag, - iframe=mCSB_container.find("iframe"), - events=[ - "touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace, //start - "touchmove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace, //move - "touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace //end - ], - touchAction=document.body.style.touchAction!==undefined && document.body.style.touchAction!==""; - mCSB_container.bind(events[0],function(e){ - _onTouchstart(e); - }).bind(events[1],function(e){ - _onTouchmove(e); - }); - mCustomScrollBox.bind(events[0],function(e){ - _onTouchstart2(e); - }).bind(events[2],function(e){ - _onTouchend(e); - }); - if(iframe.length){ - iframe.each(function(){ - $(this).bind("load",function(){ - /* bind events on accessible iframes */ - if(_canAccessIFrame(this)){ - $(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){ - _onTouchstart(e); - _onTouchstart2(e); - }).bind(events[1],function(e){ - _onTouchmove(e); - }).bind(events[2],function(e){ - _onTouchend(e); - }); - } - }); - }); - } - function _onTouchstart(e){ - if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){touchable=0; return;} - touchable=1; touchDrag=0; docDrag=0; draggable=1; - $this.removeClass("mCS_touch_action"); - var offset=mCSB_container.offset(); - dragY=_coordinates(e)[0]-offset.top; - dragX=_coordinates(e)[1]-offset.left; - touchIntent=[_coordinates(e)[0],_coordinates(e)[1]]; - } - function _onTouchmove(e){ - if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){return;} - if(!o.documentTouchScroll){e.preventDefault();} - e.stopImmediatePropagation(); - if(docDrag && !touchDrag){return;} - if(draggable){ - runningTime=_getTime(); - var offset=mCustomScrollBox.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left, - easing="mcsLinearOut"; - touchMoveY.push(y); - touchMoveX.push(x); - touchIntent[2]=Math.abs(_coordinates(e)[0]-touchIntent[0]); touchIntent[3]=Math.abs(_coordinates(e)[1]-touchIntent[1]); - if(d.overflowed[0]){ - var limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(), - prevent=((dragY-y)>0 && (y-dragY)>-(limit*d.scrollRatio.y) && (touchIntent[3]*20 && (x-dragX)>-(limitX*d.scrollRatio.x) && (touchIntent[2]*230){return;} - speed=1000/(endTime-startTime); - var easing="mcsEaseOut",slow=speed<2.5, - diff=slow ? [touchMoveY[touchMoveY.length-2],touchMoveX[touchMoveX.length-2]] : [0,0]; - distance=slow ? [(y-diff[0]),(x-diff[1])] : [y-touchStartY,x-touchStartX]; - var absDistance=[Math.abs(distance[0]),Math.abs(distance[1])]; - speed=slow ? [Math.abs(distance[0]/4),Math.abs(distance[1]/4)] : [speed,speed]; - var a=[ - Math.abs(mCSB_container[0].offsetTop)-(distance[0]*_m((absDistance[0]/speed[0]),speed[0])), - Math.abs(mCSB_container[0].offsetLeft)-(distance[1]*_m((absDistance[1]/speed[1]),speed[1])) - ]; - amount=o.axis==="yx" ? [a[0],a[1]] : o.axis==="x" ? [null,a[1]] : [a[0],null]; - durB=[(absDistance[0]*4)+o.scrollInertia,(absDistance[1]*4)+o.scrollInertia]; - var md=parseInt(o.contentTouchScroll) || 0; /* absolute minimum distance required */ - amount[0]=absDistance[0]>md ? amount[0] : 0; - amount[1]=absDistance[1]>md ? amount[1] : 0; - if(d.overflowed[0]){_drag(amount[0],durB[0],easing,"y",overwrite,false);} - if(d.overflowed[1]){_drag(amount[1],durB[1],easing,"x",overwrite,false);} - } - function _m(ds,s){ - var r=[s*1.5,s*2,s/1.5,s/2]; - if(ds>90){ - return s>4 ? r[0] : r[3]; - }else if(ds>60){ - return s>3 ? r[3] : r[2]; - }else if(ds>30){ - return s>8 ? r[1] : s>6 ? r[0] : s>4 ? s : r[2]; - }else{ - return s>8 ? s : r[3]; - } - } - function _drag(amount,dur,easing,dir,overwrite,drag){ - if(!amount){return;} - _scrollTo($this,amount.toString(),{dur:dur,scrollEasing:easing,dir:dir,overwrite:overwrite,drag:drag}); - } - }, - /* -------------------- */ - - - /* - SELECT TEXT EVENTS - scrolls content when text is selected - */ - _selectable=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential, - namespace=pluginPfx+"_"+d.idx, - mCSB_container=$("#mCSB_"+d.idx+"_container"), - wrapper=mCSB_container.parent(), - action; - mCSB_container.bind("mousedown."+namespace,function(e){ - if(touchable){return;} - if(!action){action=1; touchActive=true;} - }).add(document).bind("mousemove."+namespace,function(e){ - if(!touchable && action && _sel()){ - var offset=mCSB_container.offset(), - y=_coordinates(e)[0]-offset.top+mCSB_container[0].offsetTop,x=_coordinates(e)[1]-offset.left+mCSB_container[0].offsetLeft; - if(y>0 && y0 && xwrapper.height()){ - _seq("on",40); - } - } - if(o.axis!=="y" && d.overflowed[1]){ - if(x<0){ - _seq("on",37); - }else if(x>wrapper.width()){ - _seq("on",39); - } - } - } - } - }).bind("mouseup."+namespace+" dragend."+namespace,function(e){ - if(touchable){return;} - if(action){action=0; _seq("off",null);} - touchActive=false; - }); - function _sel(){ - return window.getSelection ? window.getSelection().toString() : - document.selection && document.selection.type!="Control" ? document.selection.createRange().text : 0; - } - function _seq(a,c,s){ - seq.type=s && action ? "stepped" : "stepless"; - seq.scrollAmount=10; - _sequentialScroll($this,a,c,"mcsLinearOut",s ? 60 : null); - } - }, - /* -------------------- */ - - - /* - MOUSE WHEEL EVENT - scrolls content via mouse-wheel - via mouse-wheel plugin (https://github.com/brandonaaron/jquery-mousewheel) - */ - _mousewheel=function(){ - if(!$(this).data(pluginPfx)){return;} /* Check if the scrollbar is ready to use mousewheel events (issue: #185) */ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - namespace=pluginPfx+"_"+d.idx, - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], - iframe=$("#mCSB_"+d.idx+"_container").find("iframe"); - if(iframe.length){ - iframe.each(function(){ - $(this).bind("load",function(){ - /* bind events on accessible iframes */ - if(_canAccessIFrame(this)){ - $(this.contentDocument || this.contentWindow.document).bind("mousewheel."+namespace,function(e,delta){ - _onMousewheel(e,delta); - }); - } - }); - }); - } - mCustomScrollBox.bind("mousewheel."+namespace,function(e,delta){ - _onMousewheel(e,delta); - }); - function _onMousewheel(e,delta){ - _stop($this); - if(_disableMousewheel($this,e.target)){return;} /* disables mouse-wheel when hovering specific elements */ - var deltaFactor=o.mouseWheel.deltaFactor!=="auto" ? parseInt(o.mouseWheel.deltaFactor) : (oldIE && e.deltaFactor<100) ? 100 : e.deltaFactor || 100, - dur=o.scrollInertia; - if(o.axis==="x" || o.mouseWheel.axis==="x"){ - var dir="x", - px=[Math.round(deltaFactor*d.scrollRatio.x),parseInt(o.mouseWheel.scrollAmount)], - amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.width() ? mCustomScrollBox.width()*0.9 : px[0], - contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetLeft), - draggerPos=mCSB_dragger[1][0].offsetLeft, - limit=mCSB_dragger[1].parent().width()-mCSB_dragger[1].width(), - dlt=o.mouseWheel.axis==="y" ? (e.deltaY || delta) : e.deltaX; - }else{ - var dir="y", - px=[Math.round(deltaFactor*d.scrollRatio.y),parseInt(o.mouseWheel.scrollAmount)], - amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.height() ? mCustomScrollBox.height()*0.9 : px[0], - contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetTop), - draggerPos=mCSB_dragger[0][0].offsetTop, - limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(), - dlt=e.deltaY || delta; - } - if((dir==="y" && !d.overflowed[0]) || (dir==="x" && !d.overflowed[1])){return;} - if(o.mouseWheel.invert || e.webkitDirectionInvertedFromDevice){dlt=-dlt;} - if(o.mouseWheel.normalizeDelta){dlt=dlt<0 ? -1 : 1;} - if((dlt>0 && draggerPos!==0) || (dlt<0 && draggerPos!==limit) || o.mouseWheel.preventDefault){ - e.stopImmediatePropagation(); - e.preventDefault(); - } - if(e.deltaFactor<5 && !o.mouseWheel.normalizeDelta){ - //very low deltaFactor values mean some kind of delta acceleration (e.g. osx trackpad), so adjusting scrolling accordingly - amount=e.deltaFactor; dur=17; - } - _scrollTo($this,(contentPos-(dlt*amount)).toString(),{dir:dir,dur:dur}); - } - }, - /* -------------------- */ - - - /* checks if iframe can be accessed */ - _canAccessIFrameCache=new Object(), - _canAccessIFrame=function(iframe){ - var result=false,cacheKey=false,html=null; - if(iframe===undefined){ - cacheKey="#empty"; - }else if($(iframe).attr("id")!==undefined){ - cacheKey=$(iframe).attr("id"); - } - if(cacheKey!==false && _canAccessIFrameCache[cacheKey]!==undefined){ - return _canAccessIFrameCache[cacheKey]; - } - if(!iframe){ - try{ - var doc=top.document; - html=doc.body.innerHTML; - }catch(err){/* do nothing */} - result=(html!==null); - }else{ - try{ - var doc=iframe.contentDocument || iframe.contentWindow.document; - html=doc.body.innerHTML; - }catch(err){/* do nothing */} - result=(html!==null); - } - if(cacheKey!==false){_canAccessIFrameCache[cacheKey]=result;} - return result; - }, - /* -------------------- */ - - - /* switches iframe's pointer-events property (drag, mousewheel etc. over cross-domain iframes) */ - _iframe=function(evt){ - var el=this.find("iframe"); - if(!el.length){return;} /* check if content contains iframes */ - var val=!evt ? "none" : "auto"; - el.css("pointer-events",val); /* for IE11, iframe's display property should not be "block" */ - }, - /* -------------------- */ - - - /* disables mouse-wheel when hovering specific elements like select, datalist etc. */ - _disableMousewheel=function(el,target){ - var tag=target.nodeName.toLowerCase(), - tags=el.data(pluginPfx).opt.mouseWheel.disableOver, - /* elements that require focus */ - focusTags=["select","textarea"]; - return $.inArray(tag,tags) > -1 && !($.inArray(tag,focusTags) > -1 && !$(target).is(":focus")); - }, - /* -------------------- */ - - - /* - DRAGGER RAIL CLICK EVENT - scrolls content via dragger rail - */ - _draggerRail=function(){ - var $this=$(this),d=$this.data(pluginPfx), - namespace=pluginPfx+"_"+d.idx, - mCSB_container=$("#mCSB_"+d.idx+"_container"), - wrapper=mCSB_container.parent(), - mCSB_draggerContainer=$(".mCSB_"+d.idx+"_scrollbar ."+classes[12]), - clickable; - mCSB_draggerContainer.bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){ - touchActive=true; - if(!$(e.target).hasClass("mCSB_dragger")){clickable=1;} - }).bind("touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){ - touchActive=false; - }).bind("click."+namespace,function(e){ - if(!clickable){return;} - clickable=0; - if($(e.target).hasClass(classes[12]) || $(e.target).hasClass("mCSB_draggerRail")){ - _stop($this); - var el=$(this),mCSB_dragger=el.find(".mCSB_dragger"); - if(el.parent(".mCSB_scrollTools_horizontal").length>0){ - if(!d.overflowed[1]){return;} - var dir="x", - clickDir=e.pageX>mCSB_dragger.offset().left ? -1 : 1, - to=Math.abs(mCSB_container[0].offsetLeft)-(clickDir*(wrapper.width()*0.9)); - }else{ - if(!d.overflowed[0]){return;} - var dir="y", - clickDir=e.pageY>mCSB_dragger.offset().top ? -1 : 1, - to=Math.abs(mCSB_container[0].offsetTop)-(clickDir*(wrapper.height()*0.9)); - } - _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); - } - }); - }, - /* -------------------- */ - - - /* - FOCUS EVENT - scrolls content via element focus (e.g. clicking an input, pressing TAB key etc.) - */ - _focus=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - namespace=pluginPfx+"_"+d.idx, - mCSB_container=$("#mCSB_"+d.idx+"_container"), - wrapper=mCSB_container.parent(); - mCSB_container.bind("focusin."+namespace,function(e){ - var el=$(document.activeElement), - nested=mCSB_container.find(".mCustomScrollBox").length, - dur=0; - if(!el.is(o.advanced.autoScrollOnFocus)){return;} - _stop($this); - clearTimeout($this[0]._focusTimeout); - $this[0]._focusTimer=nested ? (dur+17)*nested : 0; - $this[0]._focusTimeout=setTimeout(function(){ - var to=[_childPos(el)[0],_childPos(el)[1]], - contentPos=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft], - isVisible=[ - (contentPos[0]+to[0]>=0 && contentPos[0]+to[0]=0 && contentPos[0]+to[1]a"); - btn.bind("contextmenu."+namespace,function(e){ - e.preventDefault(); //prevent right click - }).bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace+" mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace+" mouseout."+namespace+" pointerout."+namespace+" MSPointerOut."+namespace+" click."+namespace,function(e){ - e.preventDefault(); - if(!_mouseBtnLeft(e)){return;} /* left mouse button only */ - var btnClass=$(this).attr("class"); - seq.type=o.scrollButtons.scrollType; - switch(e.type){ - case "mousedown": case "touchstart": case "pointerdown": case "MSPointerDown": - if(seq.type==="stepped"){return;} - touchActive=true; - d.tweenRunning=false; - _seq("on",btnClass); - break; - case "mouseup": case "touchend": case "pointerup": case "MSPointerUp": - case "mouseout": case "pointerout": case "MSPointerOut": - if(seq.type==="stepped"){return;} - touchActive=false; - if(seq.dir){_seq("off",btnClass);} - break; - case "click": - if(seq.type!=="stepped" || d.tweenRunning){return;} - _seq("on",btnClass); - break; - } - function _seq(a,c){ - seq.scrollAmount=o.scrollButtons.scrollAmount; - _sequentialScroll($this,a,c); - } - }); - }, - /* -------------------- */ - - - /* - KEYBOARD EVENTS - scrolls content via keyboard - Keys: up arrow, down arrow, left arrow, right arrow, PgUp, PgDn, Home, End - */ - _keyboard=function(){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential, - namespace=pluginPfx+"_"+d.idx, - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_container=$("#mCSB_"+d.idx+"_container"), - wrapper=mCSB_container.parent(), - editables="input,textarea,select,datalist,keygen,[contenteditable='true']", - iframe=mCSB_container.find("iframe"), - events=["blur."+namespace+" keydown."+namespace+" keyup."+namespace]; - if(iframe.length){ - iframe.each(function(){ - $(this).bind("load",function(){ - /* bind events on accessible iframes */ - if(_canAccessIFrame(this)){ - $(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){ - _onKeyboard(e); - }); - } - }); - }); - } - mCustomScrollBox.attr("tabindex","0").bind(events[0],function(e){ - _onKeyboard(e); - }); - function _onKeyboard(e){ - switch(e.type){ - case "blur": - if(d.tweenRunning && seq.dir){_seq("off",null);} - break; - case "keydown": case "keyup": - var code=e.keyCode ? e.keyCode : e.which,action="on"; - if((o.axis!=="x" && (code===38 || code===40)) || (o.axis!=="y" && (code===37 || code===39))){ - /* up (38), down (40), left (37), right (39) arrows */ - if(((code===38 || code===40) && !d.overflowed[0]) || ((code===37 || code===39) && !d.overflowed[1])){return;} - if(e.type==="keyup"){action="off";} - if(!$(document.activeElement).is(editables)){ - e.preventDefault(); - e.stopImmediatePropagation(); - _seq(action,code); - } - }else if(code===33 || code===34){ - /* PgUp (33), PgDn (34) */ - if(d.overflowed[0] || d.overflowed[1]){ - e.preventDefault(); - e.stopImmediatePropagation(); - } - if(e.type==="keyup"){ - _stop($this); - var keyboardDir=code===34 ? -1 : 1; - if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){ - var dir="x",to=Math.abs(mCSB_container[0].offsetLeft)-(keyboardDir*(wrapper.width()*0.9)); - }else{ - var dir="y",to=Math.abs(mCSB_container[0].offsetTop)-(keyboardDir*(wrapper.height()*0.9)); - } - _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); - } - }else if(code===35 || code===36){ - /* End (35), Home (36) */ - if(!$(document.activeElement).is(editables)){ - if(d.overflowed[0] || d.overflowed[1]){ - e.preventDefault(); - e.stopImmediatePropagation(); - } - if(e.type==="keyup"){ - if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){ - var dir="x",to=code===35 ? Math.abs(wrapper.width()-mCSB_container.outerWidth(false)) : 0; - }else{ - var dir="y",to=code===35 ? Math.abs(wrapper.height()-mCSB_container.outerHeight(false)) : 0; - } - _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); - } - } - } - break; - } - function _seq(a,c){ - seq.type=o.keyboard.scrollType; - seq.scrollAmount=o.keyboard.scrollAmount; - if(seq.type==="stepped" && d.tweenRunning){return;} - _sequentialScroll($this,a,c); - } - } - }, - /* -------------------- */ - - - /* scrolls content sequentially (used when scrolling via buttons, keyboard arrows etc.) */ - _sequentialScroll=function(el,action,trigger,e,s){ - var d=el.data(pluginPfx),o=d.opt,seq=d.sequential, - mCSB_container=$("#mCSB_"+d.idx+"_container"), - once=seq.type==="stepped" ? true : false, - steplessSpeed=o.scrollInertia < 26 ? 26 : o.scrollInertia, /* 26/1.5=17 */ - steppedSpeed=o.scrollInertia < 1 ? 17 : o.scrollInertia; - switch(action){ - case "on": - seq.dir=[ - (trigger===classes[16] || trigger===classes[15] || trigger===39 || trigger===37 ? "x" : "y"), - (trigger===classes[13] || trigger===classes[15] || trigger===38 || trigger===37 ? -1 : 1) - ]; - _stop(el); - if(_isNumeric(trigger) && seq.type==="stepped"){return;} - _on(once); - break; - case "off": - _off(); - if(once || (d.tweenRunning && seq.dir)){ - _on(true); - } - break; - } - - /* starts sequence */ - function _on(once){ - if(o.snapAmount){seq.scrollAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : seq.dir[0]==="x" ? o.snapAmount[1] : o.snapAmount[0];} /* scrolling snapping */ - var c=seq.type!=="stepped", /* continuous scrolling */ - t=s ? s : !once ? 1000/60 : c ? steplessSpeed/1.5 : steppedSpeed, /* timer */ - m=!once ? 2.5 : c ? 7.5 : 40, /* multiplier */ - contentPos=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)], - ratio=[d.scrollRatio.y>10 ? 10 : d.scrollRatio.y,d.scrollRatio.x>10 ? 10 : d.scrollRatio.x], - amount=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*(ratio[1]*m)) : contentPos[0]+(seq.dir[1]*(ratio[0]*m)), - px=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*parseInt(seq.scrollAmount)) : contentPos[0]+(seq.dir[1]*parseInt(seq.scrollAmount)), - to=seq.scrollAmount!=="auto" ? px : amount, - easing=e ? e : !once ? "mcsLinear" : c ? "mcsLinearOut" : "mcsEaseInOut", - onComplete=!once ? false : true; - if(once && t<17){ - to=seq.dir[0]==="x" ? contentPos[1] : contentPos[0]; - } - _scrollTo(el,to.toString(),{dir:seq.dir[0],scrollEasing:easing,dur:t,onComplete:onComplete}); - if(once){ - seq.dir=false; - return; - } - clearTimeout(seq.step); - seq.step=setTimeout(function(){ - _on(); - },t); - } - /* stops sequence */ - function _off(){ - clearTimeout(seq.step); - _delete(seq,"step"); - _stop(el); - } - }, - /* -------------------- */ - - - /* returns a yx array from value */ - _arr=function(val){ - var o=$(this).data(pluginPfx).opt,vals=[]; - if(typeof val==="function"){val=val();} /* check if the value is a single anonymous function */ - /* check if value is object or array, its length and create an array with yx values */ - if(!(val instanceof Array)){ /* object value (e.g. {y:"100",x:"100"}, 100 etc.) */ - vals[0]=val.y ? val.y : val.x || o.axis==="x" ? null : val; - vals[1]=val.x ? val.x : val.y || o.axis==="y" ? null : val; - }else{ /* array value (e.g. [100,100]) */ - vals=val.length>1 ? [val[0],val[1]] : o.axis==="x" ? [null,val[0]] : [val[0],null]; - } - /* check if array values are anonymous functions */ - if(typeof vals[0]==="function"){vals[0]=vals[0]();} - if(typeof vals[1]==="function"){vals[1]=vals[1]();} - return vals; - }, - /* -------------------- */ - - - /* translates values (e.g. "top", 100, "100px", "#id") to actual scroll-to positions */ - _to=function(val,dir){ - if(val==null || typeof val=="undefined"){return;} - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - mCSB_container=$("#mCSB_"+d.idx+"_container"), - wrapper=mCSB_container.parent(), - t=typeof val; - if(!dir){dir=o.axis==="x" ? "x" : "y";} - var contentLength=dir==="x" ? mCSB_container.outerWidth(false)-wrapper.width() : mCSB_container.outerHeight(false)-wrapper.height(), - contentPos=dir==="x" ? mCSB_container[0].offsetLeft : mCSB_container[0].offsetTop, - cssProp=dir==="x" ? "left" : "top"; - switch(t){ - case "function": /* this currently is not used. Consider removing it */ - return val(); - break; - case "object": /* js/jquery object */ - var obj=val.jquery ? val : $(val); - if(!obj.length){return;} - return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0]; - break; - case "string": case "number": - if(_isNumeric(val)){ /* numeric value */ - return Math.abs(val); - }else if(val.indexOf("%")!==-1){ /* percentage value */ - return Math.abs(contentLength*parseInt(val)/100); - }else if(val.indexOf("-=")!==-1){ /* decrease value */ - return Math.abs(contentPos-parseInt(val.split("-=")[1])); - }else if(val.indexOf("+=")!==-1){ /* inrease value */ - var p=(contentPos+parseInt(val.split("+=")[1])); - return p>=0 ? 0 : Math.abs(p); - }else if(val.indexOf("px")!==-1 && _isNumeric(val.split("px")[0])){ /* pixels string value (e.g. "100px") */ - return Math.abs(val.split("px")[0]); - }else{ - if(val==="top" || val==="left"){ /* special strings */ - return 0; - }else if(val==="bottom"){ - return Math.abs(wrapper.height()-mCSB_container.outerHeight(false)); - }else if(val==="right"){ - return Math.abs(wrapper.width()-mCSB_container.outerWidth(false)); - }else if(val==="first" || val==="last"){ - var obj=mCSB_container.find(":"+val); - return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0]; - }else{ - if($(val).length){ /* jquery selector */ - return dir==="x" ? _childPos($(val))[1] : _childPos($(val))[0]; - }else{ /* other values (e.g. "100em") */ - mCSB_container.css(cssProp,val); - methods.update.call(null,$this[0]); - return; - } - } - } - break; - } - }, - /* -------------------- */ - - - /* calls the update method automatically */ - _autoUpdate=function(rem){ - var $this=$(this),d=$this.data(pluginPfx),o=d.opt, - mCSB_container=$("#mCSB_"+d.idx+"_container"); - if(rem){ - /* - removes autoUpdate timer - usage: _autoUpdate.call(this,"remove"); - */ - clearTimeout(mCSB_container[0].autoUpdate); - _delete(mCSB_container[0],"autoUpdate"); - return; - } - upd(); - function upd(){ - clearTimeout(mCSB_container[0].autoUpdate); - if($this.parents("html").length===0){ - /* check element in dom tree */ - $this=null; - return; - } - mCSB_container[0].autoUpdate=setTimeout(function(){ - /* update on specific selector(s) length and size change */ - if(o.advanced.updateOnSelectorChange){ - d.poll.change.n=sizesSum(); - if(d.poll.change.n!==d.poll.change.o){ - d.poll.change.o=d.poll.change.n; - doUpd(3); - return; - } - } - /* update on main element and scrollbar size changes */ - if(o.advanced.updateOnContentResize){ - d.poll.size.n=$this[0].scrollHeight+$this[0].scrollWidth+mCSB_container[0].offsetHeight+$this[0].offsetHeight+$this[0].offsetWidth; - if(d.poll.size.n!==d.poll.size.o){ - d.poll.size.o=d.poll.size.n; - doUpd(1); - return; - } - } - /* update on image load */ - if(o.advanced.updateOnImageLoad){ - if(!(o.advanced.updateOnImageLoad==="auto" && o.axis==="y")){ //by default, it doesn't run on vertical content - d.poll.img.n=mCSB_container.find("img").length; - if(d.poll.img.n!==d.poll.img.o){ - d.poll.img.o=d.poll.img.n; - mCSB_container.find("img").each(function(){ - imgLoader(this); - }); - return; - } - } - } - if(o.advanced.updateOnSelectorChange || o.advanced.updateOnContentResize || o.advanced.updateOnImageLoad){upd();} - },o.advanced.autoUpdateTimeout); - } - /* a tiny image loader */ - function imgLoader(el){ - if($(el).hasClass(classes[2])){doUpd(); return;} - var img=new Image(); - function createDelegate(contextObject,delegateMethod){ - return function(){return delegateMethod.apply(contextObject,arguments);} - } - function imgOnLoad(){ - this.onload=null; - $(el).addClass(classes[2]); - doUpd(2); - } - img.onload=createDelegate(img,imgOnLoad); - img.src=el.src; - } - /* returns the total height and width sum of all elements matching the selector */ - function sizesSum(){ - if(o.advanced.updateOnSelectorChange===true){o.advanced.updateOnSelectorChange="*";} - var total=0,sel=mCSB_container.find(o.advanced.updateOnSelectorChange); - if(o.advanced.updateOnSelectorChange && sel.length>0){sel.each(function(){total+=this.offsetHeight+this.offsetWidth;});} - return total; - } - /* calls the update method */ - function doUpd(cb){ - clearTimeout(mCSB_container[0].autoUpdate); - methods.update.call(null,$this[0],cb); - } - }, - /* -------------------- */ - - - /* snaps scrolling to a multiple of a pixels number */ - _snapAmount=function(to,amount,offset){ - return (Math.round(to/amount)*amount-offset); - }, - /* -------------------- */ - - - /* stops content and scrollbar animations */ - _stop=function(el){ - var d=el.data(pluginPfx), - sel=$("#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal"); - sel.each(function(){ - _stopTween.call(this); - }); - }, - /* -------------------- */ - - - /* - ANIMATES CONTENT - This is where the actual scrolling happens - */ - _scrollTo=function(el,to,options){ - var d=el.data(pluginPfx),o=d.opt, - defaults={ - trigger:"internal", - dir:"y", - scrollEasing:"mcsEaseOut", - drag:false, - dur:o.scrollInertia, - overwrite:"all", - callbacks:true, - onStart:true, - onUpdate:true, - onComplete:true - }, - options=$.extend(defaults,options), - dur=[options.dur,(options.drag ? 0 : options.dur)], - mCustomScrollBox=$("#mCSB_"+d.idx), - mCSB_container=$("#mCSB_"+d.idx+"_container"), - wrapper=mCSB_container.parent(), - totalScrollOffsets=o.callbacks.onTotalScrollOffset ? _arr.call(el,o.callbacks.onTotalScrollOffset) : [0,0], - totalScrollBackOffsets=o.callbacks.onTotalScrollBackOffset ? _arr.call(el,o.callbacks.onTotalScrollBackOffset) : [0,0]; - d.trigger=options.trigger; - if(wrapper.scrollTop()!==0 || wrapper.scrollLeft()!==0){ /* always reset scrollTop/Left */ - $(".mCSB_"+d.idx+"_scrollbar").css("visibility","visible"); - wrapper.scrollTop(0).scrollLeft(0); - } - if(to==="_resetY" && !d.contentReset.y){ - /* callbacks: onOverflowYNone */ - if(_cb("onOverflowYNone")){o.callbacks.onOverflowYNone.call(el[0]);} - d.contentReset.y=1; - } - if(to==="_resetX" && !d.contentReset.x){ - /* callbacks: onOverflowXNone */ - if(_cb("onOverflowXNone")){o.callbacks.onOverflowXNone.call(el[0]);} - d.contentReset.x=1; - } - if(to==="_resetY" || to==="_resetX"){return;} - if((d.contentReset.y || !el[0].mcs) && d.overflowed[0]){ - /* callbacks: onOverflowY */ - if(_cb("onOverflowY")){o.callbacks.onOverflowY.call(el[0]);} - d.contentReset.x=null; - } - if((d.contentReset.x || !el[0].mcs) && d.overflowed[1]){ - /* callbacks: onOverflowX */ - if(_cb("onOverflowX")){o.callbacks.onOverflowX.call(el[0]);} - d.contentReset.x=null; - } - if(o.snapAmount){ /* scrolling snapping */ - var snapAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : options.dir==="x" ? o.snapAmount[1] : o.snapAmount[0]; - to=_snapAmount(to,snapAmount,o.snapOffset); - } - switch(options.dir){ - case "x": - var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_horizontal"), - property="left", - contentPos=mCSB_container[0].offsetLeft, - limit=[ - mCustomScrollBox.width()-mCSB_container.outerWidth(false), - mCSB_dragger.parent().width()-mCSB_dragger.width() - ], - scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.x)], - tso=totalScrollOffsets[1], - tsbo=totalScrollBackOffsets[1], - totalScrollOffset=tso>0 ? tso/d.scrollRatio.x : 0, - totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.x : 0; - break; - case "y": - var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_vertical"), - property="top", - contentPos=mCSB_container[0].offsetTop, - limit=[ - mCustomScrollBox.height()-mCSB_container.outerHeight(false), - mCSB_dragger.parent().height()-mCSB_dragger.height() - ], - scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.y)], - tso=totalScrollOffsets[0], - tsbo=totalScrollBackOffsets[0], - totalScrollOffset=tso>0 ? tso/d.scrollRatio.y : 0, - totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.y : 0; - break; - } - if(scrollTo[1]<0 || (scrollTo[0]===0 && scrollTo[1]===0)){ - scrollTo=[0,0]; - }else if(scrollTo[1]>=limit[1]){ - scrollTo=[limit[0],limit[1]]; - }else{ - scrollTo[0]=-scrollTo[0]; - } - if(!el[0].mcs){ - _mcs(); /* init mcs object (once) to make it available before callbacks */ - if(_cb("onInit")){o.callbacks.onInit.call(el[0]);} /* callbacks: onInit */ - } - clearTimeout(mCSB_container[0].onCompleteTimeout); - _tweenTo(mCSB_dragger[0],property,Math.round(scrollTo[1]),dur[1],options.scrollEasing); - if(!d.tweenRunning && ((contentPos===0 && scrollTo[0]>=0) || (contentPos===limit[0] && scrollTo[0]<=limit[0]))){return;} - _tweenTo(mCSB_container[0],property,Math.round(scrollTo[0]),dur[0],options.scrollEasing,options.overwrite,{ - onStart:function(){ - if(options.callbacks && options.onStart && !d.tweenRunning){ - /* callbacks: onScrollStart */ - if(_cb("onScrollStart")){_mcs(); o.callbacks.onScrollStart.call(el[0]);} - d.tweenRunning=true; - _onDragClasses(mCSB_dragger); - d.cbOffsets=_cbOffsets(); - } - },onUpdate:function(){ - if(options.callbacks && options.onUpdate){ - /* callbacks: whileScrolling */ - if(_cb("whileScrolling")){_mcs(); o.callbacks.whileScrolling.call(el[0]);} - } - },onComplete:function(){ - if(options.callbacks && options.onComplete){ - if(o.axis==="yx"){clearTimeout(mCSB_container[0].onCompleteTimeout);} - var t=mCSB_container[0].idleTimer || 0; - mCSB_container[0].onCompleteTimeout=setTimeout(function(){ - /* callbacks: onScroll, onTotalScroll, onTotalScrollBack */ - if(_cb("onScroll")){_mcs(); o.callbacks.onScroll.call(el[0]);} - if(_cb("onTotalScroll") && scrollTo[1]>=limit[1]-totalScrollOffset && d.cbOffsets[0]){_mcs(); o.callbacks.onTotalScroll.call(el[0]);} - if(_cb("onTotalScrollBack") && scrollTo[1]<=totalScrollBackOffset && d.cbOffsets[1]){_mcs(); o.callbacks.onTotalScrollBack.call(el[0]);} - d.tweenRunning=false; - mCSB_container[0].idleTimer=0; - _onDragClasses(mCSB_dragger,"hide"); - },t); - } - } - }); - /* checks if callback function exists */ - function _cb(cb){ - return d && o.callbacks[cb] && typeof o.callbacks[cb]==="function"; - } - /* checks whether callback offsets always trigger */ - function _cbOffsets(){ - return [o.callbacks.alwaysTriggerOffsets || contentPos>=limit[0]+tso,o.callbacks.alwaysTriggerOffsets || contentPos<=-tsbo]; - } - /* - populates object with useful values for the user - values: - content: this.mcs.content - content top position: this.mcs.top - content left position: this.mcs.left - dragger top position: this.mcs.draggerTop - dragger left position: this.mcs.draggerLeft - scrolling y percentage: this.mcs.topPct - scrolling x percentage: this.mcs.leftPct - scrolling direction: this.mcs.direction - */ - function _mcs(){ - var cp=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft], /* content position */ - dp=[mCSB_dragger[0].offsetTop,mCSB_dragger[0].offsetLeft], /* dragger position */ - cl=[mCSB_container.outerHeight(false),mCSB_container.outerWidth(false)], /* content length */ - pl=[mCustomScrollBox.height(),mCustomScrollBox.width()]; /* content parent length */ - el[0].mcs={ - content:mCSB_container, /* original content wrapper as jquery object */ - top:cp[0],left:cp[1],draggerTop:dp[0],draggerLeft:dp[1], - topPct:Math.round((100*Math.abs(cp[0]))/(Math.abs(cl[0])-pl[0])),leftPct:Math.round((100*Math.abs(cp[1]))/(Math.abs(cl[1])-pl[1])), - direction:options.dir - }; - /* - this refers to the original element containing the scrollbar(s) - usage: this.mcs.top, this.mcs.leftPct etc. - */ - } - }, - /* -------------------- */ - - - /* - CUSTOM JAVASCRIPT ANIMATION TWEEN - Lighter and faster than jquery animate() and css transitions - Animates top/left properties and includes easings - */ - _tweenTo=function(el,prop,to,duration,easing,overwrite,callbacks){ - if(!el._mTween){el._mTween={top:{},left:{}};} - var callbacks=callbacks || {}, - onStart=callbacks.onStart || function(){},onUpdate=callbacks.onUpdate || function(){},onComplete=callbacks.onComplete || function(){}, - startTime=_getTime(),_delay,progress=0,from=el.offsetTop,elStyle=el.style,_request,tobj=el._mTween[prop]; - if(prop==="left"){from=el.offsetLeft;} - var diff=to-from; - tobj.stop=0; - if(overwrite!=="none"){_cancelTween();} - _startTween(); - function _step(){ - if(tobj.stop){return;} - if(!progress){onStart.call();} - progress=_getTime()-startTime; - _tween(); - if(progress>=tobj.time){ - tobj.time=(progress>tobj.time) ? progress+_delay-(progress-tobj.time) : progress+_delay-1; - if(tobj.time0){ - tobj.currVal=_ease(tobj.time,from,diff,duration,easing); - elStyle[prop]=Math.round(tobj.currVal)+"px"; - }else{ - elStyle[prop]=to+"px"; - } - onUpdate.call(); - } - function _startTween(){ - _delay=1000/60; - tobj.time=progress+_delay; - _request=(!window.requestAnimationFrame) ? function(f){_tween(); return setTimeout(f,0.01);} : window.requestAnimationFrame; - tobj.id=_request(_step); - } - function _cancelTween(){ - if(tobj.id==null){return;} - if(!window.requestAnimationFrame){clearTimeout(tobj.id); - }else{window.cancelAnimationFrame(tobj.id);} - tobj.id=null; - } - function _ease(t,b,c,d,type){ - switch(type){ - case "linear": case "mcsLinear": - return c*t/d + b; - break; - case "mcsLinearOut": - t/=d; t--; return c * Math.sqrt(1 - t*t) + b; - break; - case "easeInOutSmooth": - t/=d/2; - if(t<1) return c/2*t*t + b; - t--; - return -c/2 * (t*(t-2) - 1) + b; - break; - case "easeInOutStrong": - t/=d/2; - if(t<1) return c/2 * Math.pow( 2, 10 * (t - 1) ) + b; - t--; - return c/2 * ( -Math.pow( 2, -10 * t) + 2 ) + b; - break; - case "easeInOut": case "mcsEaseInOut": - t/=d/2; - if(t<1) return c/2*t*t*t + b; - t-=2; - return c/2*(t*t*t + 2) + b; - break; - case "easeOutSmooth": - t/=d; t--; - return -c * (t*t*t*t - 1) + b; - break; - case "easeOutStrong": - return c * ( -Math.pow( 2, -10 * t/d ) + 1 ) + b; - break; - case "easeOut": case "mcsEaseOut": default: - var ts=(t/=d)*t,tc=ts*t; - return b+c*(0.499999999999997*tc*ts + -2.5*ts*ts + 5.5*tc + -6.5*ts + 4*t); - } - } - }, - /* -------------------- */ - - - /* returns current time */ - _getTime=function(){ - if(window.performance && window.performance.now){ - return window.performance.now(); - }else{ - if(window.performance && window.performance.webkitNow){ - return window.performance.webkitNow(); - }else{ - if(Date.now){return Date.now();}else{return new Date().getTime();} - } - } - }, - /* -------------------- */ - - - /* stops a tween */ - _stopTween=function(){ - var el=this; - if(!el._mTween){el._mTween={top:{},left:{}};} - var props=["top","left"]; - for(var i=0; i

    Based on Bootstrap Popovers.

    + + +

    Example

    + +
    +
    + + + Popover Default + + + Popover With Title + + + Dismissible Popover + + + Disabled Popover + + + Disabled Popover + +
    +
    + + +
    
    +<abp-button abp-popover="Hi, i'm popover content!">
    +       Popover Default
    +</abp-button>
    +<abp-button abp-popover-top="Hi, i'm popover content!" title="Popover Title">
    +       Popover With Title
    +</abp-button>
    +<abp-button abp-popover-right="Hi, i'm popover content!" title="Popover Title" dismissible="true">
    +       Dismissible Popover
    +</abp-button>
    +<abp-button abp-popover-left="Hi, i'm popover content!" title="Popover Title" disabled="true">
    +       Disabled Popover
    +</abp-button>
    +
    +
    + +
    
    +<button class="btn" type="button" data-busy-text="Processing..." data-toggle="popover" data-placement="bottom" data-content="Hi, i'm popover content!" data-original-title="" title="">
    +      Popover Default
    +</button>
    +<button title="" class="btn" type="button" data-busy-text="Processing..." data-toggle="popover" data-placement="top" data-content="Hi, i'm popover content!" data-original-title="Popover Title">
    +      Popover With Title
    +</button>
    +<button title="" class="btn" type="button" data-busy-text="Processing..." data-toggle="popover" data-placement="right" data-content="Hi, i'm popover content!" data-trigger="focus" data-original-title="Popover Title">
    +      Dismissible Popover
    +</button>
    +<span class="d-inline-block" title="" data-placement="left" data-toggle="popover" data-content="Hi, i'm popover content!" data-original-title="Popover Title"><button title="Popover Title" class="btn" type="button" data-busy-text="Processing..." style="pointer-events: none;">
    +      Disabled Popover
    +</button></span>
    +
    +
    +
    +
    +
    diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml.cs similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml.cs rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml.cs diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml.cs similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml.cs rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml.cs diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml.cs similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml.cs rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml.cs diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml.cs similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml.cs rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml.cs diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml.cs similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml.cs rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml.cs diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/highlightCode.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/highlightCode.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/highlightCode.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/highlightCode.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Index.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Index.cshtml similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Index.cshtml rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Index.cshtml diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Index.cshtml.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Index.cshtml.cs similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Index.cshtml.cs rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Index.cshtml.cs diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_Layout.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_Layout.cshtml similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_Layout.cshtml rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_Layout.cshtml diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_ViewImports.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_ViewImports.cshtml similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_ViewImports.cshtml rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_ViewImports.cshtml diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_ViewStart.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_ViewStart.cshtml similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_ViewStart.cshtml rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/_ViewStart.cshtml diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Program.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Program.cs similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Program.cs rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Program.cs diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Properties/launchSettings.json b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Properties/launchSettings.json similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Properties/launchSettings.json rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Properties/launchSettings.json diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Startup.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Startup.cs similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Startup.cs rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Startup.cs diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj new file mode 100644 index 0000000000..0574bb89c8 --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj @@ -0,0 +1,21 @@ + + + + + + net5.0 + true + + + + + + + + + + + + + + diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/abp.resourcemapping.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/abp.resourcemapping.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/abp.resourcemapping.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/abp.resourcemapping.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/compilerconfig.json b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/compilerconfig.json similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/compilerconfig.json rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/compilerconfig.json diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/compilerconfig.json.defaults b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/compilerconfig.json.defaults similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/compilerconfig.json.defaults rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/compilerconfig.json.defaults diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/docker-compose.yml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/docker-compose.yml similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/docker-compose.yml rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/docker-compose.yml diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/gulpfile.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/gulpfile.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/gulpfile.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/gulpfile.js diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json new file mode 100644 index 0000000000..da243d78d3 --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json @@ -0,0 +1,10 @@ +{ + "version": "1.0.0", + "name": "asp.net", + "private": true, + "dependencies": { + "@abp/aspnetcore.mvc.ui.theme.shared": "^4.3.2", + "highlight.js": "^9.13.1" + }, + "devDependencies": {} +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/publish-ignore.json b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/publish-ignore.json similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/publish-ignore.json rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/publish-ignore.json diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/css/demo.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/css/demo.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/css/demo.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/css/demo.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/css/demo.min.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/css/demo.min.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/css/demo.min.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/css/demo.min.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/css/demo.scss b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/css/demo.scss similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/css/demo.scss rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/css/demo.scss diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/imgs/demo/300x200.png b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/imgs/demo/300x200.png similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/imgs/demo/300x200.png rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/imgs/demo/300x200.png diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/all.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/all.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/all.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/all.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/v4-shims.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/v4-shims.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/v4-shims.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/v4-shims.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.eot b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.eot similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.eot rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.eot diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.svg b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.svg similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.svg rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.svg diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff2 b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff2 similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff2 rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff2 diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.svg b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.svg similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.svg rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.svg diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.ttf b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.ttf similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.ttf rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.ttf diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2 b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2 similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2 rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2 diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.svg b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.svg similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.svg rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.svg diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.ttf b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.ttf similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.ttf rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.ttf diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2 b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2 similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2 rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2 diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/jquery/abp.jquery.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/jquery/abp.jquery.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/jquery/abp.jquery.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/jquery/abp.jquery.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/luxon/abp.luxon.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/luxon/abp.luxon.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/luxon/abp.luxon.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/luxon/abp.luxon.js diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js new file mode 100644 index 0000000000..28ebcc3765 --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js @@ -0,0 +1,694 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('just-compare')) : + typeof define === 'function' && define.amd ? define('@abp/utils', ['exports', 'just-compare'], factory) : + (global = global || self, factory((global.abp = global.abp || {}, global.abp.utils = global.abp.utils || {}, global.abp.utils.common = {}), global.compare)); +}(this, (function (exports, compare) { 'use strict'; + + compare = compare && Object.prototype.hasOwnProperty.call(compare, 'default') ? compare['default'] : compare; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + ***************************************************************************** */ + /* global Reflect, Promise */ + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) + if (b.hasOwnProperty(p)) + d[p] = b[p]; }; + return extendStatics(d, b); + }; + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + var __assign = function () { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + function __rest(s, e) { + var t = {}; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; + } + function __decorate(decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") + r = Reflect.decorate(decorators, target, key, desc); + else + for (var i = decorators.length - 1; i >= 0; i--) + if (d = decorators[i]) + r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; + } + function __param(paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); }; + } + function __metadata(metadataKey, metadataValue) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") + return Reflect.metadata(metadataKey, metadataValue); + } + function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { + step(generator.next(value)); + } + catch (e) { + reject(e); + } } + function rejected(value) { try { + step(generator["throw"](value)); + } + catch (e) { + reject(e); + } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + } + function __generator(thisArg, body) { + var _ = { label: 0, sent: function () { if (t[0] & 1) + throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) + throw new TypeError("Generator is already executing."); + while (_) + try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) + return t; + if (y = 0, t) + op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: + case 1: + t = op; + break; + case 4: + _.label++; + return { value: op[1], done: false }; + case 5: + _.label++; + y = op[1]; + op = [0]; + continue; + case 7: + op = _.ops.pop(); + _.trys.pop(); + continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { + _ = 0; + continue; + } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { + _.label = op[1]; + break; + } + if (op[0] === 6 && _.label < t[1]) { + _.label = t[1]; + t = op; + break; + } + if (t && _.label < t[2]) { + _.label = t[2]; + _.ops.push(op); + break; + } + if (t[2]) + _.ops.pop(); + _.trys.pop(); + continue; + } + op = body.call(thisArg, _); + } + catch (e) { + op = [6, e]; + y = 0; + } + finally { + f = t = 0; + } + if (op[0] & 5) + throw op[1]; + return { value: op[0] ? op[1] : void 0, done: true }; + } + } + var __createBinding = Object.create ? (function (o, m, k, k2) { + if (k2 === undefined) + k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } }); + }) : (function (o, m, k, k2) { + if (k2 === undefined) + k2 = k; + o[k2] = m[k]; + }); + function __exportStar(m, exports) { + for (var p in m) + if (p !== "default" && !exports.hasOwnProperty(p)) + __createBinding(exports, m, p); + } + function __values(o) { + var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; + if (m) + return m.call(o); + if (o && typeof o.length === "number") + return { + next: function () { + if (o && i >= o.length) + o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); + } + function __read(o, n) { + var m = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m) + return o; + var i = m.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) + ar.push(r.value); + } + catch (error) { + e = { error: error }; + } + finally { + try { + if (r && !r.done && (m = i["return"])) + m.call(i); + } + finally { + if (e) + throw e.error; + } + } + return ar; + } + function __spread() { + for (var ar = [], i = 0; i < arguments.length; i++) + ar = ar.concat(__read(arguments[i])); + return ar; + } + function __spreadArrays() { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) + s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; + } + ; + function __await(v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); + } + function __asyncGenerator(thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) + throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; + function verb(n) { if (g[n]) + i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + function resume(n, v) { try { + step(g[n](v)); + } + catch (e) { + settle(q[0][3], e); + } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) + resume(q[0][0], q[0][1]); } + } + function __asyncDelegator(o) { + var i, p; + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; } + } + function __asyncValues(o) { + if (!Symbol.asyncIterator) + throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); } + } + function __makeTemplateObject(cooked, raw) { + if (Object.defineProperty) { + Object.defineProperty(cooked, "raw", { value: raw }); + } + else { + cooked.raw = raw; + } + return cooked; + } + ; + var __setModuleDefault = Object.create ? (function (o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + }) : function (o, v) { + o["default"] = v; + }; + function __importStar(mod) { + if (mod && mod.__esModule) + return mod; + var result = {}; + if (mod != null) + for (var k in mod) + if (Object.hasOwnProperty.call(mod, k)) + __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; + } + function __importDefault(mod) { + return (mod && mod.__esModule) ? mod : { default: mod }; + } + function __classPrivateFieldGet(receiver, privateMap) { + if (!privateMap.has(receiver)) { + throw new TypeError("attempted to get private field on non-instance"); + } + return privateMap.get(receiver); + } + function __classPrivateFieldSet(receiver, privateMap, value) { + if (!privateMap.has(receiver)) { + throw new TypeError("attempted to set private field on non-instance"); + } + privateMap.set(receiver, value); + return value; + } + + var ListNode = /** @class */ (function () { + function ListNode(value) { + this.value = value; + } + return ListNode; + }()); + var LinkedList = /** @class */ (function () { + function LinkedList() { + this.size = 0; + } + Object.defineProperty(LinkedList.prototype, "head", { + get: function () { + return this.first; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(LinkedList.prototype, "tail", { + get: function () { + return this.last; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(LinkedList.prototype, "length", { + get: function () { + return this.size; + }, + enumerable: false, + configurable: true + }); + LinkedList.prototype.attach = function (value, previousNode, nextNode) { + if (!previousNode) + return this.addHead(value); + if (!nextNode) + return this.addTail(value); + var node = new ListNode(value); + node.previous = previousNode; + previousNode.next = node; + node.next = nextNode; + nextNode.previous = node; + this.size++; + return node; + }; + LinkedList.prototype.attachMany = function (values, previousNode, nextNode) { + if (!values.length) + return []; + if (!previousNode) + return this.addManyHead(values); + if (!nextNode) + return this.addManyTail(values); + var list = new LinkedList(); + list.addManyTail(values); + list.first.previous = previousNode; + previousNode.next = list.first; + list.last.next = nextNode; + nextNode.previous = list.last; + this.size += values.length; + return list.toNodeArray(); + }; + LinkedList.prototype.detach = function (node) { + if (!node.previous) + return this.dropHead(); + if (!node.next) + return this.dropTail(); + node.previous.next = node.next; + node.next.previous = node.previous; + this.size--; + return node; + }; + LinkedList.prototype.add = function (value) { + var _this = this; + return { + after: function () { + var _a; + var params = []; + for (var _i = 0; _i < arguments.length; _i++) { + params[_i] = arguments[_i]; + } + return (_a = _this.addAfter).call.apply(_a, __spread([_this, value], params)); + }, + before: function () { + var _a; + var params = []; + for (var _i = 0; _i < arguments.length; _i++) { + params[_i] = arguments[_i]; + } + return (_a = _this.addBefore).call.apply(_a, __spread([_this, value], params)); + }, + byIndex: function (position) { return _this.addByIndex(value, position); }, + head: function () { return _this.addHead(value); }, + tail: function () { return _this.addTail(value); }, + }; + }; + LinkedList.prototype.addMany = function (values) { + var _this = this; + return { + after: function () { + var _a; + var params = []; + for (var _i = 0; _i < arguments.length; _i++) { + params[_i] = arguments[_i]; + } + return (_a = _this.addManyAfter).call.apply(_a, __spread([_this, values], params)); + }, + before: function () { + var _a; + var params = []; + for (var _i = 0; _i < arguments.length; _i++) { + params[_i] = arguments[_i]; + } + return (_a = _this.addManyBefore).call.apply(_a, __spread([_this, values], params)); + }, + byIndex: function (position) { return _this.addManyByIndex(values, position); }, + head: function () { return _this.addManyHead(values); }, + tail: function () { return _this.addManyTail(values); }, + }; + }; + LinkedList.prototype.addAfter = function (value, previousValue, compareFn) { + if (compareFn === void 0) { compareFn = compare; } + var previous = this.find(function (node) { return compareFn(node.value, previousValue); }); + return previous ? this.attach(value, previous, previous.next) : this.addTail(value); + }; + LinkedList.prototype.addBefore = function (value, nextValue, compareFn) { + if (compareFn === void 0) { compareFn = compare; } + var next = this.find(function (node) { return compareFn(node.value, nextValue); }); + return next ? this.attach(value, next.previous, next) : this.addHead(value); + }; + LinkedList.prototype.addByIndex = function (value, position) { + if (position < 0) + position += this.size; + else if (position >= this.size) + return this.addTail(value); + if (position <= 0) + return this.addHead(value); + var next = this.get(position); + return this.attach(value, next.previous, next); + }; + LinkedList.prototype.addHead = function (value) { + var node = new ListNode(value); + node.next = this.first; + if (this.first) + this.first.previous = node; + else + this.last = node; + this.first = node; + this.size++; + return node; + }; + LinkedList.prototype.addTail = function (value) { + var node = new ListNode(value); + if (this.first) { + node.previous = this.last; + this.last.next = node; + this.last = node; + } + else { + this.first = node; + this.last = node; + } + this.size++; + return node; + }; + LinkedList.prototype.addManyAfter = function (values, previousValue, compareFn) { + if (compareFn === void 0) { compareFn = compare; } + var previous = this.find(function (node) { return compareFn(node.value, previousValue); }); + return previous ? this.attachMany(values, previous, previous.next) : this.addManyTail(values); + }; + LinkedList.prototype.addManyBefore = function (values, nextValue, compareFn) { + if (compareFn === void 0) { compareFn = compare; } + var next = this.find(function (node) { return compareFn(node.value, nextValue); }); + return next ? this.attachMany(values, next.previous, next) : this.addManyHead(values); + }; + LinkedList.prototype.addManyByIndex = function (values, position) { + if (position < 0) + position += this.size; + if (position <= 0) + return this.addManyHead(values); + if (position >= this.size) + return this.addManyTail(values); + var next = this.get(position); + return this.attachMany(values, next.previous, next); + }; + LinkedList.prototype.addManyHead = function (values) { + var _this = this; + return values.reduceRight(function (nodes, value) { + nodes.unshift(_this.addHead(value)); + return nodes; + }, []); + }; + LinkedList.prototype.addManyTail = function (values) { + var _this = this; + return values.map(function (value) { return _this.addTail(value); }); + }; + LinkedList.prototype.drop = function () { + var _this = this; + return { + byIndex: function (position) { return _this.dropByIndex(position); }, + byValue: function () { + var params = []; + for (var _i = 0; _i < arguments.length; _i++) { + params[_i] = arguments[_i]; + } + return _this.dropByValue.apply(_this, params); + }, + byValueAll: function () { + var params = []; + for (var _i = 0; _i < arguments.length; _i++) { + params[_i] = arguments[_i]; + } + return _this.dropByValueAll.apply(_this, params); + }, + head: function () { return _this.dropHead(); }, + tail: function () { return _this.dropTail(); }, + }; + }; + LinkedList.prototype.dropMany = function (count) { + var _this = this; + return { + byIndex: function (position) { return _this.dropManyByIndex(count, position); }, + head: function () { return _this.dropManyHead(count); }, + tail: function () { return _this.dropManyTail(count); }, + }; + }; + LinkedList.prototype.dropByIndex = function (position) { + if (position < 0) + position += this.size; + var current = this.get(position); + return current ? this.detach(current) : undefined; + }; + LinkedList.prototype.dropByValue = function (value, compareFn) { + if (compareFn === void 0) { compareFn = compare; } + var position = this.findIndex(function (node) { return compareFn(node.value, value); }); + return position < 0 ? undefined : this.dropByIndex(position); + }; + LinkedList.prototype.dropByValueAll = function (value, compareFn) { + if (compareFn === void 0) { compareFn = compare; } + var dropped = []; + for (var current = this.first, position = 0; current; position++, current = current.next) { + if (compareFn(current.value, value)) { + dropped.push(this.dropByIndex(position - dropped.length)); + } + } + return dropped; + }; + LinkedList.prototype.dropHead = function () { + var head = this.first; + if (head) { + this.first = head.next; + if (this.first) + this.first.previous = undefined; + else + this.last = undefined; + this.size--; + return head; + } + return undefined; + }; + LinkedList.prototype.dropTail = function () { + var tail = this.last; + if (tail) { + this.last = tail.previous; + if (this.last) + this.last.next = undefined; + else + this.first = undefined; + this.size--; + return tail; + } + return undefined; + }; + LinkedList.prototype.dropManyByIndex = function (count, position) { + if (count <= 0) + return []; + if (position < 0) + position = Math.max(position + this.size, 0); + else if (position >= this.size) + return []; + count = Math.min(count, this.size - position); + var dropped = []; + while (count--) { + var current = this.get(position); + dropped.push(this.detach(current)); + } + return dropped; + }; + LinkedList.prototype.dropManyHead = function (count) { + if (count <= 0) + return []; + count = Math.min(count, this.size); + var dropped = []; + while (count--) + dropped.unshift(this.dropHead()); + return dropped; + }; + LinkedList.prototype.dropManyTail = function (count) { + if (count <= 0) + return []; + count = Math.min(count, this.size); + var dropped = []; + while (count--) + dropped.push(this.dropTail()); + return dropped; + }; + LinkedList.prototype.find = function (predicate) { + for (var current = this.first, position = 0; current; position++, current = current.next) { + if (predicate(current, position, this)) + return current; + } + return undefined; + }; + LinkedList.prototype.findIndex = function (predicate) { + for (var current = this.first, position = 0; current; position++, current = current.next) { + if (predicate(current, position, this)) + return position; + } + return -1; + }; + LinkedList.prototype.forEach = function (iteratorFn) { + for (var node = this.first, position = 0; node; position++, node = node.next) { + iteratorFn(node, position, this); + } + }; + LinkedList.prototype.get = function (position) { + return this.find(function (_, index) { return position === index; }); + }; + LinkedList.prototype.indexOf = function (value, compareFn) { + if (compareFn === void 0) { compareFn = compare; } + return this.findIndex(function (node) { return compareFn(node.value, value); }); + }; + LinkedList.prototype.toArray = function () { + var array = new Array(this.size); + this.forEach(function (node, index) { return (array[index] = node.value); }); + return array; + }; + LinkedList.prototype.toNodeArray = function () { + var array = new Array(this.size); + this.forEach(function (node, index) { return (array[index] = node); }); + return array; + }; + LinkedList.prototype.toString = function (mapperFn) { + if (mapperFn === void 0) { mapperFn = JSON.stringify; } + return this.toArray() + .map(function (value) { return mapperFn(value); }) + .join(' <-> '); + }; + // Cannot use Generator type because of ng-packagr + LinkedList.prototype[Symbol.iterator] = function () { + var node, position; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + node = this.first, position = 0; + _a.label = 1; + case 1: + if (!node) return [3 /*break*/, 4]; + return [4 /*yield*/, node.value]; + case 2: + _a.sent(); + _a.label = 3; + case 3: + position++, node = node.next; + return [3 /*break*/, 1]; + case 4: return [2 /*return*/]; + } + }); + }; + return LinkedList; + }()); + + /* + * Public API Surface of utils + */ + + /** + * Generated bundle index. Do not edit. + */ + + exports.LinkedList = LinkedList; + exports.ListNode = ListNode; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); +//# sourceMappingURL=abp-utils.umd.js.map diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js.map b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js.map similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js.map rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js.map diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js.map b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js.map similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js.map rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js.map diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.css.map b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.css.map similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.css.map rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.css.map diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.min.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.min.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.min.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.min.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker-en-CA.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker-en-CA.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker-en-CA.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker-en-CA.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ar-tn.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ar-tn.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ar-tn.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ar-tn.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ar.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ar.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ar.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ar.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.az.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.az.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.az.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.az.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bg.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bg.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bg.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bg.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bm.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bm.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bm.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bm.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bn.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bn.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bn.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bn.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.br.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.br.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.br.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.br.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bs.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bs.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bs.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bs.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ca.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ca.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ca.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ca.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.cs.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.cs.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.cs.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.cs.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.cy.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.cy.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.cy.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.cy.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.da.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.da.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.da.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.da.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.de.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.de.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.de.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.de.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.el.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.el.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.el.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.el.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-AU.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-AU.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-AU.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-AU.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-CA.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-CA.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-CA.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-CA.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-GB.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-GB.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-GB.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-GB.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-IE.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-IE.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-IE.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-IE.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-NZ.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-NZ.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-NZ.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-NZ.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-ZA.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-ZA.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-ZA.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.en-ZA.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.eo.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.eo.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.eo.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.eo.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.es.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.es.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.es.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.es.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.et.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.et.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.et.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.et.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.eu.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.eu.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.eu.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.eu.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fa.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fa.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fa.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fa.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fi.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fi.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fi.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fi.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fo.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fo.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fo.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fo.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fr-CH.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fr-CH.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fr-CH.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fr-CH.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fr.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fr.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fr.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.fr.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.gl.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.gl.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.gl.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.gl.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.he.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.he.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.he.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.he.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hi.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hi.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hi.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hi.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hr.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hr.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hr.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hr.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hu.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hu.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hu.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hu.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hy.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hy.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hy.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.hy.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.id.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.id.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.id.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.id.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.is.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.is.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.is.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.is.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.it-CH.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.it-CH.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.it-CH.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.it-CH.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.it.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.it.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.it.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.it.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ja.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ja.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ja.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ja.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ka.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ka.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ka.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ka.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.kh.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.kh.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.kh.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.kh.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.kk.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.kk.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.kk.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.kk.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.km.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.km.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.km.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.km.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ko.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ko.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ko.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ko.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.kr.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.kr.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.kr.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.kr.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.lt.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.lt.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.lt.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.lt.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.lv.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.lv.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.lv.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.lv.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.me.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.me.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.me.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.me.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.mk.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.mk.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.mk.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.mk.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.mn.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.mn.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.mn.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.mn.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ms.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ms.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ms.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ms.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.nl-BE.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.nl-BE.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.nl-BE.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.nl-BE.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.nl.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.nl.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.nl.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.nl.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.no.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.no.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.no.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.no.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.oc.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.oc.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.oc.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.oc.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.pl.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.pl.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.pl.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.pl.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.pt-BR.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.pt-BR.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.pt-BR.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.pt-BR.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.pt.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.pt.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.pt.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.pt.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ro.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ro.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ro.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ro.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.rs-latin.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.rs-latin.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.rs-latin.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.rs-latin.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.rs.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.rs.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.rs.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.rs.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ru.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ru.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ru.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ru.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.si.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.si.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.si.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.si.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sk.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sk.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sk.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sk.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sl.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sl.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sl.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sl.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sq.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sq.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sq.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sq.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sr-latin.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sr-latin.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sr-latin.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sr-latin.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sr.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sr.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sr.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sr.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sv.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sv.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sv.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sv.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sw.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sw.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sw.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.sw.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ta.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ta.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ta.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ta.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.tg.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.tg.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.tg.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.tg.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.th.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.th.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.th.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.th.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.tk.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.tk.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.tk.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.tk.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.tr.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.tr.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.tr.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.tr.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.uk.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.uk.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.uk.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.uk.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.uz-cyrl.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.uz-cyrl.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.uz-cyrl.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.uz-cyrl.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.uz-latn.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.uz-latn.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.uz-latn.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.uz-latn.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.vi.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.vi.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.vi.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.vi.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.zh-CN.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.zh-CN.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.zh-CN.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.zh-CN.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.zh-TW.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.zh-TW.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.zh-TW.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.zh-TW.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.css old mode 100755 new mode 100644 similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.css.map b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.css.map old mode 100755 new mode 100644 similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.css.map rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.css.map diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.min.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.min.css old mode 100755 new mode 100644 similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.min.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.min.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.min.css.map b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.min.css.map old mode 100755 new mode 100644 similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.min.css.map rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap-rtl.min.css.map diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.css.map b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.css.map similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.css.map rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.css.map diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.min.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.min.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.min.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.min.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.min.css.map b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.min.css.map similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.min.css.map rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/css/bootstrap.min.css.map diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.js.map b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.js.map similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.js.map rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.js.map diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.min.js.map b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.min.js.map similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.min.js.map rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap/js/bootstrap.bundle.min.js.map diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/datatables.net-bs4/css/dataTables.bootstrap4.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/datatables.net-bs4/css/dataTables.bootstrap4.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/datatables.net-bs4/css/dataTables.bootstrap4.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/datatables.net-bs4/css/dataTables.bootstrap4.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/datatables.net-bs4/js/dataTables.bootstrap4.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/datatables.net-bs4/js/dataTables.bootstrap4.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/datatables.net-bs4/js/dataTables.bootstrap4.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/datatables.net-bs4/js/dataTables.bootstrap4.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/datatables.net/js/jquery.dataTables.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/datatables.net/js/jquery.dataTables.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/datatables.net/js/jquery.dataTables.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/datatables.net/js/jquery.dataTables.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/README.md b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/README.md similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/README.md rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/README.md diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/api.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/api.rst similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/api.rst rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/api.rst diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/building-testing.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/building-testing.rst similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/building-testing.rst rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/building-testing.rst diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/css-classes-reference.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/css-classes-reference.rst similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/css-classes-reference.rst rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/css-classes-reference.rst diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/index.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/index.rst similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/index.rst rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/index.rst diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-contribution.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-contribution.rst similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-contribution.rst rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-contribution.rst diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-guide.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-guide.rst similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-guide.rst rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-guide.rst diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-requests.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-requests.rst similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-requests.rst rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/language-requests.rst diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/line-numbers.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/line-numbers.rst similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/line-numbers.rst rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/line-numbers.rst diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/maintainers-guide.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/maintainers-guide.rst similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/maintainers-guide.rst rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/maintainers-guide.rst diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/reference.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/reference.rst similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/reference.rst rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/reference.rst diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/style-guide.rst b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/style-guide.rst similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/style-guide.rst rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/docs/style-guide.rst diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/highlight.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/highlight.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/highlight.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/highlight.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/index.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/index.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/index.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/index.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/1c.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/1c.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/1c.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/1c.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/abnf.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/abnf.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/abnf.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/abnf.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/accesslog.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/accesslog.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/accesslog.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/accesslog.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/actionscript.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/actionscript.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/actionscript.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/actionscript.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ada.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ada.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ada.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ada.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/angelscript.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/angelscript.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/angelscript.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/angelscript.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/apache.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/apache.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/apache.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/apache.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/applescript.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/applescript.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/applescript.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/applescript.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/arcade.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/arcade.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/arcade.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/arcade.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/arduino.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/arduino.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/arduino.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/arduino.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/armasm.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/armasm.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/armasm.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/armasm.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/asciidoc.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/asciidoc.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/asciidoc.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/asciidoc.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/aspectj.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/aspectj.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/aspectj.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/aspectj.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/autohotkey.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/autohotkey.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/autohotkey.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/autohotkey.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/autoit.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/autoit.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/autoit.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/autoit.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/avrasm.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/avrasm.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/avrasm.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/avrasm.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/awk.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/awk.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/awk.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/awk.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/axapta.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/axapta.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/axapta.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/axapta.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/bash.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/bash.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/bash.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/bash.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/basic.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/basic.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/basic.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/basic.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/bnf.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/bnf.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/bnf.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/bnf.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/brainfuck.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/brainfuck.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/brainfuck.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/brainfuck.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cal.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cal.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cal.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cal.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/capnproto.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/capnproto.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/capnproto.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/capnproto.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ceylon.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ceylon.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ceylon.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ceylon.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/clean.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/clean.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/clean.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/clean.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/clojure-repl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/clojure-repl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/clojure-repl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/clojure-repl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/clojure.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/clojure.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/clojure.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/clojure.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cmake.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cmake.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cmake.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cmake.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/coffeescript.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/coffeescript.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/coffeescript.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/coffeescript.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/coq.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/coq.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/coq.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/coq.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cos.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cos.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cos.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cos.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cpp.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cpp.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cpp.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cpp.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/crmsh.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/crmsh.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/crmsh.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/crmsh.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/crystal.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/crystal.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/crystal.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/crystal.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cs.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cs.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cs.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/cs.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/csp.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/csp.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/csp.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/csp.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/css.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/css.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/css.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/css.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/d.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/d.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/d.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/d.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dart.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dart.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dart.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dart.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/delphi.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/delphi.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/delphi.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/delphi.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/diff.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/diff.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/diff.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/diff.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/django.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/django.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/django.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/django.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dns.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dns.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dns.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dns.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dockerfile.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dockerfile.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dockerfile.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dockerfile.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dos.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dos.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dos.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dos.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dsconfig.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dsconfig.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dsconfig.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dsconfig.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dts.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dts.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dts.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dts.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dust.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dust.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dust.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/dust.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ebnf.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ebnf.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ebnf.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ebnf.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/elixir.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/elixir.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/elixir.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/elixir.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/elm.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/elm.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/elm.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/elm.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/erb.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/erb.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/erb.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/erb.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/erlang-repl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/erlang-repl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/erlang-repl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/erlang-repl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/erlang.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/erlang.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/erlang.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/erlang.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/excel.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/excel.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/excel.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/excel.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/fix.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/fix.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/fix.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/fix.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/flix.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/flix.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/flix.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/flix.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/fortran.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/fortran.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/fortran.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/fortran.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/fsharp.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/fsharp.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/fsharp.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/fsharp.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gams.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gams.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gams.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gams.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gauss.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gauss.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gauss.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gauss.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gcode.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gcode.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gcode.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gcode.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gherkin.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gherkin.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gherkin.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gherkin.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/glsl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/glsl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/glsl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/glsl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gml.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gml.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gml.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gml.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/go.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/go.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/go.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/go.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/golo.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/golo.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/golo.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/golo.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gradle.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gradle.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gradle.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/gradle.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/groovy.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/groovy.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/groovy.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/groovy.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/haml.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/haml.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/haml.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/haml.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/handlebars.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/handlebars.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/handlebars.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/handlebars.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/haskell.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/haskell.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/haskell.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/haskell.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/haxe.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/haxe.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/haxe.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/haxe.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/hsp.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/hsp.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/hsp.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/hsp.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/htmlbars.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/htmlbars.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/htmlbars.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/htmlbars.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/http.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/http.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/http.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/http.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/hy.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/hy.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/hy.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/hy.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/inform7.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/inform7.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/inform7.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/inform7.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ini.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ini.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ini.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ini.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/irpf90.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/irpf90.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/irpf90.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/irpf90.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/isbl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/isbl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/isbl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/isbl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/java.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/java.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/java.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/java.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/javascript.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/javascript.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/javascript.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/javascript.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/jboss-cli.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/jboss-cli.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/jboss-cli.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/jboss-cli.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/json.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/json.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/json.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/json.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/julia-repl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/julia-repl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/julia-repl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/julia-repl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/julia.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/julia.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/julia.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/julia.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/kotlin.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/kotlin.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/kotlin.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/kotlin.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lasso.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lasso.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lasso.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lasso.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ldif.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ldif.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ldif.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ldif.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/leaf.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/leaf.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/leaf.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/leaf.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/less.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/less.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/less.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/less.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lisp.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lisp.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lisp.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lisp.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/livecodeserver.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/livecodeserver.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/livecodeserver.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/livecodeserver.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/livescript.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/livescript.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/livescript.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/livescript.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/llvm.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/llvm.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/llvm.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/llvm.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lsl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lsl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lsl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lsl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lua.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lua.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lua.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/lua.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/makefile.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/makefile.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/makefile.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/makefile.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/markdown.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/markdown.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/markdown.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/markdown.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mathematica.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mathematica.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mathematica.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mathematica.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/matlab.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/matlab.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/matlab.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/matlab.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/maxima.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/maxima.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/maxima.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/maxima.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mel.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mel.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mel.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mel.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mercury.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mercury.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mercury.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mercury.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mipsasm.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mipsasm.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mipsasm.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mipsasm.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mizar.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mizar.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mizar.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mizar.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mojolicious.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mojolicious.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mojolicious.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/mojolicious.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/monkey.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/monkey.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/monkey.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/monkey.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/moonscript.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/moonscript.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/moonscript.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/moonscript.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/n1ql.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/n1ql.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/n1ql.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/n1ql.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nginx.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nginx.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nginx.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nginx.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nimrod.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nimrod.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nimrod.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nimrod.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nix.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nix.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nix.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nix.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nsis.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nsis.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nsis.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/nsis.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/objectivec.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/objectivec.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/objectivec.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/objectivec.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ocaml.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ocaml.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ocaml.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ocaml.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/openscad.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/openscad.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/openscad.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/openscad.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/oxygene.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/oxygene.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/oxygene.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/oxygene.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/parser3.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/parser3.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/parser3.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/parser3.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/perl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/perl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/perl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/perl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/pf.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/pf.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/pf.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/pf.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/pgsql.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/pgsql.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/pgsql.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/pgsql.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/php.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/php.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/php.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/php.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/plaintext.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/plaintext.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/plaintext.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/plaintext.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/pony.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/pony.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/pony.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/pony.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/powershell.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/powershell.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/powershell.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/powershell.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/processing.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/processing.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/processing.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/processing.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/profile.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/profile.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/profile.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/profile.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/prolog.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/prolog.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/prolog.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/prolog.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/properties.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/properties.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/properties.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/properties.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/protobuf.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/protobuf.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/protobuf.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/protobuf.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/puppet.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/puppet.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/puppet.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/puppet.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/purebasic.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/purebasic.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/purebasic.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/purebasic.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/python.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/python.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/python.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/python.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/q.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/q.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/q.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/q.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/qml.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/qml.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/qml.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/qml.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/r.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/r.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/r.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/r.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/reasonml.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/reasonml.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/reasonml.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/reasonml.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/rib.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/rib.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/rib.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/rib.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/roboconf.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/roboconf.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/roboconf.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/roboconf.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/routeros.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/routeros.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/routeros.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/routeros.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/rsl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/rsl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/rsl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/rsl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ruby.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ruby.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ruby.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ruby.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ruleslanguage.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ruleslanguage.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ruleslanguage.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/ruleslanguage.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/rust.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/rust.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/rust.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/rust.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sas.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sas.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sas.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sas.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scala.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scala.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scala.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scala.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scheme.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scheme.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scheme.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scheme.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scilab.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scilab.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scilab.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scilab.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scss.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scss.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scss.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/scss.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/shell.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/shell.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/shell.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/shell.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/smali.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/smali.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/smali.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/smali.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/smalltalk.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/smalltalk.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/smalltalk.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/smalltalk.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sml.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sml.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sml.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sml.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sqf.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sqf.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sqf.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sqf.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sql.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sql.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sql.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/sql.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/stan.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/stan.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/stan.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/stan.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/stata.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/stata.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/stata.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/stata.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/step21.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/step21.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/step21.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/step21.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/stylus.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/stylus.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/stylus.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/stylus.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/subunit.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/subunit.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/subunit.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/subunit.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/swift.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/swift.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/swift.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/swift.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/taggerscript.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/taggerscript.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/taggerscript.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/taggerscript.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tap.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tap.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tap.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tap.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tcl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tcl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tcl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tcl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tex.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tex.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tex.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tex.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/thrift.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/thrift.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/thrift.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/thrift.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tp.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tp.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tp.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/tp.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/twig.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/twig.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/twig.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/twig.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/typescript.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/typescript.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/typescript.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/typescript.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vala.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vala.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vala.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vala.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vbnet.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vbnet.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vbnet.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vbnet.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vbscript-html.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vbscript-html.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vbscript-html.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vbscript-html.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vbscript.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vbscript.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vbscript.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vbscript.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/verilog.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/verilog.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/verilog.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/verilog.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vhdl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vhdl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vhdl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vhdl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vim.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vim.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vim.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/vim.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/x86asm.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/x86asm.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/x86asm.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/x86asm.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/xl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/xl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/xl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/xl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/xml.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/xml.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/xml.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/xml.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/xquery.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/xquery.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/xquery.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/xquery.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/yaml.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/yaml.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/yaml.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/yaml.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/zephir.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/zephir.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/zephir.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/lib/languages/zephir.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/package.json b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/package.json similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/package.json rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/package.json diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/a11y-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/a11y-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/a11y-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/a11y-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/a11y-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/a11y-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/a11y-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/a11y-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/agate.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/agate.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/agate.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/agate.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/an-old-hope.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/an-old-hope.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/an-old-hope.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/an-old-hope.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/androidstudio.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/androidstudio.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/androidstudio.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/androidstudio.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/arduino-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/arduino-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/arduino-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/arduino-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/arta.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/arta.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/arta.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/arta.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/ascetic.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/ascetic.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/ascetic.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/ascetic.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-cave-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-cave-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-cave-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-cave-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-cave-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-cave-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-cave-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-cave-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-dune-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-dune-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-dune-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-dune-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-dune-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-dune-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-dune-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-dune-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-estuary-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-estuary-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-estuary-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-estuary-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-estuary-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-estuary-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-estuary-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-estuary-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-forest-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-forest-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-forest-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-forest-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-forest-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-forest-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-forest-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-forest-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-heath-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-heath-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-heath-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-heath-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-heath-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-heath-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-heath-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-heath-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-lakeside-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-lakeside-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-lakeside-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-lakeside-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-lakeside-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-lakeside-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-lakeside-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-lakeside-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-plateau-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-plateau-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-plateau-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-plateau-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-plateau-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-plateau-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-plateau-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-plateau-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-savanna-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-savanna-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-savanna-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-savanna-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-savanna-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-savanna-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-savanna-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-savanna-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-seaside-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-seaside-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-seaside-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-seaside-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-seaside-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-seaside-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-seaside-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-seaside-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-sulphurpool-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-sulphurpool-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-sulphurpool-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-sulphurpool-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-sulphurpool-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-sulphurpool-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-sulphurpool-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atelier-sulphurpool-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atom-one-dark-reasonable.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atom-one-dark-reasonable.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atom-one-dark-reasonable.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atom-one-dark-reasonable.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atom-one-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atom-one-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atom-one-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atom-one-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atom-one-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atom-one-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atom-one-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/atom-one-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/brown-paper.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/brown-paper.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/brown-paper.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/brown-paper.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/brown-papersq.png b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/brown-papersq.png similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/brown-papersq.png rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/brown-papersq.png diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/codepen-embed.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/codepen-embed.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/codepen-embed.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/codepen-embed.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/color-brewer.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/color-brewer.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/color-brewer.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/color-brewer.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/darcula.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/darcula.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/darcula.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/darcula.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/darkula.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/darkula.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/darkula.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/darkula.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/default.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/default.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/default.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/default.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/docco.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/docco.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/docco.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/docco.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/dracula.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/dracula.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/dracula.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/dracula.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/far.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/far.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/far.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/far.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/foundation.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/foundation.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/foundation.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/foundation.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/github-gist.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/github-gist.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/github-gist.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/github-gist.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/github.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/github.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/github.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/github.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/gml.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/gml.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/gml.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/gml.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/googlecode.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/googlecode.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/googlecode.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/googlecode.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/grayscale.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/grayscale.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/grayscale.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/grayscale.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/gruvbox-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/gruvbox-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/gruvbox-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/gruvbox-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/gruvbox-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/gruvbox-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/gruvbox-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/gruvbox-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/hopscotch.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/hopscotch.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/hopscotch.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/hopscotch.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/hybrid.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/hybrid.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/hybrid.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/hybrid.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/idea.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/idea.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/idea.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/idea.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/ir-black.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/ir-black.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/ir-black.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/ir-black.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/isbl-editor-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/isbl-editor-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/isbl-editor-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/isbl-editor-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/isbl-editor-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/isbl-editor-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/isbl-editor-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/isbl-editor-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/kimbie.dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/kimbie.dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/kimbie.dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/kimbie.dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/kimbie.light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/kimbie.light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/kimbie.light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/kimbie.light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/lightfair.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/lightfair.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/lightfair.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/lightfair.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/magula.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/magula.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/magula.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/magula.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/mono-blue.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/mono-blue.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/mono-blue.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/mono-blue.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/monokai-sublime.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/monokai-sublime.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/monokai-sublime.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/monokai-sublime.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/monokai.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/monokai.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/monokai.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/monokai.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/nord.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/nord.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/nord.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/nord.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/obsidian.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/obsidian.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/obsidian.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/obsidian.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/ocean.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/ocean.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/ocean.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/ocean.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/paraiso-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/paraiso-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/paraiso-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/paraiso-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/paraiso-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/paraiso-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/paraiso-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/paraiso-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/pojoaque.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/pojoaque.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/pojoaque.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/pojoaque.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/pojoaque.jpg b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/pojoaque.jpg similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/pojoaque.jpg rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/pojoaque.jpg diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/purebasic.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/purebasic.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/purebasic.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/purebasic.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/qtcreator_dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/qtcreator_dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/qtcreator_dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/qtcreator_dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/qtcreator_light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/qtcreator_light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/qtcreator_light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/qtcreator_light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/railscasts.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/railscasts.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/railscasts.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/railscasts.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/rainbow.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/rainbow.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/rainbow.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/rainbow.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/routeros.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/routeros.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/routeros.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/routeros.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/school-book.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/school-book.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/school-book.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/school-book.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/school-book.png b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/school-book.png similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/school-book.png rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/school-book.png diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/shades-of-purple.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/shades-of-purple.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/shades-of-purple.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/shades-of-purple.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/solarized-dark.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/solarized-dark.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/solarized-dark.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/solarized-dark.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/solarized-light.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/solarized-light.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/solarized-light.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/solarized-light.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/sunburst.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/sunburst.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/sunburst.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/sunburst.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night-blue.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night-blue.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night-blue.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night-blue.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night-bright.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night-bright.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night-bright.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night-bright.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night-eighties.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night-eighties.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night-eighties.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night-eighties.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow-night.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/tomorrow.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/vs.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/vs.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/vs.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/vs.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/vs2015.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/vs2015.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/vs2015.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/vs2015.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/xcode.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/xcode.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/xcode.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/xcode.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/xt256.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/xt256.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/xt256.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/xt256.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/zenburn.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/zenburn.css similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/zenburn.css rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/highlight.js/styles/zenburn.css diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-form/jquery.form.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-form/jquery.form.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-form/jquery.form.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-form/jquery.form.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-form/jquery.form.min.js.map b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-form/jquery.form.min.js.map similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-form/jquery.form.min.js.map rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-form/jquery.form.min.js.map diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/jquery.validate.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/jquery.validate.js new file mode 100644 index 0000000000..12674b08b2 --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/jquery.validate.js @@ -0,0 +1,1601 @@ +/*! + * jQuery Validation Plugin v1.17.0 + * + * https://jqueryvalidation.org/ + * + * Copyright (c) 2017 Jörn Zaefferer + * Released under the MIT license + */ +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + define( ["jquery"], factory ); + } else if (typeof module === "object" && module.exports) { + module.exports = factory( require( "jquery" ) ); + } else { + factory( jQuery ); + } +}(function( $ ) { + +$.extend( $.fn, { + + // https://jqueryvalidation.org/validate/ + validate: function( options ) { + + // If nothing is selected, return nothing; can't chain anyway + if ( !this.length ) { + if ( options && options.debug && window.console ) { + console.warn( "Nothing selected, can't validate, returning nothing." ); + } + return; + } + + // Check if a validator for this form was already created + var validator = $.data( this[ 0 ], "validator" ); + if ( validator ) { + return validator; + } + + // Add novalidate tag if HTML5. + this.attr( "novalidate", "novalidate" ); + + validator = new $.validator( options, this[ 0 ] ); + $.data( this[ 0 ], "validator", validator ); + + if ( validator.settings.onsubmit ) { + + this.on( "click.validate", ":submit", function( event ) { + + // Track the used submit button to properly handle scripted + // submits later. + validator.submitButton = event.currentTarget; + + // Allow suppressing validation by adding a cancel class to the submit button + if ( $( this ).hasClass( "cancel" ) ) { + validator.cancelSubmit = true; + } + + // Allow suppressing validation by adding the html5 formnovalidate attribute to the submit button + if ( $( this ).attr( "formnovalidate" ) !== undefined ) { + validator.cancelSubmit = true; + } + } ); + + // Validate the form on submit + this.on( "submit.validate", function( event ) { + if ( validator.settings.debug ) { + + // Prevent form submit to be able to see console output + event.preventDefault(); + } + function handle() { + var hidden, result; + + // Insert a hidden input as a replacement for the missing submit button + // The hidden input is inserted in two cases: + // - A user defined a `submitHandler` + // - There was a pending request due to `remote` method and `stopRequest()` + // was called to submit the form in case it's valid + if ( validator.submitButton && ( validator.settings.submitHandler || validator.formSubmitted ) ) { + hidden = $( "" ) + .attr( "name", validator.submitButton.name ) + .val( $( validator.submitButton ).val() ) + .appendTo( validator.currentForm ); + } + + if ( validator.settings.submitHandler ) { + result = validator.settings.submitHandler.call( validator, validator.currentForm, event ); + if ( hidden ) { + + // And clean up afterwards; thanks to no-block-scope, hidden can be referenced + hidden.remove(); + } + if ( result !== undefined ) { + return result; + } + return false; + } + return true; + } + + // Prevent submit for invalid forms or custom submit handlers + if ( validator.cancelSubmit ) { + validator.cancelSubmit = false; + return handle(); + } + if ( validator.form() ) { + if ( validator.pendingRequest ) { + validator.formSubmitted = true; + return false; + } + return handle(); + } else { + validator.focusInvalid(); + return false; + } + } ); + } + + return validator; + }, + + // https://jqueryvalidation.org/valid/ + valid: function() { + var valid, validator, errorList; + + if ( $( this[ 0 ] ).is( "form" ) ) { + valid = this.validate().form(); + } else { + errorList = []; + valid = true; + validator = $( this[ 0 ].form ).validate(); + this.each( function() { + valid = validator.element( this ) && valid; + if ( !valid ) { + errorList = errorList.concat( validator.errorList ); + } + } ); + validator.errorList = errorList; + } + return valid; + }, + + // https://jqueryvalidation.org/rules/ + rules: function( command, argument ) { + var element = this[ 0 ], + settings, staticRules, existingRules, data, param, filtered; + + // If nothing is selected, return empty object; can't chain anyway + if ( element == null ) { + return; + } + + if ( !element.form && element.hasAttribute( "contenteditable" ) ) { + element.form = this.closest( "form" )[ 0 ]; + element.name = this.attr( "name" ); + } + + if ( element.form == null ) { + return; + } + + if ( command ) { + settings = $.data( element.form, "validator" ).settings; + staticRules = settings.rules; + existingRules = $.validator.staticRules( element ); + switch ( command ) { + case "add": + $.extend( existingRules, $.validator.normalizeRule( argument ) ); + + // Remove messages from rules, but allow them to be set separately + delete existingRules.messages; + staticRules[ element.name ] = existingRules; + if ( argument.messages ) { + settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages ); + } + break; + case "remove": + if ( !argument ) { + delete staticRules[ element.name ]; + return existingRules; + } + filtered = {}; + $.each( argument.split( /\s/ ), function( index, method ) { + filtered[ method ] = existingRules[ method ]; + delete existingRules[ method ]; + } ); + return filtered; + } + } + + data = $.validator.normalizeRules( + $.extend( + {}, + $.validator.classRules( element ), + $.validator.attributeRules( element ), + $.validator.dataRules( element ), + $.validator.staticRules( element ) + ), element ); + + // Make sure required is at front + if ( data.required ) { + param = data.required; + delete data.required; + data = $.extend( { required: param }, data ); + } + + // Make sure remote is at back + if ( data.remote ) { + param = data.remote; + delete data.remote; + data = $.extend( data, { remote: param } ); + } + + return data; + } +} ); + +// Custom selectors +$.extend( $.expr.pseudos || $.expr[ ":" ], { // '|| $.expr[ ":" ]' here enables backwards compatibility to jQuery 1.7. Can be removed when dropping jQ 1.7.x support + + // https://jqueryvalidation.org/blank-selector/ + blank: function( a ) { + return !$.trim( "" + $( a ).val() ); + }, + + // https://jqueryvalidation.org/filled-selector/ + filled: function( a ) { + var val = $( a ).val(); + return val !== null && !!$.trim( "" + val ); + }, + + // https://jqueryvalidation.org/unchecked-selector/ + unchecked: function( a ) { + return !$( a ).prop( "checked" ); + } +} ); + +// Constructor for validator +$.validator = function( options, form ) { + this.settings = $.extend( true, {}, $.validator.defaults, options ); + this.currentForm = form; + this.init(); +}; + +// https://jqueryvalidation.org/jQuery.validator.format/ +$.validator.format = function( source, params ) { + if ( arguments.length === 1 ) { + return function() { + var args = $.makeArray( arguments ); + args.unshift( source ); + return $.validator.format.apply( this, args ); + }; + } + if ( params === undefined ) { + return source; + } + if ( arguments.length > 2 && params.constructor !== Array ) { + params = $.makeArray( arguments ).slice( 1 ); + } + if ( params.constructor !== Array ) { + params = [ params ]; + } + $.each( params, function( i, n ) { + source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() { + return n; + } ); + } ); + return source; +}; + +$.extend( $.validator, { + + defaults: { + messages: {}, + groups: {}, + rules: {}, + errorClass: "error", + pendingClass: "pending", + validClass: "valid", + errorElement: "label", + focusCleanup: false, + focusInvalid: true, + errorContainer: $( [] ), + errorLabelContainer: $( [] ), + onsubmit: true, + ignore: ":hidden", + ignoreTitle: false, + onfocusin: function( element ) { + this.lastActive = element; + + // Hide error label and remove error class on focus if enabled + if ( this.settings.focusCleanup ) { + if ( this.settings.unhighlight ) { + this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); + } + this.hideThese( this.errorsFor( element ) ); + } + }, + onfocusout: function( element ) { + if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) { + this.element( element ); + } + }, + onkeyup: function( element, event ) { + + // Avoid revalidate the field when pressing one of the following keys + // Shift => 16 + // Ctrl => 17 + // Alt => 18 + // Caps lock => 20 + // End => 35 + // Home => 36 + // Left arrow => 37 + // Up arrow => 38 + // Right arrow => 39 + // Down arrow => 40 + // Insert => 45 + // Num lock => 144 + // AltGr key => 225 + var excludedKeys = [ + 16, 17, 18, 20, 35, 36, 37, + 38, 39, 40, 45, 144, 225 + ]; + + if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) { + return; + } else if ( element.name in this.submitted || element.name in this.invalid ) { + this.element( element ); + } + }, + onclick: function( element ) { + + // Click on selects, radiobuttons and checkboxes + if ( element.name in this.submitted ) { + this.element( element ); + + // Or option elements, check parent select in that case + } else if ( element.parentNode.name in this.submitted ) { + this.element( element.parentNode ); + } + }, + highlight: function( element, errorClass, validClass ) { + if ( element.type === "radio" ) { + this.findByName( element.name ).addClass( errorClass ).removeClass( validClass ); + } else { + $( element ).addClass( errorClass ).removeClass( validClass ); + } + }, + unhighlight: function( element, errorClass, validClass ) { + if ( element.type === "radio" ) { + this.findByName( element.name ).removeClass( errorClass ).addClass( validClass ); + } else { + $( element ).removeClass( errorClass ).addClass( validClass ); + } + } + }, + + // https://jqueryvalidation.org/jQuery.validator.setDefaults/ + setDefaults: function( settings ) { + $.extend( $.validator.defaults, settings ); + }, + + messages: { + required: "This field is required.", + remote: "Please fix this field.", + email: "Please enter a valid email address.", + url: "Please enter a valid URL.", + date: "Please enter a valid date.", + dateISO: "Please enter a valid date (ISO).", + number: "Please enter a valid number.", + digits: "Please enter only digits.", + equalTo: "Please enter the same value again.", + maxlength: $.validator.format( "Please enter no more than {0} characters." ), + minlength: $.validator.format( "Please enter at least {0} characters." ), + rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ), + range: $.validator.format( "Please enter a value between {0} and {1}." ), + max: $.validator.format( "Please enter a value less than or equal to {0}." ), + min: $.validator.format( "Please enter a value greater than or equal to {0}." ), + step: $.validator.format( "Please enter a multiple of {0}." ) + }, + + autoCreateRanges: false, + + prototype: { + + init: function() { + this.labelContainer = $( this.settings.errorLabelContainer ); + this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm ); + this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer ); + this.submitted = {}; + this.valueCache = {}; + this.pendingRequest = 0; + this.pending = {}; + this.invalid = {}; + this.reset(); + + var groups = ( this.groups = {} ), + rules; + $.each( this.settings.groups, function( key, value ) { + if ( typeof value === "string" ) { + value = value.split( /\s/ ); + } + $.each( value, function( index, name ) { + groups[ name ] = key; + } ); + } ); + rules = this.settings.rules; + $.each( rules, function( key, value ) { + rules[ key ] = $.validator.normalizeRule( value ); + } ); + + function delegate( event ) { + + // Set form expando on contenteditable + if ( !this.form && this.hasAttribute( "contenteditable" ) ) { + this.form = $( this ).closest( "form" )[ 0 ]; + this.name = $( this ).attr( "name" ); + } + + var validator = $.data( this.form, "validator" ), + eventType = "on" + event.type.replace( /^validate/, "" ), + settings = validator.settings; + if ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) { + settings[ eventType ].call( validator, this, event ); + } + } + + $( this.currentForm ) + .on( "focusin.validate focusout.validate keyup.validate", + ":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " + + "[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " + + "[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " + + "[type='radio'], [type='checkbox'], [contenteditable], [type='button']", delegate ) + + // Support: Chrome, oldIE + // "select" is provided as event.target when clicking a option + .on( "click.validate", "select, option, [type='radio'], [type='checkbox']", delegate ); + + if ( this.settings.invalidHandler ) { + $( this.currentForm ).on( "invalid-form.validate", this.settings.invalidHandler ); + } + }, + + // https://jqueryvalidation.org/Validator.form/ + form: function() { + this.checkForm(); + $.extend( this.submitted, this.errorMap ); + this.invalid = $.extend( {}, this.errorMap ); + if ( !this.valid() ) { + $( this.currentForm ).triggerHandler( "invalid-form", [ this ] ); + } + this.showErrors(); + return this.valid(); + }, + + checkForm: function() { + this.prepareForm(); + for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) { + this.check( elements[ i ] ); + } + return this.valid(); + }, + + // https://jqueryvalidation.org/Validator.element/ + element: function( element ) { + var cleanElement = this.clean( element ), + checkElement = this.validationTargetFor( cleanElement ), + v = this, + result = true, + rs, group; + + if ( checkElement === undefined ) { + delete this.invalid[ cleanElement.name ]; + } else { + this.prepareElement( checkElement ); + this.currentElements = $( checkElement ); + + // If this element is grouped, then validate all group elements already + // containing a value + group = this.groups[ checkElement.name ]; + if ( group ) { + $.each( this.groups, function( name, testgroup ) { + if ( testgroup === group && name !== checkElement.name ) { + cleanElement = v.validationTargetFor( v.clean( v.findByName( name ) ) ); + if ( cleanElement && cleanElement.name in v.invalid ) { + v.currentElements.push( cleanElement ); + result = v.check( cleanElement ) && result; + } + } + } ); + } + + rs = this.check( checkElement ) !== false; + result = result && rs; + if ( rs ) { + this.invalid[ checkElement.name ] = false; + } else { + this.invalid[ checkElement.name ] = true; + } + + if ( !this.numberOfInvalids() ) { + + // Hide error containers on last error + this.toHide = this.toHide.add( this.containers ); + } + this.showErrors(); + + // Add aria-invalid status for screen readers + $( element ).attr( "aria-invalid", !rs ); + } + + return result; + }, + + // https://jqueryvalidation.org/Validator.showErrors/ + showErrors: function( errors ) { + if ( errors ) { + var validator = this; + + // Add items to error list and map + $.extend( this.errorMap, errors ); + this.errorList = $.map( this.errorMap, function( message, name ) { + return { + message: message, + element: validator.findByName( name )[ 0 ] + }; + } ); + + // Remove items from success list + this.successList = $.grep( this.successList, function( element ) { + return !( element.name in errors ); + } ); + } + if ( this.settings.showErrors ) { + this.settings.showErrors.call( this, this.errorMap, this.errorList ); + } else { + this.defaultShowErrors(); + } + }, + + // https://jqueryvalidation.org/Validator.resetForm/ + resetForm: function() { + if ( $.fn.resetForm ) { + $( this.currentForm ).resetForm(); + } + this.invalid = {}; + this.submitted = {}; + this.prepareForm(); + this.hideErrors(); + var elements = this.elements() + .removeData( "previousValue" ) + .removeAttr( "aria-invalid" ); + + this.resetElements( elements ); + }, + + resetElements: function( elements ) { + var i; + + if ( this.settings.unhighlight ) { + for ( i = 0; elements[ i ]; i++ ) { + this.settings.unhighlight.call( this, elements[ i ], + this.settings.errorClass, "" ); + this.findByName( elements[ i ].name ).removeClass( this.settings.validClass ); + } + } else { + elements + .removeClass( this.settings.errorClass ) + .removeClass( this.settings.validClass ); + } + }, + + numberOfInvalids: function() { + return this.objectLength( this.invalid ); + }, + + objectLength: function( obj ) { + /* jshint unused: false */ + var count = 0, + i; + for ( i in obj ) { + + // This check allows counting elements with empty error + // message as invalid elements + if ( obj[ i ] !== undefined && obj[ i ] !== null && obj[ i ] !== false ) { + count++; + } + } + return count; + }, + + hideErrors: function() { + this.hideThese( this.toHide ); + }, + + hideThese: function( errors ) { + errors.not( this.containers ).text( "" ); + this.addWrapper( errors ).hide(); + }, + + valid: function() { + return this.size() === 0; + }, + + size: function() { + return this.errorList.length; + }, + + focusInvalid: function() { + if ( this.settings.focusInvalid ) { + try { + $( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [] ) + .filter( ":visible" ) + .focus() + + // Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find + .trigger( "focusin" ); + } catch ( e ) { + + // Ignore IE throwing errors when focusing hidden elements + } + } + }, + + findLastActive: function() { + var lastActive = this.lastActive; + return lastActive && $.grep( this.errorList, function( n ) { + return n.element.name === lastActive.name; + } ).length === 1 && lastActive; + }, + + elements: function() { + var validator = this, + rulesCache = {}; + + // Select all valid inputs inside the form (no submit or reset buttons) + return $( this.currentForm ) + .find( "input, select, textarea, [contenteditable]" ) + .not( ":submit, :reset, :image, :disabled" ) + .not( this.settings.ignore ) + .filter( function() { + var name = this.name || $( this ).attr( "name" ); // For contenteditable + if ( !name && validator.settings.debug && window.console ) { + console.error( "%o has no name assigned", this ); + } + + // Set form expando on contenteditable + if ( this.hasAttribute( "contenteditable" ) ) { + this.form = $( this ).closest( "form" )[ 0 ]; + this.name = name; + } + + // Select only the first element for each name, and only those with rules specified + if ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) { + return false; + } + + rulesCache[ name ] = true; + return true; + } ); + }, + + clean: function( selector ) { + return $( selector )[ 0 ]; + }, + + errors: function() { + var errorClass = this.settings.errorClass.split( " " ).join( "." ); + return $( this.settings.errorElement + "." + errorClass, this.errorContext ); + }, + + resetInternals: function() { + this.successList = []; + this.errorList = []; + this.errorMap = {}; + this.toShow = $( [] ); + this.toHide = $( [] ); + }, + + reset: function() { + this.resetInternals(); + this.currentElements = $( [] ); + }, + + prepareForm: function() { + this.reset(); + this.toHide = this.errors().add( this.containers ); + }, + + prepareElement: function( element ) { + this.reset(); + this.toHide = this.errorsFor( element ); + }, + + elementValue: function( element ) { + var $element = $( element ), + type = element.type, + val, idx; + + if ( type === "radio" || type === "checkbox" ) { + return this.findByName( element.name ).filter( ":checked" ).val(); + } else if ( type === "number" && typeof element.validity !== "undefined" ) { + return element.validity.badInput ? "NaN" : $element.val(); + } + + if ( element.hasAttribute( "contenteditable" ) ) { + val = $element.text(); + } else { + val = $element.val(); + } + + if ( type === "file" ) { + + // Modern browser (chrome & safari) + if ( val.substr( 0, 12 ) === "C:\\fakepath\\" ) { + return val.substr( 12 ); + } + + // Legacy browsers + // Unix-based path + idx = val.lastIndexOf( "/" ); + if ( idx >= 0 ) { + return val.substr( idx + 1 ); + } + + // Windows-based path + idx = val.lastIndexOf( "\\" ); + if ( idx >= 0 ) { + return val.substr( idx + 1 ); + } + + // Just the file name + return val; + } + + if ( typeof val === "string" ) { + return val.replace( /\r/g, "" ); + } + return val; + }, + + check: function( element ) { + element = this.validationTargetFor( this.clean( element ) ); + + var rules = $( element ).rules(), + rulesCount = $.map( rules, function( n, i ) { + return i; + } ).length, + dependencyMismatch = false, + val = this.elementValue( element ), + result, method, rule, normalizer; + + // Prioritize the local normalizer defined for this element over the global one + // if the former exists, otherwise user the global one in case it exists. + if ( typeof rules.normalizer === "function" ) { + normalizer = rules.normalizer; + } else if ( typeof this.settings.normalizer === "function" ) { + normalizer = this.settings.normalizer; + } + + // If normalizer is defined, then call it to retreive the changed value instead + // of using the real one. + // Note that `this` in the normalizer is `element`. + if ( normalizer ) { + val = normalizer.call( element, val ); + + if ( typeof val !== "string" ) { + throw new TypeError( "The normalizer should return a string value." ); + } + + // Delete the normalizer from rules to avoid treating it as a pre-defined method. + delete rules.normalizer; + } + + for ( method in rules ) { + rule = { method: method, parameters: rules[ method ] }; + try { + result = $.validator.methods[ method ].call( this, val, element, rule.parameters ); + + // If a method indicates that the field is optional and therefore valid, + // don't mark it as valid when there are no other rules + if ( result === "dependency-mismatch" && rulesCount === 1 ) { + dependencyMismatch = true; + continue; + } + dependencyMismatch = false; + + if ( result === "pending" ) { + this.toHide = this.toHide.not( this.errorsFor( element ) ); + return; + } + + if ( !result ) { + this.formatAndAdd( element, rule ); + return false; + } + } catch ( e ) { + if ( this.settings.debug && window.console ) { + console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e ); + } + if ( e instanceof TypeError ) { + e.message += ". Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method."; + } + + throw e; + } + } + if ( dependencyMismatch ) { + return; + } + if ( this.objectLength( rules ) ) { + this.successList.push( element ); + } + return true; + }, + + // Return the custom message for the given element and validation method + // specified in the element's HTML5 data attribute + // return the generic message if present and no method specific message is present + customDataMessage: function( element, method ) { + return $( element ).data( "msg" + method.charAt( 0 ).toUpperCase() + + method.substring( 1 ).toLowerCase() ) || $( element ).data( "msg" ); + }, + + // Return the custom message for the given element name and validation method + customMessage: function( name, method ) { + var m = this.settings.messages[ name ]; + return m && ( m.constructor === String ? m : m[ method ] ); + }, + + // Return the first defined argument, allowing empty strings + findDefined: function() { + for ( var i = 0; i < arguments.length; i++ ) { + if ( arguments[ i ] !== undefined ) { + return arguments[ i ]; + } + } + return undefined; + }, + + // The second parameter 'rule' used to be a string, and extended to an object literal + // of the following form: + // rule = { + // method: "method name", + // parameters: "the given method parameters" + // } + // + // The old behavior still supported, kept to maintain backward compatibility with + // old code, and will be removed in the next major release. + defaultMessage: function( element, rule ) { + if ( typeof rule === "string" ) { + rule = { method: rule }; + } + + var message = this.findDefined( + this.customMessage( element.name, rule.method ), + this.customDataMessage( element, rule.method ), + + // 'title' is never undefined, so handle empty string as undefined + !this.settings.ignoreTitle && element.title || undefined, + $.validator.messages[ rule.method ], + "Warning: No message defined for " + element.name + "" + ), + theregex = /\$?\{(\d+)\}/g; + if ( typeof message === "function" ) { + message = message.call( this, rule.parameters, element ); + } else if ( theregex.test( message ) ) { + message = $.validator.format( message.replace( theregex, "{$1}" ), rule.parameters ); + } + + return message; + }, + + formatAndAdd: function( element, rule ) { + var message = this.defaultMessage( element, rule ); + + this.errorList.push( { + message: message, + element: element, + method: rule.method + } ); + + this.errorMap[ element.name ] = message; + this.submitted[ element.name ] = message; + }, + + addWrapper: function( toToggle ) { + if ( this.settings.wrapper ) { + toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); + } + return toToggle; + }, + + defaultShowErrors: function() { + var i, elements, error; + for ( i = 0; this.errorList[ i ]; i++ ) { + error = this.errorList[ i ]; + if ( this.settings.highlight ) { + this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass ); + } + this.showLabel( error.element, error.message ); + } + if ( this.errorList.length ) { + this.toShow = this.toShow.add( this.containers ); + } + if ( this.settings.success ) { + for ( i = 0; this.successList[ i ]; i++ ) { + this.showLabel( this.successList[ i ] ); + } + } + if ( this.settings.unhighlight ) { + for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) { + this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass ); + } + } + this.toHide = this.toHide.not( this.toShow ); + this.hideErrors(); + this.addWrapper( this.toShow ).show(); + }, + + validElements: function() { + return this.currentElements.not( this.invalidElements() ); + }, + + invalidElements: function() { + return $( this.errorList ).map( function() { + return this.element; + } ); + }, + + showLabel: function( element, message ) { + var place, group, errorID, v, + error = this.errorsFor( element ), + elementID = this.idOrName( element ), + describedBy = $( element ).attr( "aria-describedby" ); + + if ( error.length ) { + + // Refresh error/success class + error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass ); + + // Replace message on existing label + error.html( message ); + } else { + + // Create error element + error = $( "<" + this.settings.errorElement + ">" ) + .attr( "id", elementID + "-error" ) + .addClass( this.settings.errorClass ) + .html( message || "" ); + + // Maintain reference to the element to be placed into the DOM + place = error; + if ( this.settings.wrapper ) { + + // Make sure the element is visible, even in IE + // actually showing the wrapped element is handled elsewhere + place = error.hide().show().wrap( "<" + this.settings.wrapper + "/>" ).parent(); + } + if ( this.labelContainer.length ) { + this.labelContainer.append( place ); + } else if ( this.settings.errorPlacement ) { + this.settings.errorPlacement.call( this, place, $( element ) ); + } else { + place.insertAfter( element ); + } + + // Link error back to the element + if ( error.is( "label" ) ) { + + // If the error is a label, then associate using 'for' + error.attr( "for", elementID ); + + // If the element is not a child of an associated label, then it's necessary + // to explicitly apply aria-describedby + } else if ( error.parents( "label[for='" + this.escapeCssMeta( elementID ) + "']" ).length === 0 ) { + errorID = error.attr( "id" ); + + // Respect existing non-error aria-describedby + if ( !describedBy ) { + describedBy = errorID; + } else if ( !describedBy.match( new RegExp( "\\b" + this.escapeCssMeta( errorID ) + "\\b" ) ) ) { + + // Add to end of list if not already present + describedBy += " " + errorID; + } + $( element ).attr( "aria-describedby", describedBy ); + + // If this element is grouped, then assign to all elements in the same group + group = this.groups[ element.name ]; + if ( group ) { + v = this; + $.each( v.groups, function( name, testgroup ) { + if ( testgroup === group ) { + $( "[name='" + v.escapeCssMeta( name ) + "']", v.currentForm ) + .attr( "aria-describedby", error.attr( "id" ) ); + } + } ); + } + } + } + if ( !message && this.settings.success ) { + error.text( "" ); + if ( typeof this.settings.success === "string" ) { + error.addClass( this.settings.success ); + } else { + this.settings.success( error, element ); + } + } + this.toShow = this.toShow.add( error ); + }, + + errorsFor: function( element ) { + var name = this.escapeCssMeta( this.idOrName( element ) ), + describer = $( element ).attr( "aria-describedby" ), + selector = "label[for='" + name + "'], label[for='" + name + "'] *"; + + // 'aria-describedby' should directly reference the error element + if ( describer ) { + selector = selector + ", #" + this.escapeCssMeta( describer ) + .replace( /\s+/g, ", #" ); + } + + return this + .errors() + .filter( selector ); + }, + + // See https://api.jquery.com/category/selectors/, for CSS + // meta-characters that should be escaped in order to be used with JQuery + // as a literal part of a name/id or any selector. + escapeCssMeta: function( string ) { + return string.replace( /([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g, "\\$1" ); + }, + + idOrName: function( element ) { + return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name ); + }, + + validationTargetFor: function( element ) { + + // If radio/checkbox, validate first element in group instead + if ( this.checkable( element ) ) { + element = this.findByName( element.name ); + } + + // Always apply ignore filter + return $( element ).not( this.settings.ignore )[ 0 ]; + }, + + checkable: function( element ) { + return ( /radio|checkbox/i ).test( element.type ); + }, + + findByName: function( name ) { + return $( this.currentForm ).find( "[name='" + this.escapeCssMeta( name ) + "']" ); + }, + + getLength: function( value, element ) { + switch ( element.nodeName.toLowerCase() ) { + case "select": + return $( "option:selected", element ).length; + case "input": + if ( this.checkable( element ) ) { + return this.findByName( element.name ).filter( ":checked" ).length; + } + } + return value.length; + }, + + depend: function( param, element ) { + return this.dependTypes[ typeof param ] ? this.dependTypes[ typeof param ]( param, element ) : true; + }, + + dependTypes: { + "boolean": function( param ) { + return param; + }, + "string": function( param, element ) { + return !!$( param, element.form ).length; + }, + "function": function( param, element ) { + return param( element ); + } + }, + + optional: function( element ) { + var val = this.elementValue( element ); + return !$.validator.methods.required.call( this, val, element ) && "dependency-mismatch"; + }, + + startRequest: function( element ) { + if ( !this.pending[ element.name ] ) { + this.pendingRequest++; + $( element ).addClass( this.settings.pendingClass ); + this.pending[ element.name ] = true; + } + }, + + stopRequest: function( element, valid ) { + this.pendingRequest--; + + // Sometimes synchronization fails, make sure pendingRequest is never < 0 + if ( this.pendingRequest < 0 ) { + this.pendingRequest = 0; + } + delete this.pending[ element.name ]; + $( element ).removeClass( this.settings.pendingClass ); + if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) { + $( this.currentForm ).submit(); + + // Remove the hidden input that was used as a replacement for the + // missing submit button. The hidden input is added by `handle()` + // to ensure that the value of the used submit button is passed on + // for scripted submits triggered by this method + if ( this.submitButton ) { + $( "input:hidden[name='" + this.submitButton.name + "']", this.currentForm ).remove(); + } + + this.formSubmitted = false; + } else if ( !valid && this.pendingRequest === 0 && this.formSubmitted ) { + $( this.currentForm ).triggerHandler( "invalid-form", [ this ] ); + this.formSubmitted = false; + } + }, + + previousValue: function( element, method ) { + method = typeof method === "string" && method || "remote"; + + return $.data( element, "previousValue" ) || $.data( element, "previousValue", { + old: null, + valid: true, + message: this.defaultMessage( element, { method: method } ) + } ); + }, + + // Cleans up all forms and elements, removes validator-specific events + destroy: function() { + this.resetForm(); + + $( this.currentForm ) + .off( ".validate" ) + .removeData( "validator" ) + .find( ".validate-equalTo-blur" ) + .off( ".validate-equalTo" ) + .removeClass( "validate-equalTo-blur" ); + } + + }, + + classRuleSettings: { + required: { required: true }, + email: { email: true }, + url: { url: true }, + date: { date: true }, + dateISO: { dateISO: true }, + number: { number: true }, + digits: { digits: true }, + creditcard: { creditcard: true } + }, + + addClassRules: function( className, rules ) { + if ( className.constructor === String ) { + this.classRuleSettings[ className ] = rules; + } else { + $.extend( this.classRuleSettings, className ); + } + }, + + classRules: function( element ) { + var rules = {}, + classes = $( element ).attr( "class" ); + + if ( classes ) { + $.each( classes.split( " " ), function() { + if ( this in $.validator.classRuleSettings ) { + $.extend( rules, $.validator.classRuleSettings[ this ] ); + } + } ); + } + return rules; + }, + + normalizeAttributeRule: function( rules, type, method, value ) { + + // Convert the value to a number for number inputs, and for text for backwards compability + // allows type="date" and others to be compared as strings + if ( /min|max|step/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) { + value = Number( value ); + + // Support Opera Mini, which returns NaN for undefined minlength + if ( isNaN( value ) ) { + value = undefined; + } + } + + if ( value || value === 0 ) { + rules[ method ] = value; + } else if ( type === method && type !== "range" ) { + + // Exception: the jquery validate 'range' method + // does not test for the html5 'range' type + rules[ method ] = true; + } + }, + + attributeRules: function( element ) { + var rules = {}, + $element = $( element ), + type = element.getAttribute( "type" ), + method, value; + + for ( method in $.validator.methods ) { + + // Support for in both html5 and older browsers + if ( method === "required" ) { + value = element.getAttribute( method ); + + // Some browsers return an empty string for the required attribute + // and non-HTML5 browsers might have required="" markup + if ( value === "" ) { + value = true; + } + + // Force non-HTML5 browsers to return bool + value = !!value; + } else { + value = $element.attr( method ); + } + + this.normalizeAttributeRule( rules, type, method, value ); + } + + // 'maxlength' may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs + if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) { + delete rules.maxlength; + } + + return rules; + }, + + dataRules: function( element ) { + var rules = {}, + $element = $( element ), + type = element.getAttribute( "type" ), + method, value; + + for ( method in $.validator.methods ) { + value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() ); + this.normalizeAttributeRule( rules, type, method, value ); + } + return rules; + }, + + staticRules: function( element ) { + var rules = {}, + validator = $.data( element.form, "validator" ); + + if ( validator.settings.rules ) { + rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {}; + } + return rules; + }, + + normalizeRules: function( rules, element ) { + + // Handle dependency check + $.each( rules, function( prop, val ) { + + // Ignore rule when param is explicitly false, eg. required:false + if ( val === false ) { + delete rules[ prop ]; + return; + } + if ( val.param || val.depends ) { + var keepRule = true; + switch ( typeof val.depends ) { + case "string": + keepRule = !!$( val.depends, element.form ).length; + break; + case "function": + keepRule = val.depends.call( element, element ); + break; + } + if ( keepRule ) { + rules[ prop ] = val.param !== undefined ? val.param : true; + } else { + $.data( element.form, "validator" ).resetElements( $( element ) ); + delete rules[ prop ]; + } + } + } ); + + // Evaluate parameters + $.each( rules, function( rule, parameter ) { + rules[ rule ] = $.isFunction( parameter ) && rule !== "normalizer" ? parameter( element ) : parameter; + } ); + + // Clean number parameters + $.each( [ "minlength", "maxlength" ], function() { + if ( rules[ this ] ) { + rules[ this ] = Number( rules[ this ] ); + } + } ); + $.each( [ "rangelength", "range" ], function() { + var parts; + if ( rules[ this ] ) { + if ( $.isArray( rules[ this ] ) ) { + rules[ this ] = [ Number( rules[ this ][ 0 ] ), Number( rules[ this ][ 1 ] ) ]; + } else if ( typeof rules[ this ] === "string" ) { + parts = rules[ this ].replace( /[\[\]]/g, "" ).split( /[\s,]+/ ); + rules[ this ] = [ Number( parts[ 0 ] ), Number( parts[ 1 ] ) ]; + } + } + } ); + + if ( $.validator.autoCreateRanges ) { + + // Auto-create ranges + if ( rules.min != null && rules.max != null ) { + rules.range = [ rules.min, rules.max ]; + delete rules.min; + delete rules.max; + } + if ( rules.minlength != null && rules.maxlength != null ) { + rules.rangelength = [ rules.minlength, rules.maxlength ]; + delete rules.minlength; + delete rules.maxlength; + } + } + + return rules; + }, + + // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} + normalizeRule: function( data ) { + if ( typeof data === "string" ) { + var transformed = {}; + $.each( data.split( /\s/ ), function() { + transformed[ this ] = true; + } ); + data = transformed; + } + return data; + }, + + // https://jqueryvalidation.org/jQuery.validator.addMethod/ + addMethod: function( name, method, message ) { + $.validator.methods[ name ] = method; + $.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ]; + if ( method.length < 3 ) { + $.validator.addClassRules( name, $.validator.normalizeRule( name ) ); + } + }, + + // https://jqueryvalidation.org/jQuery.validator.methods/ + methods: { + + // https://jqueryvalidation.org/required-method/ + required: function( value, element, param ) { + + // Check if dependency is met + if ( !this.depend( param, element ) ) { + return "dependency-mismatch"; + } + if ( element.nodeName.toLowerCase() === "select" ) { + + // Could be an array for select-multiple or a string, both are fine this way + var val = $( element ).val(); + return val && val.length > 0; + } + if ( this.checkable( element ) ) { + return this.getLength( value, element ) > 0; + } + return value.length > 0; + }, + + // https://jqueryvalidation.org/email-method/ + email: function( value, element ) { + + // From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address + // Retrieved 2014-01-14 + // If you have a problem with this implementation, report a bug against the above spec + // Or use custom methods to implement your own email validation + return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value ); + }, + + // https://jqueryvalidation.org/url-method/ + url: function( value, element ) { + + // Copyright (c) 2010-2013 Diego Perini, MIT licensed + // https://gist.github.com/dperini/729294 + // see also https://mathiasbynens.be/demo/url-regex + // modified to allow protocol-relative URLs + return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value ); + }, + + // https://jqueryvalidation.org/date-method/ + date: function( value, element ) { + return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() ); + }, + + // https://jqueryvalidation.org/dateISO-method/ + dateISO: function( value, element ) { + return this.optional( element ) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value ); + }, + + // https://jqueryvalidation.org/number-method/ + number: function( value, element ) { + return this.optional( element ) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value ); + }, + + // https://jqueryvalidation.org/digits-method/ + digits: function( value, element ) { + return this.optional( element ) || /^\d+$/.test( value ); + }, + + // https://jqueryvalidation.org/minlength-method/ + minlength: function( value, element, param ) { + var length = $.isArray( value ) ? value.length : this.getLength( value, element ); + return this.optional( element ) || length >= param; + }, + + // https://jqueryvalidation.org/maxlength-method/ + maxlength: function( value, element, param ) { + var length = $.isArray( value ) ? value.length : this.getLength( value, element ); + return this.optional( element ) || length <= param; + }, + + // https://jqueryvalidation.org/rangelength-method/ + rangelength: function( value, element, param ) { + var length = $.isArray( value ) ? value.length : this.getLength( value, element ); + return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] ); + }, + + // https://jqueryvalidation.org/min-method/ + min: function( value, element, param ) { + return this.optional( element ) || value >= param; + }, + + // https://jqueryvalidation.org/max-method/ + max: function( value, element, param ) { + return this.optional( element ) || value <= param; + }, + + // https://jqueryvalidation.org/range-method/ + range: function( value, element, param ) { + return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] ); + }, + + // https://jqueryvalidation.org/step-method/ + step: function( value, element, param ) { + var type = $( element ).attr( "type" ), + errorMessage = "Step attribute on input type " + type + " is not supported.", + supportedTypes = [ "text", "number", "range" ], + re = new RegExp( "\\b" + type + "\\b" ), + notSupported = type && !re.test( supportedTypes.join() ), + decimalPlaces = function( num ) { + var match = ( "" + num ).match( /(?:\.(\d+))?$/ ); + if ( !match ) { + return 0; + } + + // Number of digits right of decimal point. + return match[ 1 ] ? match[ 1 ].length : 0; + }, + toInt = function( num ) { + return Math.round( num * Math.pow( 10, decimals ) ); + }, + valid = true, + decimals; + + // Works only for text, number and range input types + // TODO find a way to support input types date, datetime, datetime-local, month, time and week + if ( notSupported ) { + throw new Error( errorMessage ); + } + + decimals = decimalPlaces( param ); + + // Value can't have too many decimals + if ( decimalPlaces( value ) > decimals || toInt( value ) % toInt( param ) !== 0 ) { + valid = false; + } + + return this.optional( element ) || valid; + }, + + // https://jqueryvalidation.org/equalTo-method/ + equalTo: function( value, element, param ) { + + // Bind to the blur event of the target in order to revalidate whenever the target field is updated + var target = $( param ); + if ( this.settings.onfocusout && target.not( ".validate-equalTo-blur" ).length ) { + target.addClass( "validate-equalTo-blur" ).on( "blur.validate-equalTo", function() { + $( element ).valid(); + } ); + } + return value === target.val(); + }, + + // https://jqueryvalidation.org/remote-method/ + remote: function( value, element, param, method ) { + if ( this.optional( element ) ) { + return "dependency-mismatch"; + } + + method = typeof method === "string" && method || "remote"; + + var previous = this.previousValue( element, method ), + validator, data, optionDataString; + + if ( !this.settings.messages[ element.name ] ) { + this.settings.messages[ element.name ] = {}; + } + previous.originalMessage = previous.originalMessage || this.settings.messages[ element.name ][ method ]; + this.settings.messages[ element.name ][ method ] = previous.message; + + param = typeof param === "string" && { url: param } || param; + optionDataString = $.param( $.extend( { data: value }, param.data ) ); + if ( previous.old === optionDataString ) { + return previous.valid; + } + + previous.old = optionDataString; + validator = this; + this.startRequest( element ); + data = {}; + data[ element.name ] = value; + $.ajax( $.extend( true, { + mode: "abort", + port: "validate" + element.name, + dataType: "json", + data: data, + context: validator.currentForm, + success: function( response ) { + var valid = response === true || response === "true", + errors, message, submitted; + + validator.settings.messages[ element.name ][ method ] = previous.originalMessage; + if ( valid ) { + submitted = validator.formSubmitted; + validator.resetInternals(); + validator.toHide = validator.errorsFor( element ); + validator.formSubmitted = submitted; + validator.successList.push( element ); + validator.invalid[ element.name ] = false; + validator.showErrors(); + } else { + errors = {}; + message = response || validator.defaultMessage( element, { method: method, parameters: value } ); + errors[ element.name ] = previous.message = message; + validator.invalid[ element.name ] = true; + validator.showErrors( errors ); + } + previous.valid = valid; + validator.stopRequest( element, valid ); + } + }, param ) ); + return "pending"; + } + } + +} ); + +// Ajax mode: abort +// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); +// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() + +var pendingRequests = {}, + ajax; + +// Use a prefilter if available (1.5+) +if ( $.ajaxPrefilter ) { + $.ajaxPrefilter( function( settings, _, xhr ) { + var port = settings.port; + if ( settings.mode === "abort" ) { + if ( pendingRequests[ port ] ) { + pendingRequests[ port ].abort(); + } + pendingRequests[ port ] = xhr; + } + } ); +} else { + + // Proxy ajax + ajax = $.ajax; + $.ajax = function( settings ) { + var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode, + port = ( "port" in settings ? settings : $.ajaxSettings ).port; + if ( mode === "abort" ) { + if ( pendingRequests[ port ] ) { + pendingRequests[ port ].abort(); + } + pendingRequests[ port ] = ajax.apply( this, arguments ); + return pendingRequests[ port ]; + } + return ajax.apply( this, arguments ); + }; +} +return $; +})); \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ar.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ar.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ar.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ar.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_az.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_az.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_az.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_az.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_bg.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_bg.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_bg.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_bg.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_bn_BD.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_bn_BD.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_bn_BD.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_bn_BD.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ca.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ca.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ca.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ca.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_cs.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_cs.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_cs.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_cs.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_da.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_da.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_da.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_da.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_de.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_de.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_de.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_de.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_el.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_el.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_el.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_el.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_es.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_es.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_es.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_es.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_es_AR.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_es_AR.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_es_AR.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_es_AR.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_es_PE.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_es_PE.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_es_PE.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_es_PE.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_et.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_et.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_et.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_et.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_eu.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_eu.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_eu.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_eu.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_fa.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_fa.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_fa.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_fa.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_fi.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_fi.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_fi.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_fi.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_fr.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_fr.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_fr.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_fr.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ge.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ge.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ge.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ge.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_gl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_gl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_gl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_gl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_he.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_he.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_he.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_he.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_hr.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_hr.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_hr.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_hr.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_hu.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_hu.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_hu.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_hu.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_hy_AM.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_hy_AM.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_hy_AM.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_hy_AM.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_id.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_id.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_id.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_id.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_is.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_is.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_is.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_is.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_it.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_it.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_it.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_it.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ja.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ja.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ja.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ja.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ka.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ka.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ka.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ka.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_kk.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_kk.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_kk.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_kk.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ko.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ko.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ko.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ko.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_lt.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_lt.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_lt.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_lt.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_lv.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_lv.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_lv.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_lv.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_mk.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_mk.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_mk.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_mk.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_my.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_my.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_my.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_my.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_nl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_nl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_nl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_nl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_no.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_no.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_no.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_no.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_pl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_pl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_pl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_pl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_pt_BR.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_pt_BR.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_pt_BR.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_pt_BR.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_pt_PT.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_pt_PT.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_pt_PT.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_pt_PT.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ro.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ro.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ro.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ro.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ru.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ru.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ru.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ru.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sd.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sd.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sd.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sd.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_si.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_si.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_si.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_si.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sk.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sk.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sk.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sk.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sr.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sr.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sr.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sr.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sr_lat.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sr_lat.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sr_lat.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sr_lat.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sv.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sv.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sv.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_sv.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_th.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_th.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_th.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_th.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_tj.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_tj.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_tj.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_tj.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_tr.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_tr.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_tr.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_tr.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_uk.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_uk.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_uk.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_uk.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ur.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ur.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ur.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_ur.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_vi.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_vi.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_vi.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_vi.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_zh.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_zh.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_zh.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_zh.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_zh_TW.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_zh_TW.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_zh_TW.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/messages_zh_TW.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_de.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_de.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_de.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_de.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_es_CL.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_es_CL.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_es_CL.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_es_CL.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_fi.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_fi.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_fi.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_fi.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_nl.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_nl.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_nl.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_nl.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_pt.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_pt.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_pt.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery-validation/localization/methods_pt.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery/jquery.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery/jquery.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery/jquery.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/jquery/jquery.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/lodash/lodash.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/lodash/lodash.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/lodash/lodash.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/lodash/lodash.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.js.map b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.js.map similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.js.map rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.js.map diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.min.js similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.min.js rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.min.js diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.min.js.map b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.min.js.map similarity index 100% rename from framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.min.js.map rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/luxon/luxon.min.js.map diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js new file mode 100644 index 0000000000..611808654e --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js @@ -0,0 +1,5 @@ +/* == jquery mousewheel plugin == Version: 3.1.13, License: MIT License (MIT) */ +!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})}); +/* == malihu jquery custom scrollbar plugin == Version: 3.1.5, License: MIT License (MIT) */ +!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"undefined"!=typeof module&&module.exports?module.exports=e:e(jQuery,window,document)}(function(e){!function(t){var o="function"==typeof define&&define.amd,a="undefined"!=typeof module&&module.exports,n="https:"==document.location.protocol?"https:":"http:",i="cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js";o||(a?require("jquery-mousewheel")(e):e.event.special.mousewheel||e("head").append(decodeURI("%3Cscript src="+n+"//"+i+"%3E%3C/script%3E"))),t()}(function(){var t,o="mCustomScrollbar",a="mCS",n=".mCustomScrollbar",i={setTop:0,setLeft:0,axis:"y",scrollbarPosition:"inside",scrollInertia:950,autoDraggerLength:!0,alwaysShowScrollbar:0,snapOffset:0,mouseWheel:{enable:!0,scrollAmount:"auto",axis:"y",deltaFactor:"auto",disableOver:["select","option","keygen","datalist","textarea"]},scrollButtons:{scrollType:"stepless",scrollAmount:"auto"},keyboard:{enable:!0,scrollType:"stepless",scrollAmount:"auto"},contentTouchScroll:25,documentTouchScroll:!0,advanced:{autoScrollOnFocus:"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']",updateOnContentResize:!0,updateOnImageLoad:"auto",autoUpdateTimeout:60},theme:"light",callbacks:{onTotalScrollOffset:0,onTotalScrollBackOffset:0,alwaysTriggerOffsets:!0}},r=0,l={},s=window.attachEvent&&!window.addEventListener?1:0,c=!1,d=["mCSB_dragger_onDrag","mCSB_scrollTools_onDrag","mCS_img_loaded","mCS_disabled","mCS_destroyed","mCS_no_scrollbar","mCS-autoHide","mCS-dir-rtl","mCS_no_scrollbar_y","mCS_no_scrollbar_x","mCS_y_hidden","mCS_x_hidden","mCSB_draggerContainer","mCSB_buttonUp","mCSB_buttonDown","mCSB_buttonLeft","mCSB_buttonRight"],u={init:function(t){var t=e.extend(!0,{},i,t),o=f.call(this);if(t.live){var s=t.liveSelector||this.selector||n,c=e(s);if("off"===t.live)return void m(s);l[s]=setTimeout(function(){c.mCustomScrollbar(t),"once"===t.live&&c.length&&m(s)},500)}else m(s);return t.setWidth=t.set_width?t.set_width:t.setWidth,t.setHeight=t.set_height?t.set_height:t.setHeight,t.axis=t.horizontalScroll?"x":p(t.axis),t.scrollInertia=t.scrollInertia>0&&t.scrollInertia<17?17:t.scrollInertia,"object"!=typeof t.mouseWheel&&1==t.mouseWheel&&(t.mouseWheel={enable:!0,scrollAmount:"auto",axis:"y",preventDefault:!1,deltaFactor:"auto",normalizeDelta:!1,invert:!1}),t.mouseWheel.scrollAmount=t.mouseWheelPixels?t.mouseWheelPixels:t.mouseWheel.scrollAmount,t.mouseWheel.normalizeDelta=t.advanced.normalizeMouseWheelDelta?t.advanced.normalizeMouseWheelDelta:t.mouseWheel.normalizeDelta,t.scrollButtons.scrollType=g(t.scrollButtons.scrollType),h(t),e(o).each(function(){var o=e(this);if(!o.data(a)){o.data(a,{idx:++r,opt:t,scrollRatio:{y:null,x:null},overflowed:null,contentReset:{y:null,x:null},bindEvents:!1,tweenRunning:!1,sequential:{},langDir:o.css("direction"),cbOffsets:null,trigger:null,poll:{size:{o:0,n:0},img:{o:0,n:0},change:{o:0,n:0}}});var n=o.data(a),i=n.opt,l=o.data("mcs-axis"),s=o.data("mcs-scrollbar-position"),c=o.data("mcs-theme");l&&(i.axis=l),s&&(i.scrollbarPosition=s),c&&(i.theme=c,h(i)),v.call(this),n&&i.callbacks.onCreate&&"function"==typeof i.callbacks.onCreate&&i.callbacks.onCreate.call(this),e("#mCSB_"+n.idx+"_container img:not(."+d[2]+")").addClass(d[2]),u.update.call(null,o)}})},update:function(t,o){var n=t||f.call(this);return e(n).each(function(){var t=e(this);if(t.data(a)){var n=t.data(a),i=n.opt,r=e("#mCSB_"+n.idx+"_container"),l=e("#mCSB_"+n.idx),s=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")];if(!r.length)return;n.tweenRunning&&Q(t),o&&n&&i.callbacks.onBeforeUpdate&&"function"==typeof i.callbacks.onBeforeUpdate&&i.callbacks.onBeforeUpdate.call(this),t.hasClass(d[3])&&t.removeClass(d[3]),t.hasClass(d[4])&&t.removeClass(d[4]),l.css("max-height","none"),l.height()!==t.height()&&l.css("max-height",t.height()),_.call(this),"y"===i.axis||i.advanced.autoExpandHorizontalScroll||r.css("width",x(r)),n.overflowed=y.call(this),M.call(this),i.autoDraggerLength&&S.call(this),b.call(this),T.call(this);var c=[Math.abs(r[0].offsetTop),Math.abs(r[0].offsetLeft)];"x"!==i.axis&&(n.overflowed[0]?s[0].height()>s[0].parent().height()?B.call(this):(G(t,c[0].toString(),{dir:"y",dur:0,overwrite:"none"}),n.contentReset.y=null):(B.call(this),"y"===i.axis?k.call(this):"yx"===i.axis&&n.overflowed[1]&&G(t,c[1].toString(),{dir:"x",dur:0,overwrite:"none"}))),"y"!==i.axis&&(n.overflowed[1]?s[1].width()>s[1].parent().width()?B.call(this):(G(t,c[1].toString(),{dir:"x",dur:0,overwrite:"none"}),n.contentReset.x=null):(B.call(this),"x"===i.axis?k.call(this):"yx"===i.axis&&n.overflowed[0]&&G(t,c[0].toString(),{dir:"y",dur:0,overwrite:"none"}))),o&&n&&(2===o&&i.callbacks.onImageLoad&&"function"==typeof i.callbacks.onImageLoad?i.callbacks.onImageLoad.call(this):3===o&&i.callbacks.onSelectorChange&&"function"==typeof i.callbacks.onSelectorChange?i.callbacks.onSelectorChange.call(this):i.callbacks.onUpdate&&"function"==typeof i.callbacks.onUpdate&&i.callbacks.onUpdate.call(this)),N.call(this)}})},scrollTo:function(t,o){if("undefined"!=typeof t&&null!=t){var n=f.call(this);return e(n).each(function(){var n=e(this);if(n.data(a)){var i=n.data(a),r=i.opt,l={trigger:"external",scrollInertia:r.scrollInertia,scrollEasing:"mcsEaseInOut",moveDragger:!1,timeout:60,callbacks:!0,onStart:!0,onUpdate:!0,onComplete:!0},s=e.extend(!0,{},l,o),c=Y.call(this,t),d=s.scrollInertia>0&&s.scrollInertia<17?17:s.scrollInertia;c[0]=X.call(this,c[0],"y"),c[1]=X.call(this,c[1],"x"),s.moveDragger&&(c[0]*=i.scrollRatio.y,c[1]*=i.scrollRatio.x),s.dur=ne()?0:d,setTimeout(function(){null!==c[0]&&"undefined"!=typeof c[0]&&"x"!==r.axis&&i.overflowed[0]&&(s.dir="y",s.overwrite="all",G(n,c[0].toString(),s)),null!==c[1]&&"undefined"!=typeof c[1]&&"y"!==r.axis&&i.overflowed[1]&&(s.dir="x",s.overwrite="none",G(n,c[1].toString(),s))},s.timeout)}})}},stop:function(){var t=f.call(this);return e(t).each(function(){var t=e(this);t.data(a)&&Q(t)})},disable:function(t){var o=f.call(this);return e(o).each(function(){var o=e(this);if(o.data(a)){o.data(a);N.call(this,"remove"),k.call(this),t&&B.call(this),M.call(this,!0),o.addClass(d[3])}})},destroy:function(){var t=f.call(this);return e(t).each(function(){var n=e(this);if(n.data(a)){var i=n.data(a),r=i.opt,l=e("#mCSB_"+i.idx),s=e("#mCSB_"+i.idx+"_container"),c=e(".mCSB_"+i.idx+"_scrollbar");r.live&&m(r.liveSelector||e(t).selector),N.call(this,"remove"),k.call(this),B.call(this),n.removeData(a),$(this,"mcs"),c.remove(),s.find("img."+d[2]).removeClass(d[2]),l.replaceWith(s.contents()),n.removeClass(o+" _"+a+"_"+i.idx+" "+d[6]+" "+d[7]+" "+d[5]+" "+d[3]).addClass(d[4])}})}},f=function(){return"object"!=typeof e(this)||e(this).length<1?n:this},h=function(t){var o=["rounded","rounded-dark","rounded-dots","rounded-dots-dark"],a=["rounded-dots","rounded-dots-dark","3d","3d-dark","3d-thick","3d-thick-dark","inset","inset-dark","inset-2","inset-2-dark","inset-3","inset-3-dark"],n=["minimal","minimal-dark"],i=["minimal","minimal-dark"],r=["minimal","minimal-dark"];t.autoDraggerLength=e.inArray(t.theme,o)>-1?!1:t.autoDraggerLength,t.autoExpandScrollbar=e.inArray(t.theme,a)>-1?!1:t.autoExpandScrollbar,t.scrollButtons.enable=e.inArray(t.theme,n)>-1?!1:t.scrollButtons.enable,t.autoHideScrollbar=e.inArray(t.theme,i)>-1?!0:t.autoHideScrollbar,t.scrollbarPosition=e.inArray(t.theme,r)>-1?"outside":t.scrollbarPosition},m=function(e){l[e]&&(clearTimeout(l[e]),$(l,e))},p=function(e){return"yx"===e||"xy"===e||"auto"===e?"yx":"x"===e||"horizontal"===e?"x":"y"},g=function(e){return"stepped"===e||"pixels"===e||"step"===e||"click"===e?"stepped":"stepless"},v=function(){var t=e(this),n=t.data(a),i=n.opt,r=i.autoExpandScrollbar?" "+d[1]+"_expand":"",l=["
    ","
    "],s="yx"===i.axis?"mCSB_vertical_horizontal":"x"===i.axis?"mCSB_horizontal":"mCSB_vertical",c="yx"===i.axis?l[0]+l[1]:"x"===i.axis?l[1]:l[0],u="yx"===i.axis?"
    ":"",f=i.autoHideScrollbar?" "+d[6]:"",h="x"!==i.axis&&"rtl"===n.langDir?" "+d[7]:"";i.setWidth&&t.css("width",i.setWidth),i.setHeight&&t.css("height",i.setHeight),i.setLeft="y"!==i.axis&&"rtl"===n.langDir?"989999px":i.setLeft,t.addClass(o+" _"+a+"_"+n.idx+f+h).wrapInner("
    ");var m=e("#mCSB_"+n.idx),p=e("#mCSB_"+n.idx+"_container");"y"===i.axis||i.advanced.autoExpandHorizontalScroll||p.css("width",x(p)),"outside"===i.scrollbarPosition?("static"===t.css("position")&&t.css("position","relative"),t.css("overflow","visible"),m.addClass("mCSB_outside").after(c)):(m.addClass("mCSB_inside").append(c),p.wrap(u)),w.call(this);var g=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")];g[0].css("min-height",g[0].height()),g[1].css("min-width",g[1].width())},x=function(t){var o=[t[0].scrollWidth,Math.max.apply(Math,t.children().map(function(){return e(this).outerWidth(!0)}).get())],a=t.parent().width();return o[0]>a?o[0]:o[1]>a?o[1]:"100%"},_=function(){var t=e(this),o=t.data(a),n=o.opt,i=e("#mCSB_"+o.idx+"_container");if(n.advanced.autoExpandHorizontalScroll&&"y"!==n.axis){i.css({width:"auto","min-width":0,"overflow-x":"scroll"});var r=Math.ceil(i[0].scrollWidth);3===n.advanced.autoExpandHorizontalScroll||2!==n.advanced.autoExpandHorizontalScroll&&r>i.parent().width()?i.css({width:r,"min-width":"100%","overflow-x":"inherit"}):i.css({"overflow-x":"inherit",position:"absolute"}).wrap("
    ").css({width:Math.ceil(i[0].getBoundingClientRect().right+.4)-Math.floor(i[0].getBoundingClientRect().left),"min-width":"100%",position:"relative"}).unwrap()}},w=function(){var t=e(this),o=t.data(a),n=o.opt,i=e(".mCSB_"+o.idx+"_scrollbar:first"),r=oe(n.scrollButtons.tabindex)?"tabindex='"+n.scrollButtons.tabindex+"'":"",l=["","","",""],s=["x"===n.axis?l[2]:l[0],"x"===n.axis?l[3]:l[1],l[2],l[3]];n.scrollButtons.enable&&i.prepend(s[0]).append(s[1]).next(".mCSB_scrollTools").prepend(s[2]).append(s[3])},S=function(){var t=e(this),o=t.data(a),n=e("#mCSB_"+o.idx),i=e("#mCSB_"+o.idx+"_container"),r=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")],l=[n.height()/i.outerHeight(!1),n.width()/i.outerWidth(!1)],c=[parseInt(r[0].css("min-height")),Math.round(l[0]*r[0].parent().height()),parseInt(r[1].css("min-width")),Math.round(l[1]*r[1].parent().width())],d=s&&c[1]r&&(r=s),c>l&&(l=c),[r>n.height(),l>n.width()]},B=function(){var t=e(this),o=t.data(a),n=o.opt,i=e("#mCSB_"+o.idx),r=e("#mCSB_"+o.idx+"_container"),l=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")];if(Q(t),("x"!==n.axis&&!o.overflowed[0]||"y"===n.axis&&o.overflowed[0])&&(l[0].add(r).css("top",0),G(t,"_resetY")),"y"!==n.axis&&!o.overflowed[1]||"x"===n.axis&&o.overflowed[1]){var s=dx=0;"rtl"===o.langDir&&(s=i.width()-r.outerWidth(!1),dx=Math.abs(s/o.scrollRatio.x)),r.css("left",s),l[1].css("left",dx),G(t,"_resetX")}},T=function(){function t(){r=setTimeout(function(){e.event.special.mousewheel?(clearTimeout(r),W.call(o[0])):t()},100)}var o=e(this),n=o.data(a),i=n.opt;if(!n.bindEvents){if(I.call(this),i.contentTouchScroll&&D.call(this),E.call(this),i.mouseWheel.enable){var r;t()}P.call(this),U.call(this),i.advanced.autoScrollOnFocus&&H.call(this),i.scrollButtons.enable&&F.call(this),i.keyboard.enable&&q.call(this),n.bindEvents=!0}},k=function(){var t=e(this),o=t.data(a),n=o.opt,i=a+"_"+o.idx,r=".mCSB_"+o.idx+"_scrollbar",l=e("#mCSB_"+o.idx+",#mCSB_"+o.idx+"_container,#mCSB_"+o.idx+"_container_wrapper,"+r+" ."+d[12]+",#mCSB_"+o.idx+"_dragger_vertical,#mCSB_"+o.idx+"_dragger_horizontal,"+r+">a"),s=e("#mCSB_"+o.idx+"_container");n.advanced.releaseDraggableSelectors&&l.add(e(n.advanced.releaseDraggableSelectors)),n.advanced.extraDraggableSelectors&&l.add(e(n.advanced.extraDraggableSelectors)),o.bindEvents&&(e(document).add(e(!A()||top.document)).unbind("."+i),l.each(function(){e(this).unbind("."+i)}),clearTimeout(t[0]._focusTimeout),$(t[0],"_focusTimeout"),clearTimeout(o.sequential.step),$(o.sequential,"step"),clearTimeout(s[0].onCompleteTimeout),$(s[0],"onCompleteTimeout"),o.bindEvents=!1)},M=function(t){var o=e(this),n=o.data(a),i=n.opt,r=e("#mCSB_"+n.idx+"_container_wrapper"),l=r.length?r:e("#mCSB_"+n.idx+"_container"),s=[e("#mCSB_"+n.idx+"_scrollbar_vertical"),e("#mCSB_"+n.idx+"_scrollbar_horizontal")],c=[s[0].find(".mCSB_dragger"),s[1].find(".mCSB_dragger")];"x"!==i.axis&&(n.overflowed[0]&&!t?(s[0].add(c[0]).add(s[0].children("a")).css("display","block"),l.removeClass(d[8]+" "+d[10])):(i.alwaysShowScrollbar?(2!==i.alwaysShowScrollbar&&c[0].css("display","none"),l.removeClass(d[10])):(s[0].css("display","none"),l.addClass(d[10])),l.addClass(d[8]))),"y"!==i.axis&&(n.overflowed[1]&&!t?(s[1].add(c[1]).add(s[1].children("a")).css("display","block"),l.removeClass(d[9]+" "+d[11])):(i.alwaysShowScrollbar?(2!==i.alwaysShowScrollbar&&c[1].css("display","none"),l.removeClass(d[11])):(s[1].css("display","none"),l.addClass(d[11])),l.addClass(d[9]))),n.overflowed[0]||n.overflowed[1]?o.removeClass(d[5]):o.addClass(d[5])},O=function(t){var o=t.type,a=t.target.ownerDocument!==document&&null!==frameElement?[e(frameElement).offset().top,e(frameElement).offset().left]:null,n=A()&&t.target.ownerDocument!==top.document&&null!==frameElement?[e(t.view.frameElement).offset().top,e(t.view.frameElement).offset().left]:[0,0];switch(o){case"pointerdown":case"MSPointerDown":case"pointermove":case"MSPointerMove":case"pointerup":case"MSPointerUp":return a?[t.originalEvent.pageY-a[0]+n[0],t.originalEvent.pageX-a[1]+n[1],!1]:[t.originalEvent.pageY,t.originalEvent.pageX,!1];case"touchstart":case"touchmove":case"touchend":var i=t.originalEvent.touches[0]||t.originalEvent.changedTouches[0],r=t.originalEvent.touches.length||t.originalEvent.changedTouches.length;return t.target.ownerDocument!==document?[i.screenY,i.screenX,r>1]:[i.pageY,i.pageX,r>1];default:return a?[t.pageY-a[0]+n[0],t.pageX-a[1]+n[1],!1]:[t.pageY,t.pageX,!1]}},I=function(){function t(e,t,a,n){if(h[0].idleTimer=d.scrollInertia<233?250:0,o.attr("id")===f[1])var i="x",s=(o[0].offsetLeft-t+n)*l.scrollRatio.x;else var i="y",s=(o[0].offsetTop-e+a)*l.scrollRatio.y;G(r,s.toString(),{dir:i,drag:!0})}var o,n,i,r=e(this),l=r.data(a),d=l.opt,u=a+"_"+l.idx,f=["mCSB_"+l.idx+"_dragger_vertical","mCSB_"+l.idx+"_dragger_horizontal"],h=e("#mCSB_"+l.idx+"_container"),m=e("#"+f[0]+",#"+f[1]),p=d.advanced.releaseDraggableSelectors?m.add(e(d.advanced.releaseDraggableSelectors)):m,g=d.advanced.extraDraggableSelectors?e(!A()||top.document).add(e(d.advanced.extraDraggableSelectors)):e(!A()||top.document);m.bind("contextmenu."+u,function(e){e.preventDefault()}).bind("mousedown."+u+" touchstart."+u+" pointerdown."+u+" MSPointerDown."+u,function(t){if(t.stopImmediatePropagation(),t.preventDefault(),ee(t)){c=!0,s&&(document.onselectstart=function(){return!1}),L.call(h,!1),Q(r),o=e(this);var a=o.offset(),l=O(t)[0]-a.top,u=O(t)[1]-a.left,f=o.height()+a.top,m=o.width()+a.left;f>l&&l>0&&m>u&&u>0&&(n=l,i=u),C(o,"active",d.autoExpandScrollbar)}}).bind("touchmove."+u,function(e){e.stopImmediatePropagation(),e.preventDefault();var a=o.offset(),r=O(e)[0]-a.top,l=O(e)[1]-a.left;t(n,i,r,l)}),e(document).add(g).bind("mousemove."+u+" pointermove."+u+" MSPointerMove."+u,function(e){if(o){var a=o.offset(),r=O(e)[0]-a.top,l=O(e)[1]-a.left;if(n===r&&i===l)return;t(n,i,r,l)}}).add(p).bind("mouseup."+u+" touchend."+u+" pointerup."+u+" MSPointerUp."+u,function(){o&&(C(o,"active",d.autoExpandScrollbar),o=null),c=!1,s&&(document.onselectstart=null),L.call(h,!0)})},D=function(){function o(e){if(!te(e)||c||O(e)[2])return void(t=0);t=1,b=0,C=0,d=1,y.removeClass("mCS_touch_action");var o=I.offset();u=O(e)[0]-o.top,f=O(e)[1]-o.left,z=[O(e)[0],O(e)[1]]}function n(e){if(te(e)&&!c&&!O(e)[2]&&(T.documentTouchScroll||e.preventDefault(),e.stopImmediatePropagation(),(!C||b)&&d)){g=K();var t=M.offset(),o=O(e)[0]-t.top,a=O(e)[1]-t.left,n="mcsLinearOut";if(E.push(o),W.push(a),z[2]=Math.abs(O(e)[0]-z[0]),z[3]=Math.abs(O(e)[1]-z[1]),B.overflowed[0])var i=D[0].parent().height()-D[0].height(),r=u-o>0&&o-u>-(i*B.scrollRatio.y)&&(2*z[3]0&&a-f>-(l*B.scrollRatio.x)&&(2*z[2]30)){_=1e3/(v-p);var n="mcsEaseOut",i=2.5>_,r=i?[E[E.length-2],W[W.length-2]]:[0,0];x=i?[o-r[0],a-r[1]]:[o-h,a-m];var u=[Math.abs(x[0]),Math.abs(x[1])];_=i?[Math.abs(x[0]/4),Math.abs(x[1]/4)]:[_,_];var f=[Math.abs(I[0].offsetTop)-x[0]*l(u[0]/_[0],_[0]),Math.abs(I[0].offsetLeft)-x[1]*l(u[1]/_[1],_[1])];w="yx"===T.axis?[f[0],f[1]]:"x"===T.axis?[null,f[1]]:[f[0],null],S=[4*u[0]+T.scrollInertia,4*u[1]+T.scrollInertia];var y=parseInt(T.contentTouchScroll)||0;w[0]=u[0]>y?w[0]:0,w[1]=u[1]>y?w[1]:0,B.overflowed[0]&&s(w[0],S[0],n,"y",L,!1),B.overflowed[1]&&s(w[1],S[1],n,"x",L,!1)}}}function l(e,t){var o=[1.5*t,2*t,t/1.5,t/2];return e>90?t>4?o[0]:o[3]:e>60?t>3?o[3]:o[2]:e>30?t>8?o[1]:t>6?o[0]:t>4?t:o[2]:t>8?t:o[3]}function s(e,t,o,a,n,i){e&&G(y,e.toString(),{dur:t,scrollEasing:o,dir:a,overwrite:n,drag:i})}var d,u,f,h,m,p,g,v,x,_,w,S,b,C,y=e(this),B=y.data(a),T=B.opt,k=a+"_"+B.idx,M=e("#mCSB_"+B.idx),I=e("#mCSB_"+B.idx+"_container"),D=[e("#mCSB_"+B.idx+"_dragger_vertical"),e("#mCSB_"+B.idx+"_dragger_horizontal")],E=[],W=[],R=0,L="yx"===T.axis?"none":"all",z=[],P=I.find("iframe"),H=["touchstart."+k+" pointerdown."+k+" MSPointerDown."+k,"touchmove."+k+" pointermove."+k+" MSPointerMove."+k,"touchend."+k+" pointerup."+k+" MSPointerUp."+k],U=void 0!==document.body.style.touchAction&&""!==document.body.style.touchAction;I.bind(H[0],function(e){o(e)}).bind(H[1],function(e){n(e)}),M.bind(H[0],function(e){i(e)}).bind(H[2],function(e){r(e)}),P.length&&P.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind(H[0],function(e){o(e),i(e)}).bind(H[1],function(e){n(e)}).bind(H[2],function(e){r(e)})})})},E=function(){function o(){return window.getSelection?window.getSelection().toString():document.selection&&"Control"!=document.selection.type?document.selection.createRange().text:0}function n(e,t,o){d.type=o&&i?"stepped":"stepless",d.scrollAmount=10,j(r,e,t,"mcsLinearOut",o?60:null)}var i,r=e(this),l=r.data(a),s=l.opt,d=l.sequential,u=a+"_"+l.idx,f=e("#mCSB_"+l.idx+"_container"),h=f.parent();f.bind("mousedown."+u,function(){t||i||(i=1,c=!0)}).add(document).bind("mousemove."+u,function(e){if(!t&&i&&o()){var a=f.offset(),r=O(e)[0]-a.top+f[0].offsetTop,c=O(e)[1]-a.left+f[0].offsetLeft;r>0&&r0&&cr?n("on",38):r>h.height()&&n("on",40)),"y"!==s.axis&&l.overflowed[1]&&(0>c?n("on",37):c>h.width()&&n("on",39)))}}).bind("mouseup."+u+" dragend."+u,function(){t||(i&&(i=0,n("off",null)),c=!1)})},W=function(){function t(t,a){if(Q(o),!z(o,t.target)){var r="auto"!==i.mouseWheel.deltaFactor?parseInt(i.mouseWheel.deltaFactor):s&&t.deltaFactor<100?100:t.deltaFactor||100,d=i.scrollInertia;if("x"===i.axis||"x"===i.mouseWheel.axis)var u="x",f=[Math.round(r*n.scrollRatio.x),parseInt(i.mouseWheel.scrollAmount)],h="auto"!==i.mouseWheel.scrollAmount?f[1]:f[0]>=l.width()?.9*l.width():f[0],m=Math.abs(e("#mCSB_"+n.idx+"_container")[0].offsetLeft),p=c[1][0].offsetLeft,g=c[1].parent().width()-c[1].width(),v="y"===i.mouseWheel.axis?t.deltaY||a:t.deltaX;else var u="y",f=[Math.round(r*n.scrollRatio.y),parseInt(i.mouseWheel.scrollAmount)],h="auto"!==i.mouseWheel.scrollAmount?f[1]:f[0]>=l.height()?.9*l.height():f[0],m=Math.abs(e("#mCSB_"+n.idx+"_container")[0].offsetTop),p=c[0][0].offsetTop,g=c[0].parent().height()-c[0].height(),v=t.deltaY||a;"y"===u&&!n.overflowed[0]||"x"===u&&!n.overflowed[1]||((i.mouseWheel.invert||t.webkitDirectionInvertedFromDevice)&&(v=-v),i.mouseWheel.normalizeDelta&&(v=0>v?-1:1),(v>0&&0!==p||0>v&&p!==g||i.mouseWheel.preventDefault)&&(t.stopImmediatePropagation(),t.preventDefault()),t.deltaFactor<5&&!i.mouseWheel.normalizeDelta&&(h=t.deltaFactor,d=17),G(o,(m-v*h).toString(),{dir:u,dur:d}))}}if(e(this).data(a)){var o=e(this),n=o.data(a),i=n.opt,r=a+"_"+n.idx,l=e("#mCSB_"+n.idx),c=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")],d=e("#mCSB_"+n.idx+"_container").find("iframe");d.length&&d.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind("mousewheel."+r,function(e,o){t(e,o)})})}),l.bind("mousewheel."+r,function(e,o){t(e,o)})}},R=new Object,A=function(t){var o=!1,a=!1,n=null;if(void 0===t?a="#empty":void 0!==e(t).attr("id")&&(a=e(t).attr("id")),a!==!1&&void 0!==R[a])return R[a];if(t){try{var i=t.contentDocument||t.contentWindow.document;n=i.body.innerHTML}catch(r){}o=null!==n}else{try{var i=top.document;n=i.body.innerHTML}catch(r){}o=null!==n}return a!==!1&&(R[a]=o),o},L=function(e){var t=this.find("iframe");if(t.length){var o=e?"auto":"none";t.css("pointer-events",o)}},z=function(t,o){var n=o.nodeName.toLowerCase(),i=t.data(a).opt.mouseWheel.disableOver,r=["select","textarea"];return e.inArray(n,i)>-1&&!(e.inArray(n,r)>-1&&!e(o).is(":focus"))},P=function(){var t,o=e(this),n=o.data(a),i=a+"_"+n.idx,r=e("#mCSB_"+n.idx+"_container"),l=r.parent(),s=e(".mCSB_"+n.idx+"_scrollbar ."+d[12]);s.bind("mousedown."+i+" touchstart."+i+" pointerdown."+i+" MSPointerDown."+i,function(o){c=!0,e(o.target).hasClass("mCSB_dragger")||(t=1)}).bind("touchend."+i+" pointerup."+i+" MSPointerUp."+i,function(){c=!1}).bind("click."+i,function(a){if(t&&(t=0,e(a.target).hasClass(d[12])||e(a.target).hasClass("mCSB_draggerRail"))){Q(o);var i=e(this),s=i.find(".mCSB_dragger");if(i.parent(".mCSB_scrollTools_horizontal").length>0){if(!n.overflowed[1])return;var c="x",u=a.pageX>s.offset().left?-1:1,f=Math.abs(r[0].offsetLeft)-u*(.9*l.width())}else{if(!n.overflowed[0])return;var c="y",u=a.pageY>s.offset().top?-1:1,f=Math.abs(r[0].offsetTop)-u*(.9*l.height())}G(o,f.toString(),{dir:c,scrollEasing:"mcsEaseInOut"})}})},H=function(){var t=e(this),o=t.data(a),n=o.opt,i=a+"_"+o.idx,r=e("#mCSB_"+o.idx+"_container"),l=r.parent();r.bind("focusin."+i,function(){var o=e(document.activeElement),a=r.find(".mCustomScrollBox").length,i=0;o.is(n.advanced.autoScrollOnFocus)&&(Q(t),clearTimeout(t[0]._focusTimeout),t[0]._focusTimer=a?(i+17)*a:0,t[0]._focusTimeout=setTimeout(function(){var e=[ae(o)[0],ae(o)[1]],a=[r[0].offsetTop,r[0].offsetLeft],s=[a[0]+e[0]>=0&&a[0]+e[0]=0&&a[0]+e[1]a");s.bind("contextmenu."+r,function(e){e.preventDefault()}).bind("mousedown."+r+" touchstart."+r+" pointerdown."+r+" MSPointerDown."+r+" mouseup."+r+" touchend."+r+" pointerup."+r+" MSPointerUp."+r+" mouseout."+r+" pointerout."+r+" MSPointerOut."+r+" click."+r,function(a){function r(e,o){i.scrollAmount=n.scrollButtons.scrollAmount,j(t,e,o)}if(a.preventDefault(),ee(a)){var l=e(this).attr("class");switch(i.type=n.scrollButtons.scrollType,a.type){case"mousedown":case"touchstart":case"pointerdown":case"MSPointerDown":if("stepped"===i.type)return;c=!0,o.tweenRunning=!1,r("on",l);break;case"mouseup":case"touchend":case"pointerup":case"MSPointerUp":case"mouseout":case"pointerout":case"MSPointerOut":if("stepped"===i.type)return;c=!1,i.dir&&r("off",l);break;case"click":if("stepped"!==i.type||o.tweenRunning)return;r("on",l)}}})},q=function(){function t(t){function a(e,t){r.type=i.keyboard.scrollType,r.scrollAmount=i.keyboard.scrollAmount,"stepped"===r.type&&n.tweenRunning||j(o,e,t)}switch(t.type){case"blur":n.tweenRunning&&r.dir&&a("off",null);break;case"keydown":case"keyup":var l=t.keyCode?t.keyCode:t.which,s="on";if("x"!==i.axis&&(38===l||40===l)||"y"!==i.axis&&(37===l||39===l)){if((38===l||40===l)&&!n.overflowed[0]||(37===l||39===l)&&!n.overflowed[1])return;"keyup"===t.type&&(s="off"),e(document.activeElement).is(u)||(t.preventDefault(),t.stopImmediatePropagation(),a(s,l))}else if(33===l||34===l){if((n.overflowed[0]||n.overflowed[1])&&(t.preventDefault(),t.stopImmediatePropagation()),"keyup"===t.type){Q(o);var f=34===l?-1:1;if("x"===i.axis||"yx"===i.axis&&n.overflowed[1]&&!n.overflowed[0])var h="x",m=Math.abs(c[0].offsetLeft)-f*(.9*d.width());else var h="y",m=Math.abs(c[0].offsetTop)-f*(.9*d.height());G(o,m.toString(),{dir:h,scrollEasing:"mcsEaseInOut"})}}else if((35===l||36===l)&&!e(document.activeElement).is(u)&&((n.overflowed[0]||n.overflowed[1])&&(t.preventDefault(),t.stopImmediatePropagation()),"keyup"===t.type)){if("x"===i.axis||"yx"===i.axis&&n.overflowed[1]&&!n.overflowed[0])var h="x",m=35===l?Math.abs(d.width()-c.outerWidth(!1)):0;else var h="y",m=35===l?Math.abs(d.height()-c.outerHeight(!1)):0;G(o,m.toString(),{dir:h,scrollEasing:"mcsEaseInOut"})}}}var o=e(this),n=o.data(a),i=n.opt,r=n.sequential,l=a+"_"+n.idx,s=e("#mCSB_"+n.idx),c=e("#mCSB_"+n.idx+"_container"),d=c.parent(),u="input,textarea,select,datalist,keygen,[contenteditable='true']",f=c.find("iframe"),h=["blur."+l+" keydown."+l+" keyup."+l];f.length&&f.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind(h[0],function(e){t(e)})})}),s.attr("tabindex","0").bind(h[0],function(e){t(e)})},j=function(t,o,n,i,r){function l(e){u.snapAmount&&(f.scrollAmount=u.snapAmount instanceof Array?"x"===f.dir[0]?u.snapAmount[1]:u.snapAmount[0]:u.snapAmount);var o="stepped"!==f.type,a=r?r:e?o?p/1.5:g:1e3/60,n=e?o?7.5:40:2.5,s=[Math.abs(h[0].offsetTop),Math.abs(h[0].offsetLeft)],d=[c.scrollRatio.y>10?10:c.scrollRatio.y,c.scrollRatio.x>10?10:c.scrollRatio.x],m="x"===f.dir[0]?s[1]+f.dir[1]*(d[1]*n):s[0]+f.dir[1]*(d[0]*n),v="x"===f.dir[0]?s[1]+f.dir[1]*parseInt(f.scrollAmount):s[0]+f.dir[1]*parseInt(f.scrollAmount),x="auto"!==f.scrollAmount?v:m,_=i?i:e?o?"mcsLinearOut":"mcsEaseInOut":"mcsLinear",w=!!e;return e&&17>a&&(x="x"===f.dir[0]?s[1]:s[0]),G(t,x.toString(),{dir:f.dir[0],scrollEasing:_,dur:a,onComplete:w}),e?void(f.dir=!1):(clearTimeout(f.step),void(f.step=setTimeout(function(){l()},a)))}function s(){clearTimeout(f.step),$(f,"step"),Q(t)}var c=t.data(a),u=c.opt,f=c.sequential,h=e("#mCSB_"+c.idx+"_container"),m="stepped"===f.type,p=u.scrollInertia<26?26:u.scrollInertia,g=u.scrollInertia<1?17:u.scrollInertia;switch(o){case"on":if(f.dir=[n===d[16]||n===d[15]||39===n||37===n?"x":"y",n===d[13]||n===d[15]||38===n||37===n?-1:1],Q(t),oe(n)&&"stepped"===f.type)return;l(m);break;case"off":s(),(m||c.tweenRunning&&f.dir)&&l(!0)}},Y=function(t){var o=e(this).data(a).opt,n=[];return"function"==typeof t&&(t=t()),t instanceof Array?n=t.length>1?[t[0],t[1]]:"x"===o.axis?[null,t[0]]:[t[0],null]:(n[0]=t.y?t.y:t.x||"x"===o.axis?null:t,n[1]=t.x?t.x:t.y||"y"===o.axis?null:t),"function"==typeof n[0]&&(n[0]=n[0]()),"function"==typeof n[1]&&(n[1]=n[1]()),n},X=function(t,o){if(null!=t&&"undefined"!=typeof t){var n=e(this),i=n.data(a),r=i.opt,l=e("#mCSB_"+i.idx+"_container"),s=l.parent(),c=typeof t;o||(o="x"===r.axis?"x":"y");var d="x"===o?l.outerWidth(!1)-s.width():l.outerHeight(!1)-s.height(),f="x"===o?l[0].offsetLeft:l[0].offsetTop,h="x"===o?"left":"top";switch(c){case"function":return t();case"object":var m=t.jquery?t:e(t);if(!m.length)return;return"x"===o?ae(m)[1]:ae(m)[0];case"string":case"number":if(oe(t))return Math.abs(t);if(-1!==t.indexOf("%"))return Math.abs(d*parseInt(t)/100);if(-1!==t.indexOf("-="))return Math.abs(f-parseInt(t.split("-=")[1]));if(-1!==t.indexOf("+=")){var p=f+parseInt(t.split("+=")[1]);return p>=0?0:Math.abs(p)}if(-1!==t.indexOf("px")&&oe(t.split("px")[0]))return Math.abs(t.split("px")[0]);if("top"===t||"left"===t)return 0;if("bottom"===t)return Math.abs(s.height()-l.outerHeight(!1));if("right"===t)return Math.abs(s.width()-l.outerWidth(!1));if("first"===t||"last"===t){var m=l.find(":"+t);return"x"===o?ae(m)[1]:ae(m)[0]}return e(t).length?"x"===o?ae(e(t))[1]:ae(e(t))[0]:(l.css(h,t),void u.update.call(null,n[0]))}}},N=function(t){function o(){return clearTimeout(f[0].autoUpdate),0===l.parents("html").length?void(l=null):void(f[0].autoUpdate=setTimeout(function(){return c.advanced.updateOnSelectorChange&&(s.poll.change.n=i(),s.poll.change.n!==s.poll.change.o)?(s.poll.change.o=s.poll.change.n,void r(3)):c.advanced.updateOnContentResize&&(s.poll.size.n=l[0].scrollHeight+l[0].scrollWidth+f[0].offsetHeight+l[0].offsetHeight+l[0].offsetWidth,s.poll.size.n!==s.poll.size.o)?(s.poll.size.o=s.poll.size.n,void r(1)):!c.advanced.updateOnImageLoad||"auto"===c.advanced.updateOnImageLoad&&"y"===c.axis||(s.poll.img.n=f.find("img").length,s.poll.img.n===s.poll.img.o)?void((c.advanced.updateOnSelectorChange||c.advanced.updateOnContentResize||c.advanced.updateOnImageLoad)&&o()):(s.poll.img.o=s.poll.img.n,void f.find("img").each(function(){n(this)}))},c.advanced.autoUpdateTimeout))}function n(t){function o(e,t){return function(){ +return t.apply(e,arguments)}}function a(){this.onload=null,e(t).addClass(d[2]),r(2)}if(e(t).hasClass(d[2]))return void r();var n=new Image;n.onload=o(n,a),n.src=t.src}function i(){c.advanced.updateOnSelectorChange===!0&&(c.advanced.updateOnSelectorChange="*");var e=0,t=f.find(c.advanced.updateOnSelectorChange);return c.advanced.updateOnSelectorChange&&t.length>0&&t.each(function(){e+=this.offsetHeight+this.offsetWidth}),e}function r(e){clearTimeout(f[0].autoUpdate),u.update.call(null,l[0],e)}var l=e(this),s=l.data(a),c=s.opt,f=e("#mCSB_"+s.idx+"_container");return t?(clearTimeout(f[0].autoUpdate),void $(f[0],"autoUpdate")):void o()},V=function(e,t,o){return Math.round(e/t)*t-o},Q=function(t){var o=t.data(a),n=e("#mCSB_"+o.idx+"_container,#mCSB_"+o.idx+"_container_wrapper,#mCSB_"+o.idx+"_dragger_vertical,#mCSB_"+o.idx+"_dragger_horizontal");n.each(function(){Z.call(this)})},G=function(t,o,n){function i(e){return s&&c.callbacks[e]&&"function"==typeof c.callbacks[e]}function r(){return[c.callbacks.alwaysTriggerOffsets||w>=S[0]+y,c.callbacks.alwaysTriggerOffsets||-B>=w]}function l(){var e=[h[0].offsetTop,h[0].offsetLeft],o=[x[0].offsetTop,x[0].offsetLeft],a=[h.outerHeight(!1),h.outerWidth(!1)],i=[f.height(),f.width()];t[0].mcs={content:h,top:e[0],left:e[1],draggerTop:o[0],draggerLeft:o[1],topPct:Math.round(100*Math.abs(e[0])/(Math.abs(a[0])-i[0])),leftPct:Math.round(100*Math.abs(e[1])/(Math.abs(a[1])-i[1])),direction:n.dir}}var s=t.data(a),c=s.opt,d={trigger:"internal",dir:"y",scrollEasing:"mcsEaseOut",drag:!1,dur:c.scrollInertia,overwrite:"all",callbacks:!0,onStart:!0,onUpdate:!0,onComplete:!0},n=e.extend(d,n),u=[n.dur,n.drag?0:n.dur],f=e("#mCSB_"+s.idx),h=e("#mCSB_"+s.idx+"_container"),m=h.parent(),p=c.callbacks.onTotalScrollOffset?Y.call(t,c.callbacks.onTotalScrollOffset):[0,0],g=c.callbacks.onTotalScrollBackOffset?Y.call(t,c.callbacks.onTotalScrollBackOffset):[0,0];if(s.trigger=n.trigger,0===m.scrollTop()&&0===m.scrollLeft()||(e(".mCSB_"+s.idx+"_scrollbar").css("visibility","visible"),m.scrollTop(0).scrollLeft(0)),"_resetY"!==o||s.contentReset.y||(i("onOverflowYNone")&&c.callbacks.onOverflowYNone.call(t[0]),s.contentReset.y=1),"_resetX"!==o||s.contentReset.x||(i("onOverflowXNone")&&c.callbacks.onOverflowXNone.call(t[0]),s.contentReset.x=1),"_resetY"!==o&&"_resetX"!==o){if(!s.contentReset.y&&t[0].mcs||!s.overflowed[0]||(i("onOverflowY")&&c.callbacks.onOverflowY.call(t[0]),s.contentReset.x=null),!s.contentReset.x&&t[0].mcs||!s.overflowed[1]||(i("onOverflowX")&&c.callbacks.onOverflowX.call(t[0]),s.contentReset.x=null),c.snapAmount){var v=c.snapAmount instanceof Array?"x"===n.dir?c.snapAmount[1]:c.snapAmount[0]:c.snapAmount;o=V(o,v,c.snapOffset)}switch(n.dir){case"x":var x=e("#mCSB_"+s.idx+"_dragger_horizontal"),_="left",w=h[0].offsetLeft,S=[f.width()-h.outerWidth(!1),x.parent().width()-x.width()],b=[o,0===o?0:o/s.scrollRatio.x],y=p[1],B=g[1],T=y>0?y/s.scrollRatio.x:0,k=B>0?B/s.scrollRatio.x:0;break;case"y":var x=e("#mCSB_"+s.idx+"_dragger_vertical"),_="top",w=h[0].offsetTop,S=[f.height()-h.outerHeight(!1),x.parent().height()-x.height()],b=[o,0===o?0:o/s.scrollRatio.y],y=p[0],B=g[0],T=y>0?y/s.scrollRatio.y:0,k=B>0?B/s.scrollRatio.y:0}b[1]<0||0===b[0]&&0===b[1]?b=[0,0]:b[1]>=S[1]?b=[S[0],S[1]]:b[0]=-b[0],t[0].mcs||(l(),i("onInit")&&c.callbacks.onInit.call(t[0])),clearTimeout(h[0].onCompleteTimeout),J(x[0],_,Math.round(b[1]),u[1],n.scrollEasing),!s.tweenRunning&&(0===w&&b[0]>=0||w===S[0]&&b[0]<=S[0])||J(h[0],_,Math.round(b[0]),u[0],n.scrollEasing,n.overwrite,{onStart:function(){n.callbacks&&n.onStart&&!s.tweenRunning&&(i("onScrollStart")&&(l(),c.callbacks.onScrollStart.call(t[0])),s.tweenRunning=!0,C(x),s.cbOffsets=r())},onUpdate:function(){n.callbacks&&n.onUpdate&&i("whileScrolling")&&(l(),c.callbacks.whileScrolling.call(t[0]))},onComplete:function(){if(n.callbacks&&n.onComplete){"yx"===c.axis&&clearTimeout(h[0].onCompleteTimeout);var e=h[0].idleTimer||0;h[0].onCompleteTimeout=setTimeout(function(){i("onScroll")&&(l(),c.callbacks.onScroll.call(t[0])),i("onTotalScroll")&&b[1]>=S[1]-T&&s.cbOffsets[0]&&(l(),c.callbacks.onTotalScroll.call(t[0])),i("onTotalScrollBack")&&b[1]<=k&&s.cbOffsets[1]&&(l(),c.callbacks.onTotalScrollBack.call(t[0])),s.tweenRunning=!1,h[0].idleTimer=0,C(x,"hide")},e)}}})}},J=function(e,t,o,a,n,i,r){function l(){S.stop||(x||m.call(),x=K()-v,s(),x>=S.time&&(S.time=x>S.time?x+f-(x-S.time):x+f-1,S.time0?(S.currVal=u(S.time,_,b,a,n),w[t]=Math.round(S.currVal)+"px"):w[t]=o+"px",p.call()}function c(){f=1e3/60,S.time=x+f,h=window.requestAnimationFrame?window.requestAnimationFrame:function(e){return s(),setTimeout(e,.01)},S.id=h(l)}function d(){null!=S.id&&(window.requestAnimationFrame?window.cancelAnimationFrame(S.id):clearTimeout(S.id),S.id=null)}function u(e,t,o,a,n){switch(n){case"linear":case"mcsLinear":return o*e/a+t;case"mcsLinearOut":return e/=a,e--,o*Math.sqrt(1-e*e)+t;case"easeInOutSmooth":return e/=a/2,1>e?o/2*e*e+t:(e--,-o/2*(e*(e-2)-1)+t);case"easeInOutStrong":return e/=a/2,1>e?o/2*Math.pow(2,10*(e-1))+t:(e--,o/2*(-Math.pow(2,-10*e)+2)+t);case"easeInOut":case"mcsEaseInOut":return e/=a/2,1>e?o/2*e*e*e+t:(e-=2,o/2*(e*e*e+2)+t);case"easeOutSmooth":return e/=a,e--,-o*(e*e*e*e-1)+t;case"easeOutStrong":return o*(-Math.pow(2,-10*e/a)+1)+t;case"easeOut":case"mcsEaseOut":default:var i=(e/=a)*e,r=i*e;return t+o*(.499999999999997*r*i+-2.5*i*i+5.5*r+-6.5*i+4*e)}}e._mTween||(e._mTween={top:{},left:{}});var f,h,r=r||{},m=r.onStart||function(){},p=r.onUpdate||function(){},g=r.onComplete||function(){},v=K(),x=0,_=e.offsetTop,w=e.style,S=e._mTween[t];"left"===t&&(_=e.offsetLeft);var b=o-_;S.stop=0,"none"!==i&&d(),c()},K=function(){return window.performance&&window.performance.now?window.performance.now():window.performance&&window.performance.webkitNow?window.performance.webkitNow():Date.now?Date.now():(new Date).getTime()},Z=function(){var e=this;e._mTween||(e._mTween={top:{},left:{}});for(var t=["top","left"],o=0;o=0&&a[0]+ae(n)[0]=0&&a[1]+ae(n)[1]=0&&r[1]-i[1]*l[1][0]<0&&r[1]+n[1]-i[1]*l[1][1]>=0},mcsOverflow:e.expr[":"].mcsOverflow||function(t){var o=e(t).data(a);if(o)return o.overflowed[0]||o.overflowed[1]}})})})}); \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css new file mode 100644 index 0000000000..45152c1bec --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css @@ -0,0 +1,1267 @@ +/* +== malihu jquery custom scrollbar plugin == +Plugin URI: http://manos.malihu.gr/jquery-custom-content-scroller +*/ + + + +/* +CONTENTS: + 1. BASIC STYLE - Plugin's basic/essential CSS properties (normally, should not be edited). + 2. VERTICAL SCROLLBAR - Positioning and dimensions of vertical scrollbar. + 3. HORIZONTAL SCROLLBAR - Positioning and dimensions of horizontal scrollbar. + 4. VERTICAL AND HORIZONTAL SCROLLBARS - Positioning and dimensions of 2-axis scrollbars. + 5. TRANSITIONS - CSS3 transitions for hover events, auto-expanded and auto-hidden scrollbars. + 6. SCROLLBAR COLORS, OPACITY AND BACKGROUNDS + 6.1 THEMES - Scrollbar colors, opacity, dimensions, backgrounds etc. via ready-to-use themes. +*/ + + + +/* +------------------------------------------------------------------------------------------------------------------------ +1. BASIC STYLE +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCustomScrollbar{ -ms-touch-action: pinch-zoom; touch-action: pinch-zoom; /* direct pointer events to js */ } + .mCustomScrollbar.mCS_no_scrollbar, .mCustomScrollbar.mCS_touch_action{ -ms-touch-action: auto; touch-action: auto; } + + .mCustomScrollBox{ /* contains plugin's markup */ + position: relative; + overflow: hidden; + height: 100%; + max-width: 100%; + outline: none; + direction: ltr; + } + + .mCSB_container{ /* contains the original content */ + overflow: hidden; + width: auto; + height: auto; + } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +2. VERTICAL SCROLLBAR +y-axis +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCSB_inside > .mCSB_container{ margin-right: 30px; } + + .mCSB_container.mCS_no_scrollbar_y.mCS_y_hidden{ margin-right: 0; } /* non-visible scrollbar */ + + .mCS-dir-rtl > .mCSB_inside > .mCSB_container{ /* RTL direction/left-side scrollbar */ + margin-right: 0; + margin-left: 30px; + } + + .mCS-dir-rtl > .mCSB_inside > .mCSB_container.mCS_no_scrollbar_y.mCS_y_hidden{ margin-left: 0; } /* RTL direction/left-side scrollbar */ + + .mCSB_scrollTools{ /* contains scrollbar markup (draggable element, dragger rail, buttons etc.) */ + position: absolute; + width: 16px; + height: auto; + left: auto; + top: 0; + right: 0; + bottom: 0; + } + + .mCSB_outside + .mCSB_scrollTools{ right: -26px; } /* scrollbar position: outside */ + + .mCS-dir-rtl > .mCSB_inside > .mCSB_scrollTools, + .mCS-dir-rtl > .mCSB_outside + .mCSB_scrollTools{ /* RTL direction/left-side scrollbar */ + right: auto; + left: 0; + } + + .mCS-dir-rtl > .mCSB_outside + .mCSB_scrollTools{ left: -26px; } /* RTL direction/left-side scrollbar (scrollbar position: outside) */ + + .mCSB_scrollTools .mCSB_draggerContainer{ /* contains the draggable element and dragger rail markup */ + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + height: auto; + } + + .mCSB_scrollTools a + .mCSB_draggerContainer{ margin: 20px 0; } + + .mCSB_scrollTools .mCSB_draggerRail{ + width: 2px; + height: 100%; + margin: 0 auto; + -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; + } + + .mCSB_scrollTools .mCSB_dragger{ /* the draggable element */ + cursor: pointer; + width: 100%; + height: 30px; /* minimum dragger height */ + z-index: 1; + } + + .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ /* the dragger element */ + position: relative; + width: 4px; + height: 100%; + margin: 0 auto; + -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; + text-align: center; + } + + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ width: 12px; /* auto-expanded scrollbar */ } + + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ width: 8px; /* auto-expanded scrollbar */ } + + .mCSB_scrollTools .mCSB_buttonUp, + .mCSB_scrollTools .mCSB_buttonDown{ + display: block; + position: absolute; + height: 20px; + width: 100%; + overflow: hidden; + margin: 0 auto; + cursor: pointer; + } + + .mCSB_scrollTools .mCSB_buttonDown{ bottom: 0; } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +3. HORIZONTAL SCROLLBAR +x-axis +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCSB_horizontal.mCSB_inside > .mCSB_container{ + margin-right: 0; + margin-bottom: 30px; + } + + .mCSB_horizontal.mCSB_outside > .mCSB_container{ min-height: 100%; } + + .mCSB_horizontal > .mCSB_container.mCS_no_scrollbar_x.mCS_x_hidden{ margin-bottom: 0; } /* non-visible scrollbar */ + + .mCSB_scrollTools.mCSB_scrollTools_horizontal{ + width: auto; + height: 16px; + top: auto; + right: 0; + bottom: 0; + left: 0; + } + + .mCustomScrollBox + .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCustomScrollBox + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal{ bottom: -26px; } /* scrollbar position: outside */ + + .mCSB_scrollTools.mCSB_scrollTools_horizontal a + .mCSB_draggerContainer{ margin: 0 20px; } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 2px; + margin: 7px 0; + } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_dragger{ + width: 30px; /* minimum dragger width */ + height: 100%; + left: 0; + } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 4px; + margin: 6px auto; + } + + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ + height: 12px; /* auto-expanded scrollbar */ + margin: 2px auto; + } + + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ + height: 8px; /* auto-expanded scrollbar */ + margin: 4px 0; + } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonLeft, + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonRight{ + display: block; + position: absolute; + width: 20px; + height: 100%; + overflow: hidden; + margin: 0 auto; + cursor: pointer; + } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonLeft{ left: 0; } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonRight{ right: 0; } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +4. VERTICAL AND HORIZONTAL SCROLLBARS +yx-axis +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCSB_container_wrapper{ + position: absolute; + height: auto; + width: auto; + overflow: hidden; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin-right: 30px; + margin-bottom: 30px; + } + + .mCSB_container_wrapper > .mCSB_container{ + padding-right: 30px; + padding-bottom: 30px; + -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; + } + + .mCSB_vertical_horizontal > .mCSB_scrollTools.mCSB_scrollTools_vertical{ bottom: 20px; } + + .mCSB_vertical_horizontal > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ right: 20px; } + + /* non-visible horizontal scrollbar */ + .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden + .mCSB_scrollTools.mCSB_scrollTools_vertical{ bottom: 0; } + + /* non-visible vertical scrollbar/RTL direction/left-side scrollbar */ + .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden + .mCSB_scrollTools ~ .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ right: 0; } + + /* RTL direction/left-side scrollbar */ + .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ left: 20px; } + + /* non-visible scrollbar/RTL direction/left-side scrollbar */ + .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden + .mCSB_scrollTools ~ .mCSB_scrollTools.mCSB_scrollTools_horizontal{ left: 0; } + + .mCS-dir-rtl > .mCSB_inside > .mCSB_container_wrapper{ /* RTL direction/left-side scrollbar */ + margin-right: 0; + margin-left: 30px; + } + + .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden > .mCSB_container{ padding-right: 0; } + + .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden > .mCSB_container{ padding-bottom: 0; } + + .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden{ + margin-right: 0; /* non-visible scrollbar */ + margin-left: 0; + } + + /* non-visible horizontal scrollbar */ + .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden{ margin-bottom: 0; } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +5. TRANSITIONS +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCSB_scrollTools, + .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCSB_scrollTools .mCSB_buttonUp, + .mCSB_scrollTools .mCSB_buttonDown, + .mCSB_scrollTools .mCSB_buttonLeft, + .mCSB_scrollTools .mCSB_buttonRight{ + -webkit-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; + -moz-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; + -o-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; + transition: opacity .2s ease-in-out, background-color .2s ease-in-out; + } + + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger_bar, /* auto-expanded scrollbar */ + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerRail, + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger_bar, + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerRail{ + -webkit-transition: width .2s ease-out .2s, height .2s ease-out .2s, + margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, + margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, + opacity .2s ease-in-out, background-color .2s ease-in-out; + -moz-transition: width .2s ease-out .2s, height .2s ease-out .2s, + margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, + margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, + opacity .2s ease-in-out, background-color .2s ease-in-out; + -o-transition: width .2s ease-out .2s, height .2s ease-out .2s, + margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, + margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, + opacity .2s ease-in-out, background-color .2s ease-in-out; + transition: width .2s ease-out .2s, height .2s ease-out .2s, + margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, + margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, + opacity .2s ease-in-out, background-color .2s ease-in-out; + } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +6. SCROLLBAR COLORS, OPACITY AND BACKGROUNDS +------------------------------------------------------------------------------------------------------------------------ +*/ + + /* + ---------------------------------------- + 6.1 THEMES + ---------------------------------------- + */ + + /* default theme ("light") */ + + .mCSB_scrollTools{ opacity: 0.75; filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; } + + .mCS-autoHide > .mCustomScrollBox > .mCSB_scrollTools, + .mCS-autoHide > .mCustomScrollBox ~ .mCSB_scrollTools{ opacity: 0; filter: "alpha(opacity=0)"; -ms-filter: "alpha(opacity=0)"; } + + .mCustomScrollbar > .mCustomScrollBox > .mCSB_scrollTools.mCSB_scrollTools_onDrag, + .mCustomScrollbar > .mCustomScrollBox ~ .mCSB_scrollTools.mCSB_scrollTools_onDrag, + .mCustomScrollBox:hover > .mCSB_scrollTools, + .mCustomScrollBox:hover ~ .mCSB_scrollTools, + .mCS-autoHide:hover > .mCustomScrollBox > .mCSB_scrollTools, + .mCS-autoHide:hover > .mCustomScrollBox ~ .mCSB_scrollTools{ opacity: 1; filter: "alpha(opacity=100)"; -ms-filter: "alpha(opacity=100)"; } + + .mCSB_scrollTools .mCSB_draggerRail{ + background-color: #000; background-color: rgba(0,0,0,0.4); + filter: "alpha(opacity=40)"; -ms-filter: "alpha(opacity=40)"; + } + + .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.75); + filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; + } + + .mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.85); + filter: "alpha(opacity=85)"; -ms-filter: "alpha(opacity=85)"; + } + .mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.9); + filter: "alpha(opacity=90)"; -ms-filter: "alpha(opacity=90)"; + } + + .mCSB_scrollTools .mCSB_buttonUp, + .mCSB_scrollTools .mCSB_buttonDown, + .mCSB_scrollTools .mCSB_buttonLeft, + .mCSB_scrollTools .mCSB_buttonRight{ + background-image: url(mCSB_buttons.png); /* css sprites */ + background-repeat: no-repeat; + opacity: 0.4; filter: "alpha(opacity=40)"; -ms-filter: "alpha(opacity=40)"; + } + + .mCSB_scrollTools .mCSB_buttonUp{ + background-position: 0 0; + /* + sprites locations + light: 0 0, -16px 0, -32px 0, -48px 0, 0 -72px, -16px -72px, -32px -72px + dark: -80px 0, -96px 0, -112px 0, -128px 0, -80px -72px, -96px -72px, -112px -72px + */ + } + + .mCSB_scrollTools .mCSB_buttonDown{ + background-position: 0 -20px; + /* + sprites locations + light: 0 -20px, -16px -20px, -32px -20px, -48px -20px, 0 -92px, -16px -92px, -32px -92px + dark: -80px -20px, -96px -20px, -112px -20px, -128px -20px, -80px -92px, -96px -92px, -112 -92px + */ + } + + .mCSB_scrollTools .mCSB_buttonLeft{ + background-position: 0 -40px; + /* + sprites locations + light: 0 -40px, -20px -40px, -40px -40px, -60px -40px, 0 -112px, -20px -112px, -40px -112px + dark: -80px -40px, -100px -40px, -120px -40px, -140px -40px, -80px -112px, -100px -112px, -120px -112px + */ + } + + .mCSB_scrollTools .mCSB_buttonRight{ + background-position: 0 -56px; + /* + sprites locations + light: 0 -56px, -20px -56px, -40px -56px, -60px -56px, 0 -128px, -20px -128px, -40px -128px + dark: -80px -56px, -100px -56px, -120px -56px, -140px -56px, -80px -128px, -100px -128px, -120px -128px + */ + } + + .mCSB_scrollTools .mCSB_buttonUp:hover, + .mCSB_scrollTools .mCSB_buttonDown:hover, + .mCSB_scrollTools .mCSB_buttonLeft:hover, + .mCSB_scrollTools .mCSB_buttonRight:hover{ opacity: 0.75; filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; } + + .mCSB_scrollTools .mCSB_buttonUp:active, + .mCSB_scrollTools .mCSB_buttonDown:active, + .mCSB_scrollTools .mCSB_buttonLeft:active, + .mCSB_scrollTools .mCSB_buttonRight:active{ opacity: 0.9; filter: "alpha(opacity=90)"; -ms-filter: "alpha(opacity=90)"; } + + + /* theme: "dark" */ + + .mCS-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } + + .mCS-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: rgba(0,0,0,0.85); } + + .mCS-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: rgba(0,0,0,0.9); } + + .mCS-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px 0; } + + .mCS-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -20px; } + + .mCS-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -40px; } + + .mCS-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -56px; } + + /* ---------------------------------------- */ + + + + /* theme: "light-2", "dark-2" */ + + .mCS-light-2.mCSB_scrollTools .mCSB_draggerRail, + .mCS-dark-2.mCSB_scrollTools .mCSB_draggerRail{ + width: 4px; + background-color: #fff; background-color: rgba(255,255,255,0.1); + -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; + } + + .mCS-light-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width: 4px; + background-color: #fff; background-color: rgba(255,255,255,0.75); + -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; + } + + .mCS-light-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-dark-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-light-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 4px; + margin: 6px auto; + } + + .mCS-light-2.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } + + .mCS-light-2.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-light-2.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } + + .mCS-light-2.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px 0; } + + .mCS-light-2.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -20px; } + + .mCS-light-2.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -40px; } + + .mCS-light-2.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -56px; } + + + /* theme: "dark-2" */ + + .mCS-dark-2.mCSB_scrollTools .mCSB_draggerRail{ + background-color: #000; background-color: rgba(0,0,0,0.1); + -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; + } + + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #000; background-color: rgba(0,0,0,0.75); + -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; + } + + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-dark-2.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px 0; } + + .mCS-dark-2.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -20px; } + + .mCS-dark-2.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -40px; } + + .mCS-dark-2.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -56px; } + + /* ---------------------------------------- */ + + + + /* theme: "light-thick", "dark-thick" */ + + .mCS-light-thick.mCSB_scrollTools .mCSB_draggerRail, + .mCS-dark-thick.mCSB_scrollTools .mCSB_draggerRail{ + width: 4px; + background-color: #fff; background-color: rgba(255,255,255,0.1); + -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; + } + + .mCS-light-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width: 6px; + background-color: #fff; background-color: rgba(255,255,255,0.75); + -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; + } + + .mCS-light-thick.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-dark-thick.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 4px; + margin: 6px 0; + } + + .mCS-light-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 6px; + margin: 5px auto; + } + + .mCS-light-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } + + .mCS-light-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-light-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } + + .mCS-light-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -16px 0; } + + .mCS-light-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -16px -20px; } + + .mCS-light-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -20px -40px; } + + .mCS-light-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -20px -56px; } + + + /* theme: "dark-thick" */ + + .mCS-dark-thick.mCSB_scrollTools .mCSB_draggerRail{ + background-color: #000; background-color: rgba(0,0,0,0.1); + -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; + } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #000; background-color: rgba(0,0,0,0.75); + -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; + } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -96px 0; } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -96px -20px; } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -100px -40px; } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -100px -56px; } + + /* ---------------------------------------- */ + + + + /* theme: "light-thin", "dark-thin" */ + + .mCS-light-thin.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.1); } + + .mCS-light-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 2px; } + + .mCS-light-thin.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-dark-thin.mCSB_scrollTools_horizontal .mCSB_draggerRail{ width: 100%; } + + .mCS-light-thin.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-thin.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 2px; + margin: 7px auto; + } + + + /* theme "dark-thin" */ + + .mCS-dark-thin.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px 0; } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -20px; } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -40px; } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -56px; } + + /* ---------------------------------------- */ + + + + /* theme "rounded", "rounded-dark", "rounded-dots", "rounded-dots-dark" */ + + .mCS-rounded.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.15); } + + .mCS-rounded.mCSB_scrollTools .mCSB_dragger, + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger, + .mCS-rounded-dots.mCSB_scrollTools .mCSB_dragger, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger{ height: 14px; } + + .mCS-rounded.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width: 14px; + margin: 0 1px; + } + + .mCS-rounded.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-rounded-dark.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 14px; } + + .mCS-rounded.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + height: 14px; + margin: 1px 0; + } + + .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ + width: 16px; /* auto-expanded scrollbar */ + height: 16px; + margin: -1px 0; + } + + .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, + .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ width: 4px; /* auto-expanded scrollbar */ } + + .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ + height: 16px; /* auto-expanded scrollbar */ + width: 16px; + margin: 0 -1px; + } + + .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, + .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ + height: 4px; /* auto-expanded scrollbar */ + margin: 6px 0; + } + + .mCS-rounded.mCSB_scrollTools .mCSB_buttonUp{ background-position: 0 -72px; } + + .mCS-rounded.mCSB_scrollTools .mCSB_buttonDown{ background-position: 0 -92px; } + + .mCS-rounded.mCSB_scrollTools .mCSB_buttonLeft{ background-position: 0 -112px; } + + .mCS-rounded.mCSB_scrollTools .mCSB_buttonRight{ background-position: 0 -128px; } + + + /* theme "rounded-dark", "rounded-dots-dark" */ + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px -72px; } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -92px; } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -112px; } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -128px; } + + + /* theme "rounded-dots", "rounded-dots-dark" */ + + .mCS-rounded-dots.mCSB_scrollTools_vertical .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools_vertical .mCSB_draggerRail{ width: 4px; } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + background-color: transparent; + background-position: center; + } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail{ + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAANElEQVQYV2NkIAAYiVbw//9/Y6DiM1ANJoyMjGdBbLgJQAX/kU0DKgDLkaQAvxW4HEvQFwCRcxIJK1XznAAAAABJRU5ErkJggg=="); + background-repeat: repeat-y; + opacity: 0.3; + filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; + } + + .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + height: 4px; + margin: 6px 0; + background-repeat: repeat-x; + } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonUp{ background-position: -16px -72px; } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonDown{ background-position: -16px -92px; } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -20px -112px; } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonRight{ background-position: -20px -128px; } + + + /* theme "rounded-dots-dark" */ + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail{ + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAALElEQVQYV2NkIAAYSVFgDFR8BqrBBEifBbGRTfiPZhpYjiQFBK3A6l6CvgAAE9kGCd1mvgEAAAAASUVORK5CYII="); + } + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -96px -72px; } + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -96px -92px; } + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -100px -112px; } + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -100px -128px; } + + /* ---------------------------------------- */ + + + + /* theme "3d", "3d-dark", "3d-thick", "3d-thick-dark" */ + + .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-repeat: repeat-y; + background-image: -moz-linear-gradient(left, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 100%); + background-image: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(255,255,255,0.5)), color-stop(100%,rgba(255,255,255,0))); + background-image: -webkit-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: -o-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: -ms-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: linear-gradient(to right, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + } + + .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + background-repeat: repeat-x; + background-image: -moz-linear-gradient(top, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 100%); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,0.5)), color-stop(100%,rgba(255,255,255,0))); + background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: -o-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: -ms-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: linear-gradient(to bottom, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + } + + + /* theme "3d", "3d-dark" */ + + .mCS-3d.mCSB_scrollTools_vertical .mCSB_dragger, + .mCS-3d-dark.mCSB_scrollTools_vertical .mCSB_dragger{ height: 70px; } + + .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 70px; } + + .mCS-3d.mCSB_scrollTools, + .mCS-3d-dark.mCSB_scrollTools{ + opacity: 1; + filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; + } + + .mCS-3d.mCSB_scrollTools .mCSB_draggerRail, + .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; } + + .mCS-3d.mCSB_scrollTools .mCSB_draggerRail, + .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail{ + width: 8px; + background-color: #000; background-color: rgba(0,0,0,0.2); + box-shadow: inset 1px 0 1px rgba(0,0,0,0.5), inset -1px 0 1px rgba(255,255,255,0.2); + } + + .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-3d.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-3d.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #555; } + + .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 8px; } + + .mCS-3d.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 8px; + margin: 4px 0; + box-shadow: inset 0 1px 1px rgba(0,0,0,0.5), inset 0 -1px 1px rgba(255,255,255,0.2); + } + + .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 8px; + margin: 4px auto; + } + + .mCS-3d.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } + + .mCS-3d.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } + + .mCS-3d.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } + + .mCS-3d.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } + + + /* theme "3d-dark" */ + + .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail{ + background-color: #000; background-color: rgba(0,0,0,0.1); + box-shadow: inset 1px 0 1px rgba(0,0,0,0.1); + } + + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ box-shadow: inset 0 1px 1px rgba(0,0,0,0.1); } + + .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } + + .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } + + .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } + + .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } + + /* ---------------------------------------- */ + + + + /* theme: "3d-thick", "3d-thick-dark" */ + + .mCS-3d-thick.mCSB_scrollTools, + .mCS-3d-thick-dark.mCSB_scrollTools{ + opacity: 1; + filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; + } + + .mCS-3d-thick.mCSB_scrollTools, + .mCS-3d-thick-dark.mCSB_scrollTools, + .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerContainer, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerContainer{ -webkit-border-radius: 7px; -moz-border-radius: 7px; border-radius: 7px; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } + + .mCSB_inside + .mCS-3d-thick.mCSB_scrollTools_vertical, + .mCSB_inside + .mCS-3d-thick-dark.mCSB_scrollTools_vertical{ right: 1px; } + + .mCS-3d-thick.mCSB_scrollTools_vertical, + .mCS-3d-thick-dark.mCSB_scrollTools_vertical{ box-shadow: inset 1px 0 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.5); } + + .mCS-3d-thick.mCSB_scrollTools_horizontal, + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal{ + bottom: 1px; + box-shadow: inset 0 1px 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.5); + } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + box-shadow: inset 1px 0 0 rgba(255,255,255,0.4); + width: 12px; + margin: 2px; + position: absolute; + height: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + } + + .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 0 1px 0 rgba(255,255,255,0.4); } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #555; } + + .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + height: 12px; + width: auto; + } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerContainer{ + background-color: #000; background-color: rgba(0,0,0,0.05); + box-shadow: inset 1px 1px 16px rgba(0,0,0,0.1); + } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } + + + /* theme: "3d-thick-dark" */ + + .mCS-3d-thick-dark.mCSB_scrollTools{ box-shadow: inset 0 0 14px rgba(0,0,0,0.2); } + + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal{ box-shadow: inset 0 1px 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.2); } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 1px 0 0 rgba(255,255,255,0.4), inset -1px 0 0 rgba(0,0,0,0.2); } + + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 0 1px 0 rgba(255,255,255,0.4), inset 0 -1px 0 rgba(0,0,0,0.2); } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #777; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerContainer{ + background-color: #fff; background-color: rgba(0,0,0,0.05); + box-shadow: inset 1px 1px 16px rgba(0,0,0,0.1); + } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } + + /* ---------------------------------------- */ + + + + /* theme: "minimal", "minimal-dark" */ + + .mCSB_outside + .mCS-minimal.mCSB_scrollTools_vertical, + .mCSB_outside + .mCS-minimal-dark.mCSB_scrollTools_vertical{ + right: 0; + margin: 12px 0; + } + + .mCustomScrollBox.mCS-minimal + .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCustomScrollBox.mCS-minimal + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCustomScrollBox.mCS-minimal-dark + .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCustomScrollBox.mCS-minimal-dark + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal{ + bottom: 0; + margin: 0 12px; + } + + /* RTL direction/left-side scrollbar */ + .mCS-dir-rtl > .mCSB_outside + .mCS-minimal.mCSB_scrollTools_vertical, + .mCS-dir-rtl > .mCSB_outside + .mCS-minimal-dark.mCSB_scrollTools_vertical{ + left: 0; + right: auto; + } + + .mCS-minimal.mCSB_scrollTools .mCSB_draggerRail, + .mCS-minimal-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } + + .mCS-minimal.mCSB_scrollTools_vertical .mCSB_dragger, + .mCS-minimal-dark.mCSB_scrollTools_vertical .mCSB_dragger{ height: 50px; } + + .mCS-minimal.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-minimal-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 50px; } + + .mCS-minimal.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.2); + filter: "alpha(opacity=20)"; -ms-filter: "alpha(opacity=20)"; + } + + .mCS-minimal.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-minimal.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.5); + filter: "alpha(opacity=50)"; -ms-filter: "alpha(opacity=50)"; + } + + + /* theme: "minimal-dark" */ + + .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #000; background-color: rgba(0,0,0,0.2); + filter: "alpha(opacity=20)"; -ms-filter: "alpha(opacity=20)"; + } + + .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background-color: #000; background-color: rgba(0,0,0,0.5); + filter: "alpha(opacity=50)"; -ms-filter: "alpha(opacity=50)"; + } + + /* ---------------------------------------- */ + + + + /* theme "light-3", "dark-3" */ + + .mCS-light-3.mCSB_scrollTools .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools .mCSB_draggerRail{ + width: 6px; + background-color: #000; background-color: rgba(0,0,0,0.2); + } + + .mCS-light-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 6px; } + + .mCS-light-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-light-3.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 6px; + margin: 5px 0; + } + + .mCS-light-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-light-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ + width: 12px; + } + + .mCS-light-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-light-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ + height: 12px; + margin: 2px 0; + } + + .mCS-light-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } + + .mCS-light-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } + + .mCS-light-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } + + .mCS-light-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } + + + /* theme "dark-3" */ + + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-dark-3.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.1); } + + .mCS-dark-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } + + .mCS-dark-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } + + .mCS-dark-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } + + .mCS-dark-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } + + /* ---------------------------------------- */ + + + + /* theme "inset", "inset-dark", "inset-2", "inset-2-dark", "inset-3", "inset-3-dark" */ + + .mCS-inset.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-2.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-3.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ + width: 12px; + background-color: #000; background-color: rgba(0,0,0,0.2); + } + + .mCS-inset.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width: 6px; + margin: 3px 5px; + position: absolute; + height: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + } + + .mCS-inset.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + height: 6px; + margin: 5px 3px; + position: absolute; + width: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + } + + .mCS-inset.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-2-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-3.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-3-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 12px; + margin: 2px 0; + } + + .mCS-inset.mCSB_scrollTools .mCSB_buttonUp, + .mCS-inset-2.mCSB_scrollTools .mCSB_buttonUp, + .mCS-inset-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } + + .mCS-inset.mCSB_scrollTools .mCSB_buttonDown, + .mCS-inset-2.mCSB_scrollTools .mCSB_buttonDown, + .mCS-inset-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } + + .mCS-inset.mCSB_scrollTools .mCSB_buttonLeft, + .mCS-inset-2.mCSB_scrollTools .mCSB_buttonLeft, + .mCS-inset-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } + + .mCS-inset.mCSB_scrollTools .mCSB_buttonRight, + .mCS-inset-2.mCSB_scrollTools .mCSB_buttonRight, + .mCS-inset-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } + + + /* theme "inset-dark", "inset-2-dark", "inset-3-dark" */ + + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.1); } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonUp, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonUp, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonDown, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonDown, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonLeft, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonLeft, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonRight, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonRight, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } + + + /* theme "inset-2", "inset-2-dark" */ + + .mCS-inset-2.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail{ + background-color: transparent; + border-width: 1px; + border-style: solid; + border-color: #fff; + border-color: rgba(255,255,255,0.2); + -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; + } + + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail{ border-color: #000; border-color: rgba(0,0,0,0.2); } + + + /* theme "inset-3", "inset-3-dark" */ + + .mCS-inset-3.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.6); } + + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.6); } + + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.75); } + + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } + + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } + + /* ---------------------------------------- */ diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js new file mode 100644 index 0000000000..4c9a0b2e52 --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js @@ -0,0 +1,2458 @@ +/* +== malihu jquery custom scrollbar plugin == +Version: 3.1.5 +Plugin URI: http://manos.malihu.gr/jquery-custom-content-scroller +Author: malihu +Author URI: http://manos.malihu.gr +License: MIT License (MIT) +*/ + +/* +Copyright Manos Malihutsakis (email: manos@malihu.gr) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/* +The code below is fairly long, fully commented and should be normally used in development. +For production, use either the minified jquery.mCustomScrollbar.min.js script or +the production-ready jquery.mCustomScrollbar.concat.min.js which contains the plugin +and dependencies (minified). +*/ + +(function(factory){ + if(typeof define==="function" && define.amd){ + define(["jquery"],factory); + }else if(typeof module!=="undefined" && module.exports){ + module.exports=factory; + }else{ + factory(jQuery,window,document); + } +}(function($){ +(function(init){ + var _rjs=typeof define==="function" && define.amd, /* RequireJS */ + _njs=typeof module !== "undefined" && module.exports, /* NodeJS */ + _dlp=("https:"==document.location.protocol) ? "https:" : "http:", /* location protocol */ + _url="cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js"; + if(!_rjs){ + if(_njs){ + require("jquery-mousewheel")($); + }else{ + /* load jquery-mousewheel plugin (via CDN) if it's not present or not loaded via RequireJS + (works when mCustomScrollbar fn is called on window load) */ + $.event.special.mousewheel || $("head").append(decodeURI("%3Cscript src="+_dlp+"//"+_url+"%3E%3C/script%3E")); + } + } + init(); +}(function(){ + + /* + ---------------------------------------- + PLUGIN NAMESPACE, PREFIX, DEFAULT SELECTOR(S) + ---------------------------------------- + */ + + var pluginNS="mCustomScrollbar", + pluginPfx="mCS", + defaultSelector=".mCustomScrollbar", + + + + + + /* + ---------------------------------------- + DEFAULT OPTIONS + ---------------------------------------- + */ + + defaults={ + /* + set element/content width/height programmatically + values: boolean, pixels, percentage + option default + ------------------------------------- + setWidth false + setHeight false + */ + /* + set the initial css top property of content + values: string (e.g. "-100px", "10%" etc.) + */ + setTop:0, + /* + set the initial css left property of content + values: string (e.g. "-100px", "10%" etc.) + */ + setLeft:0, + /* + scrollbar axis (vertical and/or horizontal scrollbars) + values (string): "y", "x", "yx" + */ + axis:"y", + /* + position of scrollbar relative to content + values (string): "inside", "outside" ("outside" requires elements with position:relative) + */ + scrollbarPosition:"inside", + /* + scrolling inertia + values: integer (milliseconds) + */ + scrollInertia:950, + /* + auto-adjust scrollbar dragger length + values: boolean + */ + autoDraggerLength:true, + /* + auto-hide scrollbar when idle + values: boolean + option default + ------------------------------------- + autoHideScrollbar false + */ + /* + auto-expands scrollbar on mouse-over and dragging + values: boolean + option default + ------------------------------------- + autoExpandScrollbar false + */ + /* + always show scrollbar, even when there's nothing to scroll + values: integer (0=disable, 1=always show dragger rail and buttons, 2=always show dragger rail, dragger and buttons), boolean + */ + alwaysShowScrollbar:0, + /* + scrolling always snaps to a multiple of this number in pixels + values: integer, array ([y,x]) + option default + ------------------------------------- + snapAmount null + */ + /* + when snapping, snap with this number in pixels as an offset + values: integer + */ + snapOffset:0, + /* + mouse-wheel scrolling + */ + mouseWheel:{ + /* + enable mouse-wheel scrolling + values: boolean + */ + enable:true, + /* + scrolling amount in pixels + values: "auto", integer + */ + scrollAmount:"auto", + /* + mouse-wheel scrolling axis + the default scrolling direction when both vertical and horizontal scrollbars are present + values (string): "y", "x" + */ + axis:"y", + /* + prevent the default behaviour which automatically scrolls the parent element(s) when end of scrolling is reached + values: boolean + option default + ------------------------------------- + preventDefault null + */ + /* + the reported mouse-wheel delta value. The number of lines (translated to pixels) one wheel notch scrolls. + values: "auto", integer + "auto" uses the default OS/browser value + */ + deltaFactor:"auto", + /* + normalize mouse-wheel delta to -1 or 1 (disables mouse-wheel acceleration) + values: boolean + option default + ------------------------------------- + normalizeDelta null + */ + /* + invert mouse-wheel scrolling direction + values: boolean + option default + ------------------------------------- + invert null + */ + /* + the tags that disable mouse-wheel when cursor is over them + */ + disableOver:["select","option","keygen","datalist","textarea"] + }, + /* + scrollbar buttons + */ + scrollButtons:{ + /* + enable scrollbar buttons + values: boolean + option default + ------------------------------------- + enable null + */ + /* + scrollbar buttons scrolling type + values (string): "stepless", "stepped" + */ + scrollType:"stepless", + /* + scrolling amount in pixels + values: "auto", integer + */ + scrollAmount:"auto" + /* + tabindex of the scrollbar buttons + values: false, integer + option default + ------------------------------------- + tabindex null + */ + }, + /* + keyboard scrolling + */ + keyboard:{ + /* + enable scrolling via keyboard + values: boolean + */ + enable:true, + /* + keyboard scrolling type + values (string): "stepless", "stepped" + */ + scrollType:"stepless", + /* + scrolling amount in pixels + values: "auto", integer + */ + scrollAmount:"auto" + }, + /* + enable content touch-swipe scrolling + values: boolean, integer, string (number) + integer values define the axis-specific minimum amount required for scrolling momentum + */ + contentTouchScroll:25, + /* + enable/disable document (default) touch-swipe scrolling + */ + documentTouchScroll:true, + /* + advanced option parameters + */ + advanced:{ + /* + auto-expand content horizontally (for "x" or "yx" axis) + values: boolean, integer (the value 2 forces the non scrollHeight/scrollWidth method, the value 3 forces the scrollHeight/scrollWidth method) + option default + ------------------------------------- + autoExpandHorizontalScroll null + */ + /* + auto-scroll to elements with focus + */ + autoScrollOnFocus:"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']", + /* + auto-update scrollbars on content, element or viewport resize + should be true for fluid layouts/elements, adding/removing content dynamically, hiding/showing elements, content with images etc. + values: boolean + */ + updateOnContentResize:true, + /* + auto-update scrollbars each time each image inside the element is fully loaded + values: "auto", boolean + */ + updateOnImageLoad:"auto", + /* + auto-update scrollbars based on the amount and size changes of specific selectors + useful when you need to update the scrollbar(s) automatically, each time a type of element is added, removed or changes its size + values: boolean, string (e.g. "ul li" will auto-update scrollbars each time list-items inside the element are changed) + a value of true (boolean) will auto-update scrollbars each time any element is changed + option default + ------------------------------------- + updateOnSelectorChange null + */ + /* + extra selectors that'll allow scrollbar dragging upon mousemove/up, pointermove/up, touchend etc. (e.g. "selector-1, selector-2") + option default + ------------------------------------- + extraDraggableSelectors null + */ + /* + extra selectors that'll release scrollbar dragging upon mouseup, pointerup, touchend etc. (e.g. "selector-1, selector-2") + option default + ------------------------------------- + releaseDraggableSelectors null + */ + /* + auto-update timeout + values: integer (milliseconds) + */ + autoUpdateTimeout:60 + }, + /* + scrollbar theme + values: string (see CSS/plugin URI for a list of ready-to-use themes) + */ + theme:"light", + /* + user defined callback functions + */ + callbacks:{ + /* + Available callbacks: + callback default + ------------------------------------- + onCreate null + onInit null + onScrollStart null + onScroll null + onTotalScroll null + onTotalScrollBack null + whileScrolling null + onOverflowY null + onOverflowX null + onOverflowYNone null + onOverflowXNone null + onImageLoad null + onSelectorChange null + onBeforeUpdate null + onUpdate null + */ + onTotalScrollOffset:0, + onTotalScrollBackOffset:0, + alwaysTriggerOffsets:true + } + /* + add scrollbar(s) on all elements matching the current selector, now and in the future + values: boolean, string + string values: "on" (enable), "once" (disable after first invocation), "off" (disable) + liveSelector values: string (selector) + option default + ------------------------------------- + live false + liveSelector null + */ + }, + + + + + + /* + ---------------------------------------- + VARS, CONSTANTS + ---------------------------------------- + */ + + totalInstances=0, /* plugin instances amount */ + liveTimers={}, /* live option timers */ + oldIE=(window.attachEvent && !window.addEventListener) ? 1 : 0, /* detect IE < 9 */ + touchActive=false,touchable, /* global touch vars (for touch and pointer events) */ + /* general plugin classes */ + classes=[ + "mCSB_dragger_onDrag","mCSB_scrollTools_onDrag","mCS_img_loaded","mCS_disabled","mCS_destroyed","mCS_no_scrollbar", + "mCS-autoHide","mCS-dir-rtl","mCS_no_scrollbar_y","mCS_no_scrollbar_x","mCS_y_hidden","mCS_x_hidden","mCSB_draggerContainer", + "mCSB_buttonUp","mCSB_buttonDown","mCSB_buttonLeft","mCSB_buttonRight" + ], + + + + + + /* + ---------------------------------------- + METHODS + ---------------------------------------- + */ + + methods={ + + /* + plugin initialization method + creates the scrollbar(s), plugin data object and options + ---------------------------------------- + */ + + init:function(options){ + + var options=$.extend(true,{},defaults,options), + selector=_selector.call(this); /* validate selector */ + + /* + if live option is enabled, monitor for elements matching the current selector and + apply scrollbar(s) when found (now and in the future) + */ + if(options.live){ + var liveSelector=options.liveSelector || this.selector || defaultSelector, /* live selector(s) */ + $liveSelector=$(liveSelector); /* live selector(s) as jquery object */ + if(options.live==="off"){ + /* + disable live if requested + usage: $(selector).mCustomScrollbar({live:"off"}); + */ + removeLiveTimers(liveSelector); + return; + } + liveTimers[liveSelector]=setTimeout(function(){ + /* call mCustomScrollbar fn on live selector(s) every half-second */ + $liveSelector.mCustomScrollbar(options); + if(options.live==="once" && $liveSelector.length){ + /* disable live after first invocation */ + removeLiveTimers(liveSelector); + } + },500); + }else{ + removeLiveTimers(liveSelector); + } + + /* options backward compatibility (for versions < 3.0.0) and normalization */ + options.setWidth=(options.set_width) ? options.set_width : options.setWidth; + options.setHeight=(options.set_height) ? options.set_height : options.setHeight; + options.axis=(options.horizontalScroll) ? "x" : _findAxis(options.axis); + options.scrollInertia=options.scrollInertia>0 && options.scrollInertia<17 ? 17 : options.scrollInertia; + if(typeof options.mouseWheel!=="object" && options.mouseWheel==true){ /* old school mouseWheel option (non-object) */ + options.mouseWheel={enable:true,scrollAmount:"auto",axis:"y",preventDefault:false,deltaFactor:"auto",normalizeDelta:false,invert:false} + } + options.mouseWheel.scrollAmount=!options.mouseWheelPixels ? options.mouseWheel.scrollAmount : options.mouseWheelPixels; + options.mouseWheel.normalizeDelta=!options.advanced.normalizeMouseWheelDelta ? options.mouseWheel.normalizeDelta : options.advanced.normalizeMouseWheelDelta; + options.scrollButtons.scrollType=_findScrollButtonsType(options.scrollButtons.scrollType); + + _theme(options); /* theme-specific options */ + + /* plugin constructor */ + return $(selector).each(function(){ + + var $this=$(this); + + if(!$this.data(pluginPfx)){ /* prevent multiple instantiations */ + + /* store options and create objects in jquery data */ + $this.data(pluginPfx,{ + idx:++totalInstances, /* instance index */ + opt:options, /* options */ + scrollRatio:{y:null,x:null}, /* scrollbar to content ratio */ + overflowed:null, /* overflowed axis */ + contentReset:{y:null,x:null}, /* object to check when content resets */ + bindEvents:false, /* object to check if events are bound */ + tweenRunning:false, /* object to check if tween is running */ + sequential:{}, /* sequential scrolling object */ + langDir:$this.css("direction"), /* detect/store direction (ltr or rtl) */ + cbOffsets:null, /* object to check whether callback offsets always trigger */ + /* + object to check how scrolling events where last triggered + "internal" (default - triggered by this script), "external" (triggered by other scripts, e.g. via scrollTo method) + usage: object.data("mCS").trigger + */ + trigger:null, + /* + object to check for changes in elements in order to call the update method automatically + */ + poll:{size:{o:0,n:0},img:{o:0,n:0},change:{o:0,n:0}} + }); + + var d=$this.data(pluginPfx),o=d.opt, + /* HTML data attributes */ + htmlDataAxis=$this.data("mcs-axis"),htmlDataSbPos=$this.data("mcs-scrollbar-position"),htmlDataTheme=$this.data("mcs-theme"); + + if(htmlDataAxis){o.axis=htmlDataAxis;} /* usage example: data-mcs-axis="y" */ + if(htmlDataSbPos){o.scrollbarPosition=htmlDataSbPos;} /* usage example: data-mcs-scrollbar-position="outside" */ + if(htmlDataTheme){ /* usage example: data-mcs-theme="minimal" */ + o.theme=htmlDataTheme; + _theme(o); /* theme-specific options */ + } + + _pluginMarkup.call(this); /* add plugin markup */ + + if(d && o.callbacks.onCreate && typeof o.callbacks.onCreate==="function"){o.callbacks.onCreate.call(this);} /* callbacks: onCreate */ + + $("#mCSB_"+d.idx+"_container img:not(."+classes[2]+")").addClass(classes[2]); /* flag loaded images */ + + methods.update.call(null,$this); /* call the update method */ + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin update method + updates content and scrollbar(s) values, events and status + ---------------------------------------- + usage: $(selector).mCustomScrollbar("update"); + */ + + update:function(el,cb){ + + var selector=el || _selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + var d=$this.data(pluginPfx),o=d.opt, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; + + if(!mCSB_container.length){return;} + + if(d.tweenRunning){_stop($this);} /* stop any running tweens while updating */ + + if(cb && d && o.callbacks.onBeforeUpdate && typeof o.callbacks.onBeforeUpdate==="function"){o.callbacks.onBeforeUpdate.call(this);} /* callbacks: onBeforeUpdate */ + + /* if element was disabled or destroyed, remove class(es) */ + if($this.hasClass(classes[3])){$this.removeClass(classes[3]);} + if($this.hasClass(classes[4])){$this.removeClass(classes[4]);} + + /* css flexbox fix, detect/set max-height */ + mCustomScrollBox.css("max-height","none"); + if(mCustomScrollBox.height()!==$this.height()){mCustomScrollBox.css("max-height",$this.height());} + + _expandContentHorizontally.call(this); /* expand content horizontally */ + + if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){ + mCSB_container.css("width",_contentWidth(mCSB_container)); + } + + d.overflowed=_overflowed.call(this); /* determine if scrolling is required */ + + _scrollbarVisibility.call(this); /* show/hide scrollbar(s) */ + + /* auto-adjust scrollbar dragger length analogous to content */ + if(o.autoDraggerLength){_setDraggerLength.call(this);} + + _scrollRatio.call(this); /* calculate and store scrollbar to content ratio */ + + _bindEvents.call(this); /* bind scrollbar events */ + + /* reset scrolling position and/or events */ + var to=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)]; + if(o.axis!=="x"){ /* y/yx axis */ + if(!d.overflowed[0]){ /* y scrolling is not required */ + _resetContentPosition.call(this); /* reset content position */ + if(o.axis==="y"){ + _unbindEvents.call(this); + }else if(o.axis==="yx" && d.overflowed[1]){ + _scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"}); + } + }else if(mCSB_dragger[0].height()>mCSB_dragger[0].parent().height()){ + _resetContentPosition.call(this); /* reset content position */ + }else{ /* y scrolling is required */ + _scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"}); + d.contentReset.y=null; + } + } + if(o.axis!=="y"){ /* x/yx axis */ + if(!d.overflowed[1]){ /* x scrolling is not required */ + _resetContentPosition.call(this); /* reset content position */ + if(o.axis==="x"){ + _unbindEvents.call(this); + }else if(o.axis==="yx" && d.overflowed[0]){ + _scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"}); + } + }else if(mCSB_dragger[1].width()>mCSB_dragger[1].parent().width()){ + _resetContentPosition.call(this); /* reset content position */ + }else{ /* x scrolling is required */ + _scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"}); + d.contentReset.x=null; + } + } + + /* callbacks: onImageLoad, onSelectorChange, onUpdate */ + if(cb && d){ + if(cb===2 && o.callbacks.onImageLoad && typeof o.callbacks.onImageLoad==="function"){ + o.callbacks.onImageLoad.call(this); + }else if(cb===3 && o.callbacks.onSelectorChange && typeof o.callbacks.onSelectorChange==="function"){ + o.callbacks.onSelectorChange.call(this); + }else if(o.callbacks.onUpdate && typeof o.callbacks.onUpdate==="function"){ + o.callbacks.onUpdate.call(this); + } + } + + _autoUpdate.call(this); /* initialize automatic updating (for dynamic content, fluid layouts etc.) */ + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin scrollTo method + triggers a scrolling event to a specific value + ---------------------------------------- + usage: $(selector).mCustomScrollbar("scrollTo",value,options); + */ + + scrollTo:function(val,options){ + + /* prevent silly things like $(selector).mCustomScrollbar("scrollTo",undefined); */ + if(typeof val=="undefined" || val==null){return;} + + var selector=_selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + var d=$this.data(pluginPfx),o=d.opt, + /* method default options */ + methodDefaults={ + trigger:"external", /* method is by default triggered externally (e.g. from other scripts) */ + scrollInertia:o.scrollInertia, /* scrolling inertia (animation duration) */ + scrollEasing:"mcsEaseInOut", /* animation easing */ + moveDragger:false, /* move dragger instead of content */ + timeout:60, /* scroll-to delay */ + callbacks:true, /* enable/disable callbacks */ + onStart:true, + onUpdate:true, + onComplete:true + }, + methodOptions=$.extend(true,{},methodDefaults,options), + to=_arr.call(this,val),dur=methodOptions.scrollInertia>0 && methodOptions.scrollInertia<17 ? 17 : methodOptions.scrollInertia; + + /* translate yx values to actual scroll-to positions */ + to[0]=_to.call(this,to[0],"y"); + to[1]=_to.call(this,to[1],"x"); + + /* + check if scroll-to value moves the dragger instead of content. + Only pixel values apply on dragger (e.g. 100, "100px", "-=100" etc.) + */ + if(methodOptions.moveDragger){ + to[0]*=d.scrollRatio.y; + to[1]*=d.scrollRatio.x; + } + + methodOptions.dur=_isTabHidden() ? 0 : dur; //skip animations if browser tab is hidden + + setTimeout(function(){ + /* do the scrolling */ + if(to[0]!==null && typeof to[0]!=="undefined" && o.axis!=="x" && d.overflowed[0]){ /* scroll y */ + methodOptions.dir="y"; + methodOptions.overwrite="all"; + _scrollTo($this,to[0].toString(),methodOptions); + } + if(to[1]!==null && typeof to[1]!=="undefined" && o.axis!=="y" && d.overflowed[1]){ /* scroll x */ + methodOptions.dir="x"; + methodOptions.overwrite="none"; + _scrollTo($this,to[1].toString(),methodOptions); + } + },methodOptions.timeout); + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin stop method + stops scrolling animation + ---------------------------------------- + usage: $(selector).mCustomScrollbar("stop"); + */ + stop:function(){ + + var selector=_selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + _stop($this); + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin disable method + temporarily disables the scrollbar(s) + ---------------------------------------- + usage: $(selector).mCustomScrollbar("disable",reset); + reset (boolean): resets content position to 0 + */ + disable:function(r){ + + var selector=_selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + var d=$this.data(pluginPfx); + + _autoUpdate.call(this,"remove"); /* remove automatic updating */ + + _unbindEvents.call(this); /* unbind events */ + + if(r){_resetContentPosition.call(this);} /* reset content position */ + + _scrollbarVisibility.call(this,true); /* show/hide scrollbar(s) */ + + $this.addClass(classes[3]); /* add disable class */ + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin destroy method + completely removes the scrollbar(s) and returns the element to its original state + ---------------------------------------- + usage: $(selector).mCustomScrollbar("destroy"); + */ + destroy:function(){ + + var selector=_selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + var d=$this.data(pluginPfx),o=d.opt, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + scrollbar=$(".mCSB_"+d.idx+"_scrollbar"); + + if(o.live){removeLiveTimers(o.liveSelector || $(selector).selector);} /* remove live timers */ + + _autoUpdate.call(this,"remove"); /* remove automatic updating */ + + _unbindEvents.call(this); /* unbind events */ + + _resetContentPosition.call(this); /* reset content position */ + + $this.removeData(pluginPfx); /* remove plugin data object */ + + _delete(this,"mcs"); /* delete callbacks object */ + + /* remove plugin markup */ + scrollbar.remove(); /* remove scrollbar(s) first (those can be either inside or outside plugin's inner wrapper) */ + mCSB_container.find("img."+classes[2]).removeClass(classes[2]); /* remove loaded images flag */ + mCustomScrollBox.replaceWith(mCSB_container.contents()); /* replace plugin's inner wrapper with the original content */ + /* remove plugin classes from the element and add destroy class */ + $this.removeClass(pluginNS+" _"+pluginPfx+"_"+d.idx+" "+classes[6]+" "+classes[7]+" "+classes[5]+" "+classes[3]).addClass(classes[4]); + + } + + }); + + } + /* ---------------------------------------- */ + + }, + + + + + + /* + ---------------------------------------- + FUNCTIONS + ---------------------------------------- + */ + + /* validates selector (if selector is invalid or undefined uses the default one) */ + _selector=function(){ + return (typeof $(this)!=="object" || $(this).length<1) ? defaultSelector : this; + }, + /* -------------------- */ + + + /* changes options according to theme */ + _theme=function(obj){ + var fixedSizeScrollbarThemes=["rounded","rounded-dark","rounded-dots","rounded-dots-dark"], + nonExpandedScrollbarThemes=["rounded-dots","rounded-dots-dark","3d","3d-dark","3d-thick","3d-thick-dark","inset","inset-dark","inset-2","inset-2-dark","inset-3","inset-3-dark"], + disabledScrollButtonsThemes=["minimal","minimal-dark"], + enabledAutoHideScrollbarThemes=["minimal","minimal-dark"], + scrollbarPositionOutsideThemes=["minimal","minimal-dark"]; + obj.autoDraggerLength=$.inArray(obj.theme,fixedSizeScrollbarThemes) > -1 ? false : obj.autoDraggerLength; + obj.autoExpandScrollbar=$.inArray(obj.theme,nonExpandedScrollbarThemes) > -1 ? false : obj.autoExpandScrollbar; + obj.scrollButtons.enable=$.inArray(obj.theme,disabledScrollButtonsThemes) > -1 ? false : obj.scrollButtons.enable; + obj.autoHideScrollbar=$.inArray(obj.theme,enabledAutoHideScrollbarThemes) > -1 ? true : obj.autoHideScrollbar; + obj.scrollbarPosition=$.inArray(obj.theme,scrollbarPositionOutsideThemes) > -1 ? "outside" : obj.scrollbarPosition; + }, + /* -------------------- */ + + + /* live option timers removal */ + removeLiveTimers=function(selector){ + if(liveTimers[selector]){ + clearTimeout(liveTimers[selector]); + _delete(liveTimers,selector); + } + }, + /* -------------------- */ + + + /* normalizes axis option to valid values: "y", "x", "yx" */ + _findAxis=function(val){ + return (val==="yx" || val==="xy" || val==="auto") ? "yx" : (val==="x" || val==="horizontal") ? "x" : "y"; + }, + /* -------------------- */ + + + /* normalizes scrollButtons.scrollType option to valid values: "stepless", "stepped" */ + _findScrollButtonsType=function(val){ + return (val==="stepped" || val==="pixels" || val==="step" || val==="click") ? "stepped" : "stepless"; + }, + /* -------------------- */ + + + /* generates plugin markup */ + _pluginMarkup=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + expandClass=o.autoExpandScrollbar ? " "+classes[1]+"_expand" : "", + scrollbar=["
    ","
    "], + wrapperClass=o.axis==="yx" ? "mCSB_vertical_horizontal" : o.axis==="x" ? "mCSB_horizontal" : "mCSB_vertical", + scrollbars=o.axis==="yx" ? scrollbar[0]+scrollbar[1] : o.axis==="x" ? scrollbar[1] : scrollbar[0], + contentWrapper=o.axis==="yx" ? "
    " : "", + autoHideClass=o.autoHideScrollbar ? " "+classes[6] : "", + scrollbarDirClass=(o.axis!=="x" && d.langDir==="rtl") ? " "+classes[7] : ""; + if(o.setWidth){$this.css("width",o.setWidth);} /* set element width */ + if(o.setHeight){$this.css("height",o.setHeight);} /* set element height */ + o.setLeft=(o.axis!=="y" && d.langDir==="rtl") ? "989999px" : o.setLeft; /* adjust left position for rtl direction */ + $this.addClass(pluginNS+" _"+pluginPfx+"_"+d.idx+autoHideClass+scrollbarDirClass).wrapInner("
    "); + var mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"); + if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){ + mCSB_container.css("width",_contentWidth(mCSB_container)); + } + if(o.scrollbarPosition==="outside"){ + if($this.css("position")==="static"){ /* requires elements with non-static position */ + $this.css("position","relative"); + } + $this.css("overflow","visible"); + mCustomScrollBox.addClass("mCSB_outside").after(scrollbars); + }else{ + mCustomScrollBox.addClass("mCSB_inside").append(scrollbars); + mCSB_container.wrap(contentWrapper); + } + _scrollButtons.call(this); /* add scrollbar buttons */ + /* minimum dragger length */ + var mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; + mCSB_dragger[0].css("min-height",mCSB_dragger[0].height()); + mCSB_dragger[1].css("min-width",mCSB_dragger[1].width()); + }, + /* -------------------- */ + + + /* calculates content width */ + _contentWidth=function(el){ + var val=[el[0].scrollWidth,Math.max.apply(Math,el.children().map(function(){return $(this).outerWidth(true);}).get())],w=el.parent().width(); + return val[0]>w ? val[0] : val[1]>w ? val[1] : "100%"; + }, + /* -------------------- */ + + + /* expands content horizontally */ + _expandContentHorizontally=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCSB_container=$("#mCSB_"+d.idx+"_container"); + if(o.advanced.autoExpandHorizontalScroll && o.axis!=="y"){ + /* calculate scrollWidth */ + mCSB_container.css({"width":"auto","min-width":0,"overflow-x":"scroll"}); + var w=Math.ceil(mCSB_container[0].scrollWidth); + if(o.advanced.autoExpandHorizontalScroll===3 || (o.advanced.autoExpandHorizontalScroll!==2 && w>mCSB_container.parent().width())){ + mCSB_container.css({"width":w,"min-width":"100%","overflow-x":"inherit"}); + }else{ + /* + wrap content with an infinite width div and set its position to absolute and width to auto. + Setting width to auto before calculating the actual width is important! + We must let the browser set the width as browser zoom values are impossible to calculate. + */ + mCSB_container.css({"overflow-x":"inherit","position":"absolute"}) + .wrap("
    ") + .css({ /* set actual width, original position and un-wrap */ + /* + get the exact width (with decimals) and then round-up. + Using jquery outerWidth() will round the width value which will mess up with inner elements that have non-integer width + */ + "width":(Math.ceil(mCSB_container[0].getBoundingClientRect().right+0.4)-Math.floor(mCSB_container[0].getBoundingClientRect().left)), + "min-width":"100%", + "position":"relative" + }).unwrap(); + } + } + }, + /* -------------------- */ + + + /* adds scrollbar buttons */ + _scrollButtons=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCSB_scrollTools=$(".mCSB_"+d.idx+"_scrollbar:first"), + tabindex=!_isNumeric(o.scrollButtons.tabindex) ? "" : "tabindex='"+o.scrollButtons.tabindex+"'", + btnHTML=[ + "", + "", + "", + "" + ], + btn=[(o.axis==="x" ? btnHTML[2] : btnHTML[0]),(o.axis==="x" ? btnHTML[3] : btnHTML[1]),btnHTML[2],btnHTML[3]]; + if(o.scrollButtons.enable){ + mCSB_scrollTools.prepend(btn[0]).append(btn[1]).next(".mCSB_scrollTools").prepend(btn[2]).append(btn[3]); + } + }, + /* -------------------- */ + + + /* auto-adjusts scrollbar dragger length */ + _setDraggerLength=function(){ + var $this=$(this),d=$this.data(pluginPfx), + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], + ratio=[mCustomScrollBox.height()/mCSB_container.outerHeight(false),mCustomScrollBox.width()/mCSB_container.outerWidth(false)], + l=[ + parseInt(mCSB_dragger[0].css("min-height")),Math.round(ratio[0]*mCSB_dragger[0].parent().height()), + parseInt(mCSB_dragger[1].css("min-width")),Math.round(ratio[1]*mCSB_dragger[1].parent().width()) + ], + h=oldIE && (l[1]contentHeight){contentHeight=h;} + if(w>contentWidth){contentWidth=w;} + return [contentHeight>mCustomScrollBox.height(),contentWidth>mCustomScrollBox.width()]; + }, + /* -------------------- */ + + + /* resets content position to 0 */ + _resetContentPosition=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; + _stop($this); /* stop any current scrolling before resetting */ + if((o.axis!=="x" && !d.overflowed[0]) || (o.axis==="y" && d.overflowed[0])){ /* reset y */ + mCSB_dragger[0].add(mCSB_container).css("top",0); + _scrollTo($this,"_resetY"); + } + if((o.axis!=="y" && !d.overflowed[1]) || (o.axis==="x" && d.overflowed[1])){ /* reset x */ + var cx=dx=0; + if(d.langDir==="rtl"){ /* adjust left position for rtl direction */ + cx=mCustomScrollBox.width()-mCSB_container.outerWidth(false); + dx=Math.abs(cx/d.scrollRatio.x); + } + mCSB_container.css("left",cx); + mCSB_dragger[1].css("left",dx); + _scrollTo($this,"_resetX"); + } + }, + /* -------------------- */ + + + /* binds scrollbar events */ + _bindEvents=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt; + if(!d.bindEvents){ /* check if events are already bound */ + _draggable.call(this); + if(o.contentTouchScroll){_contentDraggable.call(this);} + _selectable.call(this); + if(o.mouseWheel.enable){ /* bind mousewheel fn when plugin is available */ + function _mwt(){ + mousewheelTimeout=setTimeout(function(){ + if(!$.event.special.mousewheel){ + _mwt(); + }else{ + clearTimeout(mousewheelTimeout); + _mousewheel.call($this[0]); + } + },100); + } + var mousewheelTimeout; + _mwt(); + } + _draggerRail.call(this); + _wrapperScroll.call(this); + if(o.advanced.autoScrollOnFocus){_focus.call(this);} + if(o.scrollButtons.enable){_buttons.call(this);} + if(o.keyboard.enable){_keyboard.call(this);} + d.bindEvents=true; + } + }, + /* -------------------- */ + + + /* unbinds scrollbar events */ + _unbindEvents=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + sb=".mCSB_"+d.idx+"_scrollbar", + sel=$("#mCSB_"+d.idx+",#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,"+sb+" ."+classes[12]+",#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal,"+sb+">a"), + mCSB_container=$("#mCSB_"+d.idx+"_container"); + if(o.advanced.releaseDraggableSelectors){sel.add($(o.advanced.releaseDraggableSelectors));} + if(o.advanced.extraDraggableSelectors){sel.add($(o.advanced.extraDraggableSelectors));} + if(d.bindEvents){ /* check if events are bound */ + /* unbind namespaced events from document/selectors */ + $(document).add($(!_canAccessIFrame() || top.document)).unbind("."+namespace); + sel.each(function(){ + $(this).unbind("."+namespace); + }); + /* clear and delete timeouts/objects */ + clearTimeout($this[0]._focusTimeout); _delete($this[0],"_focusTimeout"); + clearTimeout(d.sequential.step); _delete(d.sequential,"step"); + clearTimeout(mCSB_container[0].onCompleteTimeout); _delete(mCSB_container[0],"onCompleteTimeout"); + d.bindEvents=false; + } + }, + /* -------------------- */ + + + /* toggles scrollbar visibility */ + _scrollbarVisibility=function(disabled){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + contentWrapper=$("#mCSB_"+d.idx+"_container_wrapper"), + content=contentWrapper.length ? contentWrapper : $("#mCSB_"+d.idx+"_container"), + scrollbar=[$("#mCSB_"+d.idx+"_scrollbar_vertical"),$("#mCSB_"+d.idx+"_scrollbar_horizontal")], + mCSB_dragger=[scrollbar[0].find(".mCSB_dragger"),scrollbar[1].find(".mCSB_dragger")]; + if(o.axis!=="x"){ + if(d.overflowed[0] && !disabled){ + scrollbar[0].add(mCSB_dragger[0]).add(scrollbar[0].children("a")).css("display","block"); + content.removeClass(classes[8]+" "+classes[10]); + }else{ + if(o.alwaysShowScrollbar){ + if(o.alwaysShowScrollbar!==2){mCSB_dragger[0].css("display","none");} + content.removeClass(classes[10]); + }else{ + scrollbar[0].css("display","none"); + content.addClass(classes[10]); + } + content.addClass(classes[8]); + } + } + if(o.axis!=="y"){ + if(d.overflowed[1] && !disabled){ + scrollbar[1].add(mCSB_dragger[1]).add(scrollbar[1].children("a")).css("display","block"); + content.removeClass(classes[9]+" "+classes[11]); + }else{ + if(o.alwaysShowScrollbar){ + if(o.alwaysShowScrollbar!==2){mCSB_dragger[1].css("display","none");} + content.removeClass(classes[11]); + }else{ + scrollbar[1].css("display","none"); + content.addClass(classes[11]); + } + content.addClass(classes[9]); + } + } + if(!d.overflowed[0] && !d.overflowed[1]){ + $this.addClass(classes[5]); + }else{ + $this.removeClass(classes[5]); + } + }, + /* -------------------- */ + + + /* returns input coordinates of pointer, touch and mouse events (relative to document) */ + _coordinates=function(e){ + var t=e.type,o=e.target.ownerDocument!==document && frameElement!==null ? [$(frameElement).offset().top,$(frameElement).offset().left] : null, + io=_canAccessIFrame() && e.target.ownerDocument!==top.document && frameElement!==null ? [$(e.view.frameElement).offset().top,$(e.view.frameElement).offset().left] : [0,0]; + switch(t){ + case "pointerdown": case "MSPointerDown": case "pointermove": case "MSPointerMove": case "pointerup": case "MSPointerUp": + return o ? [e.originalEvent.pageY-o[0]+io[0],e.originalEvent.pageX-o[1]+io[1],false] : [e.originalEvent.pageY,e.originalEvent.pageX,false]; + break; + case "touchstart": case "touchmove": case "touchend": + var touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0], + touches=e.originalEvent.touches.length || e.originalEvent.changedTouches.length; + return e.target.ownerDocument!==document ? [touch.screenY,touch.screenX,touches>1] : [touch.pageY,touch.pageX,touches>1]; + break; + default: + return o ? [e.pageY-o[0]+io[0],e.pageX-o[1]+io[1],false] : [e.pageY,e.pageX,false]; + } + }, + /* -------------------- */ + + + /* + SCROLLBAR DRAG EVENTS + scrolls content via scrollbar dragging + */ + _draggable=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + draggerId=["mCSB_"+d.idx+"_dragger_vertical","mCSB_"+d.idx+"_dragger_horizontal"], + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCSB_dragger=$("#"+draggerId[0]+",#"+draggerId[1]), + draggable,dragY,dragX, + rds=o.advanced.releaseDraggableSelectors ? mCSB_dragger.add($(o.advanced.releaseDraggableSelectors)) : mCSB_dragger, + eds=o.advanced.extraDraggableSelectors ? $(!_canAccessIFrame() || top.document).add($(o.advanced.extraDraggableSelectors)) : $(!_canAccessIFrame() || top.document); + mCSB_dragger.bind("contextmenu."+namespace,function(e){ + e.preventDefault(); //prevent right click + }).bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){ + e.stopImmediatePropagation(); + e.preventDefault(); + if(!_mouseBtnLeft(e)){return;} /* left mouse button only */ + touchActive=true; + if(oldIE){document.onselectstart=function(){return false;}} /* disable text selection for IE < 9 */ + _iframe.call(mCSB_container,false); /* enable scrollbar dragging over iframes by disabling their events */ + _stop($this); + draggable=$(this); + var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left, + h=draggable.height()+offset.top,w=draggable.width()+offset.left; + if(y0 && x0){ + dragY=y; + dragX=x; + } + _onDragClasses(draggable,"active",o.autoExpandScrollbar); + }).bind("touchmove."+namespace,function(e){ + e.stopImmediatePropagation(); + e.preventDefault(); + var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left; + _drag(dragY,dragX,y,x); + }); + $(document).add(eds).bind("mousemove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace,function(e){ + if(draggable){ + var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left; + if(dragY===y && dragX===x){return;} /* has it really moved? */ + _drag(dragY,dragX,y,x); + } + }).add(rds).bind("mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){ + if(draggable){ + _onDragClasses(draggable,"active",o.autoExpandScrollbar); + draggable=null; + } + touchActive=false; + if(oldIE){document.onselectstart=null;} /* enable text selection for IE < 9 */ + _iframe.call(mCSB_container,true); /* enable iframes events */ + }); + function _drag(dragY,dragX,y,x){ + mCSB_container[0].idleTimer=o.scrollInertia<233 ? 250 : 0; + if(draggable.attr("id")===draggerId[1]){ + var dir="x",to=((draggable[0].offsetLeft-dragX)+x)*d.scrollRatio.x; + }else{ + var dir="y",to=((draggable[0].offsetTop-dragY)+y)*d.scrollRatio.y; + } + _scrollTo($this,to.toString(),{dir:dir,drag:true}); + } + }, + /* -------------------- */ + + + /* + TOUCH SWIPE EVENTS + scrolls content via touch swipe + Emulates the native touch-swipe scrolling with momentum found in iOS, Android and WP devices + */ + _contentDraggable=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], + draggable,dragY,dragX,touchStartY,touchStartX,touchMoveY=[],touchMoveX=[],startTime,runningTime,endTime,distance,speed,amount, + durA=0,durB,overwrite=o.axis==="yx" ? "none" : "all",touchIntent=[],touchDrag,docDrag, + iframe=mCSB_container.find("iframe"), + events=[ + "touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace, //start + "touchmove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace, //move + "touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace //end + ], + touchAction=document.body.style.touchAction!==undefined && document.body.style.touchAction!==""; + mCSB_container.bind(events[0],function(e){ + _onTouchstart(e); + }).bind(events[1],function(e){ + _onTouchmove(e); + }); + mCustomScrollBox.bind(events[0],function(e){ + _onTouchstart2(e); + }).bind(events[2],function(e){ + _onTouchend(e); + }); + if(iframe.length){ + iframe.each(function(){ + $(this).bind("load",function(){ + /* bind events on accessible iframes */ + if(_canAccessIFrame(this)){ + $(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){ + _onTouchstart(e); + _onTouchstart2(e); + }).bind(events[1],function(e){ + _onTouchmove(e); + }).bind(events[2],function(e){ + _onTouchend(e); + }); + } + }); + }); + } + function _onTouchstart(e){ + if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){touchable=0; return;} + touchable=1; touchDrag=0; docDrag=0; draggable=1; + $this.removeClass("mCS_touch_action"); + var offset=mCSB_container.offset(); + dragY=_coordinates(e)[0]-offset.top; + dragX=_coordinates(e)[1]-offset.left; + touchIntent=[_coordinates(e)[0],_coordinates(e)[1]]; + } + function _onTouchmove(e){ + if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){return;} + if(!o.documentTouchScroll){e.preventDefault();} + e.stopImmediatePropagation(); + if(docDrag && !touchDrag){return;} + if(draggable){ + runningTime=_getTime(); + var offset=mCustomScrollBox.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left, + easing="mcsLinearOut"; + touchMoveY.push(y); + touchMoveX.push(x); + touchIntent[2]=Math.abs(_coordinates(e)[0]-touchIntent[0]); touchIntent[3]=Math.abs(_coordinates(e)[1]-touchIntent[1]); + if(d.overflowed[0]){ + var limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(), + prevent=((dragY-y)>0 && (y-dragY)>-(limit*d.scrollRatio.y) && (touchIntent[3]*20 && (x-dragX)>-(limitX*d.scrollRatio.x) && (touchIntent[2]*230){return;} + speed=1000/(endTime-startTime); + var easing="mcsEaseOut",slow=speed<2.5, + diff=slow ? [touchMoveY[touchMoveY.length-2],touchMoveX[touchMoveX.length-2]] : [0,0]; + distance=slow ? [(y-diff[0]),(x-diff[1])] : [y-touchStartY,x-touchStartX]; + var absDistance=[Math.abs(distance[0]),Math.abs(distance[1])]; + speed=slow ? [Math.abs(distance[0]/4),Math.abs(distance[1]/4)] : [speed,speed]; + var a=[ + Math.abs(mCSB_container[0].offsetTop)-(distance[0]*_m((absDistance[0]/speed[0]),speed[0])), + Math.abs(mCSB_container[0].offsetLeft)-(distance[1]*_m((absDistance[1]/speed[1]),speed[1])) + ]; + amount=o.axis==="yx" ? [a[0],a[1]] : o.axis==="x" ? [null,a[1]] : [a[0],null]; + durB=[(absDistance[0]*4)+o.scrollInertia,(absDistance[1]*4)+o.scrollInertia]; + var md=parseInt(o.contentTouchScroll) || 0; /* absolute minimum distance required */ + amount[0]=absDistance[0]>md ? amount[0] : 0; + amount[1]=absDistance[1]>md ? amount[1] : 0; + if(d.overflowed[0]){_drag(amount[0],durB[0],easing,"y",overwrite,false);} + if(d.overflowed[1]){_drag(amount[1],durB[1],easing,"x",overwrite,false);} + } + function _m(ds,s){ + var r=[s*1.5,s*2,s/1.5,s/2]; + if(ds>90){ + return s>4 ? r[0] : r[3]; + }else if(ds>60){ + return s>3 ? r[3] : r[2]; + }else if(ds>30){ + return s>8 ? r[1] : s>6 ? r[0] : s>4 ? s : r[2]; + }else{ + return s>8 ? s : r[3]; + } + } + function _drag(amount,dur,easing,dir,overwrite,drag){ + if(!amount){return;} + _scrollTo($this,amount.toString(),{dur:dur,scrollEasing:easing,dir:dir,overwrite:overwrite,drag:drag}); + } + }, + /* -------------------- */ + + + /* + SELECT TEXT EVENTS + scrolls content when text is selected + */ + _selectable=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential, + namespace=pluginPfx+"_"+d.idx, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + action; + mCSB_container.bind("mousedown."+namespace,function(e){ + if(touchable){return;} + if(!action){action=1; touchActive=true;} + }).add(document).bind("mousemove."+namespace,function(e){ + if(!touchable && action && _sel()){ + var offset=mCSB_container.offset(), + y=_coordinates(e)[0]-offset.top+mCSB_container[0].offsetTop,x=_coordinates(e)[1]-offset.left+mCSB_container[0].offsetLeft; + if(y>0 && y0 && xwrapper.height()){ + _seq("on",40); + } + } + if(o.axis!=="y" && d.overflowed[1]){ + if(x<0){ + _seq("on",37); + }else if(x>wrapper.width()){ + _seq("on",39); + } + } + } + } + }).bind("mouseup."+namespace+" dragend."+namespace,function(e){ + if(touchable){return;} + if(action){action=0; _seq("off",null);} + touchActive=false; + }); + function _sel(){ + return window.getSelection ? window.getSelection().toString() : + document.selection && document.selection.type!="Control" ? document.selection.createRange().text : 0; + } + function _seq(a,c,s){ + seq.type=s && action ? "stepped" : "stepless"; + seq.scrollAmount=10; + _sequentialScroll($this,a,c,"mcsLinearOut",s ? 60 : null); + } + }, + /* -------------------- */ + + + /* + MOUSE WHEEL EVENT + scrolls content via mouse-wheel + via mouse-wheel plugin (https://github.com/brandonaaron/jquery-mousewheel) + */ + _mousewheel=function(){ + if(!$(this).data(pluginPfx)){return;} /* Check if the scrollbar is ready to use mousewheel events (issue: #185) */ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], + iframe=$("#mCSB_"+d.idx+"_container").find("iframe"); + if(iframe.length){ + iframe.each(function(){ + $(this).bind("load",function(){ + /* bind events on accessible iframes */ + if(_canAccessIFrame(this)){ + $(this.contentDocument || this.contentWindow.document).bind("mousewheel."+namespace,function(e,delta){ + _onMousewheel(e,delta); + }); + } + }); + }); + } + mCustomScrollBox.bind("mousewheel."+namespace,function(e,delta){ + _onMousewheel(e,delta); + }); + function _onMousewheel(e,delta){ + _stop($this); + if(_disableMousewheel($this,e.target)){return;} /* disables mouse-wheel when hovering specific elements */ + var deltaFactor=o.mouseWheel.deltaFactor!=="auto" ? parseInt(o.mouseWheel.deltaFactor) : (oldIE && e.deltaFactor<100) ? 100 : e.deltaFactor || 100, + dur=o.scrollInertia; + if(o.axis==="x" || o.mouseWheel.axis==="x"){ + var dir="x", + px=[Math.round(deltaFactor*d.scrollRatio.x),parseInt(o.mouseWheel.scrollAmount)], + amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.width() ? mCustomScrollBox.width()*0.9 : px[0], + contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetLeft), + draggerPos=mCSB_dragger[1][0].offsetLeft, + limit=mCSB_dragger[1].parent().width()-mCSB_dragger[1].width(), + dlt=o.mouseWheel.axis==="y" ? (e.deltaY || delta) : e.deltaX; + }else{ + var dir="y", + px=[Math.round(deltaFactor*d.scrollRatio.y),parseInt(o.mouseWheel.scrollAmount)], + amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.height() ? mCustomScrollBox.height()*0.9 : px[0], + contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetTop), + draggerPos=mCSB_dragger[0][0].offsetTop, + limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(), + dlt=e.deltaY || delta; + } + if((dir==="y" && !d.overflowed[0]) || (dir==="x" && !d.overflowed[1])){return;} + if(o.mouseWheel.invert || e.webkitDirectionInvertedFromDevice){dlt=-dlt;} + if(o.mouseWheel.normalizeDelta){dlt=dlt<0 ? -1 : 1;} + if((dlt>0 && draggerPos!==0) || (dlt<0 && draggerPos!==limit) || o.mouseWheel.preventDefault){ + e.stopImmediatePropagation(); + e.preventDefault(); + } + if(e.deltaFactor<5 && !o.mouseWheel.normalizeDelta){ + //very low deltaFactor values mean some kind of delta acceleration (e.g. osx trackpad), so adjusting scrolling accordingly + amount=e.deltaFactor; dur=17; + } + _scrollTo($this,(contentPos-(dlt*amount)).toString(),{dir:dir,dur:dur}); + } + }, + /* -------------------- */ + + + /* checks if iframe can be accessed */ + _canAccessIFrameCache=new Object(), + _canAccessIFrame=function(iframe){ + var result=false,cacheKey=false,html=null; + if(iframe===undefined){ + cacheKey="#empty"; + }else if($(iframe).attr("id")!==undefined){ + cacheKey=$(iframe).attr("id"); + } + if(cacheKey!==false && _canAccessIFrameCache[cacheKey]!==undefined){ + return _canAccessIFrameCache[cacheKey]; + } + if(!iframe){ + try{ + var doc=top.document; + html=doc.body.innerHTML; + }catch(err){/* do nothing */} + result=(html!==null); + }else{ + try{ + var doc=iframe.contentDocument || iframe.contentWindow.document; + html=doc.body.innerHTML; + }catch(err){/* do nothing */} + result=(html!==null); + } + if(cacheKey!==false){_canAccessIFrameCache[cacheKey]=result;} + return result; + }, + /* -------------------- */ + + + /* switches iframe's pointer-events property (drag, mousewheel etc. over cross-domain iframes) */ + _iframe=function(evt){ + var el=this.find("iframe"); + if(!el.length){return;} /* check if content contains iframes */ + var val=!evt ? "none" : "auto"; + el.css("pointer-events",val); /* for IE11, iframe's display property should not be "block" */ + }, + /* -------------------- */ + + + /* disables mouse-wheel when hovering specific elements like select, datalist etc. */ + _disableMousewheel=function(el,target){ + var tag=target.nodeName.toLowerCase(), + tags=el.data(pluginPfx).opt.mouseWheel.disableOver, + /* elements that require focus */ + focusTags=["select","textarea"]; + return $.inArray(tag,tags) > -1 && !($.inArray(tag,focusTags) > -1 && !$(target).is(":focus")); + }, + /* -------------------- */ + + + /* + DRAGGER RAIL CLICK EVENT + scrolls content via dragger rail + */ + _draggerRail=function(){ + var $this=$(this),d=$this.data(pluginPfx), + namespace=pluginPfx+"_"+d.idx, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + mCSB_draggerContainer=$(".mCSB_"+d.idx+"_scrollbar ."+classes[12]), + clickable; + mCSB_draggerContainer.bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){ + touchActive=true; + if(!$(e.target).hasClass("mCSB_dragger")){clickable=1;} + }).bind("touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){ + touchActive=false; + }).bind("click."+namespace,function(e){ + if(!clickable){return;} + clickable=0; + if($(e.target).hasClass(classes[12]) || $(e.target).hasClass("mCSB_draggerRail")){ + _stop($this); + var el=$(this),mCSB_dragger=el.find(".mCSB_dragger"); + if(el.parent(".mCSB_scrollTools_horizontal").length>0){ + if(!d.overflowed[1]){return;} + var dir="x", + clickDir=e.pageX>mCSB_dragger.offset().left ? -1 : 1, + to=Math.abs(mCSB_container[0].offsetLeft)-(clickDir*(wrapper.width()*0.9)); + }else{ + if(!d.overflowed[0]){return;} + var dir="y", + clickDir=e.pageY>mCSB_dragger.offset().top ? -1 : 1, + to=Math.abs(mCSB_container[0].offsetTop)-(clickDir*(wrapper.height()*0.9)); + } + _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); + } + }); + }, + /* -------------------- */ + + + /* + FOCUS EVENT + scrolls content via element focus (e.g. clicking an input, pressing TAB key etc.) + */ + _focus=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(); + mCSB_container.bind("focusin."+namespace,function(e){ + var el=$(document.activeElement), + nested=mCSB_container.find(".mCustomScrollBox").length, + dur=0; + if(!el.is(o.advanced.autoScrollOnFocus)){return;} + _stop($this); + clearTimeout($this[0]._focusTimeout); + $this[0]._focusTimer=nested ? (dur+17)*nested : 0; + $this[0]._focusTimeout=setTimeout(function(){ + var to=[_childPos(el)[0],_childPos(el)[1]], + contentPos=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft], + isVisible=[ + (contentPos[0]+to[0]>=0 && contentPos[0]+to[0]=0 && contentPos[0]+to[1]a"); + btn.bind("contextmenu."+namespace,function(e){ + e.preventDefault(); //prevent right click + }).bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace+" mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace+" mouseout."+namespace+" pointerout."+namespace+" MSPointerOut."+namespace+" click."+namespace,function(e){ + e.preventDefault(); + if(!_mouseBtnLeft(e)){return;} /* left mouse button only */ + var btnClass=$(this).attr("class"); + seq.type=o.scrollButtons.scrollType; + switch(e.type){ + case "mousedown": case "touchstart": case "pointerdown": case "MSPointerDown": + if(seq.type==="stepped"){return;} + touchActive=true; + d.tweenRunning=false; + _seq("on",btnClass); + break; + case "mouseup": case "touchend": case "pointerup": case "MSPointerUp": + case "mouseout": case "pointerout": case "MSPointerOut": + if(seq.type==="stepped"){return;} + touchActive=false; + if(seq.dir){_seq("off",btnClass);} + break; + case "click": + if(seq.type!=="stepped" || d.tweenRunning){return;} + _seq("on",btnClass); + break; + } + function _seq(a,c){ + seq.scrollAmount=o.scrollButtons.scrollAmount; + _sequentialScroll($this,a,c); + } + }); + }, + /* -------------------- */ + + + /* + KEYBOARD EVENTS + scrolls content via keyboard + Keys: up arrow, down arrow, left arrow, right arrow, PgUp, PgDn, Home, End + */ + _keyboard=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential, + namespace=pluginPfx+"_"+d.idx, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + editables="input,textarea,select,datalist,keygen,[contenteditable='true']", + iframe=mCSB_container.find("iframe"), + events=["blur."+namespace+" keydown."+namespace+" keyup."+namespace]; + if(iframe.length){ + iframe.each(function(){ + $(this).bind("load",function(){ + /* bind events on accessible iframes */ + if(_canAccessIFrame(this)){ + $(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){ + _onKeyboard(e); + }); + } + }); + }); + } + mCustomScrollBox.attr("tabindex","0").bind(events[0],function(e){ + _onKeyboard(e); + }); + function _onKeyboard(e){ + switch(e.type){ + case "blur": + if(d.tweenRunning && seq.dir){_seq("off",null);} + break; + case "keydown": case "keyup": + var code=e.keyCode ? e.keyCode : e.which,action="on"; + if((o.axis!=="x" && (code===38 || code===40)) || (o.axis!=="y" && (code===37 || code===39))){ + /* up (38), down (40), left (37), right (39) arrows */ + if(((code===38 || code===40) && !d.overflowed[0]) || ((code===37 || code===39) && !d.overflowed[1])){return;} + if(e.type==="keyup"){action="off";} + if(!$(document.activeElement).is(editables)){ + e.preventDefault(); + e.stopImmediatePropagation(); + _seq(action,code); + } + }else if(code===33 || code===34){ + /* PgUp (33), PgDn (34) */ + if(d.overflowed[0] || d.overflowed[1]){ + e.preventDefault(); + e.stopImmediatePropagation(); + } + if(e.type==="keyup"){ + _stop($this); + var keyboardDir=code===34 ? -1 : 1; + if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){ + var dir="x",to=Math.abs(mCSB_container[0].offsetLeft)-(keyboardDir*(wrapper.width()*0.9)); + }else{ + var dir="y",to=Math.abs(mCSB_container[0].offsetTop)-(keyboardDir*(wrapper.height()*0.9)); + } + _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); + } + }else if(code===35 || code===36){ + /* End (35), Home (36) */ + if(!$(document.activeElement).is(editables)){ + if(d.overflowed[0] || d.overflowed[1]){ + e.preventDefault(); + e.stopImmediatePropagation(); + } + if(e.type==="keyup"){ + if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){ + var dir="x",to=code===35 ? Math.abs(wrapper.width()-mCSB_container.outerWidth(false)) : 0; + }else{ + var dir="y",to=code===35 ? Math.abs(wrapper.height()-mCSB_container.outerHeight(false)) : 0; + } + _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); + } + } + } + break; + } + function _seq(a,c){ + seq.type=o.keyboard.scrollType; + seq.scrollAmount=o.keyboard.scrollAmount; + if(seq.type==="stepped" && d.tweenRunning){return;} + _sequentialScroll($this,a,c); + } + } + }, + /* -------------------- */ + + + /* scrolls content sequentially (used when scrolling via buttons, keyboard arrows etc.) */ + _sequentialScroll=function(el,action,trigger,e,s){ + var d=el.data(pluginPfx),o=d.opt,seq=d.sequential, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + once=seq.type==="stepped" ? true : false, + steplessSpeed=o.scrollInertia < 26 ? 26 : o.scrollInertia, /* 26/1.5=17 */ + steppedSpeed=o.scrollInertia < 1 ? 17 : o.scrollInertia; + switch(action){ + case "on": + seq.dir=[ + (trigger===classes[16] || trigger===classes[15] || trigger===39 || trigger===37 ? "x" : "y"), + (trigger===classes[13] || trigger===classes[15] || trigger===38 || trigger===37 ? -1 : 1) + ]; + _stop(el); + if(_isNumeric(trigger) && seq.type==="stepped"){return;} + _on(once); + break; + case "off": + _off(); + if(once || (d.tweenRunning && seq.dir)){ + _on(true); + } + break; + } + + /* starts sequence */ + function _on(once){ + if(o.snapAmount){seq.scrollAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : seq.dir[0]==="x" ? o.snapAmount[1] : o.snapAmount[0];} /* scrolling snapping */ + var c=seq.type!=="stepped", /* continuous scrolling */ + t=s ? s : !once ? 1000/60 : c ? steplessSpeed/1.5 : steppedSpeed, /* timer */ + m=!once ? 2.5 : c ? 7.5 : 40, /* multiplier */ + contentPos=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)], + ratio=[d.scrollRatio.y>10 ? 10 : d.scrollRatio.y,d.scrollRatio.x>10 ? 10 : d.scrollRatio.x], + amount=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*(ratio[1]*m)) : contentPos[0]+(seq.dir[1]*(ratio[0]*m)), + px=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*parseInt(seq.scrollAmount)) : contentPos[0]+(seq.dir[1]*parseInt(seq.scrollAmount)), + to=seq.scrollAmount!=="auto" ? px : amount, + easing=e ? e : !once ? "mcsLinear" : c ? "mcsLinearOut" : "mcsEaseInOut", + onComplete=!once ? false : true; + if(once && t<17){ + to=seq.dir[0]==="x" ? contentPos[1] : contentPos[0]; + } + _scrollTo(el,to.toString(),{dir:seq.dir[0],scrollEasing:easing,dur:t,onComplete:onComplete}); + if(once){ + seq.dir=false; + return; + } + clearTimeout(seq.step); + seq.step=setTimeout(function(){ + _on(); + },t); + } + /* stops sequence */ + function _off(){ + clearTimeout(seq.step); + _delete(seq,"step"); + _stop(el); + } + }, + /* -------------------- */ + + + /* returns a yx array from value */ + _arr=function(val){ + var o=$(this).data(pluginPfx).opt,vals=[]; + if(typeof val==="function"){val=val();} /* check if the value is a single anonymous function */ + /* check if value is object or array, its length and create an array with yx values */ + if(!(val instanceof Array)){ /* object value (e.g. {y:"100",x:"100"}, 100 etc.) */ + vals[0]=val.y ? val.y : val.x || o.axis==="x" ? null : val; + vals[1]=val.x ? val.x : val.y || o.axis==="y" ? null : val; + }else{ /* array value (e.g. [100,100]) */ + vals=val.length>1 ? [val[0],val[1]] : o.axis==="x" ? [null,val[0]] : [val[0],null]; + } + /* check if array values are anonymous functions */ + if(typeof vals[0]==="function"){vals[0]=vals[0]();} + if(typeof vals[1]==="function"){vals[1]=vals[1]();} + return vals; + }, + /* -------------------- */ + + + /* translates values (e.g. "top", 100, "100px", "#id") to actual scroll-to positions */ + _to=function(val,dir){ + if(val==null || typeof val=="undefined"){return;} + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + t=typeof val; + if(!dir){dir=o.axis==="x" ? "x" : "y";} + var contentLength=dir==="x" ? mCSB_container.outerWidth(false)-wrapper.width() : mCSB_container.outerHeight(false)-wrapper.height(), + contentPos=dir==="x" ? mCSB_container[0].offsetLeft : mCSB_container[0].offsetTop, + cssProp=dir==="x" ? "left" : "top"; + switch(t){ + case "function": /* this currently is not used. Consider removing it */ + return val(); + break; + case "object": /* js/jquery object */ + var obj=val.jquery ? val : $(val); + if(!obj.length){return;} + return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0]; + break; + case "string": case "number": + if(_isNumeric(val)){ /* numeric value */ + return Math.abs(val); + }else if(val.indexOf("%")!==-1){ /* percentage value */ + return Math.abs(contentLength*parseInt(val)/100); + }else if(val.indexOf("-=")!==-1){ /* decrease value */ + return Math.abs(contentPos-parseInt(val.split("-=")[1])); + }else if(val.indexOf("+=")!==-1){ /* inrease value */ + var p=(contentPos+parseInt(val.split("+=")[1])); + return p>=0 ? 0 : Math.abs(p); + }else if(val.indexOf("px")!==-1 && _isNumeric(val.split("px")[0])){ /* pixels string value (e.g. "100px") */ + return Math.abs(val.split("px")[0]); + }else{ + if(val==="top" || val==="left"){ /* special strings */ + return 0; + }else if(val==="bottom"){ + return Math.abs(wrapper.height()-mCSB_container.outerHeight(false)); + }else if(val==="right"){ + return Math.abs(wrapper.width()-mCSB_container.outerWidth(false)); + }else if(val==="first" || val==="last"){ + var obj=mCSB_container.find(":"+val); + return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0]; + }else{ + if($(val).length){ /* jquery selector */ + return dir==="x" ? _childPos($(val))[1] : _childPos($(val))[0]; + }else{ /* other values (e.g. "100em") */ + mCSB_container.css(cssProp,val); + methods.update.call(null,$this[0]); + return; + } + } + } + break; + } + }, + /* -------------------- */ + + + /* calls the update method automatically */ + _autoUpdate=function(rem){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCSB_container=$("#mCSB_"+d.idx+"_container"); + if(rem){ + /* + removes autoUpdate timer + usage: _autoUpdate.call(this,"remove"); + */ + clearTimeout(mCSB_container[0].autoUpdate); + _delete(mCSB_container[0],"autoUpdate"); + return; + } + upd(); + function upd(){ + clearTimeout(mCSB_container[0].autoUpdate); + if($this.parents("html").length===0){ + /* check element in dom tree */ + $this=null; + return; + } + mCSB_container[0].autoUpdate=setTimeout(function(){ + /* update on specific selector(s) length and size change */ + if(o.advanced.updateOnSelectorChange){ + d.poll.change.n=sizesSum(); + if(d.poll.change.n!==d.poll.change.o){ + d.poll.change.o=d.poll.change.n; + doUpd(3); + return; + } + } + /* update on main element and scrollbar size changes */ + if(o.advanced.updateOnContentResize){ + d.poll.size.n=$this[0].scrollHeight+$this[0].scrollWidth+mCSB_container[0].offsetHeight+$this[0].offsetHeight+$this[0].offsetWidth; + if(d.poll.size.n!==d.poll.size.o){ + d.poll.size.o=d.poll.size.n; + doUpd(1); + return; + } + } + /* update on image load */ + if(o.advanced.updateOnImageLoad){ + if(!(o.advanced.updateOnImageLoad==="auto" && o.axis==="y")){ //by default, it doesn't run on vertical content + d.poll.img.n=mCSB_container.find("img").length; + if(d.poll.img.n!==d.poll.img.o){ + d.poll.img.o=d.poll.img.n; + mCSB_container.find("img").each(function(){ + imgLoader(this); + }); + return; + } + } + } + if(o.advanced.updateOnSelectorChange || o.advanced.updateOnContentResize || o.advanced.updateOnImageLoad){upd();} + },o.advanced.autoUpdateTimeout); + } + /* a tiny image loader */ + function imgLoader(el){ + if($(el).hasClass(classes[2])){doUpd(); return;} + var img=new Image(); + function createDelegate(contextObject,delegateMethod){ + return function(){return delegateMethod.apply(contextObject,arguments);} + } + function imgOnLoad(){ + this.onload=null; + $(el).addClass(classes[2]); + doUpd(2); + } + img.onload=createDelegate(img,imgOnLoad); + img.src=el.src; + } + /* returns the total height and width sum of all elements matching the selector */ + function sizesSum(){ + if(o.advanced.updateOnSelectorChange===true){o.advanced.updateOnSelectorChange="*";} + var total=0,sel=mCSB_container.find(o.advanced.updateOnSelectorChange); + if(o.advanced.updateOnSelectorChange && sel.length>0){sel.each(function(){total+=this.offsetHeight+this.offsetWidth;});} + return total; + } + /* calls the update method */ + function doUpd(cb){ + clearTimeout(mCSB_container[0].autoUpdate); + methods.update.call(null,$this[0],cb); + } + }, + /* -------------------- */ + + + /* snaps scrolling to a multiple of a pixels number */ + _snapAmount=function(to,amount,offset){ + return (Math.round(to/amount)*amount-offset); + }, + /* -------------------- */ + + + /* stops content and scrollbar animations */ + _stop=function(el){ + var d=el.data(pluginPfx), + sel=$("#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal"); + sel.each(function(){ + _stopTween.call(this); + }); + }, + /* -------------------- */ + + + /* + ANIMATES CONTENT + This is where the actual scrolling happens + */ + _scrollTo=function(el,to,options){ + var d=el.data(pluginPfx),o=d.opt, + defaults={ + trigger:"internal", + dir:"y", + scrollEasing:"mcsEaseOut", + drag:false, + dur:o.scrollInertia, + overwrite:"all", + callbacks:true, + onStart:true, + onUpdate:true, + onComplete:true + }, + options=$.extend(defaults,options), + dur=[options.dur,(options.drag ? 0 : options.dur)], + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + totalScrollOffsets=o.callbacks.onTotalScrollOffset ? _arr.call(el,o.callbacks.onTotalScrollOffset) : [0,0], + totalScrollBackOffsets=o.callbacks.onTotalScrollBackOffset ? _arr.call(el,o.callbacks.onTotalScrollBackOffset) : [0,0]; + d.trigger=options.trigger; + if(wrapper.scrollTop()!==0 || wrapper.scrollLeft()!==0){ /* always reset scrollTop/Left */ + $(".mCSB_"+d.idx+"_scrollbar").css("visibility","visible"); + wrapper.scrollTop(0).scrollLeft(0); + } + if(to==="_resetY" && !d.contentReset.y){ + /* callbacks: onOverflowYNone */ + if(_cb("onOverflowYNone")){o.callbacks.onOverflowYNone.call(el[0]);} + d.contentReset.y=1; + } + if(to==="_resetX" && !d.contentReset.x){ + /* callbacks: onOverflowXNone */ + if(_cb("onOverflowXNone")){o.callbacks.onOverflowXNone.call(el[0]);} + d.contentReset.x=1; + } + if(to==="_resetY" || to==="_resetX"){return;} + if((d.contentReset.y || !el[0].mcs) && d.overflowed[0]){ + /* callbacks: onOverflowY */ + if(_cb("onOverflowY")){o.callbacks.onOverflowY.call(el[0]);} + d.contentReset.x=null; + } + if((d.contentReset.x || !el[0].mcs) && d.overflowed[1]){ + /* callbacks: onOverflowX */ + if(_cb("onOverflowX")){o.callbacks.onOverflowX.call(el[0]);} + d.contentReset.x=null; + } + if(o.snapAmount){ /* scrolling snapping */ + var snapAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : options.dir==="x" ? o.snapAmount[1] : o.snapAmount[0]; + to=_snapAmount(to,snapAmount,o.snapOffset); + } + switch(options.dir){ + case "x": + var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_horizontal"), + property="left", + contentPos=mCSB_container[0].offsetLeft, + limit=[ + mCustomScrollBox.width()-mCSB_container.outerWidth(false), + mCSB_dragger.parent().width()-mCSB_dragger.width() + ], + scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.x)], + tso=totalScrollOffsets[1], + tsbo=totalScrollBackOffsets[1], + totalScrollOffset=tso>0 ? tso/d.scrollRatio.x : 0, + totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.x : 0; + break; + case "y": + var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_vertical"), + property="top", + contentPos=mCSB_container[0].offsetTop, + limit=[ + mCustomScrollBox.height()-mCSB_container.outerHeight(false), + mCSB_dragger.parent().height()-mCSB_dragger.height() + ], + scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.y)], + tso=totalScrollOffsets[0], + tsbo=totalScrollBackOffsets[0], + totalScrollOffset=tso>0 ? tso/d.scrollRatio.y : 0, + totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.y : 0; + break; + } + if(scrollTo[1]<0 || (scrollTo[0]===0 && scrollTo[1]===0)){ + scrollTo=[0,0]; + }else if(scrollTo[1]>=limit[1]){ + scrollTo=[limit[0],limit[1]]; + }else{ + scrollTo[0]=-scrollTo[0]; + } + if(!el[0].mcs){ + _mcs(); /* init mcs object (once) to make it available before callbacks */ + if(_cb("onInit")){o.callbacks.onInit.call(el[0]);} /* callbacks: onInit */ + } + clearTimeout(mCSB_container[0].onCompleteTimeout); + _tweenTo(mCSB_dragger[0],property,Math.round(scrollTo[1]),dur[1],options.scrollEasing); + if(!d.tweenRunning && ((contentPos===0 && scrollTo[0]>=0) || (contentPos===limit[0] && scrollTo[0]<=limit[0]))){return;} + _tweenTo(mCSB_container[0],property,Math.round(scrollTo[0]),dur[0],options.scrollEasing,options.overwrite,{ + onStart:function(){ + if(options.callbacks && options.onStart && !d.tweenRunning){ + /* callbacks: onScrollStart */ + if(_cb("onScrollStart")){_mcs(); o.callbacks.onScrollStart.call(el[0]);} + d.tweenRunning=true; + _onDragClasses(mCSB_dragger); + d.cbOffsets=_cbOffsets(); + } + },onUpdate:function(){ + if(options.callbacks && options.onUpdate){ + /* callbacks: whileScrolling */ + if(_cb("whileScrolling")){_mcs(); o.callbacks.whileScrolling.call(el[0]);} + } + },onComplete:function(){ + if(options.callbacks && options.onComplete){ + if(o.axis==="yx"){clearTimeout(mCSB_container[0].onCompleteTimeout);} + var t=mCSB_container[0].idleTimer || 0; + mCSB_container[0].onCompleteTimeout=setTimeout(function(){ + /* callbacks: onScroll, onTotalScroll, onTotalScrollBack */ + if(_cb("onScroll")){_mcs(); o.callbacks.onScroll.call(el[0]);} + if(_cb("onTotalScroll") && scrollTo[1]>=limit[1]-totalScrollOffset && d.cbOffsets[0]){_mcs(); o.callbacks.onTotalScroll.call(el[0]);} + if(_cb("onTotalScrollBack") && scrollTo[1]<=totalScrollBackOffset && d.cbOffsets[1]){_mcs(); o.callbacks.onTotalScrollBack.call(el[0]);} + d.tweenRunning=false; + mCSB_container[0].idleTimer=0; + _onDragClasses(mCSB_dragger,"hide"); + },t); + } + } + }); + /* checks if callback function exists */ + function _cb(cb){ + return d && o.callbacks[cb] && typeof o.callbacks[cb]==="function"; + } + /* checks whether callback offsets always trigger */ + function _cbOffsets(){ + return [o.callbacks.alwaysTriggerOffsets || contentPos>=limit[0]+tso,o.callbacks.alwaysTriggerOffsets || contentPos<=-tsbo]; + } + /* + populates object with useful values for the user + values: + content: this.mcs.content + content top position: this.mcs.top + content left position: this.mcs.left + dragger top position: this.mcs.draggerTop + dragger left position: this.mcs.draggerLeft + scrolling y percentage: this.mcs.topPct + scrolling x percentage: this.mcs.leftPct + scrolling direction: this.mcs.direction + */ + function _mcs(){ + var cp=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft], /* content position */ + dp=[mCSB_dragger[0].offsetTop,mCSB_dragger[0].offsetLeft], /* dragger position */ + cl=[mCSB_container.outerHeight(false),mCSB_container.outerWidth(false)], /* content length */ + pl=[mCustomScrollBox.height(),mCustomScrollBox.width()]; /* content parent length */ + el[0].mcs={ + content:mCSB_container, /* original content wrapper as jquery object */ + top:cp[0],left:cp[1],draggerTop:dp[0],draggerLeft:dp[1], + topPct:Math.round((100*Math.abs(cp[0]))/(Math.abs(cl[0])-pl[0])),leftPct:Math.round((100*Math.abs(cp[1]))/(Math.abs(cl[1])-pl[1])), + direction:options.dir + }; + /* + this refers to the original element containing the scrollbar(s) + usage: this.mcs.top, this.mcs.leftPct etc. + */ + } + }, + /* -------------------- */ + + + /* + CUSTOM JAVASCRIPT ANIMATION TWEEN + Lighter and faster than jquery animate() and css transitions + Animates top/left properties and includes easings + */ + _tweenTo=function(el,prop,to,duration,easing,overwrite,callbacks){ + if(!el._mTween){el._mTween={top:{},left:{}};} + var callbacks=callbacks || {}, + onStart=callbacks.onStart || function(){},onUpdate=callbacks.onUpdate || function(){},onComplete=callbacks.onComplete || function(){}, + startTime=_getTime(),_delay,progress=0,from=el.offsetTop,elStyle=el.style,_request,tobj=el._mTween[prop]; + if(prop==="left"){from=el.offsetLeft;} + var diff=to-from; + tobj.stop=0; + if(overwrite!=="none"){_cancelTween();} + _startTween(); + function _step(){ + if(tobj.stop){return;} + if(!progress){onStart.call();} + progress=_getTime()-startTime; + _tween(); + if(progress>=tobj.time){ + tobj.time=(progress>tobj.time) ? progress+_delay-(progress-tobj.time) : progress+_delay-1; + if(tobj.time0){ + tobj.currVal=_ease(tobj.time,from,diff,duration,easing); + elStyle[prop]=Math.round(tobj.currVal)+"px"; + }else{ + elStyle[prop]=to+"px"; + } + onUpdate.call(); + } + function _startTween(){ + _delay=1000/60; + tobj.time=progress+_delay; + _request=(!window.requestAnimationFrame) ? function(f){_tween(); return setTimeout(f,0.01);} : window.requestAnimationFrame; + tobj.id=_request(_step); + } + function _cancelTween(){ + if(tobj.id==null){return;} + if(!window.requestAnimationFrame){clearTimeout(tobj.id); + }else{window.cancelAnimationFrame(tobj.id);} + tobj.id=null; + } + function _ease(t,b,c,d,type){ + switch(type){ + case "linear": case "mcsLinear": + return c*t/d + b; + break; + case "mcsLinearOut": + t/=d; t--; return c * Math.sqrt(1 - t*t) + b; + break; + case "easeInOutSmooth": + t/=d/2; + if(t<1) return c/2*t*t + b; + t--; + return -c/2 * (t*(t-2) - 1) + b; + break; + case "easeInOutStrong": + t/=d/2; + if(t<1) return c/2 * Math.pow( 2, 10 * (t - 1) ) + b; + t--; + return c/2 * ( -Math.pow( 2, -10 * t) + 2 ) + b; + break; + case "easeInOut": case "mcsEaseInOut": + t/=d/2; + if(t<1) return c/2*t*t*t + b; + t-=2; + return c/2*(t*t*t + 2) + b; + break; + case "easeOutSmooth": + t/=d; t--; + return -c * (t*t*t*t - 1) + b; + break; + case "easeOutStrong": + return c * ( -Math.pow( 2, -10 * t/d ) + 1 ) + b; + break; + case "easeOut": case "mcsEaseOut": default: + var ts=(t/=d)*t,tc=ts*t; + return b+c*(0.499999999999997*tc*ts + -2.5*ts*ts + 5.5*tc + -6.5*ts + 4*t); + } + } + }, + /* -------------------- */ + + + /* returns current time */ + _getTime=function(){ + if(window.performance && window.performance.now){ + return window.performance.now(); + }else{ + if(window.performance && window.performance.webkitNow){ + return window.performance.webkitNow(); + }else{ + if(Date.now){return Date.now();}else{return new Date().getTime();} + } + } + }, + /* -------------------- */ + + + /* stops a tween */ + _stopTween=function(){ + var el=this; + if(!el._mTween){el._mTween={top:{},left:{}};} + var props=["top","left"]; + for(var i=0; i
    ","
    "],s="yx"===i.axis?"mCSB_vertical_horizontal":"x"===i.axis?"mCSB_horizontal":"mCSB_vertical",c="yx"===i.axis?l[0]+l[1]:"x"===i.axis?l[1]:l[0],u="yx"===i.axis?"
    ":"",f=i.autoHideScrollbar?" "+d[6]:"",h="x"!==i.axis&&"rtl"===n.langDir?" "+d[7]:"";i.setWidth&&t.css("width",i.setWidth),i.setHeight&&t.css("height",i.setHeight),i.setLeft="y"!==i.axis&&"rtl"===n.langDir?"989999px":i.setLeft,t.addClass(o+" _"+a+"_"+n.idx+f+h).wrapInner("
    ");var m=e("#mCSB_"+n.idx),p=e("#mCSB_"+n.idx+"_container");"y"===i.axis||i.advanced.autoExpandHorizontalScroll||p.css("width",x(p)),"outside"===i.scrollbarPosition?("static"===t.css("position")&&t.css("position","relative"),t.css("overflow","visible"),m.addClass("mCSB_outside").after(c)):(m.addClass("mCSB_inside").append(c),p.wrap(u)),w.call(this);var g=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")];g[0].css("min-height",g[0].height()),g[1].css("min-width",g[1].width())},x=function(t){var o=[t[0].scrollWidth,Math.max.apply(Math,t.children().map(function(){return e(this).outerWidth(!0)}).get())],a=t.parent().width();return o[0]>a?o[0]:o[1]>a?o[1]:"100%"},_=function(){var t=e(this),o=t.data(a),n=o.opt,i=e("#mCSB_"+o.idx+"_container");if(n.advanced.autoExpandHorizontalScroll&&"y"!==n.axis){i.css({width:"auto","min-width":0,"overflow-x":"scroll"});var r=Math.ceil(i[0].scrollWidth);3===n.advanced.autoExpandHorizontalScroll||2!==n.advanced.autoExpandHorizontalScroll&&r>i.parent().width()?i.css({width:r,"min-width":"100%","overflow-x":"inherit"}):i.css({"overflow-x":"inherit",position:"absolute"}).wrap("
    ").css({width:Math.ceil(i[0].getBoundingClientRect().right+.4)-Math.floor(i[0].getBoundingClientRect().left),"min-width":"100%",position:"relative"}).unwrap()}},w=function(){var t=e(this),o=t.data(a),n=o.opt,i=e(".mCSB_"+o.idx+"_scrollbar:first"),r=oe(n.scrollButtons.tabindex)?"tabindex='"+n.scrollButtons.tabindex+"'":"",l=["","","",""],s=["x"===n.axis?l[2]:l[0],"x"===n.axis?l[3]:l[1],l[2],l[3]];n.scrollButtons.enable&&i.prepend(s[0]).append(s[1]).next(".mCSB_scrollTools").prepend(s[2]).append(s[3])},S=function(){var t=e(this),o=t.data(a),n=e("#mCSB_"+o.idx),i=e("#mCSB_"+o.idx+"_container"),r=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")],l=[n.height()/i.outerHeight(!1),n.width()/i.outerWidth(!1)],c=[parseInt(r[0].css("min-height")),Math.round(l[0]*r[0].parent().height()),parseInt(r[1].css("min-width")),Math.round(l[1]*r[1].parent().width())],d=s&&c[1]r&&(r=s),c>l&&(l=c),[r>n.height(),l>n.width()]},B=function(){var t=e(this),o=t.data(a),n=o.opt,i=e("#mCSB_"+o.idx),r=e("#mCSB_"+o.idx+"_container"),l=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")];if(Q(t),("x"!==n.axis&&!o.overflowed[0]||"y"===n.axis&&o.overflowed[0])&&(l[0].add(r).css("top",0),G(t,"_resetY")),"y"!==n.axis&&!o.overflowed[1]||"x"===n.axis&&o.overflowed[1]){var s=dx=0;"rtl"===o.langDir&&(s=i.width()-r.outerWidth(!1),dx=Math.abs(s/o.scrollRatio.x)),r.css("left",s),l[1].css("left",dx),G(t,"_resetX")}},T=function(){function t(){r=setTimeout(function(){e.event.special.mousewheel?(clearTimeout(r),W.call(o[0])):t()},100)}var o=e(this),n=o.data(a),i=n.opt;if(!n.bindEvents){if(I.call(this),i.contentTouchScroll&&D.call(this),E.call(this),i.mouseWheel.enable){var r;t()}P.call(this),U.call(this),i.advanced.autoScrollOnFocus&&H.call(this),i.scrollButtons.enable&&F.call(this),i.keyboard.enable&&q.call(this),n.bindEvents=!0}},k=function(){var t=e(this),o=t.data(a),n=o.opt,i=a+"_"+o.idx,r=".mCSB_"+o.idx+"_scrollbar",l=e("#mCSB_"+o.idx+",#mCSB_"+o.idx+"_container,#mCSB_"+o.idx+"_container_wrapper,"+r+" ."+d[12]+",#mCSB_"+o.idx+"_dragger_vertical,#mCSB_"+o.idx+"_dragger_horizontal,"+r+">a"),s=e("#mCSB_"+o.idx+"_container");n.advanced.releaseDraggableSelectors&&l.add(e(n.advanced.releaseDraggableSelectors)),n.advanced.extraDraggableSelectors&&l.add(e(n.advanced.extraDraggableSelectors)),o.bindEvents&&(e(document).add(e(!A()||top.document)).unbind("."+i),l.each(function(){e(this).unbind("."+i)}),clearTimeout(t[0]._focusTimeout),$(t[0],"_focusTimeout"),clearTimeout(o.sequential.step),$(o.sequential,"step"),clearTimeout(s[0].onCompleteTimeout),$(s[0],"onCompleteTimeout"),o.bindEvents=!1)},M=function(t){var o=e(this),n=o.data(a),i=n.opt,r=e("#mCSB_"+n.idx+"_container_wrapper"),l=r.length?r:e("#mCSB_"+n.idx+"_container"),s=[e("#mCSB_"+n.idx+"_scrollbar_vertical"),e("#mCSB_"+n.idx+"_scrollbar_horizontal")],c=[s[0].find(".mCSB_dragger"),s[1].find(".mCSB_dragger")];"x"!==i.axis&&(n.overflowed[0]&&!t?(s[0].add(c[0]).add(s[0].children("a")).css("display","block"),l.removeClass(d[8]+" "+d[10])):(i.alwaysShowScrollbar?(2!==i.alwaysShowScrollbar&&c[0].css("display","none"),l.removeClass(d[10])):(s[0].css("display","none"),l.addClass(d[10])),l.addClass(d[8]))),"y"!==i.axis&&(n.overflowed[1]&&!t?(s[1].add(c[1]).add(s[1].children("a")).css("display","block"),l.removeClass(d[9]+" "+d[11])):(i.alwaysShowScrollbar?(2!==i.alwaysShowScrollbar&&c[1].css("display","none"),l.removeClass(d[11])):(s[1].css("display","none"),l.addClass(d[11])),l.addClass(d[9]))),n.overflowed[0]||n.overflowed[1]?o.removeClass(d[5]):o.addClass(d[5])},O=function(t){var o=t.type,a=t.target.ownerDocument!==document&&null!==frameElement?[e(frameElement).offset().top,e(frameElement).offset().left]:null,n=A()&&t.target.ownerDocument!==top.document&&null!==frameElement?[e(t.view.frameElement).offset().top,e(t.view.frameElement).offset().left]:[0,0];switch(o){case"pointerdown":case"MSPointerDown":case"pointermove":case"MSPointerMove":case"pointerup":case"MSPointerUp":return a?[t.originalEvent.pageY-a[0]+n[0],t.originalEvent.pageX-a[1]+n[1],!1]:[t.originalEvent.pageY,t.originalEvent.pageX,!1];case"touchstart":case"touchmove":case"touchend":var i=t.originalEvent.touches[0]||t.originalEvent.changedTouches[0],r=t.originalEvent.touches.length||t.originalEvent.changedTouches.length;return t.target.ownerDocument!==document?[i.screenY,i.screenX,r>1]:[i.pageY,i.pageX,r>1];default:return a?[t.pageY-a[0]+n[0],t.pageX-a[1]+n[1],!1]:[t.pageY,t.pageX,!1]}},I=function(){function t(e,t,a,n){if(h[0].idleTimer=d.scrollInertia<233?250:0,o.attr("id")===f[1])var i="x",s=(o[0].offsetLeft-t+n)*l.scrollRatio.x;else var i="y",s=(o[0].offsetTop-e+a)*l.scrollRatio.y;G(r,s.toString(),{dir:i,drag:!0})}var o,n,i,r=e(this),l=r.data(a),d=l.opt,u=a+"_"+l.idx,f=["mCSB_"+l.idx+"_dragger_vertical","mCSB_"+l.idx+"_dragger_horizontal"],h=e("#mCSB_"+l.idx+"_container"),m=e("#"+f[0]+",#"+f[1]),p=d.advanced.releaseDraggableSelectors?m.add(e(d.advanced.releaseDraggableSelectors)):m,g=d.advanced.extraDraggableSelectors?e(!A()||top.document).add(e(d.advanced.extraDraggableSelectors)):e(!A()||top.document);m.bind("contextmenu."+u,function(e){e.preventDefault()}).bind("mousedown."+u+" touchstart."+u+" pointerdown."+u+" MSPointerDown."+u,function(t){if(t.stopImmediatePropagation(),t.preventDefault(),ee(t)){c=!0,s&&(document.onselectstart=function(){return!1}),L.call(h,!1),Q(r),o=e(this);var a=o.offset(),l=O(t)[0]-a.top,u=O(t)[1]-a.left,f=o.height()+a.top,m=o.width()+a.left;f>l&&l>0&&m>u&&u>0&&(n=l,i=u),C(o,"active",d.autoExpandScrollbar)}}).bind("touchmove."+u,function(e){e.stopImmediatePropagation(),e.preventDefault();var a=o.offset(),r=O(e)[0]-a.top,l=O(e)[1]-a.left;t(n,i,r,l)}),e(document).add(g).bind("mousemove."+u+" pointermove."+u+" MSPointerMove."+u,function(e){if(o){var a=o.offset(),r=O(e)[0]-a.top,l=O(e)[1]-a.left;if(n===r&&i===l)return;t(n,i,r,l)}}).add(p).bind("mouseup."+u+" touchend."+u+" pointerup."+u+" MSPointerUp."+u,function(){o&&(C(o,"active",d.autoExpandScrollbar),o=null),c=!1,s&&(document.onselectstart=null),L.call(h,!0)})},D=function(){function o(e){if(!te(e)||c||O(e)[2])return void(t=0);t=1,b=0,C=0,d=1,y.removeClass("mCS_touch_action");var o=I.offset();u=O(e)[0]-o.top,f=O(e)[1]-o.left,z=[O(e)[0],O(e)[1]]}function n(e){if(te(e)&&!c&&!O(e)[2]&&(T.documentTouchScroll||e.preventDefault(),e.stopImmediatePropagation(),(!C||b)&&d)){g=K();var t=M.offset(),o=O(e)[0]-t.top,a=O(e)[1]-t.left,n="mcsLinearOut";if(E.push(o),W.push(a),z[2]=Math.abs(O(e)[0]-z[0]),z[3]=Math.abs(O(e)[1]-z[1]),B.overflowed[0])var i=D[0].parent().height()-D[0].height(),r=u-o>0&&o-u>-(i*B.scrollRatio.y)&&(2*z[3]0&&a-f>-(l*B.scrollRatio.x)&&(2*z[2]30)){_=1e3/(v-p);var n="mcsEaseOut",i=2.5>_,r=i?[E[E.length-2],W[W.length-2]]:[0,0];x=i?[o-r[0],a-r[1]]:[o-h,a-m];var u=[Math.abs(x[0]),Math.abs(x[1])];_=i?[Math.abs(x[0]/4),Math.abs(x[1]/4)]:[_,_];var f=[Math.abs(I[0].offsetTop)-x[0]*l(u[0]/_[0],_[0]),Math.abs(I[0].offsetLeft)-x[1]*l(u[1]/_[1],_[1])];w="yx"===T.axis?[f[0],f[1]]:"x"===T.axis?[null,f[1]]:[f[0],null],S=[4*u[0]+T.scrollInertia,4*u[1]+T.scrollInertia];var y=parseInt(T.contentTouchScroll)||0;w[0]=u[0]>y?w[0]:0,w[1]=u[1]>y?w[1]:0,B.overflowed[0]&&s(w[0],S[0],n,"y",L,!1),B.overflowed[1]&&s(w[1],S[1],n,"x",L,!1)}}}function l(e,t){var o=[1.5*t,2*t,t/1.5,t/2];return e>90?t>4?o[0]:o[3]:e>60?t>3?o[3]:o[2]:e>30?t>8?o[1]:t>6?o[0]:t>4?t:o[2]:t>8?t:o[3]}function s(e,t,o,a,n,i){e&&G(y,e.toString(),{dur:t,scrollEasing:o,dir:a,overwrite:n,drag:i})}var d,u,f,h,m,p,g,v,x,_,w,S,b,C,y=e(this),B=y.data(a),T=B.opt,k=a+"_"+B.idx,M=e("#mCSB_"+B.idx),I=e("#mCSB_"+B.idx+"_container"),D=[e("#mCSB_"+B.idx+"_dragger_vertical"),e("#mCSB_"+B.idx+"_dragger_horizontal")],E=[],W=[],R=0,L="yx"===T.axis?"none":"all",z=[],P=I.find("iframe"),H=["touchstart."+k+" pointerdown."+k+" MSPointerDown."+k,"touchmove."+k+" pointermove."+k+" MSPointerMove."+k,"touchend."+k+" pointerup."+k+" MSPointerUp."+k],U=void 0!==document.body.style.touchAction&&""!==document.body.style.touchAction;I.bind(H[0],function(e){o(e)}).bind(H[1],function(e){n(e)}),M.bind(H[0],function(e){i(e)}).bind(H[2],function(e){r(e)}),P.length&&P.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind(H[0],function(e){o(e),i(e)}).bind(H[1],function(e){n(e)}).bind(H[2],function(e){r(e)})})})},E=function(){function o(){return window.getSelection?window.getSelection().toString():document.selection&&"Control"!=document.selection.type?document.selection.createRange().text:0}function n(e,t,o){d.type=o&&i?"stepped":"stepless",d.scrollAmount=10,j(r,e,t,"mcsLinearOut",o?60:null)}var i,r=e(this),l=r.data(a),s=l.opt,d=l.sequential,u=a+"_"+l.idx,f=e("#mCSB_"+l.idx+"_container"),h=f.parent();f.bind("mousedown."+u,function(){t||i||(i=1,c=!0)}).add(document).bind("mousemove."+u,function(e){if(!t&&i&&o()){var a=f.offset(),r=O(e)[0]-a.top+f[0].offsetTop,c=O(e)[1]-a.left+f[0].offsetLeft;r>0&&r0&&cr?n("on",38):r>h.height()&&n("on",40)),"y"!==s.axis&&l.overflowed[1]&&(0>c?n("on",37):c>h.width()&&n("on",39)))}}).bind("mouseup."+u+" dragend."+u,function(){t||(i&&(i=0,n("off",null)),c=!1)})},W=function(){function t(t,a){if(Q(o),!z(o,t.target)){var r="auto"!==i.mouseWheel.deltaFactor?parseInt(i.mouseWheel.deltaFactor):s&&t.deltaFactor<100?100:t.deltaFactor||100,d=i.scrollInertia;if("x"===i.axis||"x"===i.mouseWheel.axis)var u="x",f=[Math.round(r*n.scrollRatio.x),parseInt(i.mouseWheel.scrollAmount)],h="auto"!==i.mouseWheel.scrollAmount?f[1]:f[0]>=l.width()?.9*l.width():f[0],m=Math.abs(e("#mCSB_"+n.idx+"_container")[0].offsetLeft),p=c[1][0].offsetLeft,g=c[1].parent().width()-c[1].width(),v="y"===i.mouseWheel.axis?t.deltaY||a:t.deltaX;else var u="y",f=[Math.round(r*n.scrollRatio.y),parseInt(i.mouseWheel.scrollAmount)],h="auto"!==i.mouseWheel.scrollAmount?f[1]:f[0]>=l.height()?.9*l.height():f[0],m=Math.abs(e("#mCSB_"+n.idx+"_container")[0].offsetTop),p=c[0][0].offsetTop,g=c[0].parent().height()-c[0].height(),v=t.deltaY||a;"y"===u&&!n.overflowed[0]||"x"===u&&!n.overflowed[1]||((i.mouseWheel.invert||t.webkitDirectionInvertedFromDevice)&&(v=-v),i.mouseWheel.normalizeDelta&&(v=0>v?-1:1),(v>0&&0!==p||0>v&&p!==g||i.mouseWheel.preventDefault)&&(t.stopImmediatePropagation(),t.preventDefault()),t.deltaFactor<5&&!i.mouseWheel.normalizeDelta&&(h=t.deltaFactor,d=17),G(o,(m-v*h).toString(),{dir:u,dur:d}))}}if(e(this).data(a)){var o=e(this),n=o.data(a),i=n.opt,r=a+"_"+n.idx,l=e("#mCSB_"+n.idx),c=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")],d=e("#mCSB_"+n.idx+"_container").find("iframe");d.length&&d.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind("mousewheel."+r,function(e,o){t(e,o)})})}),l.bind("mousewheel."+r,function(e,o){t(e,o)})}},R=new Object,A=function(t){var o=!1,a=!1,n=null;if(void 0===t?a="#empty":void 0!==e(t).attr("id")&&(a=e(t).attr("id")),a!==!1&&void 0!==R[a])return R[a];if(t){try{var i=t.contentDocument||t.contentWindow.document;n=i.body.innerHTML}catch(r){}o=null!==n}else{try{var i=top.document;n=i.body.innerHTML}catch(r){}o=null!==n}return a!==!1&&(R[a]=o),o},L=function(e){var t=this.find("iframe");if(t.length){var o=e?"auto":"none";t.css("pointer-events",o)}},z=function(t,o){var n=o.nodeName.toLowerCase(),i=t.data(a).opt.mouseWheel.disableOver,r=["select","textarea"];return e.inArray(n,i)>-1&&!(e.inArray(n,r)>-1&&!e(o).is(":focus"))},P=function(){var t,o=e(this),n=o.data(a),i=a+"_"+n.idx,r=e("#mCSB_"+n.idx+"_container"),l=r.parent(),s=e(".mCSB_"+n.idx+"_scrollbar ."+d[12]);s.bind("mousedown."+i+" touchstart."+i+" pointerdown."+i+" MSPointerDown."+i,function(o){c=!0,e(o.target).hasClass("mCSB_dragger")||(t=1)}).bind("touchend."+i+" pointerup."+i+" MSPointerUp."+i,function(){c=!1}).bind("click."+i,function(a){if(t&&(t=0,e(a.target).hasClass(d[12])||e(a.target).hasClass("mCSB_draggerRail"))){Q(o);var i=e(this),s=i.find(".mCSB_dragger");if(i.parent(".mCSB_scrollTools_horizontal").length>0){if(!n.overflowed[1])return;var c="x",u=a.pageX>s.offset().left?-1:1,f=Math.abs(r[0].offsetLeft)-u*(.9*l.width())}else{if(!n.overflowed[0])return;var c="y",u=a.pageY>s.offset().top?-1:1,f=Math.abs(r[0].offsetTop)-u*(.9*l.height())}G(o,f.toString(),{dir:c,scrollEasing:"mcsEaseInOut"})}})},H=function(){var t=e(this),o=t.data(a),n=o.opt,i=a+"_"+o.idx,r=e("#mCSB_"+o.idx+"_container"),l=r.parent();r.bind("focusin."+i,function(){var o=e(document.activeElement),a=r.find(".mCustomScrollBox").length,i=0;o.is(n.advanced.autoScrollOnFocus)&&(Q(t),clearTimeout(t[0]._focusTimeout),t[0]._focusTimer=a?(i+17)*a:0,t[0]._focusTimeout=setTimeout(function(){var e=[ae(o)[0],ae(o)[1]],a=[r[0].offsetTop,r[0].offsetLeft],s=[a[0]+e[0]>=0&&a[0]+e[0]=0&&a[0]+e[1]a");s.bind("contextmenu."+r,function(e){e.preventDefault()}).bind("mousedown."+r+" touchstart."+r+" pointerdown."+r+" MSPointerDown."+r+" mouseup."+r+" touchend."+r+" pointerup."+r+" MSPointerUp."+r+" mouseout."+r+" pointerout."+r+" MSPointerOut."+r+" click."+r,function(a){function r(e,o){i.scrollAmount=n.scrollButtons.scrollAmount,j(t,e,o)}if(a.preventDefault(),ee(a)){var l=e(this).attr("class");switch(i.type=n.scrollButtons.scrollType,a.type){case"mousedown":case"touchstart":case"pointerdown":case"MSPointerDown":if("stepped"===i.type)return;c=!0,o.tweenRunning=!1,r("on",l);break;case"mouseup":case"touchend":case"pointerup":case"MSPointerUp":case"mouseout":case"pointerout":case"MSPointerOut":if("stepped"===i.type)return;c=!1,i.dir&&r("off",l);break;case"click":if("stepped"!==i.type||o.tweenRunning)return;r("on",l)}}})},q=function(){function t(t){function a(e,t){r.type=i.keyboard.scrollType,r.scrollAmount=i.keyboard.scrollAmount,"stepped"===r.type&&n.tweenRunning||j(o,e,t)}switch(t.type){case"blur":n.tweenRunning&&r.dir&&a("off",null);break;case"keydown":case"keyup":var l=t.keyCode?t.keyCode:t.which,s="on";if("x"!==i.axis&&(38===l||40===l)||"y"!==i.axis&&(37===l||39===l)){if((38===l||40===l)&&!n.overflowed[0]||(37===l||39===l)&&!n.overflowed[1])return;"keyup"===t.type&&(s="off"),e(document.activeElement).is(u)||(t.preventDefault(),t.stopImmediatePropagation(),a(s,l))}else if(33===l||34===l){if((n.overflowed[0]||n.overflowed[1])&&(t.preventDefault(),t.stopImmediatePropagation()),"keyup"===t.type){Q(o);var f=34===l?-1:1;if("x"===i.axis||"yx"===i.axis&&n.overflowed[1]&&!n.overflowed[0])var h="x",m=Math.abs(c[0].offsetLeft)-f*(.9*d.width());else var h="y",m=Math.abs(c[0].offsetTop)-f*(.9*d.height());G(o,m.toString(),{dir:h,scrollEasing:"mcsEaseInOut"})}}else if((35===l||36===l)&&!e(document.activeElement).is(u)&&((n.overflowed[0]||n.overflowed[1])&&(t.preventDefault(),t.stopImmediatePropagation()),"keyup"===t.type)){if("x"===i.axis||"yx"===i.axis&&n.overflowed[1]&&!n.overflowed[0])var h="x",m=35===l?Math.abs(d.width()-c.outerWidth(!1)):0;else var h="y",m=35===l?Math.abs(d.height()-c.outerHeight(!1)):0;G(o,m.toString(),{dir:h,scrollEasing:"mcsEaseInOut"})}}}var o=e(this),n=o.data(a),i=n.opt,r=n.sequential,l=a+"_"+n.idx,s=e("#mCSB_"+n.idx),c=e("#mCSB_"+n.idx+"_container"),d=c.parent(),u="input,textarea,select,datalist,keygen,[contenteditable='true']",f=c.find("iframe"),h=["blur."+l+" keydown."+l+" keyup."+l];f.length&&f.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind(h[0],function(e){t(e)})})}),s.attr("tabindex","0").bind(h[0],function(e){t(e)})},j=function(t,o,n,i,r){function l(e){u.snapAmount&&(f.scrollAmount=u.snapAmount instanceof Array?"x"===f.dir[0]?u.snapAmount[1]:u.snapAmount[0]:u.snapAmount);var o="stepped"!==f.type,a=r?r:e?o?p/1.5:g:1e3/60,n=e?o?7.5:40:2.5,s=[Math.abs(h[0].offsetTop),Math.abs(h[0].offsetLeft)],d=[c.scrollRatio.y>10?10:c.scrollRatio.y,c.scrollRatio.x>10?10:c.scrollRatio.x],m="x"===f.dir[0]?s[1]+f.dir[1]*(d[1]*n):s[0]+f.dir[1]*(d[0]*n),v="x"===f.dir[0]?s[1]+f.dir[1]*parseInt(f.scrollAmount):s[0]+f.dir[1]*parseInt(f.scrollAmount),x="auto"!==f.scrollAmount?v:m,_=i?i:e?o?"mcsLinearOut":"mcsEaseInOut":"mcsLinear",w=!!e;return e&&17>a&&(x="x"===f.dir[0]?s[1]:s[0]),G(t,x.toString(),{dir:f.dir[0],scrollEasing:_,dur:a,onComplete:w}),e?void(f.dir=!1):(clearTimeout(f.step),void(f.step=setTimeout(function(){l()},a)))}function s(){clearTimeout(f.step),$(f,"step"),Q(t)}var c=t.data(a),u=c.opt,f=c.sequential,h=e("#mCSB_"+c.idx+"_container"),m="stepped"===f.type,p=u.scrollInertia<26?26:u.scrollInertia,g=u.scrollInertia<1?17:u.scrollInertia;switch(o){case"on":if(f.dir=[n===d[16]||n===d[15]||39===n||37===n?"x":"y",n===d[13]||n===d[15]||38===n||37===n?-1:1],Q(t),oe(n)&&"stepped"===f.type)return;l(m);break;case"off":s(),(m||c.tweenRunning&&f.dir)&&l(!0)}},Y=function(t){var o=e(this).data(a).opt,n=[];return"function"==typeof t&&(t=t()),t instanceof Array?n=t.length>1?[t[0],t[1]]:"x"===o.axis?[null,t[0]]:[t[0],null]:(n[0]=t.y?t.y:t.x||"x"===o.axis?null:t,n[1]=t.x?t.x:t.y||"y"===o.axis?null:t),"function"==typeof n[0]&&(n[0]=n[0]()),"function"==typeof n[1]&&(n[1]=n[1]()),n},X=function(t,o){if(null!=t&&"undefined"!=typeof t){var n=e(this),i=n.data(a),r=i.opt,l=e("#mCSB_"+i.idx+"_container"),s=l.parent(),c=typeof t;o||(o="x"===r.axis?"x":"y");var d="x"===o?l.outerWidth(!1)-s.width():l.outerHeight(!1)-s.height(),f="x"===o?l[0].offsetLeft:l[0].offsetTop,h="x"===o?"left":"top";switch(c){case"function":return t();case"object":var m=t.jquery?t:e(t);if(!m.length)return;return"x"===o?ae(m)[1]:ae(m)[0];case"string":case"number":if(oe(t))return Math.abs(t);if(-1!==t.indexOf("%"))return Math.abs(d*parseInt(t)/100);if(-1!==t.indexOf("-="))return Math.abs(f-parseInt(t.split("-=")[1]));if(-1!==t.indexOf("+=")){var p=f+parseInt(t.split("+=")[1]);return p>=0?0:Math.abs(p)}if(-1!==t.indexOf("px")&&oe(t.split("px")[0]))return Math.abs(t.split("px")[0]);if("top"===t||"left"===t)return 0;if("bottom"===t)return Math.abs(s.height()-l.outerHeight(!1));if("right"===t)return Math.abs(s.width()-l.outerWidth(!1));if("first"===t||"last"===t){var m=l.find(":"+t);return"x"===o?ae(m)[1]:ae(m)[0]}return e(t).length?"x"===o?ae(e(t))[1]:ae(e(t))[0]:(l.css(h,t),void u.update.call(null,n[0]))}}},N=function(t){function o(){return clearTimeout(f[0].autoUpdate),0===l.parents("html").length?void(l=null):void(f[0].autoUpdate=setTimeout(function(){return c.advanced.updateOnSelectorChange&&(s.poll.change.n=i(),s.poll.change.n!==s.poll.change.o)?(s.poll.change.o=s.poll.change.n,void r(3)):c.advanced.updateOnContentResize&&(s.poll.size.n=l[0].scrollHeight+l[0].scrollWidth+f[0].offsetHeight+l[0].offsetHeight+l[0].offsetWidth,s.poll.size.n!==s.poll.size.o)?(s.poll.size.o=s.poll.size.n,void r(1)):!c.advanced.updateOnImageLoad||"auto"===c.advanced.updateOnImageLoad&&"y"===c.axis||(s.poll.img.n=f.find("img").length,s.poll.img.n===s.poll.img.o)?void((c.advanced.updateOnSelectorChange||c.advanced.updateOnContentResize||c.advanced.updateOnImageLoad)&&o()):(s.poll.img.o=s.poll.img.n,void f.find("img").each(function(){n(this)}))},c.advanced.autoUpdateTimeout))}function n(t){function o(e,t){return function(){ +return t.apply(e,arguments)}}function a(){this.onload=null,e(t).addClass(d[2]),r(2)}if(e(t).hasClass(d[2]))return void r();var n=new Image;n.onload=o(n,a),n.src=t.src}function i(){c.advanced.updateOnSelectorChange===!0&&(c.advanced.updateOnSelectorChange="*");var e=0,t=f.find(c.advanced.updateOnSelectorChange);return c.advanced.updateOnSelectorChange&&t.length>0&&t.each(function(){e+=this.offsetHeight+this.offsetWidth}),e}function r(e){clearTimeout(f[0].autoUpdate),u.update.call(null,l[0],e)}var l=e(this),s=l.data(a),c=s.opt,f=e("#mCSB_"+s.idx+"_container");return t?(clearTimeout(f[0].autoUpdate),void $(f[0],"autoUpdate")):void o()},V=function(e,t,o){return Math.round(e/t)*t-o},Q=function(t){var o=t.data(a),n=e("#mCSB_"+o.idx+"_container,#mCSB_"+o.idx+"_container_wrapper,#mCSB_"+o.idx+"_dragger_vertical,#mCSB_"+o.idx+"_dragger_horizontal");n.each(function(){Z.call(this)})},G=function(t,o,n){function i(e){return s&&c.callbacks[e]&&"function"==typeof c.callbacks[e]}function r(){return[c.callbacks.alwaysTriggerOffsets||w>=S[0]+y,c.callbacks.alwaysTriggerOffsets||-B>=w]}function l(){var e=[h[0].offsetTop,h[0].offsetLeft],o=[x[0].offsetTop,x[0].offsetLeft],a=[h.outerHeight(!1),h.outerWidth(!1)],i=[f.height(),f.width()];t[0].mcs={content:h,top:e[0],left:e[1],draggerTop:o[0],draggerLeft:o[1],topPct:Math.round(100*Math.abs(e[0])/(Math.abs(a[0])-i[0])),leftPct:Math.round(100*Math.abs(e[1])/(Math.abs(a[1])-i[1])),direction:n.dir}}var s=t.data(a),c=s.opt,d={trigger:"internal",dir:"y",scrollEasing:"mcsEaseOut",drag:!1,dur:c.scrollInertia,overwrite:"all",callbacks:!0,onStart:!0,onUpdate:!0,onComplete:!0},n=e.extend(d,n),u=[n.dur,n.drag?0:n.dur],f=e("#mCSB_"+s.idx),h=e("#mCSB_"+s.idx+"_container"),m=h.parent(),p=c.callbacks.onTotalScrollOffset?Y.call(t,c.callbacks.onTotalScrollOffset):[0,0],g=c.callbacks.onTotalScrollBackOffset?Y.call(t,c.callbacks.onTotalScrollBackOffset):[0,0];if(s.trigger=n.trigger,0===m.scrollTop()&&0===m.scrollLeft()||(e(".mCSB_"+s.idx+"_scrollbar").css("visibility","visible"),m.scrollTop(0).scrollLeft(0)),"_resetY"!==o||s.contentReset.y||(i("onOverflowYNone")&&c.callbacks.onOverflowYNone.call(t[0]),s.contentReset.y=1),"_resetX"!==o||s.contentReset.x||(i("onOverflowXNone")&&c.callbacks.onOverflowXNone.call(t[0]),s.contentReset.x=1),"_resetY"!==o&&"_resetX"!==o){if(!s.contentReset.y&&t[0].mcs||!s.overflowed[0]||(i("onOverflowY")&&c.callbacks.onOverflowY.call(t[0]),s.contentReset.x=null),!s.contentReset.x&&t[0].mcs||!s.overflowed[1]||(i("onOverflowX")&&c.callbacks.onOverflowX.call(t[0]),s.contentReset.x=null),c.snapAmount){var v=c.snapAmount instanceof Array?"x"===n.dir?c.snapAmount[1]:c.snapAmount[0]:c.snapAmount;o=V(o,v,c.snapOffset)}switch(n.dir){case"x":var x=e("#mCSB_"+s.idx+"_dragger_horizontal"),_="left",w=h[0].offsetLeft,S=[f.width()-h.outerWidth(!1),x.parent().width()-x.width()],b=[o,0===o?0:o/s.scrollRatio.x],y=p[1],B=g[1],T=y>0?y/s.scrollRatio.x:0,k=B>0?B/s.scrollRatio.x:0;break;case"y":var x=e("#mCSB_"+s.idx+"_dragger_vertical"),_="top",w=h[0].offsetTop,S=[f.height()-h.outerHeight(!1),x.parent().height()-x.height()],b=[o,0===o?0:o/s.scrollRatio.y],y=p[0],B=g[0],T=y>0?y/s.scrollRatio.y:0,k=B>0?B/s.scrollRatio.y:0}b[1]<0||0===b[0]&&0===b[1]?b=[0,0]:b[1]>=S[1]?b=[S[0],S[1]]:b[0]=-b[0],t[0].mcs||(l(),i("onInit")&&c.callbacks.onInit.call(t[0])),clearTimeout(h[0].onCompleteTimeout),J(x[0],_,Math.round(b[1]),u[1],n.scrollEasing),!s.tweenRunning&&(0===w&&b[0]>=0||w===S[0]&&b[0]<=S[0])||J(h[0],_,Math.round(b[0]),u[0],n.scrollEasing,n.overwrite,{onStart:function(){n.callbacks&&n.onStart&&!s.tweenRunning&&(i("onScrollStart")&&(l(),c.callbacks.onScrollStart.call(t[0])),s.tweenRunning=!0,C(x),s.cbOffsets=r())},onUpdate:function(){n.callbacks&&n.onUpdate&&i("whileScrolling")&&(l(),c.callbacks.whileScrolling.call(t[0]))},onComplete:function(){if(n.callbacks&&n.onComplete){"yx"===c.axis&&clearTimeout(h[0].onCompleteTimeout);var e=h[0].idleTimer||0;h[0].onCompleteTimeout=setTimeout(function(){i("onScroll")&&(l(),c.callbacks.onScroll.call(t[0])),i("onTotalScroll")&&b[1]>=S[1]-T&&s.cbOffsets[0]&&(l(),c.callbacks.onTotalScroll.call(t[0])),i("onTotalScrollBack")&&b[1]<=k&&s.cbOffsets[1]&&(l(),c.callbacks.onTotalScrollBack.call(t[0])),s.tweenRunning=!1,h[0].idleTimer=0,C(x,"hide")},e)}}})}},J=function(e,t,o,a,n,i,r){function l(){S.stop||(x||m.call(),x=K()-v,s(),x>=S.time&&(S.time=x>S.time?x+f-(x-S.time):x+f-1,S.time0?(S.currVal=u(S.time,_,b,a,n),w[t]=Math.round(S.currVal)+"px"):w[t]=o+"px",p.call()}function c(){f=1e3/60,S.time=x+f,h=window.requestAnimationFrame?window.requestAnimationFrame:function(e){return s(),setTimeout(e,.01)},S.id=h(l)}function d(){null!=S.id&&(window.requestAnimationFrame?window.cancelAnimationFrame(S.id):clearTimeout(S.id),S.id=null)}function u(e,t,o,a,n){switch(n){case"linear":case"mcsLinear":return o*e/a+t;case"mcsLinearOut":return e/=a,e--,o*Math.sqrt(1-e*e)+t;case"easeInOutSmooth":return e/=a/2,1>e?o/2*e*e+t:(e--,-o/2*(e*(e-2)-1)+t);case"easeInOutStrong":return e/=a/2,1>e?o/2*Math.pow(2,10*(e-1))+t:(e--,o/2*(-Math.pow(2,-10*e)+2)+t);case"easeInOut":case"mcsEaseInOut":return e/=a/2,1>e?o/2*e*e*e+t:(e-=2,o/2*(e*e*e+2)+t);case"easeOutSmooth":return e/=a,e--,-o*(e*e*e*e-1)+t;case"easeOutStrong":return o*(-Math.pow(2,-10*e/a)+1)+t;case"easeOut":case"mcsEaseOut":default:var i=(e/=a)*e,r=i*e;return t+o*(.499999999999997*r*i+-2.5*i*i+5.5*r+-6.5*i+4*e)}}e._mTween||(e._mTween={top:{},left:{}});var f,h,r=r||{},m=r.onStart||function(){},p=r.onUpdate||function(){},g=r.onComplete||function(){},v=K(),x=0,_=e.offsetTop,w=e.style,S=e._mTween[t];"left"===t&&(_=e.offsetLeft);var b=o-_;S.stop=0,"none"!==i&&d(),c()},K=function(){return window.performance&&window.performance.now?window.performance.now():window.performance&&window.performance.webkitNow?window.performance.webkitNow():Date.now?Date.now():(new Date).getTime()},Z=function(){var e=this;e._mTween||(e._mTween={top:{},left:{}});for(var t=["top","left"],o=0;o=0&&a[0]+ae(n)[0]=0&&a[1]+ae(n)[1]=0&&r[1]-i[1]*l[1][0]<0&&r[1]+n[1]-i[1]*l[1][1]>=0},mcsOverflow:e.expr[":"].mcsOverflow||function(t){var o=e(t).data(a);if(o)return o.overflowed[0]||o.overflowed[1]}})})})}); \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css new file mode 100644 index 0000000000..45152c1bec --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css @@ -0,0 +1,1267 @@ +/* +== malihu jquery custom scrollbar plugin == +Plugin URI: http://manos.malihu.gr/jquery-custom-content-scroller +*/ + + + +/* +CONTENTS: + 1. BASIC STYLE - Plugin's basic/essential CSS properties (normally, should not be edited). + 2. VERTICAL SCROLLBAR - Positioning and dimensions of vertical scrollbar. + 3. HORIZONTAL SCROLLBAR - Positioning and dimensions of horizontal scrollbar. + 4. VERTICAL AND HORIZONTAL SCROLLBARS - Positioning and dimensions of 2-axis scrollbars. + 5. TRANSITIONS - CSS3 transitions for hover events, auto-expanded and auto-hidden scrollbars. + 6. SCROLLBAR COLORS, OPACITY AND BACKGROUNDS + 6.1 THEMES - Scrollbar colors, opacity, dimensions, backgrounds etc. via ready-to-use themes. +*/ + + + +/* +------------------------------------------------------------------------------------------------------------------------ +1. BASIC STYLE +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCustomScrollbar{ -ms-touch-action: pinch-zoom; touch-action: pinch-zoom; /* direct pointer events to js */ } + .mCustomScrollbar.mCS_no_scrollbar, .mCustomScrollbar.mCS_touch_action{ -ms-touch-action: auto; touch-action: auto; } + + .mCustomScrollBox{ /* contains plugin's markup */ + position: relative; + overflow: hidden; + height: 100%; + max-width: 100%; + outline: none; + direction: ltr; + } + + .mCSB_container{ /* contains the original content */ + overflow: hidden; + width: auto; + height: auto; + } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +2. VERTICAL SCROLLBAR +y-axis +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCSB_inside > .mCSB_container{ margin-right: 30px; } + + .mCSB_container.mCS_no_scrollbar_y.mCS_y_hidden{ margin-right: 0; } /* non-visible scrollbar */ + + .mCS-dir-rtl > .mCSB_inside > .mCSB_container{ /* RTL direction/left-side scrollbar */ + margin-right: 0; + margin-left: 30px; + } + + .mCS-dir-rtl > .mCSB_inside > .mCSB_container.mCS_no_scrollbar_y.mCS_y_hidden{ margin-left: 0; } /* RTL direction/left-side scrollbar */ + + .mCSB_scrollTools{ /* contains scrollbar markup (draggable element, dragger rail, buttons etc.) */ + position: absolute; + width: 16px; + height: auto; + left: auto; + top: 0; + right: 0; + bottom: 0; + } + + .mCSB_outside + .mCSB_scrollTools{ right: -26px; } /* scrollbar position: outside */ + + .mCS-dir-rtl > .mCSB_inside > .mCSB_scrollTools, + .mCS-dir-rtl > .mCSB_outside + .mCSB_scrollTools{ /* RTL direction/left-side scrollbar */ + right: auto; + left: 0; + } + + .mCS-dir-rtl > .mCSB_outside + .mCSB_scrollTools{ left: -26px; } /* RTL direction/left-side scrollbar (scrollbar position: outside) */ + + .mCSB_scrollTools .mCSB_draggerContainer{ /* contains the draggable element and dragger rail markup */ + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + height: auto; + } + + .mCSB_scrollTools a + .mCSB_draggerContainer{ margin: 20px 0; } + + .mCSB_scrollTools .mCSB_draggerRail{ + width: 2px; + height: 100%; + margin: 0 auto; + -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; + } + + .mCSB_scrollTools .mCSB_dragger{ /* the draggable element */ + cursor: pointer; + width: 100%; + height: 30px; /* minimum dragger height */ + z-index: 1; + } + + .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ /* the dragger element */ + position: relative; + width: 4px; + height: 100%; + margin: 0 auto; + -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; + text-align: center; + } + + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ width: 12px; /* auto-expanded scrollbar */ } + + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ width: 8px; /* auto-expanded scrollbar */ } + + .mCSB_scrollTools .mCSB_buttonUp, + .mCSB_scrollTools .mCSB_buttonDown{ + display: block; + position: absolute; + height: 20px; + width: 100%; + overflow: hidden; + margin: 0 auto; + cursor: pointer; + } + + .mCSB_scrollTools .mCSB_buttonDown{ bottom: 0; } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +3. HORIZONTAL SCROLLBAR +x-axis +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCSB_horizontal.mCSB_inside > .mCSB_container{ + margin-right: 0; + margin-bottom: 30px; + } + + .mCSB_horizontal.mCSB_outside > .mCSB_container{ min-height: 100%; } + + .mCSB_horizontal > .mCSB_container.mCS_no_scrollbar_x.mCS_x_hidden{ margin-bottom: 0; } /* non-visible scrollbar */ + + .mCSB_scrollTools.mCSB_scrollTools_horizontal{ + width: auto; + height: 16px; + top: auto; + right: 0; + bottom: 0; + left: 0; + } + + .mCustomScrollBox + .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCustomScrollBox + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal{ bottom: -26px; } /* scrollbar position: outside */ + + .mCSB_scrollTools.mCSB_scrollTools_horizontal a + .mCSB_draggerContainer{ margin: 0 20px; } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 2px; + margin: 7px 0; + } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_dragger{ + width: 30px; /* minimum dragger width */ + height: 100%; + left: 0; + } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 4px; + margin: 6px auto; + } + + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ + height: 12px; /* auto-expanded scrollbar */ + margin: 2px auto; + } + + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ + height: 8px; /* auto-expanded scrollbar */ + margin: 4px 0; + } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonLeft, + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonRight{ + display: block; + position: absolute; + width: 20px; + height: 100%; + overflow: hidden; + margin: 0 auto; + cursor: pointer; + } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonLeft{ left: 0; } + + .mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonRight{ right: 0; } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +4. VERTICAL AND HORIZONTAL SCROLLBARS +yx-axis +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCSB_container_wrapper{ + position: absolute; + height: auto; + width: auto; + overflow: hidden; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin-right: 30px; + margin-bottom: 30px; + } + + .mCSB_container_wrapper > .mCSB_container{ + padding-right: 30px; + padding-bottom: 30px; + -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; + } + + .mCSB_vertical_horizontal > .mCSB_scrollTools.mCSB_scrollTools_vertical{ bottom: 20px; } + + .mCSB_vertical_horizontal > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ right: 20px; } + + /* non-visible horizontal scrollbar */ + .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden + .mCSB_scrollTools.mCSB_scrollTools_vertical{ bottom: 0; } + + /* non-visible vertical scrollbar/RTL direction/left-side scrollbar */ + .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden + .mCSB_scrollTools ~ .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ right: 0; } + + /* RTL direction/left-side scrollbar */ + .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ left: 20px; } + + /* non-visible scrollbar/RTL direction/left-side scrollbar */ + .mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden + .mCSB_scrollTools ~ .mCSB_scrollTools.mCSB_scrollTools_horizontal{ left: 0; } + + .mCS-dir-rtl > .mCSB_inside > .mCSB_container_wrapper{ /* RTL direction/left-side scrollbar */ + margin-right: 0; + margin-left: 30px; + } + + .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden > .mCSB_container{ padding-right: 0; } + + .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden > .mCSB_container{ padding-bottom: 0; } + + .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden{ + margin-right: 0; /* non-visible scrollbar */ + margin-left: 0; + } + + /* non-visible horizontal scrollbar */ + .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden{ margin-bottom: 0; } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +5. TRANSITIONS +------------------------------------------------------------------------------------------------------------------------ +*/ + + .mCSB_scrollTools, + .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCSB_scrollTools .mCSB_buttonUp, + .mCSB_scrollTools .mCSB_buttonDown, + .mCSB_scrollTools .mCSB_buttonLeft, + .mCSB_scrollTools .mCSB_buttonRight{ + -webkit-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; + -moz-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; + -o-transition: opacity .2s ease-in-out, background-color .2s ease-in-out; + transition: opacity .2s ease-in-out, background-color .2s ease-in-out; + } + + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger_bar, /* auto-expanded scrollbar */ + .mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerRail, + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger_bar, + .mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerRail{ + -webkit-transition: width .2s ease-out .2s, height .2s ease-out .2s, + margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, + margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, + opacity .2s ease-in-out, background-color .2s ease-in-out; + -moz-transition: width .2s ease-out .2s, height .2s ease-out .2s, + margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, + margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, + opacity .2s ease-in-out, background-color .2s ease-in-out; + -o-transition: width .2s ease-out .2s, height .2s ease-out .2s, + margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, + margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, + opacity .2s ease-in-out, background-color .2s ease-in-out; + transition: width .2s ease-out .2s, height .2s ease-out .2s, + margin-left .2s ease-out .2s, margin-right .2s ease-out .2s, + margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s, + opacity .2s ease-in-out, background-color .2s ease-in-out; + } + + + +/* +------------------------------------------------------------------------------------------------------------------------ +6. SCROLLBAR COLORS, OPACITY AND BACKGROUNDS +------------------------------------------------------------------------------------------------------------------------ +*/ + + /* + ---------------------------------------- + 6.1 THEMES + ---------------------------------------- + */ + + /* default theme ("light") */ + + .mCSB_scrollTools{ opacity: 0.75; filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; } + + .mCS-autoHide > .mCustomScrollBox > .mCSB_scrollTools, + .mCS-autoHide > .mCustomScrollBox ~ .mCSB_scrollTools{ opacity: 0; filter: "alpha(opacity=0)"; -ms-filter: "alpha(opacity=0)"; } + + .mCustomScrollbar > .mCustomScrollBox > .mCSB_scrollTools.mCSB_scrollTools_onDrag, + .mCustomScrollbar > .mCustomScrollBox ~ .mCSB_scrollTools.mCSB_scrollTools_onDrag, + .mCustomScrollBox:hover > .mCSB_scrollTools, + .mCustomScrollBox:hover ~ .mCSB_scrollTools, + .mCS-autoHide:hover > .mCustomScrollBox > .mCSB_scrollTools, + .mCS-autoHide:hover > .mCustomScrollBox ~ .mCSB_scrollTools{ opacity: 1; filter: "alpha(opacity=100)"; -ms-filter: "alpha(opacity=100)"; } + + .mCSB_scrollTools .mCSB_draggerRail{ + background-color: #000; background-color: rgba(0,0,0,0.4); + filter: "alpha(opacity=40)"; -ms-filter: "alpha(opacity=40)"; + } + + .mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.75); + filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; + } + + .mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.85); + filter: "alpha(opacity=85)"; -ms-filter: "alpha(opacity=85)"; + } + .mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.9); + filter: "alpha(opacity=90)"; -ms-filter: "alpha(opacity=90)"; + } + + .mCSB_scrollTools .mCSB_buttonUp, + .mCSB_scrollTools .mCSB_buttonDown, + .mCSB_scrollTools .mCSB_buttonLeft, + .mCSB_scrollTools .mCSB_buttonRight{ + background-image: url(mCSB_buttons.png); /* css sprites */ + background-repeat: no-repeat; + opacity: 0.4; filter: "alpha(opacity=40)"; -ms-filter: "alpha(opacity=40)"; + } + + .mCSB_scrollTools .mCSB_buttonUp{ + background-position: 0 0; + /* + sprites locations + light: 0 0, -16px 0, -32px 0, -48px 0, 0 -72px, -16px -72px, -32px -72px + dark: -80px 0, -96px 0, -112px 0, -128px 0, -80px -72px, -96px -72px, -112px -72px + */ + } + + .mCSB_scrollTools .mCSB_buttonDown{ + background-position: 0 -20px; + /* + sprites locations + light: 0 -20px, -16px -20px, -32px -20px, -48px -20px, 0 -92px, -16px -92px, -32px -92px + dark: -80px -20px, -96px -20px, -112px -20px, -128px -20px, -80px -92px, -96px -92px, -112 -92px + */ + } + + .mCSB_scrollTools .mCSB_buttonLeft{ + background-position: 0 -40px; + /* + sprites locations + light: 0 -40px, -20px -40px, -40px -40px, -60px -40px, 0 -112px, -20px -112px, -40px -112px + dark: -80px -40px, -100px -40px, -120px -40px, -140px -40px, -80px -112px, -100px -112px, -120px -112px + */ + } + + .mCSB_scrollTools .mCSB_buttonRight{ + background-position: 0 -56px; + /* + sprites locations + light: 0 -56px, -20px -56px, -40px -56px, -60px -56px, 0 -128px, -20px -128px, -40px -128px + dark: -80px -56px, -100px -56px, -120px -56px, -140px -56px, -80px -128px, -100px -128px, -120px -128px + */ + } + + .mCSB_scrollTools .mCSB_buttonUp:hover, + .mCSB_scrollTools .mCSB_buttonDown:hover, + .mCSB_scrollTools .mCSB_buttonLeft:hover, + .mCSB_scrollTools .mCSB_buttonRight:hover{ opacity: 0.75; filter: "alpha(opacity=75)"; -ms-filter: "alpha(opacity=75)"; } + + .mCSB_scrollTools .mCSB_buttonUp:active, + .mCSB_scrollTools .mCSB_buttonDown:active, + .mCSB_scrollTools .mCSB_buttonLeft:active, + .mCSB_scrollTools .mCSB_buttonRight:active{ opacity: 0.9; filter: "alpha(opacity=90)"; -ms-filter: "alpha(opacity=90)"; } + + + /* theme: "dark" */ + + .mCS-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } + + .mCS-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: rgba(0,0,0,0.85); } + + .mCS-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: rgba(0,0,0,0.9); } + + .mCS-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px 0; } + + .mCS-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -20px; } + + .mCS-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -40px; } + + .mCS-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -56px; } + + /* ---------------------------------------- */ + + + + /* theme: "light-2", "dark-2" */ + + .mCS-light-2.mCSB_scrollTools .mCSB_draggerRail, + .mCS-dark-2.mCSB_scrollTools .mCSB_draggerRail{ + width: 4px; + background-color: #fff; background-color: rgba(255,255,255,0.1); + -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; + } + + .mCS-light-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width: 4px; + background-color: #fff; background-color: rgba(255,255,255,0.75); + -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; + } + + .mCS-light-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-dark-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-light-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 4px; + margin: 6px auto; + } + + .mCS-light-2.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } + + .mCS-light-2.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-light-2.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } + + .mCS-light-2.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px 0; } + + .mCS-light-2.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -20px; } + + .mCS-light-2.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -40px; } + + .mCS-light-2.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -56px; } + + + /* theme: "dark-2" */ + + .mCS-dark-2.mCSB_scrollTools .mCSB_draggerRail{ + background-color: #000; background-color: rgba(0,0,0,0.1); + -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; + } + + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #000; background-color: rgba(0,0,0,0.75); + -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; + } + + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark-2.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-dark-2.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px 0; } + + .mCS-dark-2.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -20px; } + + .mCS-dark-2.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -40px; } + + .mCS-dark-2.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -56px; } + + /* ---------------------------------------- */ + + + + /* theme: "light-thick", "dark-thick" */ + + .mCS-light-thick.mCSB_scrollTools .mCSB_draggerRail, + .mCS-dark-thick.mCSB_scrollTools .mCSB_draggerRail{ + width: 4px; + background-color: #fff; background-color: rgba(255,255,255,0.1); + -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; + } + + .mCS-light-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width: 6px; + background-color: #fff; background-color: rgba(255,255,255,0.75); + -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; + } + + .mCS-light-thick.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-dark-thick.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 4px; + margin: 6px 0; + } + + .mCS-light-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 6px; + margin: 5px auto; + } + + .mCS-light-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } + + .mCS-light-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-light-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } + + .mCS-light-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -16px 0; } + + .mCS-light-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -16px -20px; } + + .mCS-light-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -20px -40px; } + + .mCS-light-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -20px -56px; } + + + /* theme: "dark-thick" */ + + .mCS-dark-thick.mCSB_scrollTools .mCSB_draggerRail{ + background-color: #000; background-color: rgba(0,0,0,0.1); + -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; + } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #000; background-color: rgba(0,0,0,0.75); + -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; + } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -96px 0; } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -96px -20px; } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -100px -40px; } + + .mCS-dark-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -100px -56px; } + + /* ---------------------------------------- */ + + + + /* theme: "light-thin", "dark-thin" */ + + .mCS-light-thin.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.1); } + + .mCS-light-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 2px; } + + .mCS-light-thin.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-dark-thin.mCSB_scrollTools_horizontal .mCSB_draggerRail{ width: 100%; } + + .mCS-light-thin.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-thin.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 2px; + margin: 7px auto; + } + + + /* theme "dark-thin" */ + + .mCS-dark-thin.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark-thin.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px 0; } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -20px; } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -40px; } + + .mCS-dark-thin.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -56px; } + + /* ---------------------------------------- */ + + + + /* theme "rounded", "rounded-dark", "rounded-dots", "rounded-dots-dark" */ + + .mCS-rounded.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.15); } + + .mCS-rounded.mCSB_scrollTools .mCSB_dragger, + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger, + .mCS-rounded-dots.mCSB_scrollTools .mCSB_dragger, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger{ height: 14px; } + + .mCS-rounded.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width: 14px; + margin: 0 1px; + } + + .mCS-rounded.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-rounded-dark.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 14px; } + + .mCS-rounded.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + height: 14px; + margin: 1px 0; + } + + .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ + width: 16px; /* auto-expanded scrollbar */ + height: 16px; + margin: -1px 0; + } + + .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-rounded.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, + .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-rounded-dark.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ width: 4px; /* auto-expanded scrollbar */ } + + .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ + height: 16px; /* auto-expanded scrollbar */ + width: 16px; + margin: 0 -1px; + } + + .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-rounded.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, + .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-rounded-dark.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ + height: 4px; /* auto-expanded scrollbar */ + margin: 6px 0; + } + + .mCS-rounded.mCSB_scrollTools .mCSB_buttonUp{ background-position: 0 -72px; } + + .mCS-rounded.mCSB_scrollTools .mCSB_buttonDown{ background-position: 0 -92px; } + + .mCS-rounded.mCSB_scrollTools .mCSB_buttonLeft{ background-position: 0 -112px; } + + .mCS-rounded.mCSB_scrollTools .mCSB_buttonRight{ background-position: 0 -128px; } + + + /* theme "rounded-dark", "rounded-dots-dark" */ + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-rounded-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px -72px; } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -92px; } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -112px; } + + .mCS-rounded-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -128px; } + + + /* theme "rounded-dots", "rounded-dots-dark" */ + + .mCS-rounded-dots.mCSB_scrollTools_vertical .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools_vertical .mCSB_draggerRail{ width: 4px; } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + background-color: transparent; + background-position: center; + } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail{ + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAANElEQVQYV2NkIAAYiVbw//9/Y6DiM1ANJoyMjGdBbLgJQAX/kU0DKgDLkaQAvxW4HEvQFwCRcxIJK1XznAAAAABJRU5ErkJggg=="); + background-repeat: repeat-y; + opacity: 0.3; + filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; + } + + .mCS-rounded-dots.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-rounded-dots-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + height: 4px; + margin: 6px 0; + background-repeat: repeat-x; + } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonUp{ background-position: -16px -72px; } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonDown{ background-position: -16px -92px; } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -20px -112px; } + + .mCS-rounded-dots.mCSB_scrollTools .mCSB_buttonRight{ background-position: -20px -128px; } + + + /* theme "rounded-dots-dark" */ + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_draggerRail{ + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAALElEQVQYV2NkIAAYSVFgDFR8BqrBBEifBbGRTfiPZhpYjiQFBK3A6l6CvgAAE9kGCd1mvgEAAAAASUVORK5CYII="); + } + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -96px -72px; } + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -96px -92px; } + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -100px -112px; } + + .mCS-rounded-dots-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -100px -128px; } + + /* ---------------------------------------- */ + + + + /* theme "3d", "3d-dark", "3d-thick", "3d-thick-dark" */ + + .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-repeat: repeat-y; + background-image: -moz-linear-gradient(left, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 100%); + background-image: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(255,255,255,0.5)), color-stop(100%,rgba(255,255,255,0))); + background-image: -webkit-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: -o-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: -ms-linear-gradient(left, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: linear-gradient(to right, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + } + + .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + background-repeat: repeat-x; + background-image: -moz-linear-gradient(top, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 100%); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,0.5)), color-stop(100%,rgba(255,255,255,0))); + background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: -o-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: -ms-linear-gradient(top, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + background-image: linear-gradient(to bottom, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 100%); + } + + + /* theme "3d", "3d-dark" */ + + .mCS-3d.mCSB_scrollTools_vertical .mCSB_dragger, + .mCS-3d-dark.mCSB_scrollTools_vertical .mCSB_dragger{ height: 70px; } + + .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 70px; } + + .mCS-3d.mCSB_scrollTools, + .mCS-3d-dark.mCSB_scrollTools{ + opacity: 1; + filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; + } + + .mCS-3d.mCSB_scrollTools .mCSB_draggerRail, + .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px; } + + .mCS-3d.mCSB_scrollTools .mCSB_draggerRail, + .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail{ + width: 8px; + background-color: #000; background-color: rgba(0,0,0,0.2); + box-shadow: inset 1px 0 1px rgba(0,0,0,0.5), inset -1px 0 1px rgba(255,255,255,0.2); + } + + .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-3d.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-3d.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #555; } + + .mCS-3d.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 8px; } + + .mCS-3d.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 8px; + margin: 4px 0; + box-shadow: inset 0 1px 1px rgba(0,0,0,0.5), inset 0 -1px 1px rgba(255,255,255,0.2); + } + + .mCS-3d.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + width: 100%; + height: 8px; + margin: 4px auto; + } + + .mCS-3d.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } + + .mCS-3d.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } + + .mCS-3d.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } + + .mCS-3d.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } + + + /* theme "3d-dark" */ + + .mCS-3d-dark.mCSB_scrollTools .mCSB_draggerRail{ + background-color: #000; background-color: rgba(0,0,0,0.1); + box-shadow: inset 1px 0 1px rgba(0,0,0,0.1); + } + + .mCS-3d-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ box-shadow: inset 0 1px 1px rgba(0,0,0,0.1); } + + .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } + + .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } + + .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } + + .mCS-3d-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } + + /* ---------------------------------------- */ + + + + /* theme: "3d-thick", "3d-thick-dark" */ + + .mCS-3d-thick.mCSB_scrollTools, + .mCS-3d-thick-dark.mCSB_scrollTools{ + opacity: 1; + filter: "alpha(opacity=30)"; -ms-filter: "alpha(opacity=30)"; + } + + .mCS-3d-thick.mCSB_scrollTools, + .mCS-3d-thick-dark.mCSB_scrollTools, + .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerContainer, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerContainer{ -webkit-border-radius: 7px; -moz-border-radius: 7px; border-radius: 7px; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } + + .mCSB_inside + .mCS-3d-thick.mCSB_scrollTools_vertical, + .mCSB_inside + .mCS-3d-thick-dark.mCSB_scrollTools_vertical{ right: 1px; } + + .mCS-3d-thick.mCSB_scrollTools_vertical, + .mCS-3d-thick-dark.mCSB_scrollTools_vertical{ box-shadow: inset 1px 0 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.5); } + + .mCS-3d-thick.mCSB_scrollTools_horizontal, + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal{ + bottom: 1px; + box-shadow: inset 0 1px 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.5); + } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + box-shadow: inset 1px 0 0 rgba(255,255,255,0.4); + width: 12px; + margin: 2px; + position: absolute; + height: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + } + + .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 0 1px 0 rgba(255,255,255,0.4); } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-3d-thick.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #555; } + + .mCS-3d-thick.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + height: 12px; + width: auto; + } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerContainer{ + background-color: #000; background-color: rgba(0,0,0,0.05); + box-shadow: inset 1px 1px 16px rgba(0,0,0,0.1); + } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } + + .mCS-3d-thick.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } + + + /* theme: "3d-thick-dark" */ + + .mCS-3d-thick-dark.mCSB_scrollTools{ box-shadow: inset 0 0 14px rgba(0,0,0,0.2); } + + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal{ box-shadow: inset 0 1px 1px rgba(0,0,0,0.1), inset 0 0 14px rgba(0,0,0,0.2); } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 1px 0 0 rgba(255,255,255,0.4), inset -1px 0 0 rgba(0,0,0,0.2); } + + .mCS-3d-thick-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ box-shadow: inset 0 1px 0 rgba(255,255,255,0.4), inset 0 -1px 0 rgba(0,0,0,0.2); } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #777; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerContainer{ + background-color: #fff; background-color: rgba(0,0,0,0.05); + box-shadow: inset 1px 1px 16px rgba(0,0,0,0.1); + } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } + + .mCS-3d-thick-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } + + /* ---------------------------------------- */ + + + + /* theme: "minimal", "minimal-dark" */ + + .mCSB_outside + .mCS-minimal.mCSB_scrollTools_vertical, + .mCSB_outside + .mCS-minimal-dark.mCSB_scrollTools_vertical{ + right: 0; + margin: 12px 0; + } + + .mCustomScrollBox.mCS-minimal + .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCustomScrollBox.mCS-minimal + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCustomScrollBox.mCS-minimal-dark + .mCSB_scrollTools.mCSB_scrollTools_horizontal, + .mCustomScrollBox.mCS-minimal-dark + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal{ + bottom: 0; + margin: 0 12px; + } + + /* RTL direction/left-side scrollbar */ + .mCS-dir-rtl > .mCSB_outside + .mCS-minimal.mCSB_scrollTools_vertical, + .mCS-dir-rtl > .mCSB_outside + .mCS-minimal-dark.mCSB_scrollTools_vertical{ + left: 0; + right: auto; + } + + .mCS-minimal.mCSB_scrollTools .mCSB_draggerRail, + .mCS-minimal-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: transparent; } + + .mCS-minimal.mCSB_scrollTools_vertical .mCSB_dragger, + .mCS-minimal-dark.mCSB_scrollTools_vertical .mCSB_dragger{ height: 50px; } + + .mCS-minimal.mCSB_scrollTools_horizontal .mCSB_dragger, + .mCS-minimal-dark.mCSB_scrollTools_horizontal .mCSB_dragger{ width: 50px; } + + .mCS-minimal.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.2); + filter: "alpha(opacity=20)"; -ms-filter: "alpha(opacity=20)"; + } + + .mCS-minimal.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-minimal.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background-color: #fff; background-color: rgba(255,255,255,0.5); + filter: "alpha(opacity=50)"; -ms-filter: "alpha(opacity=50)"; + } + + + /* theme: "minimal-dark" */ + + .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background-color: #000; background-color: rgba(0,0,0,0.2); + filter: "alpha(opacity=20)"; -ms-filter: "alpha(opacity=20)"; + } + + .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-minimal-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background-color: #000; background-color: rgba(0,0,0,0.5); + filter: "alpha(opacity=50)"; -ms-filter: "alpha(opacity=50)"; + } + + /* ---------------------------------------- */ + + + + /* theme "light-3", "dark-3" */ + + .mCS-light-3.mCSB_scrollTools .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools .mCSB_draggerRail{ + width: 6px; + background-color: #000; background-color: rgba(0,0,0,0.2); + } + + .mCS-light-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ width: 6px; } + + .mCS-light-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-dark-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-light-3.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 6px; + margin: 5px 0; + } + + .mCS-light-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-light-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ + width: 12px; + } + + .mCS-light-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-light-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail, + .mCS-dark-3.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ + height: 12px; + margin: 2px 0; + } + + .mCS-light-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } + + .mCS-light-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } + + .mCS-light-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } + + .mCS-light-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } + + + /* theme "dark-3" */ + + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-dark-3.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-dark-3.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.1); } + + .mCS-dark-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } + + .mCS-dark-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } + + .mCS-dark-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } + + .mCS-dark-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } + + /* ---------------------------------------- */ + + + + /* theme "inset", "inset-dark", "inset-2", "inset-2-dark", "inset-3", "inset-3-dark" */ + + .mCS-inset.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-2.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-3.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ + width: 12px; + background-color: #000; background-color: rgba(0,0,0,0.2); + } + + .mCS-inset.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width: 6px; + margin: 3px 5px; + position: absolute; + height: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + } + + .mCS-inset.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{ + height: 6px; + margin: 5px 3px; + position: absolute; + width: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + } + + .mCS-inset.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-2.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-2-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-3.mCSB_scrollTools_horizontal .mCSB_draggerRail, + .mCS-inset-3-dark.mCSB_scrollTools_horizontal .mCSB_draggerRail{ + width: 100%; + height: 12px; + margin: 2px 0; + } + + .mCS-inset.mCSB_scrollTools .mCSB_buttonUp, + .mCS-inset-2.mCSB_scrollTools .mCSB_buttonUp, + .mCS-inset-3.mCSB_scrollTools .mCSB_buttonUp{ background-position: -32px -72px; } + + .mCS-inset.mCSB_scrollTools .mCSB_buttonDown, + .mCS-inset-2.mCSB_scrollTools .mCSB_buttonDown, + .mCS-inset-3.mCSB_scrollTools .mCSB_buttonDown{ background-position: -32px -92px; } + + .mCS-inset.mCSB_scrollTools .mCSB_buttonLeft, + .mCS-inset-2.mCSB_scrollTools .mCSB_buttonLeft, + .mCS-inset-3.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -40px -112px; } + + .mCS-inset.mCSB_scrollTools .mCSB_buttonRight, + .mCS-inset-2.mCSB_scrollTools .mCSB_buttonRight, + .mCS-inset-3.mCSB_scrollTools .mCSB_buttonRight{ background-position: -40px -128px; } + + + /* theme "inset-dark", "inset-2-dark", "inset-3-dark" */ + + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.1); } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonUp, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonUp, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -112px -72px; } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonDown, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonDown, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -112px -92px; } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonLeft, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonLeft, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -120px -112px; } + + .mCS-inset-dark.mCSB_scrollTools .mCSB_buttonRight, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_buttonRight, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -120px -128px; } + + + /* theme "inset-2", "inset-2-dark" */ + + .mCS-inset-2.mCSB_scrollTools .mCSB_draggerRail, + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail{ + background-color: transparent; + border-width: 1px; + border-style: solid; + border-color: #fff; + border-color: rgba(255,255,255,0.2); + -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; + } + + .mCS-inset-2-dark.mCSB_scrollTools .mCSB_draggerRail{ border-color: #000; border-color: rgba(0,0,0,0.2); } + + + /* theme "inset-3", "inset-3-dark" */ + + .mCS-inset-3.mCSB_scrollTools .mCSB_draggerRail{ background-color: #fff; background-color: rgba(255,255,255,0.6); } + + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.6); } + + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); } + + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.85); } + + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-3.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.9); } + + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.75); } + + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.85); } + + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, + .mCS-inset-3-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: #fff; background-color: rgba(255,255,255,0.9); } + + /* ---------------------------------------- */ diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js new file mode 100644 index 0000000000..4c9a0b2e52 --- /dev/null +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.js @@ -0,0 +1,2458 @@ +/* +== malihu jquery custom scrollbar plugin == +Version: 3.1.5 +Plugin URI: http://manos.malihu.gr/jquery-custom-content-scroller +Author: malihu +Author URI: http://manos.malihu.gr +License: MIT License (MIT) +*/ + +/* +Copyright Manos Malihutsakis (email: manos@malihu.gr) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +/* +The code below is fairly long, fully commented and should be normally used in development. +For production, use either the minified jquery.mCustomScrollbar.min.js script or +the production-ready jquery.mCustomScrollbar.concat.min.js which contains the plugin +and dependencies (minified). +*/ + +(function(factory){ + if(typeof define==="function" && define.amd){ + define(["jquery"],factory); + }else if(typeof module!=="undefined" && module.exports){ + module.exports=factory; + }else{ + factory(jQuery,window,document); + } +}(function($){ +(function(init){ + var _rjs=typeof define==="function" && define.amd, /* RequireJS */ + _njs=typeof module !== "undefined" && module.exports, /* NodeJS */ + _dlp=("https:"==document.location.protocol) ? "https:" : "http:", /* location protocol */ + _url="cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js"; + if(!_rjs){ + if(_njs){ + require("jquery-mousewheel")($); + }else{ + /* load jquery-mousewheel plugin (via CDN) if it's not present or not loaded via RequireJS + (works when mCustomScrollbar fn is called on window load) */ + $.event.special.mousewheel || $("head").append(decodeURI("%3Cscript src="+_dlp+"//"+_url+"%3E%3C/script%3E")); + } + } + init(); +}(function(){ + + /* + ---------------------------------------- + PLUGIN NAMESPACE, PREFIX, DEFAULT SELECTOR(S) + ---------------------------------------- + */ + + var pluginNS="mCustomScrollbar", + pluginPfx="mCS", + defaultSelector=".mCustomScrollbar", + + + + + + /* + ---------------------------------------- + DEFAULT OPTIONS + ---------------------------------------- + */ + + defaults={ + /* + set element/content width/height programmatically + values: boolean, pixels, percentage + option default + ------------------------------------- + setWidth false + setHeight false + */ + /* + set the initial css top property of content + values: string (e.g. "-100px", "10%" etc.) + */ + setTop:0, + /* + set the initial css left property of content + values: string (e.g. "-100px", "10%" etc.) + */ + setLeft:0, + /* + scrollbar axis (vertical and/or horizontal scrollbars) + values (string): "y", "x", "yx" + */ + axis:"y", + /* + position of scrollbar relative to content + values (string): "inside", "outside" ("outside" requires elements with position:relative) + */ + scrollbarPosition:"inside", + /* + scrolling inertia + values: integer (milliseconds) + */ + scrollInertia:950, + /* + auto-adjust scrollbar dragger length + values: boolean + */ + autoDraggerLength:true, + /* + auto-hide scrollbar when idle + values: boolean + option default + ------------------------------------- + autoHideScrollbar false + */ + /* + auto-expands scrollbar on mouse-over and dragging + values: boolean + option default + ------------------------------------- + autoExpandScrollbar false + */ + /* + always show scrollbar, even when there's nothing to scroll + values: integer (0=disable, 1=always show dragger rail and buttons, 2=always show dragger rail, dragger and buttons), boolean + */ + alwaysShowScrollbar:0, + /* + scrolling always snaps to a multiple of this number in pixels + values: integer, array ([y,x]) + option default + ------------------------------------- + snapAmount null + */ + /* + when snapping, snap with this number in pixels as an offset + values: integer + */ + snapOffset:0, + /* + mouse-wheel scrolling + */ + mouseWheel:{ + /* + enable mouse-wheel scrolling + values: boolean + */ + enable:true, + /* + scrolling amount in pixels + values: "auto", integer + */ + scrollAmount:"auto", + /* + mouse-wheel scrolling axis + the default scrolling direction when both vertical and horizontal scrollbars are present + values (string): "y", "x" + */ + axis:"y", + /* + prevent the default behaviour which automatically scrolls the parent element(s) when end of scrolling is reached + values: boolean + option default + ------------------------------------- + preventDefault null + */ + /* + the reported mouse-wheel delta value. The number of lines (translated to pixels) one wheel notch scrolls. + values: "auto", integer + "auto" uses the default OS/browser value + */ + deltaFactor:"auto", + /* + normalize mouse-wheel delta to -1 or 1 (disables mouse-wheel acceleration) + values: boolean + option default + ------------------------------------- + normalizeDelta null + */ + /* + invert mouse-wheel scrolling direction + values: boolean + option default + ------------------------------------- + invert null + */ + /* + the tags that disable mouse-wheel when cursor is over them + */ + disableOver:["select","option","keygen","datalist","textarea"] + }, + /* + scrollbar buttons + */ + scrollButtons:{ + /* + enable scrollbar buttons + values: boolean + option default + ------------------------------------- + enable null + */ + /* + scrollbar buttons scrolling type + values (string): "stepless", "stepped" + */ + scrollType:"stepless", + /* + scrolling amount in pixels + values: "auto", integer + */ + scrollAmount:"auto" + /* + tabindex of the scrollbar buttons + values: false, integer + option default + ------------------------------------- + tabindex null + */ + }, + /* + keyboard scrolling + */ + keyboard:{ + /* + enable scrolling via keyboard + values: boolean + */ + enable:true, + /* + keyboard scrolling type + values (string): "stepless", "stepped" + */ + scrollType:"stepless", + /* + scrolling amount in pixels + values: "auto", integer + */ + scrollAmount:"auto" + }, + /* + enable content touch-swipe scrolling + values: boolean, integer, string (number) + integer values define the axis-specific minimum amount required for scrolling momentum + */ + contentTouchScroll:25, + /* + enable/disable document (default) touch-swipe scrolling + */ + documentTouchScroll:true, + /* + advanced option parameters + */ + advanced:{ + /* + auto-expand content horizontally (for "x" or "yx" axis) + values: boolean, integer (the value 2 forces the non scrollHeight/scrollWidth method, the value 3 forces the scrollHeight/scrollWidth method) + option default + ------------------------------------- + autoExpandHorizontalScroll null + */ + /* + auto-scroll to elements with focus + */ + autoScrollOnFocus:"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']", + /* + auto-update scrollbars on content, element or viewport resize + should be true for fluid layouts/elements, adding/removing content dynamically, hiding/showing elements, content with images etc. + values: boolean + */ + updateOnContentResize:true, + /* + auto-update scrollbars each time each image inside the element is fully loaded + values: "auto", boolean + */ + updateOnImageLoad:"auto", + /* + auto-update scrollbars based on the amount and size changes of specific selectors + useful when you need to update the scrollbar(s) automatically, each time a type of element is added, removed or changes its size + values: boolean, string (e.g. "ul li" will auto-update scrollbars each time list-items inside the element are changed) + a value of true (boolean) will auto-update scrollbars each time any element is changed + option default + ------------------------------------- + updateOnSelectorChange null + */ + /* + extra selectors that'll allow scrollbar dragging upon mousemove/up, pointermove/up, touchend etc. (e.g. "selector-1, selector-2") + option default + ------------------------------------- + extraDraggableSelectors null + */ + /* + extra selectors that'll release scrollbar dragging upon mouseup, pointerup, touchend etc. (e.g. "selector-1, selector-2") + option default + ------------------------------------- + releaseDraggableSelectors null + */ + /* + auto-update timeout + values: integer (milliseconds) + */ + autoUpdateTimeout:60 + }, + /* + scrollbar theme + values: string (see CSS/plugin URI for a list of ready-to-use themes) + */ + theme:"light", + /* + user defined callback functions + */ + callbacks:{ + /* + Available callbacks: + callback default + ------------------------------------- + onCreate null + onInit null + onScrollStart null + onScroll null + onTotalScroll null + onTotalScrollBack null + whileScrolling null + onOverflowY null + onOverflowX null + onOverflowYNone null + onOverflowXNone null + onImageLoad null + onSelectorChange null + onBeforeUpdate null + onUpdate null + */ + onTotalScrollOffset:0, + onTotalScrollBackOffset:0, + alwaysTriggerOffsets:true + } + /* + add scrollbar(s) on all elements matching the current selector, now and in the future + values: boolean, string + string values: "on" (enable), "once" (disable after first invocation), "off" (disable) + liveSelector values: string (selector) + option default + ------------------------------------- + live false + liveSelector null + */ + }, + + + + + + /* + ---------------------------------------- + VARS, CONSTANTS + ---------------------------------------- + */ + + totalInstances=0, /* plugin instances amount */ + liveTimers={}, /* live option timers */ + oldIE=(window.attachEvent && !window.addEventListener) ? 1 : 0, /* detect IE < 9 */ + touchActive=false,touchable, /* global touch vars (for touch and pointer events) */ + /* general plugin classes */ + classes=[ + "mCSB_dragger_onDrag","mCSB_scrollTools_onDrag","mCS_img_loaded","mCS_disabled","mCS_destroyed","mCS_no_scrollbar", + "mCS-autoHide","mCS-dir-rtl","mCS_no_scrollbar_y","mCS_no_scrollbar_x","mCS_y_hidden","mCS_x_hidden","mCSB_draggerContainer", + "mCSB_buttonUp","mCSB_buttonDown","mCSB_buttonLeft","mCSB_buttonRight" + ], + + + + + + /* + ---------------------------------------- + METHODS + ---------------------------------------- + */ + + methods={ + + /* + plugin initialization method + creates the scrollbar(s), plugin data object and options + ---------------------------------------- + */ + + init:function(options){ + + var options=$.extend(true,{},defaults,options), + selector=_selector.call(this); /* validate selector */ + + /* + if live option is enabled, monitor for elements matching the current selector and + apply scrollbar(s) when found (now and in the future) + */ + if(options.live){ + var liveSelector=options.liveSelector || this.selector || defaultSelector, /* live selector(s) */ + $liveSelector=$(liveSelector); /* live selector(s) as jquery object */ + if(options.live==="off"){ + /* + disable live if requested + usage: $(selector).mCustomScrollbar({live:"off"}); + */ + removeLiveTimers(liveSelector); + return; + } + liveTimers[liveSelector]=setTimeout(function(){ + /* call mCustomScrollbar fn on live selector(s) every half-second */ + $liveSelector.mCustomScrollbar(options); + if(options.live==="once" && $liveSelector.length){ + /* disable live after first invocation */ + removeLiveTimers(liveSelector); + } + },500); + }else{ + removeLiveTimers(liveSelector); + } + + /* options backward compatibility (for versions < 3.0.0) and normalization */ + options.setWidth=(options.set_width) ? options.set_width : options.setWidth; + options.setHeight=(options.set_height) ? options.set_height : options.setHeight; + options.axis=(options.horizontalScroll) ? "x" : _findAxis(options.axis); + options.scrollInertia=options.scrollInertia>0 && options.scrollInertia<17 ? 17 : options.scrollInertia; + if(typeof options.mouseWheel!=="object" && options.mouseWheel==true){ /* old school mouseWheel option (non-object) */ + options.mouseWheel={enable:true,scrollAmount:"auto",axis:"y",preventDefault:false,deltaFactor:"auto",normalizeDelta:false,invert:false} + } + options.mouseWheel.scrollAmount=!options.mouseWheelPixels ? options.mouseWheel.scrollAmount : options.mouseWheelPixels; + options.mouseWheel.normalizeDelta=!options.advanced.normalizeMouseWheelDelta ? options.mouseWheel.normalizeDelta : options.advanced.normalizeMouseWheelDelta; + options.scrollButtons.scrollType=_findScrollButtonsType(options.scrollButtons.scrollType); + + _theme(options); /* theme-specific options */ + + /* plugin constructor */ + return $(selector).each(function(){ + + var $this=$(this); + + if(!$this.data(pluginPfx)){ /* prevent multiple instantiations */ + + /* store options and create objects in jquery data */ + $this.data(pluginPfx,{ + idx:++totalInstances, /* instance index */ + opt:options, /* options */ + scrollRatio:{y:null,x:null}, /* scrollbar to content ratio */ + overflowed:null, /* overflowed axis */ + contentReset:{y:null,x:null}, /* object to check when content resets */ + bindEvents:false, /* object to check if events are bound */ + tweenRunning:false, /* object to check if tween is running */ + sequential:{}, /* sequential scrolling object */ + langDir:$this.css("direction"), /* detect/store direction (ltr or rtl) */ + cbOffsets:null, /* object to check whether callback offsets always trigger */ + /* + object to check how scrolling events where last triggered + "internal" (default - triggered by this script), "external" (triggered by other scripts, e.g. via scrollTo method) + usage: object.data("mCS").trigger + */ + trigger:null, + /* + object to check for changes in elements in order to call the update method automatically + */ + poll:{size:{o:0,n:0},img:{o:0,n:0},change:{o:0,n:0}} + }); + + var d=$this.data(pluginPfx),o=d.opt, + /* HTML data attributes */ + htmlDataAxis=$this.data("mcs-axis"),htmlDataSbPos=$this.data("mcs-scrollbar-position"),htmlDataTheme=$this.data("mcs-theme"); + + if(htmlDataAxis){o.axis=htmlDataAxis;} /* usage example: data-mcs-axis="y" */ + if(htmlDataSbPos){o.scrollbarPosition=htmlDataSbPos;} /* usage example: data-mcs-scrollbar-position="outside" */ + if(htmlDataTheme){ /* usage example: data-mcs-theme="minimal" */ + o.theme=htmlDataTheme; + _theme(o); /* theme-specific options */ + } + + _pluginMarkup.call(this); /* add plugin markup */ + + if(d && o.callbacks.onCreate && typeof o.callbacks.onCreate==="function"){o.callbacks.onCreate.call(this);} /* callbacks: onCreate */ + + $("#mCSB_"+d.idx+"_container img:not(."+classes[2]+")").addClass(classes[2]); /* flag loaded images */ + + methods.update.call(null,$this); /* call the update method */ + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin update method + updates content and scrollbar(s) values, events and status + ---------------------------------------- + usage: $(selector).mCustomScrollbar("update"); + */ + + update:function(el,cb){ + + var selector=el || _selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + var d=$this.data(pluginPfx),o=d.opt, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; + + if(!mCSB_container.length){return;} + + if(d.tweenRunning){_stop($this);} /* stop any running tweens while updating */ + + if(cb && d && o.callbacks.onBeforeUpdate && typeof o.callbacks.onBeforeUpdate==="function"){o.callbacks.onBeforeUpdate.call(this);} /* callbacks: onBeforeUpdate */ + + /* if element was disabled or destroyed, remove class(es) */ + if($this.hasClass(classes[3])){$this.removeClass(classes[3]);} + if($this.hasClass(classes[4])){$this.removeClass(classes[4]);} + + /* css flexbox fix, detect/set max-height */ + mCustomScrollBox.css("max-height","none"); + if(mCustomScrollBox.height()!==$this.height()){mCustomScrollBox.css("max-height",$this.height());} + + _expandContentHorizontally.call(this); /* expand content horizontally */ + + if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){ + mCSB_container.css("width",_contentWidth(mCSB_container)); + } + + d.overflowed=_overflowed.call(this); /* determine if scrolling is required */ + + _scrollbarVisibility.call(this); /* show/hide scrollbar(s) */ + + /* auto-adjust scrollbar dragger length analogous to content */ + if(o.autoDraggerLength){_setDraggerLength.call(this);} + + _scrollRatio.call(this); /* calculate and store scrollbar to content ratio */ + + _bindEvents.call(this); /* bind scrollbar events */ + + /* reset scrolling position and/or events */ + var to=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)]; + if(o.axis!=="x"){ /* y/yx axis */ + if(!d.overflowed[0]){ /* y scrolling is not required */ + _resetContentPosition.call(this); /* reset content position */ + if(o.axis==="y"){ + _unbindEvents.call(this); + }else if(o.axis==="yx" && d.overflowed[1]){ + _scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"}); + } + }else if(mCSB_dragger[0].height()>mCSB_dragger[0].parent().height()){ + _resetContentPosition.call(this); /* reset content position */ + }else{ /* y scrolling is required */ + _scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"}); + d.contentReset.y=null; + } + } + if(o.axis!=="y"){ /* x/yx axis */ + if(!d.overflowed[1]){ /* x scrolling is not required */ + _resetContentPosition.call(this); /* reset content position */ + if(o.axis==="x"){ + _unbindEvents.call(this); + }else if(o.axis==="yx" && d.overflowed[0]){ + _scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"}); + } + }else if(mCSB_dragger[1].width()>mCSB_dragger[1].parent().width()){ + _resetContentPosition.call(this); /* reset content position */ + }else{ /* x scrolling is required */ + _scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"}); + d.contentReset.x=null; + } + } + + /* callbacks: onImageLoad, onSelectorChange, onUpdate */ + if(cb && d){ + if(cb===2 && o.callbacks.onImageLoad && typeof o.callbacks.onImageLoad==="function"){ + o.callbacks.onImageLoad.call(this); + }else if(cb===3 && o.callbacks.onSelectorChange && typeof o.callbacks.onSelectorChange==="function"){ + o.callbacks.onSelectorChange.call(this); + }else if(o.callbacks.onUpdate && typeof o.callbacks.onUpdate==="function"){ + o.callbacks.onUpdate.call(this); + } + } + + _autoUpdate.call(this); /* initialize automatic updating (for dynamic content, fluid layouts etc.) */ + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin scrollTo method + triggers a scrolling event to a specific value + ---------------------------------------- + usage: $(selector).mCustomScrollbar("scrollTo",value,options); + */ + + scrollTo:function(val,options){ + + /* prevent silly things like $(selector).mCustomScrollbar("scrollTo",undefined); */ + if(typeof val=="undefined" || val==null){return;} + + var selector=_selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + var d=$this.data(pluginPfx),o=d.opt, + /* method default options */ + methodDefaults={ + trigger:"external", /* method is by default triggered externally (e.g. from other scripts) */ + scrollInertia:o.scrollInertia, /* scrolling inertia (animation duration) */ + scrollEasing:"mcsEaseInOut", /* animation easing */ + moveDragger:false, /* move dragger instead of content */ + timeout:60, /* scroll-to delay */ + callbacks:true, /* enable/disable callbacks */ + onStart:true, + onUpdate:true, + onComplete:true + }, + methodOptions=$.extend(true,{},methodDefaults,options), + to=_arr.call(this,val),dur=methodOptions.scrollInertia>0 && methodOptions.scrollInertia<17 ? 17 : methodOptions.scrollInertia; + + /* translate yx values to actual scroll-to positions */ + to[0]=_to.call(this,to[0],"y"); + to[1]=_to.call(this,to[1],"x"); + + /* + check if scroll-to value moves the dragger instead of content. + Only pixel values apply on dragger (e.g. 100, "100px", "-=100" etc.) + */ + if(methodOptions.moveDragger){ + to[0]*=d.scrollRatio.y; + to[1]*=d.scrollRatio.x; + } + + methodOptions.dur=_isTabHidden() ? 0 : dur; //skip animations if browser tab is hidden + + setTimeout(function(){ + /* do the scrolling */ + if(to[0]!==null && typeof to[0]!=="undefined" && o.axis!=="x" && d.overflowed[0]){ /* scroll y */ + methodOptions.dir="y"; + methodOptions.overwrite="all"; + _scrollTo($this,to[0].toString(),methodOptions); + } + if(to[1]!==null && typeof to[1]!=="undefined" && o.axis!=="y" && d.overflowed[1]){ /* scroll x */ + methodOptions.dir="x"; + methodOptions.overwrite="none"; + _scrollTo($this,to[1].toString(),methodOptions); + } + },methodOptions.timeout); + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin stop method + stops scrolling animation + ---------------------------------------- + usage: $(selector).mCustomScrollbar("stop"); + */ + stop:function(){ + + var selector=_selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + _stop($this); + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin disable method + temporarily disables the scrollbar(s) + ---------------------------------------- + usage: $(selector).mCustomScrollbar("disable",reset); + reset (boolean): resets content position to 0 + */ + disable:function(r){ + + var selector=_selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + var d=$this.data(pluginPfx); + + _autoUpdate.call(this,"remove"); /* remove automatic updating */ + + _unbindEvents.call(this); /* unbind events */ + + if(r){_resetContentPosition.call(this);} /* reset content position */ + + _scrollbarVisibility.call(this,true); /* show/hide scrollbar(s) */ + + $this.addClass(classes[3]); /* add disable class */ + + } + + }); + + }, + /* ---------------------------------------- */ + + + + /* + plugin destroy method + completely removes the scrollbar(s) and returns the element to its original state + ---------------------------------------- + usage: $(selector).mCustomScrollbar("destroy"); + */ + destroy:function(){ + + var selector=_selector.call(this); /* validate selector */ + + return $(selector).each(function(){ + + var $this=$(this); + + if($this.data(pluginPfx)){ /* check if plugin has initialized */ + + var d=$this.data(pluginPfx),o=d.opt, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + scrollbar=$(".mCSB_"+d.idx+"_scrollbar"); + + if(o.live){removeLiveTimers(o.liveSelector || $(selector).selector);} /* remove live timers */ + + _autoUpdate.call(this,"remove"); /* remove automatic updating */ + + _unbindEvents.call(this); /* unbind events */ + + _resetContentPosition.call(this); /* reset content position */ + + $this.removeData(pluginPfx); /* remove plugin data object */ + + _delete(this,"mcs"); /* delete callbacks object */ + + /* remove plugin markup */ + scrollbar.remove(); /* remove scrollbar(s) first (those can be either inside or outside plugin's inner wrapper) */ + mCSB_container.find("img."+classes[2]).removeClass(classes[2]); /* remove loaded images flag */ + mCustomScrollBox.replaceWith(mCSB_container.contents()); /* replace plugin's inner wrapper with the original content */ + /* remove plugin classes from the element and add destroy class */ + $this.removeClass(pluginNS+" _"+pluginPfx+"_"+d.idx+" "+classes[6]+" "+classes[7]+" "+classes[5]+" "+classes[3]).addClass(classes[4]); + + } + + }); + + } + /* ---------------------------------------- */ + + }, + + + + + + /* + ---------------------------------------- + FUNCTIONS + ---------------------------------------- + */ + + /* validates selector (if selector is invalid or undefined uses the default one) */ + _selector=function(){ + return (typeof $(this)!=="object" || $(this).length<1) ? defaultSelector : this; + }, + /* -------------------- */ + + + /* changes options according to theme */ + _theme=function(obj){ + var fixedSizeScrollbarThemes=["rounded","rounded-dark","rounded-dots","rounded-dots-dark"], + nonExpandedScrollbarThemes=["rounded-dots","rounded-dots-dark","3d","3d-dark","3d-thick","3d-thick-dark","inset","inset-dark","inset-2","inset-2-dark","inset-3","inset-3-dark"], + disabledScrollButtonsThemes=["minimal","minimal-dark"], + enabledAutoHideScrollbarThemes=["minimal","minimal-dark"], + scrollbarPositionOutsideThemes=["minimal","minimal-dark"]; + obj.autoDraggerLength=$.inArray(obj.theme,fixedSizeScrollbarThemes) > -1 ? false : obj.autoDraggerLength; + obj.autoExpandScrollbar=$.inArray(obj.theme,nonExpandedScrollbarThemes) > -1 ? false : obj.autoExpandScrollbar; + obj.scrollButtons.enable=$.inArray(obj.theme,disabledScrollButtonsThemes) > -1 ? false : obj.scrollButtons.enable; + obj.autoHideScrollbar=$.inArray(obj.theme,enabledAutoHideScrollbarThemes) > -1 ? true : obj.autoHideScrollbar; + obj.scrollbarPosition=$.inArray(obj.theme,scrollbarPositionOutsideThemes) > -1 ? "outside" : obj.scrollbarPosition; + }, + /* -------------------- */ + + + /* live option timers removal */ + removeLiveTimers=function(selector){ + if(liveTimers[selector]){ + clearTimeout(liveTimers[selector]); + _delete(liveTimers,selector); + } + }, + /* -------------------- */ + + + /* normalizes axis option to valid values: "y", "x", "yx" */ + _findAxis=function(val){ + return (val==="yx" || val==="xy" || val==="auto") ? "yx" : (val==="x" || val==="horizontal") ? "x" : "y"; + }, + /* -------------------- */ + + + /* normalizes scrollButtons.scrollType option to valid values: "stepless", "stepped" */ + _findScrollButtonsType=function(val){ + return (val==="stepped" || val==="pixels" || val==="step" || val==="click") ? "stepped" : "stepless"; + }, + /* -------------------- */ + + + /* generates plugin markup */ + _pluginMarkup=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + expandClass=o.autoExpandScrollbar ? " "+classes[1]+"_expand" : "", + scrollbar=["
    ","
    "], + wrapperClass=o.axis==="yx" ? "mCSB_vertical_horizontal" : o.axis==="x" ? "mCSB_horizontal" : "mCSB_vertical", + scrollbars=o.axis==="yx" ? scrollbar[0]+scrollbar[1] : o.axis==="x" ? scrollbar[1] : scrollbar[0], + contentWrapper=o.axis==="yx" ? "
    " : "", + autoHideClass=o.autoHideScrollbar ? " "+classes[6] : "", + scrollbarDirClass=(o.axis!=="x" && d.langDir==="rtl") ? " "+classes[7] : ""; + if(o.setWidth){$this.css("width",o.setWidth);} /* set element width */ + if(o.setHeight){$this.css("height",o.setHeight);} /* set element height */ + o.setLeft=(o.axis!=="y" && d.langDir==="rtl") ? "989999px" : o.setLeft; /* adjust left position for rtl direction */ + $this.addClass(pluginNS+" _"+pluginPfx+"_"+d.idx+autoHideClass+scrollbarDirClass).wrapInner("
    "); + var mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"); + if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){ + mCSB_container.css("width",_contentWidth(mCSB_container)); + } + if(o.scrollbarPosition==="outside"){ + if($this.css("position")==="static"){ /* requires elements with non-static position */ + $this.css("position","relative"); + } + $this.css("overflow","visible"); + mCustomScrollBox.addClass("mCSB_outside").after(scrollbars); + }else{ + mCustomScrollBox.addClass("mCSB_inside").append(scrollbars); + mCSB_container.wrap(contentWrapper); + } + _scrollButtons.call(this); /* add scrollbar buttons */ + /* minimum dragger length */ + var mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; + mCSB_dragger[0].css("min-height",mCSB_dragger[0].height()); + mCSB_dragger[1].css("min-width",mCSB_dragger[1].width()); + }, + /* -------------------- */ + + + /* calculates content width */ + _contentWidth=function(el){ + var val=[el[0].scrollWidth,Math.max.apply(Math,el.children().map(function(){return $(this).outerWidth(true);}).get())],w=el.parent().width(); + return val[0]>w ? val[0] : val[1]>w ? val[1] : "100%"; + }, + /* -------------------- */ + + + /* expands content horizontally */ + _expandContentHorizontally=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCSB_container=$("#mCSB_"+d.idx+"_container"); + if(o.advanced.autoExpandHorizontalScroll && o.axis!=="y"){ + /* calculate scrollWidth */ + mCSB_container.css({"width":"auto","min-width":0,"overflow-x":"scroll"}); + var w=Math.ceil(mCSB_container[0].scrollWidth); + if(o.advanced.autoExpandHorizontalScroll===3 || (o.advanced.autoExpandHorizontalScroll!==2 && w>mCSB_container.parent().width())){ + mCSB_container.css({"width":w,"min-width":"100%","overflow-x":"inherit"}); + }else{ + /* + wrap content with an infinite width div and set its position to absolute and width to auto. + Setting width to auto before calculating the actual width is important! + We must let the browser set the width as browser zoom values are impossible to calculate. + */ + mCSB_container.css({"overflow-x":"inherit","position":"absolute"}) + .wrap("
    ") + .css({ /* set actual width, original position and un-wrap */ + /* + get the exact width (with decimals) and then round-up. + Using jquery outerWidth() will round the width value which will mess up with inner elements that have non-integer width + */ + "width":(Math.ceil(mCSB_container[0].getBoundingClientRect().right+0.4)-Math.floor(mCSB_container[0].getBoundingClientRect().left)), + "min-width":"100%", + "position":"relative" + }).unwrap(); + } + } + }, + /* -------------------- */ + + + /* adds scrollbar buttons */ + _scrollButtons=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCSB_scrollTools=$(".mCSB_"+d.idx+"_scrollbar:first"), + tabindex=!_isNumeric(o.scrollButtons.tabindex) ? "" : "tabindex='"+o.scrollButtons.tabindex+"'", + btnHTML=[ + "", + "", + "", + "" + ], + btn=[(o.axis==="x" ? btnHTML[2] : btnHTML[0]),(o.axis==="x" ? btnHTML[3] : btnHTML[1]),btnHTML[2],btnHTML[3]]; + if(o.scrollButtons.enable){ + mCSB_scrollTools.prepend(btn[0]).append(btn[1]).next(".mCSB_scrollTools").prepend(btn[2]).append(btn[3]); + } + }, + /* -------------------- */ + + + /* auto-adjusts scrollbar dragger length */ + _setDraggerLength=function(){ + var $this=$(this),d=$this.data(pluginPfx), + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], + ratio=[mCustomScrollBox.height()/mCSB_container.outerHeight(false),mCustomScrollBox.width()/mCSB_container.outerWidth(false)], + l=[ + parseInt(mCSB_dragger[0].css("min-height")),Math.round(ratio[0]*mCSB_dragger[0].parent().height()), + parseInt(mCSB_dragger[1].css("min-width")),Math.round(ratio[1]*mCSB_dragger[1].parent().width()) + ], + h=oldIE && (l[1]contentHeight){contentHeight=h;} + if(w>contentWidth){contentWidth=w;} + return [contentHeight>mCustomScrollBox.height(),contentWidth>mCustomScrollBox.width()]; + }, + /* -------------------- */ + + + /* resets content position to 0 */ + _resetContentPosition=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")]; + _stop($this); /* stop any current scrolling before resetting */ + if((o.axis!=="x" && !d.overflowed[0]) || (o.axis==="y" && d.overflowed[0])){ /* reset y */ + mCSB_dragger[0].add(mCSB_container).css("top",0); + _scrollTo($this,"_resetY"); + } + if((o.axis!=="y" && !d.overflowed[1]) || (o.axis==="x" && d.overflowed[1])){ /* reset x */ + var cx=dx=0; + if(d.langDir==="rtl"){ /* adjust left position for rtl direction */ + cx=mCustomScrollBox.width()-mCSB_container.outerWidth(false); + dx=Math.abs(cx/d.scrollRatio.x); + } + mCSB_container.css("left",cx); + mCSB_dragger[1].css("left",dx); + _scrollTo($this,"_resetX"); + } + }, + /* -------------------- */ + + + /* binds scrollbar events */ + _bindEvents=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt; + if(!d.bindEvents){ /* check if events are already bound */ + _draggable.call(this); + if(o.contentTouchScroll){_contentDraggable.call(this);} + _selectable.call(this); + if(o.mouseWheel.enable){ /* bind mousewheel fn when plugin is available */ + function _mwt(){ + mousewheelTimeout=setTimeout(function(){ + if(!$.event.special.mousewheel){ + _mwt(); + }else{ + clearTimeout(mousewheelTimeout); + _mousewheel.call($this[0]); + } + },100); + } + var mousewheelTimeout; + _mwt(); + } + _draggerRail.call(this); + _wrapperScroll.call(this); + if(o.advanced.autoScrollOnFocus){_focus.call(this);} + if(o.scrollButtons.enable){_buttons.call(this);} + if(o.keyboard.enable){_keyboard.call(this);} + d.bindEvents=true; + } + }, + /* -------------------- */ + + + /* unbinds scrollbar events */ + _unbindEvents=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + sb=".mCSB_"+d.idx+"_scrollbar", + sel=$("#mCSB_"+d.idx+",#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,"+sb+" ."+classes[12]+",#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal,"+sb+">a"), + mCSB_container=$("#mCSB_"+d.idx+"_container"); + if(o.advanced.releaseDraggableSelectors){sel.add($(o.advanced.releaseDraggableSelectors));} + if(o.advanced.extraDraggableSelectors){sel.add($(o.advanced.extraDraggableSelectors));} + if(d.bindEvents){ /* check if events are bound */ + /* unbind namespaced events from document/selectors */ + $(document).add($(!_canAccessIFrame() || top.document)).unbind("."+namespace); + sel.each(function(){ + $(this).unbind("."+namespace); + }); + /* clear and delete timeouts/objects */ + clearTimeout($this[0]._focusTimeout); _delete($this[0],"_focusTimeout"); + clearTimeout(d.sequential.step); _delete(d.sequential,"step"); + clearTimeout(mCSB_container[0].onCompleteTimeout); _delete(mCSB_container[0],"onCompleteTimeout"); + d.bindEvents=false; + } + }, + /* -------------------- */ + + + /* toggles scrollbar visibility */ + _scrollbarVisibility=function(disabled){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + contentWrapper=$("#mCSB_"+d.idx+"_container_wrapper"), + content=contentWrapper.length ? contentWrapper : $("#mCSB_"+d.idx+"_container"), + scrollbar=[$("#mCSB_"+d.idx+"_scrollbar_vertical"),$("#mCSB_"+d.idx+"_scrollbar_horizontal")], + mCSB_dragger=[scrollbar[0].find(".mCSB_dragger"),scrollbar[1].find(".mCSB_dragger")]; + if(o.axis!=="x"){ + if(d.overflowed[0] && !disabled){ + scrollbar[0].add(mCSB_dragger[0]).add(scrollbar[0].children("a")).css("display","block"); + content.removeClass(classes[8]+" "+classes[10]); + }else{ + if(o.alwaysShowScrollbar){ + if(o.alwaysShowScrollbar!==2){mCSB_dragger[0].css("display","none");} + content.removeClass(classes[10]); + }else{ + scrollbar[0].css("display","none"); + content.addClass(classes[10]); + } + content.addClass(classes[8]); + } + } + if(o.axis!=="y"){ + if(d.overflowed[1] && !disabled){ + scrollbar[1].add(mCSB_dragger[1]).add(scrollbar[1].children("a")).css("display","block"); + content.removeClass(classes[9]+" "+classes[11]); + }else{ + if(o.alwaysShowScrollbar){ + if(o.alwaysShowScrollbar!==2){mCSB_dragger[1].css("display","none");} + content.removeClass(classes[11]); + }else{ + scrollbar[1].css("display","none"); + content.addClass(classes[11]); + } + content.addClass(classes[9]); + } + } + if(!d.overflowed[0] && !d.overflowed[1]){ + $this.addClass(classes[5]); + }else{ + $this.removeClass(classes[5]); + } + }, + /* -------------------- */ + + + /* returns input coordinates of pointer, touch and mouse events (relative to document) */ + _coordinates=function(e){ + var t=e.type,o=e.target.ownerDocument!==document && frameElement!==null ? [$(frameElement).offset().top,$(frameElement).offset().left] : null, + io=_canAccessIFrame() && e.target.ownerDocument!==top.document && frameElement!==null ? [$(e.view.frameElement).offset().top,$(e.view.frameElement).offset().left] : [0,0]; + switch(t){ + case "pointerdown": case "MSPointerDown": case "pointermove": case "MSPointerMove": case "pointerup": case "MSPointerUp": + return o ? [e.originalEvent.pageY-o[0]+io[0],e.originalEvent.pageX-o[1]+io[1],false] : [e.originalEvent.pageY,e.originalEvent.pageX,false]; + break; + case "touchstart": case "touchmove": case "touchend": + var touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0], + touches=e.originalEvent.touches.length || e.originalEvent.changedTouches.length; + return e.target.ownerDocument!==document ? [touch.screenY,touch.screenX,touches>1] : [touch.pageY,touch.pageX,touches>1]; + break; + default: + return o ? [e.pageY-o[0]+io[0],e.pageX-o[1]+io[1],false] : [e.pageY,e.pageX,false]; + } + }, + /* -------------------- */ + + + /* + SCROLLBAR DRAG EVENTS + scrolls content via scrollbar dragging + */ + _draggable=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + draggerId=["mCSB_"+d.idx+"_dragger_vertical","mCSB_"+d.idx+"_dragger_horizontal"], + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCSB_dragger=$("#"+draggerId[0]+",#"+draggerId[1]), + draggable,dragY,dragX, + rds=o.advanced.releaseDraggableSelectors ? mCSB_dragger.add($(o.advanced.releaseDraggableSelectors)) : mCSB_dragger, + eds=o.advanced.extraDraggableSelectors ? $(!_canAccessIFrame() || top.document).add($(o.advanced.extraDraggableSelectors)) : $(!_canAccessIFrame() || top.document); + mCSB_dragger.bind("contextmenu."+namespace,function(e){ + e.preventDefault(); //prevent right click + }).bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){ + e.stopImmediatePropagation(); + e.preventDefault(); + if(!_mouseBtnLeft(e)){return;} /* left mouse button only */ + touchActive=true; + if(oldIE){document.onselectstart=function(){return false;}} /* disable text selection for IE < 9 */ + _iframe.call(mCSB_container,false); /* enable scrollbar dragging over iframes by disabling their events */ + _stop($this); + draggable=$(this); + var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left, + h=draggable.height()+offset.top,w=draggable.width()+offset.left; + if(y0 && x0){ + dragY=y; + dragX=x; + } + _onDragClasses(draggable,"active",o.autoExpandScrollbar); + }).bind("touchmove."+namespace,function(e){ + e.stopImmediatePropagation(); + e.preventDefault(); + var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left; + _drag(dragY,dragX,y,x); + }); + $(document).add(eds).bind("mousemove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace,function(e){ + if(draggable){ + var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left; + if(dragY===y && dragX===x){return;} /* has it really moved? */ + _drag(dragY,dragX,y,x); + } + }).add(rds).bind("mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){ + if(draggable){ + _onDragClasses(draggable,"active",o.autoExpandScrollbar); + draggable=null; + } + touchActive=false; + if(oldIE){document.onselectstart=null;} /* enable text selection for IE < 9 */ + _iframe.call(mCSB_container,true); /* enable iframes events */ + }); + function _drag(dragY,dragX,y,x){ + mCSB_container[0].idleTimer=o.scrollInertia<233 ? 250 : 0; + if(draggable.attr("id")===draggerId[1]){ + var dir="x",to=((draggable[0].offsetLeft-dragX)+x)*d.scrollRatio.x; + }else{ + var dir="y",to=((draggable[0].offsetTop-dragY)+y)*d.scrollRatio.y; + } + _scrollTo($this,to.toString(),{dir:dir,drag:true}); + } + }, + /* -------------------- */ + + + /* + TOUCH SWIPE EVENTS + scrolls content via touch swipe + Emulates the native touch-swipe scrolling with momentum found in iOS, Android and WP devices + */ + _contentDraggable=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], + draggable,dragY,dragX,touchStartY,touchStartX,touchMoveY=[],touchMoveX=[],startTime,runningTime,endTime,distance,speed,amount, + durA=0,durB,overwrite=o.axis==="yx" ? "none" : "all",touchIntent=[],touchDrag,docDrag, + iframe=mCSB_container.find("iframe"), + events=[ + "touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace, //start + "touchmove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace, //move + "touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace //end + ], + touchAction=document.body.style.touchAction!==undefined && document.body.style.touchAction!==""; + mCSB_container.bind(events[0],function(e){ + _onTouchstart(e); + }).bind(events[1],function(e){ + _onTouchmove(e); + }); + mCustomScrollBox.bind(events[0],function(e){ + _onTouchstart2(e); + }).bind(events[2],function(e){ + _onTouchend(e); + }); + if(iframe.length){ + iframe.each(function(){ + $(this).bind("load",function(){ + /* bind events on accessible iframes */ + if(_canAccessIFrame(this)){ + $(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){ + _onTouchstart(e); + _onTouchstart2(e); + }).bind(events[1],function(e){ + _onTouchmove(e); + }).bind(events[2],function(e){ + _onTouchend(e); + }); + } + }); + }); + } + function _onTouchstart(e){ + if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){touchable=0; return;} + touchable=1; touchDrag=0; docDrag=0; draggable=1; + $this.removeClass("mCS_touch_action"); + var offset=mCSB_container.offset(); + dragY=_coordinates(e)[0]-offset.top; + dragX=_coordinates(e)[1]-offset.left; + touchIntent=[_coordinates(e)[0],_coordinates(e)[1]]; + } + function _onTouchmove(e){ + if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){return;} + if(!o.documentTouchScroll){e.preventDefault();} + e.stopImmediatePropagation(); + if(docDrag && !touchDrag){return;} + if(draggable){ + runningTime=_getTime(); + var offset=mCustomScrollBox.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left, + easing="mcsLinearOut"; + touchMoveY.push(y); + touchMoveX.push(x); + touchIntent[2]=Math.abs(_coordinates(e)[0]-touchIntent[0]); touchIntent[3]=Math.abs(_coordinates(e)[1]-touchIntent[1]); + if(d.overflowed[0]){ + var limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(), + prevent=((dragY-y)>0 && (y-dragY)>-(limit*d.scrollRatio.y) && (touchIntent[3]*20 && (x-dragX)>-(limitX*d.scrollRatio.x) && (touchIntent[2]*230){return;} + speed=1000/(endTime-startTime); + var easing="mcsEaseOut",slow=speed<2.5, + diff=slow ? [touchMoveY[touchMoveY.length-2],touchMoveX[touchMoveX.length-2]] : [0,0]; + distance=slow ? [(y-diff[0]),(x-diff[1])] : [y-touchStartY,x-touchStartX]; + var absDistance=[Math.abs(distance[0]),Math.abs(distance[1])]; + speed=slow ? [Math.abs(distance[0]/4),Math.abs(distance[1]/4)] : [speed,speed]; + var a=[ + Math.abs(mCSB_container[0].offsetTop)-(distance[0]*_m((absDistance[0]/speed[0]),speed[0])), + Math.abs(mCSB_container[0].offsetLeft)-(distance[1]*_m((absDistance[1]/speed[1]),speed[1])) + ]; + amount=o.axis==="yx" ? [a[0],a[1]] : o.axis==="x" ? [null,a[1]] : [a[0],null]; + durB=[(absDistance[0]*4)+o.scrollInertia,(absDistance[1]*4)+o.scrollInertia]; + var md=parseInt(o.contentTouchScroll) || 0; /* absolute minimum distance required */ + amount[0]=absDistance[0]>md ? amount[0] : 0; + amount[1]=absDistance[1]>md ? amount[1] : 0; + if(d.overflowed[0]){_drag(amount[0],durB[0],easing,"y",overwrite,false);} + if(d.overflowed[1]){_drag(amount[1],durB[1],easing,"x",overwrite,false);} + } + function _m(ds,s){ + var r=[s*1.5,s*2,s/1.5,s/2]; + if(ds>90){ + return s>4 ? r[0] : r[3]; + }else if(ds>60){ + return s>3 ? r[3] : r[2]; + }else if(ds>30){ + return s>8 ? r[1] : s>6 ? r[0] : s>4 ? s : r[2]; + }else{ + return s>8 ? s : r[3]; + } + } + function _drag(amount,dur,easing,dir,overwrite,drag){ + if(!amount){return;} + _scrollTo($this,amount.toString(),{dur:dur,scrollEasing:easing,dir:dir,overwrite:overwrite,drag:drag}); + } + }, + /* -------------------- */ + + + /* + SELECT TEXT EVENTS + scrolls content when text is selected + */ + _selectable=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential, + namespace=pluginPfx+"_"+d.idx, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + action; + mCSB_container.bind("mousedown."+namespace,function(e){ + if(touchable){return;} + if(!action){action=1; touchActive=true;} + }).add(document).bind("mousemove."+namespace,function(e){ + if(!touchable && action && _sel()){ + var offset=mCSB_container.offset(), + y=_coordinates(e)[0]-offset.top+mCSB_container[0].offsetTop,x=_coordinates(e)[1]-offset.left+mCSB_container[0].offsetLeft; + if(y>0 && y0 && xwrapper.height()){ + _seq("on",40); + } + } + if(o.axis!=="y" && d.overflowed[1]){ + if(x<0){ + _seq("on",37); + }else if(x>wrapper.width()){ + _seq("on",39); + } + } + } + } + }).bind("mouseup."+namespace+" dragend."+namespace,function(e){ + if(touchable){return;} + if(action){action=0; _seq("off",null);} + touchActive=false; + }); + function _sel(){ + return window.getSelection ? window.getSelection().toString() : + document.selection && document.selection.type!="Control" ? document.selection.createRange().text : 0; + } + function _seq(a,c,s){ + seq.type=s && action ? "stepped" : "stepless"; + seq.scrollAmount=10; + _sequentialScroll($this,a,c,"mcsLinearOut",s ? 60 : null); + } + }, + /* -------------------- */ + + + /* + MOUSE WHEEL EVENT + scrolls content via mouse-wheel + via mouse-wheel plugin (https://github.com/brandonaaron/jquery-mousewheel) + */ + _mousewheel=function(){ + if(!$(this).data(pluginPfx)){return;} /* Check if the scrollbar is ready to use mousewheel events (issue: #185) */ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")], + iframe=$("#mCSB_"+d.idx+"_container").find("iframe"); + if(iframe.length){ + iframe.each(function(){ + $(this).bind("load",function(){ + /* bind events on accessible iframes */ + if(_canAccessIFrame(this)){ + $(this.contentDocument || this.contentWindow.document).bind("mousewheel."+namespace,function(e,delta){ + _onMousewheel(e,delta); + }); + } + }); + }); + } + mCustomScrollBox.bind("mousewheel."+namespace,function(e,delta){ + _onMousewheel(e,delta); + }); + function _onMousewheel(e,delta){ + _stop($this); + if(_disableMousewheel($this,e.target)){return;} /* disables mouse-wheel when hovering specific elements */ + var deltaFactor=o.mouseWheel.deltaFactor!=="auto" ? parseInt(o.mouseWheel.deltaFactor) : (oldIE && e.deltaFactor<100) ? 100 : e.deltaFactor || 100, + dur=o.scrollInertia; + if(o.axis==="x" || o.mouseWheel.axis==="x"){ + var dir="x", + px=[Math.round(deltaFactor*d.scrollRatio.x),parseInt(o.mouseWheel.scrollAmount)], + amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.width() ? mCustomScrollBox.width()*0.9 : px[0], + contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetLeft), + draggerPos=mCSB_dragger[1][0].offsetLeft, + limit=mCSB_dragger[1].parent().width()-mCSB_dragger[1].width(), + dlt=o.mouseWheel.axis==="y" ? (e.deltaY || delta) : e.deltaX; + }else{ + var dir="y", + px=[Math.round(deltaFactor*d.scrollRatio.y),parseInt(o.mouseWheel.scrollAmount)], + amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.height() ? mCustomScrollBox.height()*0.9 : px[0], + contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetTop), + draggerPos=mCSB_dragger[0][0].offsetTop, + limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(), + dlt=e.deltaY || delta; + } + if((dir==="y" && !d.overflowed[0]) || (dir==="x" && !d.overflowed[1])){return;} + if(o.mouseWheel.invert || e.webkitDirectionInvertedFromDevice){dlt=-dlt;} + if(o.mouseWheel.normalizeDelta){dlt=dlt<0 ? -1 : 1;} + if((dlt>0 && draggerPos!==0) || (dlt<0 && draggerPos!==limit) || o.mouseWheel.preventDefault){ + e.stopImmediatePropagation(); + e.preventDefault(); + } + if(e.deltaFactor<5 && !o.mouseWheel.normalizeDelta){ + //very low deltaFactor values mean some kind of delta acceleration (e.g. osx trackpad), so adjusting scrolling accordingly + amount=e.deltaFactor; dur=17; + } + _scrollTo($this,(contentPos-(dlt*amount)).toString(),{dir:dir,dur:dur}); + } + }, + /* -------------------- */ + + + /* checks if iframe can be accessed */ + _canAccessIFrameCache=new Object(), + _canAccessIFrame=function(iframe){ + var result=false,cacheKey=false,html=null; + if(iframe===undefined){ + cacheKey="#empty"; + }else if($(iframe).attr("id")!==undefined){ + cacheKey=$(iframe).attr("id"); + } + if(cacheKey!==false && _canAccessIFrameCache[cacheKey]!==undefined){ + return _canAccessIFrameCache[cacheKey]; + } + if(!iframe){ + try{ + var doc=top.document; + html=doc.body.innerHTML; + }catch(err){/* do nothing */} + result=(html!==null); + }else{ + try{ + var doc=iframe.contentDocument || iframe.contentWindow.document; + html=doc.body.innerHTML; + }catch(err){/* do nothing */} + result=(html!==null); + } + if(cacheKey!==false){_canAccessIFrameCache[cacheKey]=result;} + return result; + }, + /* -------------------- */ + + + /* switches iframe's pointer-events property (drag, mousewheel etc. over cross-domain iframes) */ + _iframe=function(evt){ + var el=this.find("iframe"); + if(!el.length){return;} /* check if content contains iframes */ + var val=!evt ? "none" : "auto"; + el.css("pointer-events",val); /* for IE11, iframe's display property should not be "block" */ + }, + /* -------------------- */ + + + /* disables mouse-wheel when hovering specific elements like select, datalist etc. */ + _disableMousewheel=function(el,target){ + var tag=target.nodeName.toLowerCase(), + tags=el.data(pluginPfx).opt.mouseWheel.disableOver, + /* elements that require focus */ + focusTags=["select","textarea"]; + return $.inArray(tag,tags) > -1 && !($.inArray(tag,focusTags) > -1 && !$(target).is(":focus")); + }, + /* -------------------- */ + + + /* + DRAGGER RAIL CLICK EVENT + scrolls content via dragger rail + */ + _draggerRail=function(){ + var $this=$(this),d=$this.data(pluginPfx), + namespace=pluginPfx+"_"+d.idx, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + mCSB_draggerContainer=$(".mCSB_"+d.idx+"_scrollbar ."+classes[12]), + clickable; + mCSB_draggerContainer.bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){ + touchActive=true; + if(!$(e.target).hasClass("mCSB_dragger")){clickable=1;} + }).bind("touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){ + touchActive=false; + }).bind("click."+namespace,function(e){ + if(!clickable){return;} + clickable=0; + if($(e.target).hasClass(classes[12]) || $(e.target).hasClass("mCSB_draggerRail")){ + _stop($this); + var el=$(this),mCSB_dragger=el.find(".mCSB_dragger"); + if(el.parent(".mCSB_scrollTools_horizontal").length>0){ + if(!d.overflowed[1]){return;} + var dir="x", + clickDir=e.pageX>mCSB_dragger.offset().left ? -1 : 1, + to=Math.abs(mCSB_container[0].offsetLeft)-(clickDir*(wrapper.width()*0.9)); + }else{ + if(!d.overflowed[0]){return;} + var dir="y", + clickDir=e.pageY>mCSB_dragger.offset().top ? -1 : 1, + to=Math.abs(mCSB_container[0].offsetTop)-(clickDir*(wrapper.height()*0.9)); + } + _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); + } + }); + }, + /* -------------------- */ + + + /* + FOCUS EVENT + scrolls content via element focus (e.g. clicking an input, pressing TAB key etc.) + */ + _focus=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + namespace=pluginPfx+"_"+d.idx, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(); + mCSB_container.bind("focusin."+namespace,function(e){ + var el=$(document.activeElement), + nested=mCSB_container.find(".mCustomScrollBox").length, + dur=0; + if(!el.is(o.advanced.autoScrollOnFocus)){return;} + _stop($this); + clearTimeout($this[0]._focusTimeout); + $this[0]._focusTimer=nested ? (dur+17)*nested : 0; + $this[0]._focusTimeout=setTimeout(function(){ + var to=[_childPos(el)[0],_childPos(el)[1]], + contentPos=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft], + isVisible=[ + (contentPos[0]+to[0]>=0 && contentPos[0]+to[0]=0 && contentPos[0]+to[1]a"); + btn.bind("contextmenu."+namespace,function(e){ + e.preventDefault(); //prevent right click + }).bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace+" mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace+" mouseout."+namespace+" pointerout."+namespace+" MSPointerOut."+namespace+" click."+namespace,function(e){ + e.preventDefault(); + if(!_mouseBtnLeft(e)){return;} /* left mouse button only */ + var btnClass=$(this).attr("class"); + seq.type=o.scrollButtons.scrollType; + switch(e.type){ + case "mousedown": case "touchstart": case "pointerdown": case "MSPointerDown": + if(seq.type==="stepped"){return;} + touchActive=true; + d.tweenRunning=false; + _seq("on",btnClass); + break; + case "mouseup": case "touchend": case "pointerup": case "MSPointerUp": + case "mouseout": case "pointerout": case "MSPointerOut": + if(seq.type==="stepped"){return;} + touchActive=false; + if(seq.dir){_seq("off",btnClass);} + break; + case "click": + if(seq.type!=="stepped" || d.tweenRunning){return;} + _seq("on",btnClass); + break; + } + function _seq(a,c){ + seq.scrollAmount=o.scrollButtons.scrollAmount; + _sequentialScroll($this,a,c); + } + }); + }, + /* -------------------- */ + + + /* + KEYBOARD EVENTS + scrolls content via keyboard + Keys: up arrow, down arrow, left arrow, right arrow, PgUp, PgDn, Home, End + */ + _keyboard=function(){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential, + namespace=pluginPfx+"_"+d.idx, + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + editables="input,textarea,select,datalist,keygen,[contenteditable='true']", + iframe=mCSB_container.find("iframe"), + events=["blur."+namespace+" keydown."+namespace+" keyup."+namespace]; + if(iframe.length){ + iframe.each(function(){ + $(this).bind("load",function(){ + /* bind events on accessible iframes */ + if(_canAccessIFrame(this)){ + $(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){ + _onKeyboard(e); + }); + } + }); + }); + } + mCustomScrollBox.attr("tabindex","0").bind(events[0],function(e){ + _onKeyboard(e); + }); + function _onKeyboard(e){ + switch(e.type){ + case "blur": + if(d.tweenRunning && seq.dir){_seq("off",null);} + break; + case "keydown": case "keyup": + var code=e.keyCode ? e.keyCode : e.which,action="on"; + if((o.axis!=="x" && (code===38 || code===40)) || (o.axis!=="y" && (code===37 || code===39))){ + /* up (38), down (40), left (37), right (39) arrows */ + if(((code===38 || code===40) && !d.overflowed[0]) || ((code===37 || code===39) && !d.overflowed[1])){return;} + if(e.type==="keyup"){action="off";} + if(!$(document.activeElement).is(editables)){ + e.preventDefault(); + e.stopImmediatePropagation(); + _seq(action,code); + } + }else if(code===33 || code===34){ + /* PgUp (33), PgDn (34) */ + if(d.overflowed[0] || d.overflowed[1]){ + e.preventDefault(); + e.stopImmediatePropagation(); + } + if(e.type==="keyup"){ + _stop($this); + var keyboardDir=code===34 ? -1 : 1; + if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){ + var dir="x",to=Math.abs(mCSB_container[0].offsetLeft)-(keyboardDir*(wrapper.width()*0.9)); + }else{ + var dir="y",to=Math.abs(mCSB_container[0].offsetTop)-(keyboardDir*(wrapper.height()*0.9)); + } + _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); + } + }else if(code===35 || code===36){ + /* End (35), Home (36) */ + if(!$(document.activeElement).is(editables)){ + if(d.overflowed[0] || d.overflowed[1]){ + e.preventDefault(); + e.stopImmediatePropagation(); + } + if(e.type==="keyup"){ + if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){ + var dir="x",to=code===35 ? Math.abs(wrapper.width()-mCSB_container.outerWidth(false)) : 0; + }else{ + var dir="y",to=code===35 ? Math.abs(wrapper.height()-mCSB_container.outerHeight(false)) : 0; + } + _scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"}); + } + } + } + break; + } + function _seq(a,c){ + seq.type=o.keyboard.scrollType; + seq.scrollAmount=o.keyboard.scrollAmount; + if(seq.type==="stepped" && d.tweenRunning){return;} + _sequentialScroll($this,a,c); + } + } + }, + /* -------------------- */ + + + /* scrolls content sequentially (used when scrolling via buttons, keyboard arrows etc.) */ + _sequentialScroll=function(el,action,trigger,e,s){ + var d=el.data(pluginPfx),o=d.opt,seq=d.sequential, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + once=seq.type==="stepped" ? true : false, + steplessSpeed=o.scrollInertia < 26 ? 26 : o.scrollInertia, /* 26/1.5=17 */ + steppedSpeed=o.scrollInertia < 1 ? 17 : o.scrollInertia; + switch(action){ + case "on": + seq.dir=[ + (trigger===classes[16] || trigger===classes[15] || trigger===39 || trigger===37 ? "x" : "y"), + (trigger===classes[13] || trigger===classes[15] || trigger===38 || trigger===37 ? -1 : 1) + ]; + _stop(el); + if(_isNumeric(trigger) && seq.type==="stepped"){return;} + _on(once); + break; + case "off": + _off(); + if(once || (d.tweenRunning && seq.dir)){ + _on(true); + } + break; + } + + /* starts sequence */ + function _on(once){ + if(o.snapAmount){seq.scrollAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : seq.dir[0]==="x" ? o.snapAmount[1] : o.snapAmount[0];} /* scrolling snapping */ + var c=seq.type!=="stepped", /* continuous scrolling */ + t=s ? s : !once ? 1000/60 : c ? steplessSpeed/1.5 : steppedSpeed, /* timer */ + m=!once ? 2.5 : c ? 7.5 : 40, /* multiplier */ + contentPos=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)], + ratio=[d.scrollRatio.y>10 ? 10 : d.scrollRatio.y,d.scrollRatio.x>10 ? 10 : d.scrollRatio.x], + amount=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*(ratio[1]*m)) : contentPos[0]+(seq.dir[1]*(ratio[0]*m)), + px=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*parseInt(seq.scrollAmount)) : contentPos[0]+(seq.dir[1]*parseInt(seq.scrollAmount)), + to=seq.scrollAmount!=="auto" ? px : amount, + easing=e ? e : !once ? "mcsLinear" : c ? "mcsLinearOut" : "mcsEaseInOut", + onComplete=!once ? false : true; + if(once && t<17){ + to=seq.dir[0]==="x" ? contentPos[1] : contentPos[0]; + } + _scrollTo(el,to.toString(),{dir:seq.dir[0],scrollEasing:easing,dur:t,onComplete:onComplete}); + if(once){ + seq.dir=false; + return; + } + clearTimeout(seq.step); + seq.step=setTimeout(function(){ + _on(); + },t); + } + /* stops sequence */ + function _off(){ + clearTimeout(seq.step); + _delete(seq,"step"); + _stop(el); + } + }, + /* -------------------- */ + + + /* returns a yx array from value */ + _arr=function(val){ + var o=$(this).data(pluginPfx).opt,vals=[]; + if(typeof val==="function"){val=val();} /* check if the value is a single anonymous function */ + /* check if value is object or array, its length and create an array with yx values */ + if(!(val instanceof Array)){ /* object value (e.g. {y:"100",x:"100"}, 100 etc.) */ + vals[0]=val.y ? val.y : val.x || o.axis==="x" ? null : val; + vals[1]=val.x ? val.x : val.y || o.axis==="y" ? null : val; + }else{ /* array value (e.g. [100,100]) */ + vals=val.length>1 ? [val[0],val[1]] : o.axis==="x" ? [null,val[0]] : [val[0],null]; + } + /* check if array values are anonymous functions */ + if(typeof vals[0]==="function"){vals[0]=vals[0]();} + if(typeof vals[1]==="function"){vals[1]=vals[1]();} + return vals; + }, + /* -------------------- */ + + + /* translates values (e.g. "top", 100, "100px", "#id") to actual scroll-to positions */ + _to=function(val,dir){ + if(val==null || typeof val=="undefined"){return;} + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + t=typeof val; + if(!dir){dir=o.axis==="x" ? "x" : "y";} + var contentLength=dir==="x" ? mCSB_container.outerWidth(false)-wrapper.width() : mCSB_container.outerHeight(false)-wrapper.height(), + contentPos=dir==="x" ? mCSB_container[0].offsetLeft : mCSB_container[0].offsetTop, + cssProp=dir==="x" ? "left" : "top"; + switch(t){ + case "function": /* this currently is not used. Consider removing it */ + return val(); + break; + case "object": /* js/jquery object */ + var obj=val.jquery ? val : $(val); + if(!obj.length){return;} + return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0]; + break; + case "string": case "number": + if(_isNumeric(val)){ /* numeric value */ + return Math.abs(val); + }else if(val.indexOf("%")!==-1){ /* percentage value */ + return Math.abs(contentLength*parseInt(val)/100); + }else if(val.indexOf("-=")!==-1){ /* decrease value */ + return Math.abs(contentPos-parseInt(val.split("-=")[1])); + }else if(val.indexOf("+=")!==-1){ /* inrease value */ + var p=(contentPos+parseInt(val.split("+=")[1])); + return p>=0 ? 0 : Math.abs(p); + }else if(val.indexOf("px")!==-1 && _isNumeric(val.split("px")[0])){ /* pixels string value (e.g. "100px") */ + return Math.abs(val.split("px")[0]); + }else{ + if(val==="top" || val==="left"){ /* special strings */ + return 0; + }else if(val==="bottom"){ + return Math.abs(wrapper.height()-mCSB_container.outerHeight(false)); + }else if(val==="right"){ + return Math.abs(wrapper.width()-mCSB_container.outerWidth(false)); + }else if(val==="first" || val==="last"){ + var obj=mCSB_container.find(":"+val); + return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0]; + }else{ + if($(val).length){ /* jquery selector */ + return dir==="x" ? _childPos($(val))[1] : _childPos($(val))[0]; + }else{ /* other values (e.g. "100em") */ + mCSB_container.css(cssProp,val); + methods.update.call(null,$this[0]); + return; + } + } + } + break; + } + }, + /* -------------------- */ + + + /* calls the update method automatically */ + _autoUpdate=function(rem){ + var $this=$(this),d=$this.data(pluginPfx),o=d.opt, + mCSB_container=$("#mCSB_"+d.idx+"_container"); + if(rem){ + /* + removes autoUpdate timer + usage: _autoUpdate.call(this,"remove"); + */ + clearTimeout(mCSB_container[0].autoUpdate); + _delete(mCSB_container[0],"autoUpdate"); + return; + } + upd(); + function upd(){ + clearTimeout(mCSB_container[0].autoUpdate); + if($this.parents("html").length===0){ + /* check element in dom tree */ + $this=null; + return; + } + mCSB_container[0].autoUpdate=setTimeout(function(){ + /* update on specific selector(s) length and size change */ + if(o.advanced.updateOnSelectorChange){ + d.poll.change.n=sizesSum(); + if(d.poll.change.n!==d.poll.change.o){ + d.poll.change.o=d.poll.change.n; + doUpd(3); + return; + } + } + /* update on main element and scrollbar size changes */ + if(o.advanced.updateOnContentResize){ + d.poll.size.n=$this[0].scrollHeight+$this[0].scrollWidth+mCSB_container[0].offsetHeight+$this[0].offsetHeight+$this[0].offsetWidth; + if(d.poll.size.n!==d.poll.size.o){ + d.poll.size.o=d.poll.size.n; + doUpd(1); + return; + } + } + /* update on image load */ + if(o.advanced.updateOnImageLoad){ + if(!(o.advanced.updateOnImageLoad==="auto" && o.axis==="y")){ //by default, it doesn't run on vertical content + d.poll.img.n=mCSB_container.find("img").length; + if(d.poll.img.n!==d.poll.img.o){ + d.poll.img.o=d.poll.img.n; + mCSB_container.find("img").each(function(){ + imgLoader(this); + }); + return; + } + } + } + if(o.advanced.updateOnSelectorChange || o.advanced.updateOnContentResize || o.advanced.updateOnImageLoad){upd();} + },o.advanced.autoUpdateTimeout); + } + /* a tiny image loader */ + function imgLoader(el){ + if($(el).hasClass(classes[2])){doUpd(); return;} + var img=new Image(); + function createDelegate(contextObject,delegateMethod){ + return function(){return delegateMethod.apply(contextObject,arguments);} + } + function imgOnLoad(){ + this.onload=null; + $(el).addClass(classes[2]); + doUpd(2); + } + img.onload=createDelegate(img,imgOnLoad); + img.src=el.src; + } + /* returns the total height and width sum of all elements matching the selector */ + function sizesSum(){ + if(o.advanced.updateOnSelectorChange===true){o.advanced.updateOnSelectorChange="*";} + var total=0,sel=mCSB_container.find(o.advanced.updateOnSelectorChange); + if(o.advanced.updateOnSelectorChange && sel.length>0){sel.each(function(){total+=this.offsetHeight+this.offsetWidth;});} + return total; + } + /* calls the update method */ + function doUpd(cb){ + clearTimeout(mCSB_container[0].autoUpdate); + methods.update.call(null,$this[0],cb); + } + }, + /* -------------------- */ + + + /* snaps scrolling to a multiple of a pixels number */ + _snapAmount=function(to,amount,offset){ + return (Math.round(to/amount)*amount-offset); + }, + /* -------------------- */ + + + /* stops content and scrollbar animations */ + _stop=function(el){ + var d=el.data(pluginPfx), + sel=$("#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal"); + sel.each(function(){ + _stopTween.call(this); + }); + }, + /* -------------------- */ + + + /* + ANIMATES CONTENT + This is where the actual scrolling happens + */ + _scrollTo=function(el,to,options){ + var d=el.data(pluginPfx),o=d.opt, + defaults={ + trigger:"internal", + dir:"y", + scrollEasing:"mcsEaseOut", + drag:false, + dur:o.scrollInertia, + overwrite:"all", + callbacks:true, + onStart:true, + onUpdate:true, + onComplete:true + }, + options=$.extend(defaults,options), + dur=[options.dur,(options.drag ? 0 : options.dur)], + mCustomScrollBox=$("#mCSB_"+d.idx), + mCSB_container=$("#mCSB_"+d.idx+"_container"), + wrapper=mCSB_container.parent(), + totalScrollOffsets=o.callbacks.onTotalScrollOffset ? _arr.call(el,o.callbacks.onTotalScrollOffset) : [0,0], + totalScrollBackOffsets=o.callbacks.onTotalScrollBackOffset ? _arr.call(el,o.callbacks.onTotalScrollBackOffset) : [0,0]; + d.trigger=options.trigger; + if(wrapper.scrollTop()!==0 || wrapper.scrollLeft()!==0){ /* always reset scrollTop/Left */ + $(".mCSB_"+d.idx+"_scrollbar").css("visibility","visible"); + wrapper.scrollTop(0).scrollLeft(0); + } + if(to==="_resetY" && !d.contentReset.y){ + /* callbacks: onOverflowYNone */ + if(_cb("onOverflowYNone")){o.callbacks.onOverflowYNone.call(el[0]);} + d.contentReset.y=1; + } + if(to==="_resetX" && !d.contentReset.x){ + /* callbacks: onOverflowXNone */ + if(_cb("onOverflowXNone")){o.callbacks.onOverflowXNone.call(el[0]);} + d.contentReset.x=1; + } + if(to==="_resetY" || to==="_resetX"){return;} + if((d.contentReset.y || !el[0].mcs) && d.overflowed[0]){ + /* callbacks: onOverflowY */ + if(_cb("onOverflowY")){o.callbacks.onOverflowY.call(el[0]);} + d.contentReset.x=null; + } + if((d.contentReset.x || !el[0].mcs) && d.overflowed[1]){ + /* callbacks: onOverflowX */ + if(_cb("onOverflowX")){o.callbacks.onOverflowX.call(el[0]);} + d.contentReset.x=null; + } + if(o.snapAmount){ /* scrolling snapping */ + var snapAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : options.dir==="x" ? o.snapAmount[1] : o.snapAmount[0]; + to=_snapAmount(to,snapAmount,o.snapOffset); + } + switch(options.dir){ + case "x": + var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_horizontal"), + property="left", + contentPos=mCSB_container[0].offsetLeft, + limit=[ + mCustomScrollBox.width()-mCSB_container.outerWidth(false), + mCSB_dragger.parent().width()-mCSB_dragger.width() + ], + scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.x)], + tso=totalScrollOffsets[1], + tsbo=totalScrollBackOffsets[1], + totalScrollOffset=tso>0 ? tso/d.scrollRatio.x : 0, + totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.x : 0; + break; + case "y": + var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_vertical"), + property="top", + contentPos=mCSB_container[0].offsetTop, + limit=[ + mCustomScrollBox.height()-mCSB_container.outerHeight(false), + mCSB_dragger.parent().height()-mCSB_dragger.height() + ], + scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.y)], + tso=totalScrollOffsets[0], + tsbo=totalScrollBackOffsets[0], + totalScrollOffset=tso>0 ? tso/d.scrollRatio.y : 0, + totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.y : 0; + break; + } + if(scrollTo[1]<0 || (scrollTo[0]===0 && scrollTo[1]===0)){ + scrollTo=[0,0]; + }else if(scrollTo[1]>=limit[1]){ + scrollTo=[limit[0],limit[1]]; + }else{ + scrollTo[0]=-scrollTo[0]; + } + if(!el[0].mcs){ + _mcs(); /* init mcs object (once) to make it available before callbacks */ + if(_cb("onInit")){o.callbacks.onInit.call(el[0]);} /* callbacks: onInit */ + } + clearTimeout(mCSB_container[0].onCompleteTimeout); + _tweenTo(mCSB_dragger[0],property,Math.round(scrollTo[1]),dur[1],options.scrollEasing); + if(!d.tweenRunning && ((contentPos===0 && scrollTo[0]>=0) || (contentPos===limit[0] && scrollTo[0]<=limit[0]))){return;} + _tweenTo(mCSB_container[0],property,Math.round(scrollTo[0]),dur[0],options.scrollEasing,options.overwrite,{ + onStart:function(){ + if(options.callbacks && options.onStart && !d.tweenRunning){ + /* callbacks: onScrollStart */ + if(_cb("onScrollStart")){_mcs(); o.callbacks.onScrollStart.call(el[0]);} + d.tweenRunning=true; + _onDragClasses(mCSB_dragger); + d.cbOffsets=_cbOffsets(); + } + },onUpdate:function(){ + if(options.callbacks && options.onUpdate){ + /* callbacks: whileScrolling */ + if(_cb("whileScrolling")){_mcs(); o.callbacks.whileScrolling.call(el[0]);} + } + },onComplete:function(){ + if(options.callbacks && options.onComplete){ + if(o.axis==="yx"){clearTimeout(mCSB_container[0].onCompleteTimeout);} + var t=mCSB_container[0].idleTimer || 0; + mCSB_container[0].onCompleteTimeout=setTimeout(function(){ + /* callbacks: onScroll, onTotalScroll, onTotalScrollBack */ + if(_cb("onScroll")){_mcs(); o.callbacks.onScroll.call(el[0]);} + if(_cb("onTotalScroll") && scrollTo[1]>=limit[1]-totalScrollOffset && d.cbOffsets[0]){_mcs(); o.callbacks.onTotalScroll.call(el[0]);} + if(_cb("onTotalScrollBack") && scrollTo[1]<=totalScrollBackOffset && d.cbOffsets[1]){_mcs(); o.callbacks.onTotalScrollBack.call(el[0]);} + d.tweenRunning=false; + mCSB_container[0].idleTimer=0; + _onDragClasses(mCSB_dragger,"hide"); + },t); + } + } + }); + /* checks if callback function exists */ + function _cb(cb){ + return d && o.callbacks[cb] && typeof o.callbacks[cb]==="function"; + } + /* checks whether callback offsets always trigger */ + function _cbOffsets(){ + return [o.callbacks.alwaysTriggerOffsets || contentPos>=limit[0]+tso,o.callbacks.alwaysTriggerOffsets || contentPos<=-tsbo]; + } + /* + populates object with useful values for the user + values: + content: this.mcs.content + content top position: this.mcs.top + content left position: this.mcs.left + dragger top position: this.mcs.draggerTop + dragger left position: this.mcs.draggerLeft + scrolling y percentage: this.mcs.topPct + scrolling x percentage: this.mcs.leftPct + scrolling direction: this.mcs.direction + */ + function _mcs(){ + var cp=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft], /* content position */ + dp=[mCSB_dragger[0].offsetTop,mCSB_dragger[0].offsetLeft], /* dragger position */ + cl=[mCSB_container.outerHeight(false),mCSB_container.outerWidth(false)], /* content length */ + pl=[mCustomScrollBox.height(),mCustomScrollBox.width()]; /* content parent length */ + el[0].mcs={ + content:mCSB_container, /* original content wrapper as jquery object */ + top:cp[0],left:cp[1],draggerTop:dp[0],draggerLeft:dp[1], + topPct:Math.round((100*Math.abs(cp[0]))/(Math.abs(cl[0])-pl[0])),leftPct:Math.round((100*Math.abs(cp[1]))/(Math.abs(cl[1])-pl[1])), + direction:options.dir + }; + /* + this refers to the original element containing the scrollbar(s) + usage: this.mcs.top, this.mcs.leftPct etc. + */ + } + }, + /* -------------------- */ + + + /* + CUSTOM JAVASCRIPT ANIMATION TWEEN + Lighter and faster than jquery animate() and css transitions + Animates top/left properties and includes easings + */ + _tweenTo=function(el,prop,to,duration,easing,overwrite,callbacks){ + if(!el._mTween){el._mTween={top:{},left:{}};} + var callbacks=callbacks || {}, + onStart=callbacks.onStart || function(){},onUpdate=callbacks.onUpdate || function(){},onComplete=callbacks.onComplete || function(){}, + startTime=_getTime(),_delay,progress=0,from=el.offsetTop,elStyle=el.style,_request,tobj=el._mTween[prop]; + if(prop==="left"){from=el.offsetLeft;} + var diff=to-from; + tobj.stop=0; + if(overwrite!=="none"){_cancelTween();} + _startTween(); + function _step(){ + if(tobj.stop){return;} + if(!progress){onStart.call();} + progress=_getTime()-startTime; + _tween(); + if(progress>=tobj.time){ + tobj.time=(progress>tobj.time) ? progress+_delay-(progress-tobj.time) : progress+_delay-1; + if(tobj.time0){ + tobj.currVal=_ease(tobj.time,from,diff,duration,easing); + elStyle[prop]=Math.round(tobj.currVal)+"px"; + }else{ + elStyle[prop]=to+"px"; + } + onUpdate.call(); + } + function _startTween(){ + _delay=1000/60; + tobj.time=progress+_delay; + _request=(!window.requestAnimationFrame) ? function(f){_tween(); return setTimeout(f,0.01);} : window.requestAnimationFrame; + tobj.id=_request(_step); + } + function _cancelTween(){ + if(tobj.id==null){return;} + if(!window.requestAnimationFrame){clearTimeout(tobj.id); + }else{window.cancelAnimationFrame(tobj.id);} + tobj.id=null; + } + function _ease(t,b,c,d,type){ + switch(type){ + case "linear": case "mcsLinear": + return c*t/d + b; + break; + case "mcsLinearOut": + t/=d; t--; return c * Math.sqrt(1 - t*t) + b; + break; + case "easeInOutSmooth": + t/=d/2; + if(t<1) return c/2*t*t + b; + t--; + return -c/2 * (t*(t-2) - 1) + b; + break; + case "easeInOutStrong": + t/=d/2; + if(t<1) return c/2 * Math.pow( 2, 10 * (t - 1) ) + b; + t--; + return c/2 * ( -Math.pow( 2, -10 * t) + 2 ) + b; + break; + case "easeInOut": case "mcsEaseInOut": + t/=d/2; + if(t<1) return c/2*t*t*t + b; + t-=2; + return c/2*(t*t*t + 2) + b; + break; + case "easeOutSmooth": + t/=d; t--; + return -c * (t*t*t*t - 1) + b; + break; + case "easeOutStrong": + return c * ( -Math.pow( 2, -10 * t/d ) + 1 ) + b; + break; + case "easeOut": case "mcsEaseOut": default: + var ts=(t/=d)*t,tc=ts*t; + return b+c*(0.499999999999997*tc*ts + -2.5*ts*ts + 5.5*tc + -6.5*ts + 4*t); + } + } + }, + /* -------------------- */ + + + /* returns current time */ + _getTime=function(){ + if(window.performance && window.performance.now){ + return window.performance.now(); + }else{ + if(window.performance && window.performance.webkitNow){ + return window.performance.webkitNow(); + }else{ + if(Date.now){return Date.now();}else{return new Date().getTime();} + } + } + }, + /* -------------------- */ + + + /* stops a tween */ + _stopTween=function(){ + var el=this; + if(!el._mTween){el._mTween={top:{},left:{}};} + var props=["top","left"]; + for(var i=0; i