From 76798510640863391c90e6e0b1be74668d97f483 Mon Sep 17 00:00:00 2001 From: Uncled1023 Date: Thu, 21 Jan 2016 14:47:07 -0800 Subject: [PATCH] Added Help pages. --- Teknik/Areas/Help/Content/Help.css | 63 +++ .../Areas/Help/Controllers/HelpController.cs | 63 +++ Teknik/Areas/Help/HelpAreaRegistration.cs | 52 ++ Teknik/Areas/Help/ViewModels/HelpViewModel.cs | 13 + Teknik/Areas/Help/Views/Help/Api.cshtml | 211 +++++++ Teknik/Areas/Help/Views/Help/Blog.cshtml | 12 + Teknik/Areas/Help/Views/Help/Git.cshtml | 12 + Teknik/Areas/Help/Views/Help/Index.cshtml | 35 ++ Teknik/Areas/Help/Views/Help/Irc.cshtml | 16 + Teknik/Areas/Help/Views/Help/Mail.cshtml | 69 +++ Teknik/Areas/Help/Views/Help/Mumble.cshtml | 12 + Teknik/Areas/Help/Views/Help/Upload.cshtml | 37 ++ Teknik/Areas/Help/Views/_ViewStart.cshtml | 3 + Teknik/Areas/Help/Views/web.config | 36 ++ Teknik/Configuration/ApiConfig.cs | 18 + Teknik/Configuration/Config.cs | 5 + Teknik/Content/jquery.tocify.css | 75 +++ Teknik/Scripts/_references.js | Bin 3234 -> 3422 bytes Teknik/Scripts/jquery-ui.widgets.js | 516 ++++++++++++++++++ Teknik/Scripts/jquery.tocify.min.js | 4 + Teknik/Teknik.csproj | 20 + 21 files changed, 1272 insertions(+) create mode 100644 Teknik/Areas/Help/Content/Help.css create mode 100644 Teknik/Areas/Help/Controllers/HelpController.cs create mode 100644 Teknik/Areas/Help/HelpAreaRegistration.cs create mode 100644 Teknik/Areas/Help/ViewModels/HelpViewModel.cs create mode 100644 Teknik/Areas/Help/Views/Help/Api.cshtml create mode 100644 Teknik/Areas/Help/Views/Help/Blog.cshtml create mode 100644 Teknik/Areas/Help/Views/Help/Git.cshtml create mode 100644 Teknik/Areas/Help/Views/Help/Index.cshtml create mode 100644 Teknik/Areas/Help/Views/Help/Irc.cshtml create mode 100644 Teknik/Areas/Help/Views/Help/Mail.cshtml create mode 100644 Teknik/Areas/Help/Views/Help/Mumble.cshtml create mode 100644 Teknik/Areas/Help/Views/Help/Upload.cshtml create mode 100644 Teknik/Areas/Help/Views/_ViewStart.cshtml create mode 100644 Teknik/Areas/Help/Views/web.config create mode 100644 Teknik/Configuration/ApiConfig.cs create mode 100644 Teknik/Content/jquery.tocify.css create mode 100644 Teknik/Scripts/jquery-ui.widgets.js create mode 100644 Teknik/Scripts/jquery.tocify.min.js diff --git a/Teknik/Areas/Help/Content/Help.css b/Teknik/Areas/Help/Content/Help.css new file mode 100644 index 0000000..6401594 --- /dev/null +++ b/Teknik/Areas/Help/Content/Help.css @@ -0,0 +1,63 @@ +.api { + color: #393939; + font-size: 14px; + line-height: 1.5em; +} + +.api pre { + border: 1px solid #cacaca; + font: 12px/1.4em Consolas, "Liberation Mono", Courier, monospace; + padding: 10px; + overflow: auto; + border-radius: 3px; + background-color: #fafafb; + color: #393939; + margin: 2em 0; +} + +.api pre code { + white-space: pre; +} + +.api table { + width: 100%; + display: block; + margin: 15px 0; +} + +.api tbody { + vertical-align: middle; + border-color: inherit; +} + +.api thead { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} + +.api table tr { + border-top: 1px solid #ccc; + background-color: #fff; + vertical-align: inherit; +} + +.api table th { + border: 1px solid #ddd; + padding: 6px 13px; + font-weight: bold; + text-align: center; +} + +.api table td { + border: 1px solid #ddd; + padding: 6px 13px; +} + +.api code { + white-space: nowrap; + font: 12px Consolas, "Liberation Mono", Courier, monospace; +} \ No newline at end of file diff --git a/Teknik/Areas/Help/Controllers/HelpController.cs b/Teknik/Areas/Help/Controllers/HelpController.cs new file mode 100644 index 0000000..9affc06 --- /dev/null +++ b/Teknik/Areas/Help/Controllers/HelpController.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using Teknik.Areas.Help.ViewModels; +using Teknik.Controllers; + +namespace Teknik.Areas.Help.Controllers +{ + public class HelpController : DefaultController + { + // GET: Help/Help + [AllowAnonymous] + public ActionResult Index() + { + ViewBag.Title = "Help - " + Config.Title; + HelpViewModel model = new HelpViewModel(); + return View(model); + } + + [AllowAnonymous] + public ActionResult Topic(string topic) + { + ViewBag.Title = topic + " Help - " + Config.Title; + HelpViewModel model = new HelpViewModel(); + + string view = string.Empty; + switch(topic.ToLower()) + { + case "api": + view = "~/Areas/Help/Views/Help/Api.cshtml"; + break; + case "blog": + view = "~/Areas/Help/Views/Help/Blog.cshtml"; + break; + case "git": + view = "~/Areas/Help/Views/Help/Git.cshtml"; + break; + case "irc": + view = "~/Areas/Help/Views/Help/Irc.cshtml"; + break; + case "mail": + view = "~/Areas/Help/Views/Help/Mail.cshtml"; + break; + case "mumble": + view = "~/Areas/Help/Views/Help/Mumble.cshtml"; + break; + case "upload": + view = "~/Areas/Help/Views/Help/Upload.cshtml"; + break; + default: + break; + } + + if (!string.IsNullOrEmpty(view)) + { + return View(view, model); + } + return RedirectToRoute("*.Error.Http404"); + } + } +} \ No newline at end of file diff --git a/Teknik/Areas/Help/HelpAreaRegistration.cs b/Teknik/Areas/Help/HelpAreaRegistration.cs new file mode 100644 index 0000000..0937676 --- /dev/null +++ b/Teknik/Areas/Help/HelpAreaRegistration.cs @@ -0,0 +1,52 @@ +using System.Web.Mvc; +using System.Web.Optimization; + +namespace Teknik.Areas.Help +{ + public class HelpAreaRegistration : AreaRegistration + { + public override string AreaName + { + get + { + return "Help"; + } + } + + public override void RegisterArea(AreaRegistrationContext context) + { + context.MapSubdomainRoute( + "Help.Index", // Route name + "dev", + "Help", // URL with parameters + new { controller = "Help", action = "Index" }, // Parameter defaults + new[] { typeof(Controllers.HelpController).Namespace } + ); + context.MapSubdomainRoute( + "Help.Topic", // Route name + "dev", + "Help/{topic}", // URL with parameters + new { controller = "Help", action = "Topic" }, // Parameter defaults + new[] { typeof(Controllers.HelpController).Namespace } + ); + context.MapSubdomainRoute( + "Help.Index", // Route name + "help", + "", // URL with parameters + new { controller = "Help", action = "Index" }, // Parameter defaults + new[] { typeof(Controllers.HelpController).Namespace } + ); + context.MapSubdomainRoute( + "Help.Topic", // Route name + "help", + "{topic}", // URL with parameters + new { controller = "Help", action = "Topic" }, // Parameter defaults + new[] { typeof(Controllers.HelpController).Namespace } + ); + + // Register Style Bundles + BundleTable.Bundles.Add(new StyleBundle("~/Content/help").Include( + "~/Areas/Help/Content/Help.css")); + } + } +} \ No newline at end of file diff --git a/Teknik/Areas/Help/ViewModels/HelpViewModel.cs b/Teknik/Areas/Help/ViewModels/HelpViewModel.cs new file mode 100644 index 0000000..ba27c61 --- /dev/null +++ b/Teknik/Areas/Help/ViewModels/HelpViewModel.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Teknik.ViewModels; + +namespace Teknik.Areas.Help.ViewModels +{ + public class HelpViewModel : ViewModelBase + { + } +} diff --git a/Teknik/Areas/Help/Views/Help/Api.cshtml b/Teknik/Areas/Help/Views/Help/Api.cshtml new file mode 100644 index 0000000..d2fabf0 --- /dev/null +++ b/Teknik/Areas/Help/Views/Help/Api.cshtml @@ -0,0 +1,211 @@ +@model Teknik.Areas.Help.ViewModels.HelpViewModel + +@Styles.Render("~/Content/help"); + +
+
+

Teknik API

+
+

Overview

+

+ The Teknik API is free for everyone to use, and is defined on a per service basis. +
+
+ The general API calls can be summarized as follows: @Url.SubRouteUrl("api", "Api.Index", new { service = "Service", action = "Action", version = Model.Config.ApiConfig.Version }) +

+

Responses

+

+ All responses are returned as json. The returned json can contain any of the following sections. +
+
+ Results +

{"results":{"<resultType>":{"<resultData>":"<value>"}}}
+ Errors +
{"error":{"code":<value>, "message":"<errorMessage>"}}
+

+

Upload

+
+

This is a description of the API commands available for the Upload service.

+

Upload a File

+
POST @Url.SubRouteUrl("api", "Api.Index", new { service = "Upload", action = "Post", version = Model.Config.ApiConfig.Version })
+
Parameters
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDefaultDescription
+ file + + file + + NULL + + Required + The file that you would like to upload. +
+ encrypt + + string + + no + + If you want the file to be encrypted server side. This will regenerate the key and/or iv if none are passed in. Choose yes or no +
+ key + + string + + NULL + + If you want the file to be decrypted server side, include the key. +
+ iv + + string + + NULL + + If the file has been encrypted and you want it decrypted (Both Server and Client Side), include the iv. +
+ getDeletionKey + + string + + no + + Whether you would like to create a deletion link. Choose yes or no +
+
Response
+
{"results":{"file":{"name":"file_name", "url":"url", "type":"file_type", "size":size, "key":key, "iv":iv, "deletionKey":deletion_key}}}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
+ name + + string + + The filename of the uploaded file. +
+ url + + string + + The direct url to the uploaded file. The key is apended to the url as an anchor tag. +
+ type + + string + + The MIME file type of the uploaded file. +
+ size + + integer + + The size of the uploaded file in bytes. +
+ key + + string + + The key that was used to encrypt the file. +
+ iv + + string + + The iv that was used to encrypt the file. +
+ deletionKey + + string + + Optional + The deletion key for file. Use it as follows: @Url.SubRouteUrl("u", "Upload.Upload", new { file = "file.jpg", key = "deletionKey" }) +
+
Example
+
$ curl -F "getDeletionKey=yes" -F "encrypt=yes" -F "file=@("@")image.png" @Url.SubRouteUrl("api", "Api.Index", new { service = "Upload", version = Model.Config.ApiConfig.Version })
+
+
+
+
diff --git a/Teknik/Areas/Help/Views/Help/Blog.cshtml b/Teknik/Areas/Help/Views/Help/Blog.cshtml new file mode 100644 index 0000000..1d298fb --- /dev/null +++ b/Teknik/Areas/Help/Views/Help/Blog.cshtml @@ -0,0 +1,12 @@ +@model Teknik.Areas.Help.ViewModels.HelpViewModel + +
+
+

Blogging

+
+

Formatting

+

+ Each article uses a basic Markdown formatter to display the information. Any Html or script information will be stripped from the post before displaying. +

+
+
diff --git a/Teknik/Areas/Help/Views/Help/Git.cshtml b/Teknik/Areas/Help/Views/Help/Git.cshtml new file mode 100644 index 0000000..3c607b3 --- /dev/null +++ b/Teknik/Areas/Help/Views/Help/Git.cshtml @@ -0,0 +1,12 @@ +@model Teknik.Areas.Help.ViewModels.HelpViewModel + +
+
+

Git

+
+

Authorization

+

+ To login into your git account, you will initially need to initially use your teknik email address to login using the web interface. Once you have done so at least once, you can from then on use your teknik username. +

+
+
diff --git a/Teknik/Areas/Help/Views/Help/Index.cshtml b/Teknik/Areas/Help/Views/Help/Index.cshtml new file mode 100644 index 0000000..d2517a2 --- /dev/null +++ b/Teknik/Areas/Help/Views/Help/Index.cshtml @@ -0,0 +1,35 @@ +@model Teknik.Areas.Help.ViewModels.HelpViewModel + +
+
+
+

Teknik Services

+
+

Important Links

+
+
Site Transparency
+
All the site's transactions, statistics, and data effecting actions.
+
Privacy Policy
+
Everything about how we handle your privacy.
+
+
+

Help Topics

+
+
Api
+
Open API available to interact with the difference services.
+
Blogging
+
Blogging platform available to the users and visible to the public.
+
Git Repositories
+
All the site's transactions, statistics, and data effecting actions.
+
Irc Network
+
All the site's transactions, statistics, and data effecting actions.
+
Mail Server
+
All the site's transactions, statistics, and data effecting actions.
+
Mumble Chat Server
+
The public Mumble server and configuration settings needed.
+
Uploads
+
How the Upload service works and special considerations.
+
+
+
+
\ No newline at end of file diff --git a/Teknik/Areas/Help/Views/Help/Irc.cshtml b/Teknik/Areas/Help/Views/Help/Irc.cshtml new file mode 100644 index 0000000..d5a1081 --- /dev/null +++ b/Teknik/Areas/Help/Views/Help/Irc.cshtml @@ -0,0 +1,16 @@ +@model Teknik.Areas.Help.ViewModels.HelpViewModel + +
+
+

IRC

+
+

IRC Server Info

+

+ You can connect to the Teknik IRC using any RFC compliant client by connecting to irc.@Model.Config.Host on port 6667. +

+

Channel Information

+

+ The main channel for Teknik support is located at #teknik. +

+
+
diff --git a/Teknik/Areas/Help/Views/Help/Mail.cshtml b/Teknik/Areas/Help/Views/Help/Mail.cshtml new file mode 100644 index 0000000..ecffc02 --- /dev/null +++ b/Teknik/Areas/Help/Views/Help/Mail.cshtml @@ -0,0 +1,69 @@ +@model Teknik.Areas.Help.ViewModels.HelpViewModel + +
+
+

Mail

+
+

Mail Server Settings

+

+ At registration, each user is given an email address with 1 GB of storage space. + You can either access your email via the Web Client or by using a client of your choosing with support for IMAP or POP3. +

+
+
+
    +
  • Outlook

  • +
    +
    +
      +
    • User Information
    • +
    • Email Address:
      @string.Format("[username]@{0}", Model.Config.Host)
    • +
    • Server Information
    • +
    • Incoming Server:
      @Model.Config.SMTPConfig.Host
    • +
    • Outgoing Server:
      @Model.Config.SMTPConfig.Host
    • +
    +
    +
    +
      +
    • Logon Information
    • +
    • Username:
      @string.Format("[username]@{0}", Model.Config.Host)
    • +
    • Password:
      [password]
    • +
    • More Settings
    • +
    • Requires Authentication:
      Both
    • +
    • Incoming Server (IMAP):
      143 (993 SSL)
    • +
    • Outgoing Server (SMTP):
      25 (465 SSL)
    • +
    +
    +
+
+
+
+
+
    +
  • Thunderbird

  • +
    +
    +
      +
    • Server Settings
    • +
    • Server Name:
      @Model.Config.SMTPConfig.Host
    • +
    • Port:
      143 (993 SSL)
    • +
    • User Name:
      @string.Format("[username]@{0}", Model.Config.Host)
    • +
    • Connection Security:
      None (SSL/TLS)
    • +
    • Authentication method:
      Password
    • +
    +
    +
    +
      +
    • Outgoing Server (SMTP)
    • +
    • Server Name:
      @Model.Config.SMTPConfig.Host
    • +
    • Port:
      25 (465 SSL)
    • +
    • User Name:
      @string.Format("[username]@{0}", Model.Config.Host)
    • +
    • Connection Security:
      None (SSL/TLS)
    • +
    • Authentication method:
      Password
    • +
    +
    +
+
+
+
+
diff --git a/Teknik/Areas/Help/Views/Help/Mumble.cshtml b/Teknik/Areas/Help/Views/Help/Mumble.cshtml new file mode 100644 index 0000000..d3c8fcc --- /dev/null +++ b/Teknik/Areas/Help/Views/Help/Mumble.cshtml @@ -0,0 +1,12 @@ +@model Teknik.Areas.Help.ViewModels.HelpViewModel + +
+
+

Mumble

+
+

Mumble Server Info

+

+ You can connect to the Mumble server by connecting to mumble.@Model.Config.Host on port 64738. +

+
+
diff --git a/Teknik/Areas/Help/Views/Help/Upload.cshtml b/Teknik/Areas/Help/Views/Help/Upload.cshtml new file mode 100644 index 0000000..80c7758 --- /dev/null +++ b/Teknik/Areas/Help/Views/Help/Upload.cshtml @@ -0,0 +1,37 @@ +@model Teknik.Areas.Help.ViewModels.HelpViewModel + +
+
+
+

Uploads

+
+

Encryption Method

+
+

Using the Browser (Client Side Encryption)

+

+ When you using the web interface for uploads, the file is loaded using the javascript FileReader API. +

+

+ Once the file is completely loaded into the buffer, a key and iv are generated by a random string generator to create a key that is @Model.Config.UploadConfig.KeySize Bytes and an iv (Block Size) that is @Model.Config.UploadConfig.BlockSize Bytes. + Then the file buffer, key, and iv are passed into a Web Worker for encryption. +

+

+ The file data is passed through a progressive ciphering with a chunk size of @Model.Config.UploadConfig.ChunkSize bytes. This is to help reduce the memory usage needed by the encryption process as it only needs to process and convert each chunk instead of the entire file. +

+

+ Once all the file's data has been processed, the final buffer is then passed back to the main encryption routine and is sent to the server as a ArrayBuffer, along with the content-type, generated iv, key size, and block size. +

+

+ Once the data has been recieved by the server, a unique URL name and unique local filename are generated and saved to the database along with the passed up cipher information. The File Data is then written to the server and the resulting URL is passed back to the client. +

+

+ When the client recieves the returned URL, it then appends the generated key to the URL as an anchor tag and updates the UI to display the final URL. +

+
+

Cipher Properties

+

+ The encryption library being used is Crypto-JS and the cipher being used is AES-@Model.Config.UploadConfig.KeySize using the mode CTR. The variant of AES is determined by the size of the key used (128, 192, or 256). +

+
+
+
diff --git a/Teknik/Areas/Help/Views/_ViewStart.cshtml b/Teknik/Areas/Help/Views/_ViewStart.cshtml new file mode 100644 index 0000000..2de6241 --- /dev/null +++ b/Teknik/Areas/Help/Views/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "~/Views/Shared/_Layout.cshtml"; +} diff --git a/Teknik/Areas/Help/Views/web.config b/Teknik/Areas/Help/Views/web.config new file mode 100644 index 0000000..ada5aaf --- /dev/null +++ b/Teknik/Areas/Help/Views/web.config @@ -0,0 +1,36 @@ + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Teknik/Configuration/ApiConfig.cs b/Teknik/Configuration/ApiConfig.cs new file mode 100644 index 0000000..35beb5b --- /dev/null +++ b/Teknik/Configuration/ApiConfig.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Teknik.Configuration +{ + public class ApiConfig + { + public int Version { get; set; } + + public ApiConfig() + { + Version = 1; + } + } +} diff --git a/Teknik/Configuration/Config.cs b/Teknik/Configuration/Config.cs index 6e4a0a8..e9922f1 100644 --- a/Teknik/Configuration/Config.cs +++ b/Teknik/Configuration/Config.cs @@ -20,6 +20,7 @@ namespace Teknik.Configuration private SMTPConfig _SMTPConfig; private UploadConfig _UploadConfig; private BlogConfig _BlogConfig; + private ApiConfig _ApiConfig; private string _SupportEmail; private string _BitcoinAddress; private string _BlogTitle; @@ -50,6 +51,9 @@ namespace Teknik.Configuration // Upload Configuration public UploadConfig UploadConfig { get { return _UploadConfig; } set { _UploadConfig = value; } } + // Upload Configuration + public ApiConfig ApiConfig { get { return _ApiConfig; } set { _ApiConfig = value; } } + public Config() { _ConfigRWLock = new ReaderWriterLockSlim(); @@ -70,6 +74,7 @@ namespace Teknik.Configuration SMTPConfig = new SMTPConfig(); BlogConfig = new BlogConfig(); UploadConfig = new UploadConfig(); + ApiConfig = new ApiConfig(); SupportEmail = string.Empty; BitcoinAddress = string.Empty; } diff --git a/Teknik/Content/jquery.tocify.css b/Teknik/Content/jquery.tocify.css new file mode 100644 index 0000000..8ce3a22 --- /dev/null +++ b/Teknik/Content/jquery.tocify.css @@ -0,0 +1,75 @@ +/* + * jquery.tocify.css 1.9.1 + * Author: @gregfranko + */ + +/* The Table of Contents container element */ +.tocify { + width: 20%; + max-height: 90%; + overflow: auto; + margin-left: 2%; + position: fixed; + border: 1px solid #ccc; + webkit-border-radius: 6px; + moz-border-radius: 6px; + border-radius: 6px; +} + +/* The Table of Contents is composed of multiple nested unordered lists. These styles remove the default styling of an unordered list because it is ugly. */ +.tocify ul, .tocify li { + list-style: none; + margin: 0; + padding: 0; + border: none; + line-height: 30px; +} + +/* Top level header elements */ +.tocify-header { + text-indent: 10px; +} + +/* Top level subheader elements. These are the first nested items underneath a header element. */ +.tocify-subheader { + text-indent: 20px; + display: none; +} + +/* Makes the font smaller for all subheader elements. */ +.tocify-subheader li { + font-size: 12px; +} + +/* Further indents second level subheader elements. */ +.tocify-subheader .tocify-subheader { + text-indent: 30px; +} + +/* Further indents third level subheader elements. You can continue this pattern if you have more nested elements. */ +.tocify-subheader .tocify-subheader .tocify-subheader { + text-indent: 40px; +} + +/* Twitter Bootstrap Override Style */ +.tocify .tocify-item > a, .tocify .nav-list .nav-header { + margin: 0px; +} + +/* Twitter Bootstrap Override Styles */ +.tocify .tocify-item a, .tocify .list-group-item { + padding: 5px; +} + +.tocify .nav-pills > li { + float: none; +} + +.tocify .list-group-item:hover, .tocify .list-group-item:focus { + background-color: #f5f5f5; +} + +.tocify .list-group-item.active:hover, .tocify .list-group-item.active:focus { + background-color: #428bca; +} + /* End Twitter Bootstrap Override Styles */ \ No newline at end of file diff --git a/Teknik/Scripts/_references.js b/Teknik/Scripts/_references.js index 1eb153ec04468edc90523c880f374b3e2d4b38ea..00a76ccd149456a1aeea02af7586d37e526ced55 100644 GIT binary patch delta 65 zcmZ1^c~5G?84m6ehJ1!(hD?SuhRVscEUuFkI2AVE", + options: { + disabled: false, + + // callbacks + create: null + }, + _createWidget: function( options, element ) { + element = $( element || this.defaultElement || this )[ 0 ]; + this.element = $( element ); + this.uuid = uuid++; + this.eventNamespace = "." + this.widgetName + this.uuid; + this.options = $.widget.extend( {}, + this.options, + this._getCreateOptions(), + options ); + + this.bindings = $(); + this.hoverable = $(); + this.focusable = $(); + + if ( element !== this ) { + $.data( element, this.widgetFullName, this ); + this._on( true, this.element, { + remove: function( event ) { + if ( event.target === element ) { + this.destroy(); + } + } + }); + this.document = $( element.style ? + // element within the document + element.ownerDocument : + // element is window or document + element.document || element ); + this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); + } + + this._create(); + this._trigger( "create", null, this._getCreateEventData() ); + this._init(); + }, + _getCreateOptions: $.noop, + _getCreateEventData: $.noop, + _create: $.noop, + _init: $.noop, + + destroy: function() { + this._destroy(); + // we can probably remove the unbind calls in 2.0 + // all event bindings should go through this._on() + this.element + .unbind( this.eventNamespace ) + // 1.9 BC for #7810 + // TODO remove dual storage + .removeData( this.widgetName ) + .removeData( this.widgetFullName ) + // support: jquery <1.6.3 + // http://bugs.jquery.com/ticket/9413 + .removeData( $.camelCase( this.widgetFullName ) ); + this.widget() + .unbind( this.eventNamespace ) + .removeAttr( "aria-disabled" ) + .removeClass( + this.widgetFullName + "-disabled " + + "ui-state-disabled" ); + + // clean up events and states + this.bindings.unbind( this.eventNamespace ); + this.hoverable.removeClass( "ui-state-hover" ); + this.focusable.removeClass( "ui-state-focus" ); + }, + _destroy: $.noop, + + widget: function() { + return this.element; + }, + + option: function( key, value ) { + var options = key, + parts, + curOption, + i; + + if ( arguments.length === 0 ) { + // don't return a reference to the internal hash + return $.widget.extend( {}, this.options ); + } + + if ( typeof key === "string" ) { + // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } + options = {}; + parts = key.split( "." ); + key = parts.shift(); + if ( parts.length ) { + curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); + for ( i = 0; i < parts.length - 1; i++ ) { + curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; + curOption = curOption[ parts[ i ] ]; + } + key = parts.pop(); + if ( arguments.length === 1 ) { + return curOption[ key ] === undefined ? null : curOption[ key ]; + } + curOption[ key ] = value; + } else { + if ( arguments.length === 1 ) { + return this.options[ key ] === undefined ? null : this.options[ key ]; + } + options[ key ] = value; + } + } + + this._setOptions( options ); + + return this; + }, + _setOptions: function( options ) { + var key; + + for ( key in options ) { + this._setOption( key, options[ key ] ); + } + + return this; + }, + _setOption: function( key, value ) { + this.options[ key ] = value; + + if ( key === "disabled" ) { + this.widget() + .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value ) + .attr( "aria-disabled", value ); + this.hoverable.removeClass( "ui-state-hover" ); + this.focusable.removeClass( "ui-state-focus" ); + } + + return this; + }, + + enable: function() { + return this._setOption( "disabled", false ); + }, + disable: function() { + return this._setOption( "disabled", true ); + }, + + _on: function( suppressDisabledCheck, element, handlers ) { + var delegateElement, + instance = this; + + // no suppressDisabledCheck flag, shuffle arguments + if ( typeof suppressDisabledCheck !== "boolean" ) { + handlers = element; + element = suppressDisabledCheck; + suppressDisabledCheck = false; + } + + // no element argument, shuffle and use this.element + if ( !handlers ) { + handlers = element; + element = this.element; + delegateElement = this.widget(); + } else { + // accept selectors, DOM elements + element = delegateElement = $( element ); + this.bindings = this.bindings.add( element ); + } + + $.each( handlers, function( event, handler ) { + function handlerProxy() { + // allow widgets to customize the disabled handling + // - disabled as an array instead of boolean + // - disabled class as method for disabling individual parts + if ( !suppressDisabledCheck && + ( instance.options.disabled === true || + $( this ).hasClass( "ui-state-disabled" ) ) ) { + return; + } + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + + // copy the guid so direct unbinding works + if ( typeof handler !== "string" ) { + handlerProxy.guid = handler.guid = + handler.guid || handlerProxy.guid || $.guid++; + } + + var match = event.match( /^(\w+)\s*(.*)$/ ), + eventName = match[1] + instance.eventNamespace, + selector = match[2]; + if ( selector ) { + delegateElement.delegate( selector, eventName, handlerProxy ); + } else { + element.bind( eventName, handlerProxy ); + } + }); + }, + + _off: function( element, eventName ) { + eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; + element.unbind( eventName ).undelegate( eventName ); + }, + + _delay: function( handler, delay ) { + function handlerProxy() { + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + var instance = this; + return setTimeout( handlerProxy, delay || 0 ); + }, + + _hoverable: function( element ) { + this.hoverable = this.hoverable.add( element ); + this._on( element, { + mouseenter: function( event ) { + $( event.currentTarget ).addClass( "ui-state-hover" ); + }, + mouseleave: function( event ) { + $( event.currentTarget ).removeClass( "ui-state-hover" ); + } + }); + }, + + _focusable: function( element ) { + this.focusable = this.focusable.add( element ); + this._on( element, { + focusin: function( event ) { + $( event.currentTarget ).addClass( "ui-state-focus" ); + }, + focusout: function( event ) { + $( event.currentTarget ).removeClass( "ui-state-focus" ); + } + }); + }, + + _trigger: function( type, event, data ) { + var prop, orig, + callback = this.options[ type ]; + + data = data || {}; + event = $.Event( event ); + event.type = ( type === this.widgetEventPrefix ? + type : + this.widgetEventPrefix + type ).toLowerCase(); + // the original event may come from any element + // so we need to reset the target on the new event + event.target = this.element[ 0 ]; + + // copy original event properties over to the new event + orig = event.originalEvent; + if ( orig ) { + for ( prop in orig ) { + if ( !( prop in event ) ) { + event[ prop ] = orig[ prop ]; + } + } + } + + this.element.trigger( event, data ); + return !( $.isFunction( callback ) && + callback.apply( this.element[0], [ event ].concat( data ) ) === false || + event.isDefaultPrevented() ); + } +}; + +$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { + $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { + if ( typeof options === "string" ) { + options = { effect: options }; + } + var hasOptions, + effectName = !options ? + method : + options === true || typeof options === "number" ? + defaultEffect : + options.effect || defaultEffect; + options = options || {}; + if ( typeof options === "number" ) { + options = { duration: options }; + } + hasOptions = !$.isEmptyObject( options ); + options.complete = callback; + if ( options.delay ) { + element.delay( options.delay ); + } + if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { + element[ method ]( options ); + } else if ( effectName !== method && element[ effectName ] ) { + element[ effectName ]( options.duration, options.easing, callback ); + } else { + element.queue(function( next ) { + $( this )[ method ](); + if ( callback ) { + callback.call( element[ 0 ] ); + } + next(); + }); + } + }; +}); + +})( jQuery ); diff --git a/Teknik/Scripts/jquery.tocify.min.js b/Teknik/Scripts/jquery.tocify.min.js new file mode 100644 index 0000000..5cbad17 --- /dev/null +++ b/Teknik/Scripts/jquery.tocify.min.js @@ -0,0 +1,4 @@ +/*! jquery.tocify - v1.9.1 - 2014-09-07 +* http://gregfranko.com/jquery.tocify.js/ +* Copyright (c) 2014 Greg Franko; Licensed MIT*/ +(function(e){"use strict";e(window.jQuery,window,document)})(function(e,t,s){"use strict";var i="tocify",o="tocify-focus",n="tocify-hover",a="tocify-hide",l="tocify-header",h="."+l,r="tocify-subheader",d="."+r,c="tocify-item",f="."+c,u="tocify-extend-page",p="."+u;e.widget("toc.tocify",{version:"1.9.1",options:{context:"body",ignoreSelector:null,selectors:"h1, h2, h3",showAndHide:!0,showEffect:"slideDown",showEffectSpeed:"medium",hideEffect:"slideUp",hideEffectSpeed:"medium",smoothScroll:!0,smoothScrollSpeed:"medium",scrollTo:0,showAndHideOnScroll:!0,highlightOnScroll:!0,highlightOffset:40,theme:"bootstrap",extendPage:!0,extendPageOffset:100,history:!0,scrollHistory:!1,hashGenerator:"compact",highlightDefault:!0},_create:function(){var s=this;s.extendPageScroll=!0,s.items=[],s._generateToc(),s._addCSSClasses(),s.webkit=function(){for(var e in t)if(e&&-1!==e.toLowerCase().indexOf("webkit"))return!0;return!1}(),s._setEventHandlers(),e(t).load(function(){s._setActiveElement(!0),e("html, body").promise().done(function(){setTimeout(function(){s.extendPageScroll=!1},0)})})},_generateToc:function(){var t,s,o=this,n=o.options.ignoreSelector;return t=-1!==this.options.selectors.indexOf(",")?e(this.options.context).find(this.options.selectors.replace(/ /g,"").substr(0,this.options.selectors.indexOf(","))):e(this.options.context).find(this.options.selectors.replace(/ /g,"")),t.length?(o.element.addClass(i),t.each(function(t){e(this).is(n)||(s=e("