diff --git a/.gitignore b/.gitignore index 055a749..acec4e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.idea +npm-debug.log .bundle db/*.sqlite3 log/*.log diff --git a/Gemfile b/Gemfile index 7193977..bf2e25d 100644 --- a/Gemfile +++ b/Gemfile @@ -21,9 +21,18 @@ gem 'devise', '~> 1.5.3' # Use CanCan for user authorization gem 'cancan' +# Use for decode json strings to object +gem 'yajl-ruby' + +#Use Markdown for parsing Markdown files +gem 'markdown' + # Use reCAPTCHA gem "recaptcha", :require => "recaptcha/rails" +# Use Redcarpet for parsing Markdown files +gem 'redcarpet' + # handle ajax image uploads gem 'remotipart' diff --git a/Gemfile.lock b/Gemfile.lock index 342140d..9f336a4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -102,11 +102,13 @@ GEM railties (>= 3.2.0, < 5.0) thor (~> 0.14) json (1.7.4) + kramdown (1.0.1) libv8 (3.3.10.4) libwebsocket (0.1.5) addressable linecache19 (0.5.13) ruby_core_source (>= 0.1.4) + logutils (0.6.0) mail (2.4.4) i18n (>= 0.4.0) mime-types (~> 1.16) @@ -120,6 +122,10 @@ GEM skinny (~> 0.2, >= 0.2.1) sqlite3 (~> 1.3) thin (~> 1.2) + markdown (1.0.0) + kramdown (>= 0.13.7) + props (>= 1.0.0) + textutils (>= 0.2.0) mime-types (1.19) multi_json (1.3.6) mysql2 (0.3.11) @@ -140,6 +146,7 @@ GEM mime-types polyglot (0.3.3) populator (1.0.0) + props (1.0.0) rack (1.4.1) rack-cache (1.2) rack (>= 0.4) @@ -170,6 +177,7 @@ GEM rdoc (3.12) json (~> 1.4) recaptcha (0.3.4) + redcarpet (2.2.2) remotipart (1.0.2) ruby-debug-base19 (0.11.26) columnize (>= 0.3.1) @@ -210,6 +218,8 @@ GEM rack (~> 1.0) tilt (~> 1.1, != 1.3.0) sqlite3 (1.3.6) + textutils (0.5.3) + logutils (~> 0.5) therubyracer (0.10.1) libv8 (~> 3.3.10) thin (1.4.1) @@ -233,6 +243,7 @@ GEM will_paginate (3.0.3) xpath (0.1.4) nokogiri (~> 1.3) + yajl-ruby (1.1.0) yui-compressor (0.9.6) POpen4 (>= 0.1.4) @@ -256,12 +267,14 @@ DEPENDENCIES jquery-rails linecache19 (= 0.5.13) mailcatcher + markdown mysql2 paperclip (~> 2.3) populator rails (= 3.2.6) rails_autolink recaptcha + redcarpet remotipart ruby-debug-base19 (= 0.11.26) ruby-debug19 (= 0.11.6) @@ -274,4 +287,5 @@ DEPENDENCIES uglifier (>= 1.0.3) whenever will_paginate + yajl-ruby yui-compressor diff --git a/app/assets/javascripts/sdk.js b/app/assets/javascripts/sdk.js index bd43c13..a0b1dd4 100644 --- a/app/assets/javascripts/sdk.js +++ b/app/assets/javascripts/sdk.js @@ -1,6 +1,5 @@ //= require sdk/widgetbuilder - -$(function() { +$(function(){ // Disabling these for now // var showVideoOverlay = function(){ @@ -16,7 +15,6 @@ $(function() { // $("#videocontent_overlay").animate({opacity:'toggle'}, 300); // }); // }; - var TITLE_BASE = 'Sakai OAE Widget Library - SDK'; var History = window.History; var $lhnav = $(".wl-content-container #lhnavigation_container ul"); @@ -30,22 +28,23 @@ $(function() { var $parentElement = $toSelectElement.closest(".subnav"); // Check whether the element is a parent element or not - if($parentElement.length){ + if ($parentElement.length){ // it is a child element $toSelectElement.closest("li").addClass("selected"); $parentElement.show().prev().addClass("selected_parent"); - } else { + } else{ $toSelectElement.closest("li").addClass("selected").next().show(); } }; - $(window).on('statechange', function() { + $(window).on('statechange', + function(){ var state = History.getState(); // Update the left hand navigation updateLhnav(state); $.ajax({ url: state.url, - success: function(data) { + success: function(data){ var $containerResponse = $("
").html(data); var $sdkxhrContent = $containerResponse.find("#sdkxhr_content"); $(".wl-content-container .widgetsdk_container").html($sdkxhrContent); @@ -58,59 +57,116 @@ $(function() { }); }); + var addClassesToMarkdownText = function(){ + $('#development-environment-setup').find('ul').addClass('inline_list'); + $('#development-environment-setup').find('ol').addClass('inline_list'); + $('#development-environment-setup').find('a').addClass('wl-regular-link'); + }; + var addBinding = function(){ // $("#developer_videocontent_container").live("click", showVideoOverlay); // $("#videocontent_overlay").live("click", hideVideoOverlay); - $(".expand_all_link").live("click", function(){ + $(".expand_all_link").live("click", + function(){ var expanded = $(".expand_all_link").attr("data-expanded"); - if(expanded === "true"){ + if (expanded === "true"){ $(".expand_all_link").attr("data-expanded", "false"); - }else{ + } else{ $(".expand_all_link").attr("data-expanded", "true"); } $(this).children("span").toggle(); - $.each($(".expandable_container"), function(i, container){ + $.each($(".expandable_container"), + function(i, container){ container = $(container); - if(container.is(":visible") && expanded === "true"){ - container.animate({'height': 'toggle', 'opacity': 'toggle'}, 500); + if (container.is(":visible") && expanded === "true"){ + container.animate({ + 'height': 'toggle', + 'opacity': 'toggle' + }, + 500); container.prevAll("h3").children("a").attr("data-expanded", false); container.prevAll("h3").find("span").toggle(); - } else if(!container.is(":visible") && expanded !== "true"){ - container.animate({'height': 'toggle', 'opacity': 'toggle'}, 500); + } else if (!container.is(":visible") && expanded !== "true"){ + container.animate({ + 'height': 'toggle', + 'opacity': 'toggle' + }, + 500); container.prevAll("h3").children("a").attr("data-expanded", true); container.prevAll("h3").find("span").toggle(); } }); }); - $(".expand_link").live("click", function(){ + $(".expand_link").live("click", + function(){ $(this).children("span").toggle(); var $container = $(this).parents(".wl-widget-item").children(".expandable_container"); if ($container.is(":visible")){ $container.prevAll("h3").children("a").attr("data-expanded", false); - $container.animate({'height': 'toggle'}, 500); - } else { + $container.animate({ + 'height': 'toggle' + }, + 500); + } else{ $container.prevAll("h3").children("a").attr("data-expanded", true); - $container.animate({'height': 'toggle'}, 500); + $container.animate({ + 'height': 'toggle' + }, + 500); } }); - $("body").on("click", '#lhnavigation_container a, .wl-content-container .wl-content-right-container a[href^="/sdk/"]', function(evt){ + $("body").on("click", '#lhnavigation_container a, .wl-content-container .wl-content-right-container a[href^="/sdk/"]', + function(evt){ // Disable the default click behavior - evt.preventDefault(); + // evt.preventDefault(); // Cache the this selector var $this = $(this); var url = $this.attr("href"); var title = TITLE_BASE + ' - ' + $this.text(); var state = { section: url - }; + };d History.pushState(state, title, url); }); + + $('#reusable-css').find('.wl-widget-item h3').bind('click', function(e){ + $(e.currentTarget).next().slideToggle(); + return false; + }) + + $('#dpdVersions').change(function(e){ + var version = $(e.currentTarget).val(); + document.location = "/sdk/style-guide/reusable-css/" + version + }) + }; + + var hideCSSContentContainers = function(){ + $('#reusable-css').find('.wl-widget-item .css-content').hide(); + }; + + var showFirstCSSContentContainer = function(){ + $('#reusable-css').find('.wl-widget-item .css-content').first().show(); + }; + var splitCodeTagsOnLinebreaks = function(){ + var arrParagraphs = $("#development-environment-setup").find('p'); + $.each(arrParagraphs, + function(i){ + if (arrParagraphs[i].firstChild.tagName == "CODE"){ + var child = $(arrParagraphs[i]).find('code'); + $(child).addClass('well'); + $(child).html($(child).html().replace(/\n/g, '
')); + } + }) }; var init = function(){ + splitCodeTagsOnLinebreaks(); + hideCSSContentContainers(); + showFirstCSSContentContainer(); + addClassesToMarkdownText(); addBinding(); }; diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss index 4a7e181..81c9005 100644 --- a/app/assets/stylesheets/application.css.scss +++ b/app/assets/stylesheets/application.css.scss @@ -116,6 +116,10 @@ option { margin-right: 15px; } +.wl-margin-top-0 { + margin-top: 0 !important; +} + .wl-margin-top-9 { margin-top: 9px; } @@ -174,14 +178,26 @@ option { width: 145px; } +.wl-content-160 { + width: 160px; +} + .wl-content-165 { width: 165px; } +.wl-content-175 { + width: 175px; +} + .wl-content-185 { width: 185px; } +.wl-content-505 { + width: 505px; +} + .wl-content-710 { width: 710px; } diff --git a/app/assets/stylesheets/sdk.css.scss b/app/assets/stylesheets/sdk.css.scss index 4b2e1b7..5591417 100644 --- a/app/assets/stylesheets/sdk.css.scss +++ b/app/assets/stylesheets/sdk.css.scss @@ -4,6 +4,9 @@ p { line-height: 1.4em; } + code{ + word-wrap: break-word; + } .wl-content-container#developer_container { background: image-url("container_bg.png") no-repeat scroll center top transparent; @include border-radius(12px 12px 0 0); @@ -121,6 +124,207 @@ padding-right: 0; } } + #reusable-css { + .top{ + height: 50px; + position: relative; + h1, #frmVersions{ + width: 100%; + position: absolute !important; + } + h1{ + left: 0; + z-index: 500 !important; + } + #frmVersions{ + right: 0; + z-index: 1000 !important; + text-align: right; + line-height: 25px; + } + } + .wl-widget-item { + h3 { + margin-top: 0; + cursor: pointer; + padding-bottom: 15px; + text-transform: lowercase; + &:first-letter { + text-transform: uppercase; + } + a { + color: #2683BC; + text-decoration: none; + } + } + .css-content { + p.description, pre.selector, ul.snippets{ + display: block; + } + p.description { + line-height: 1.4em; + margin-bottom: 10px; + } + pre.selector, ul.snippets, div.snippet-demo { + padding: 10px; + } + pre.selector, ul.snippets, div.snippet-demo { + margin-bottom: 20px; + border: 1px solid #EEEEEE; + } + pre.selector{ + background-color: #FEFEFE; + br:first-child{ + display: none; + } + } + ul.snippets { + background-color: #EFEFEF; + li { + font-size: .9em; + line-height: 1.5em; + list-style-type: none; + } + } + div.snippet-demo { + overflow: hidden; + } + iframe { + width: 100%; + height: 170px; + margin-top: 5px; + margin-bottom: 20px; + } + } + &:first-of-type { + margin-top: 0 !important; + } + } + } + #development-environment-setup { + code:not(.well) { + color: red; + } + code.well { + padding: 10px; + display: block; + background-color: #FEFEFE; + border: 1px solid #EEEEEE; + + br:first-child{ + display: none; + } + } + } + #api_docs_modules_navigation { + width: 163px; + overflow: hidden; + margin-right: 10px; + border-radius: 4px; + border: 1px solid #DDDDDD; + p { + margin: 0; + padding: 0; + border-top: 1px solid #EEEEEE; + &:first-child{ + border-top: none; + } + } + a { + display: block; + width: 100%; + height: 25px; + font-size: 1.1em; + padding: 7px 5px 2px 5px; + background-color: #FDFDFD; + + &.selected, &:hover{ + color: white; + text-decoration: none; + background-color: #2683BC; + } + } + } + #api_docs_modules_detail{ + a { + text-decoration: none; + &:hover { + text-decoration: underline; + } + } + blockquote { + font-size: 14px; + padding-left: 1em; + margin-top: 10px; + margin-bottom: 15px; + h2 { + font-size: 1.2em; + } + h3 { + font-size: 1em; + } + ul > li { + margin-left: 10px; + margin-bottom: 10px; + list-style-position: inside; + } + br { + display: none; + } + code { + font-size: 14px !important; + color: red; + } + } + h1, h2, h3, h4 { + color: #2683BC; + a { + color: #2683BC; + } + } + h1 { + font-size: 2.1em; + } + h2 { + font-size: 1.6em; + } + h3 { + font-size: 1.4em; + } + h4 { + font-size: 1.2em; + } + small { + font-size: .9em; + } + table, tr, td, th { + text-align: left; + } + table { + width: 100%; + padding: 0; + border-width: 0; + margin-bottom: 10px; + background-color: white; + } + tbody tr:nth-child(even){ + background-color: #FAFAFA; + } + th { + font-size: 1.1em; + padding: 7px 8px; + font-weight: normal; + background-color: #EEEEEE; + } + td { + margin: 5px 0; + padding: 10px 8px; + strong { + display: inline-block; + margin-bottom: 5px; + } + } + } } @import "sdk/widgetsdk.css.scss"; diff --git a/app/assets/stylesheets/temp.css b/app/assets/stylesheets/temp.css new file mode 100644 index 0000000..9fa93d3 --- /dev/null +++ b/app/assets/stylesheets/temp.css @@ -0,0 +1,1097 @@ +/*! + * Copyright 2012 Sakai Foundation (SF) Licensed under the + * Educational Community License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may + * obtain a copy of the License at + * + * http://www.osedu.org/licenses/ECL-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an "AS IS" + * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +/****************** + * ACCESSIBILITY ** + ******************/ + +/** + * Used for accessibility purposes as it allows to put text content + * for items that might not have text content (e.g. icons) or create + * additional clues for screenreader users + * e.g. + */ +.oae-aural-text { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + +/** + * Style that can be used for links if we just want them to have the same color as the + * text. These links will be underlined when hovering over them. + * e.g. Google + */ +a.oae-plain-link:hover { + text-decoration: underline; +} + + +/*************** + ** THREEDOTS ** + **************/ + +/** + * Style that can be applied to text elements to make sure that the text in a text element + * doesn't use more than the space it has available. If the text is shorter than the + * available space, this will leave the text unchanged. If the text is longer than the available + * space, it will be cut off at its maximum length and will be appended with `...`. In order for + * this to work, the text element will need to have a maximum width set. + * e.g. Some very very long text + */ + +.oae-threedots { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + + +/************ + ** PANELS ** + ************/ + +/** + * Panels that can be used to show HTML content on top of a background + * color or background image. Three different panels can be used + * - `oae-panel-primary`: Panel that contains content that should really stand out + * - `oae-panel-secondary`: Panel that contains the secondary content + * - `oae-panel-tertiary`: Other panel content (e.g. search box on the landing page) + * e.g.
...
+ */ +.oae-panel-primary, .oae-panel-secondary, .oae-panel-tertiary { + padding: 15px; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +/********************** + ** VISIBILITY ICONS ** + **********************/ + +/** + * These icons are used consistently to indicate the visibility setting for an entity + * in the system. The available visibility privacy options are `private`, `loggedin` and + * `public`. + * e.g. __MSG__PRIVATE__ + * __MSG__LOGGED_IN__ + * __MSG__PUBLIC__ + * + * Large icons can be rendered by adding the `large` class to the icon. + * e.g. __MSG__PRIVATE__ + * __MSG__LOGGED_IN__ + * __MSG__PUBLIC__ + * + * Note: + * + * - The `oae-aural-text` span is added in for accessibility purposes, but can be left out when necessary. + */ + +i.icon-oae-private, +i.icon-oae-loggedin, +i.icon-oae-public { + font-size: 100%; + width: 18px; + height: 18px; +} + +i.icon-oae-private:before, +i.icon-oae-loggedin:before, +i.icon-oae-public:before { + -webkit-border-radius: 500px; + -moz-border-radius: 500px; + border-radius: 500px; + color: #313131; + font-size: 15px; + width: 18px; + height: 16px; + padding-top: 1px; + text-align: center; +} + +i.icon-oae-private:before { + background-color: #FFBC78; + content: "\f023"; +} + +i.icon-oae-loggedin:before { + background-color: #C4E6FF; + content: "\f041"; +} + +i.icon-oae-public:before { + background-color: #A6E0AB; + content: "\f0ac"; +} + +/* Large visibility icons */ + +i.icon-oae-private.large:before, +i.icon-oae-loggedin.large:before, +i.icon-oae-public.large:before { + font-size: 50px; + height: 55px; + padding-top: 5px; + width: 60px; +} + + +/************************ + ** VISIBILITY TOGGLES ** + ************************/ + +/** + * A Large group of toggle buttons for visibility settings. + * When an `oae-visibility-choice input` field changes value the + * `oae-visibility-changed` event is sent out with data: `{'radio': $(input)}` + * + * e.g.
+ * + * + * + *
+ **/ + +.oae-visibility-choice-container .oae-visibility-choice { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + height: 150px; + margin: 0 10px 20px 0; + width: 100%; +} + +.oae-visibility-choice-container label:last-child .oae-visibility-choice { + margin-right: 0; +} + +.oae-visibility-choice-container .oae-visibility-choice input { + position: absolute; + z-index: -1; /* Adding a z-index of -1 hides the element from the view but still allows for focus of the element */ +} + +.oae-visibility-choice-container .oae-visibility-choice span { + display: block; + font-size: 13px; + font-weight: bold; + margin-top: 7px; +} + +.oae-visibility-choice-container .oae-visibility-choice.checked { + border: 8px solid; + padding-top: 12px; +} + +.oae-visibility-choice-container .oae-visibility-choice + i { + display: none; +} + +.oae-visibility-choice-container .oae-visibility-choice.checked + i { + -webkit-border-radius: 100px; + -moz-border-radius: 100px; + border-radius: 100px; + bottom: 26.5%; + display: block; + margin-left: 65px; + position: absolute; +} + +.oae-visibility-choice-container .oae-visibility-choice.checked + i:before { + font-size: 24px; + height: 30px; + padding-top: 5px; + width: 35px; +} + + +/************************ + ** SUCCESS/FAIL ICONS ** + ************************/ + +/* These icons are used in situations where checks for success/failure are done */ + + +[class^="icon-"].icon-ok, +[class*=" icon-"].icon-ok, +[class^="icon-"].icon-ok:hover, +[class*=" icon-"].icon-ok:hover { + color: #468847; +} + +[class^="icon-"].icon-warning-sign, +[class*=" icon-"].icon-warning-sign, +[class^="icon-"].icon-warning-sign:hover, +[class*=" icon-"].icon-warning-sign:hover { + color: #DD2222; +} + +/**************** + ** THUMBNAILS ** + ****************/ + +/** + * A thumbnail can be used to show a thumbnail picture/profile picture for an + * entity. It will also attempt to set a default thumbnail in case no actual + * image is available, and it allows for showing a visibility icon combined with + * the thumbnail. These thumbnails will adjust in size to the space they have + * been given by their container. + * + * e.g.
+ * + * John Librarian + * + * + *
+ * + * Next to using the HTML structure, there is also a Trimpath macro that can be used + * instead from all Trimpath templates: + * + * `${renderThumbnail(entityData, [addVisibilityIcon], [large])}` + * + * - `entityData` is a standard object representing a user, group or content item or a search result for a user, group + * or content item as returned by Hilary. Alternatively, a string representing the resourceType or resourceSubType + * (i.e., 'user', 'group', 'content', 'file', 'link', 'collabdoc') can be passed in for an empty/anonymous + * entity thumbnail. + * - `addVisibilityIcon` (optional) will determine whether or not the visibility icon should be shown. By default, + * the visibility icon will be shown. However, users will not never show a visibility icon. + * - `large` (optional) determines whether or not a large default thumbnail icon should used. By default, a small icon will be used. + * + * Notes: + * + * - The actual thumbnail image is optional, and if no image is specified the + * thumbnail will show a default entity thumbnail. In order to do this, + * `icon-oae-user` should be added to the `oae-thumbnail` div for users, + * `icon-oae-group` should be added to the `oae-thumbnail` div for groups, + * `icon-oae-discussion` should be added to the `oae-thumbnail` div for discussions, + * `icon-oae-content` should be added to the `oae-thumbnail` div for generic content, + * `icon-oae-file` should be added to the `oae-thumbnail` div for uploaded files, + * `icon-oae-link` should be added to the `oae-thumbnail` div for links and + * `icon-oae-collabdoc` should be added to the `oae-thumbnail` div for collaborative documents. + * Even when an image is provided, the entity icon class can still be added as + * it will be used when the image cannot be downloaded. + * - For large thumbnails (> 100px width/height), the `oae-thumbnail-large` class + * should be added to the `oae-thumbnail` container. It will cause the default + * thumbnail to be larger. + * - An optional visibility icon can be added to the thumbnail as well and will + * automatically be positioned correctly. The available visibility icons are + * `icon-oae-private`, `icon-oae-loggedin` and `icon-oae-public` (See Visibility + * icons section). + * - The link inside of the thumbnail can be used to link to the entity's profile page. + * This link is optional and can be left out. + */ + +div.oae-thumbnail { + width: 100%; + height: 100%; + text-align: center; + display: inline-block; + position: relative; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.35); + -moz-box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.35); + box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.35); +} + +div.oae-thumbnail a, +div.oae-thumbnail img { + position: absolute; + left: 0; + top: 0; + min-width: 100%; + height: 100%; + font-size: 12px; +} + +div.oae-thumbnail:before { + font-size: 20px; + padding-top: 50%; + margin-top: -11px; +} + +div.oae-thumbnail.oae-thumbnail-large:before { + font-size: 50px; + margin-top: -25px; +} + +/* Default entity thumbnails */ + +div.oae-thumbnail.icon-oae-content:before, div.oae-thumbnail.icon-oae-file:before { + content: "\f016"; +} + +div.oae-thumbnail.icon-oae-link:before { + content: "\f0c1"; +} + +div.oae-thumbnail.icon-oae-collabdoc:before { + content: "\f044"; +} + +div.oae-thumbnail.icon-oae-discussion:before { + content: "\f086"; +} + +div.oae-thumbnail.icon-oae-group:before { + content: "\f0c0"; +} + +div.oae-thumbnail.icon-oae-user:before { + content: "\f007"; +} + +/* Visibility icon positioning */ + +div.oae-thumbnail i[class^="icon-"] { + position: absolute; + bottom: -8px; + right: -8px; +} + + +/*********** + ** CLIPS ** +***********/ + +/** + * Clips are the elements that are used for page (entity) titles and page actions. + * They are folded onto the top of a container, which is usually the main page content + * container. Each clip can have a set of actions associated to it, which will automatically + * show when opening the clip through the dropdown icon. + * + * The HTML structure required for creating a clip is the following: + * + *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * + *
+ *
    + *
  • + *
  • + *
  • + *
+ *
+ *
+ *
+ *
+ *
+ * + * Notes: + * + * - A clip needs to be inside of an `oae-clip-container` div. Inside of this container, you can specify the + * clips that should go on the left by adding them to a `oae-clip-container-left` div. You can specify the + * clips that should go on the right by adding them to a `oae-clip-container-right div inside of this container. + * - The fold on a clip can be on the left of the clip or on the right of the clip. By default, the + * fold will be on the right. When a fold on the left is required, an `oae-clip-flipped` class should + * be added to the .`oae-clip` element. + * - Clips are available in two different skinnable styles. By default, the primary style will be used. If + * the secundary style is needed, this can be done by adding an 'oae-clip-secondary' class to the + * `.oae-clip` element. + * - A thumbnail image can be added to the clip by adding an `oae-thumbnail` div as the first element of the + * main button. This can also show a default entity picture (in case no image is provided) as well as a + * visibility icon (See the `Thumbnail` section for details on how to create a thumbnail). + * The thumbnail image is optional and can be left out as well. + * - The `icon-caret-down` element is optional. If it is not provided, the clip will be shown in view + * only mode. If it is provided, the clip will be toggleable and the action menu will be shown when clicked. + * - The `small` tag is used to show some additional clip metadata and is optional. + * - When a clip should not be clickable (e.g. in non-manager mode of a page), the `disabled` attribute + * should be added to the button. This will hide any caret icons and will make the clip unclickable. + */ + +/* Clip container */ + +.oae-clip-container { + position: relative; + margin-bottom: 55px; +} + +.oae-clip-container .oae-clip-container-left, +.oae-clip-container .oae-clip-container-right { + position: absolute; +} + +.oae-clip-container .oae-clip-container-right { + margin-right: 55px; + right: 0px; +} + +.oae-clip { + float: left; + margin: -16px 10px 10px; + position: relative; + z-index: 100; +} + + + +/* Clip fold */ + +.oae-clip .oae-clip-fold { + height: 6px; + float: right; + margin-right: -7px; + position: relative; + width: 7px; + z-index: 10; +} + +.oae-clip.oae-clip-flipped .oae-clip-fold { + float: left; + margin-left: -9px; +} + +.oae-clip .oae-clip-fold .oae-clip-fold-inner { + -webkit-border-radius: 50px 50px 0 0; + -moz-border-radius: 50px 50px 0 0; + border-radius: 50px 50px 0 0; + float: left; + height: 6px; + margin-left: -1px; + position: absolute; + width: 9px; + z-index: 1; +} +.oae-clip.oae-clip-flipped .oae-clip-fold .oae-clip-fold-inner { + margin-left: 0; +} + +.oae-clip .oae-clip-fold .oae-clip-fold-outer { + float: right; + height: 6px; + margin-left: -5px; + position: absolute; + width: 7px; + z-index: 0; +} +.oae-clip.oae-clip-flipped .oae-clip-fold .oae-clip-fold-outer { + margin-left: 4px; +} + +/* Clip content */ + +.oae-clip .oae-clip-content { + -webkit-border-radius: 6px 0 6px 6px; + -moz-border-radius: 6px 0 6px 6px; + border-radius: 6px 0 6px 6px; + -webkit-box-shadow: 0 1px 2px 1px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 1px 2px 1px rgba(0, 0, 0, 0.3); + box-shadow: 0 1px 2px 1px rgba(0, 0, 0, 0.3); +} + +.oae-clip.oae-clip-flipped .oae-clip-content { + -webkit-border-radius: 0 6px 6px; + -moz-border-radius: 0 6px 6px; + border-radius: 0 6px 6px; +} + +.oae-clip .oae-clip-content > button, +.oae-clip .oae-clip-content ul li button { + background: none; + border: none; + font-weight: 600; + padding: 14px 20px 14px 14px; + text-align: left; +} + +.oae-clip .oae-clip-content > button:disabled { + cursor: default; +} + +.oae-clip .oae-clip-content > button > div { + float: left +} + +.oae-clip .oae-clip-content > button > div:nth-child(2) > div { + display: table-cell; + height: 35px; + vertical-align: middle; +} + +.oae-clip .oae-clip-content > button div.oae-thumbnail { + height: 35px; + width: 35px; + margin-right: 12px; +} + +.oae-clip .oae-clip-content > button i.icon-caret-down, +.oae-clip .oae-clip-content > button i.icon-caret-up { + margin-left: 10px; + line-height: 16px; + position: relative; + top: 2px; +} + +.oae-clip .oae-clip-content > button:disabled i.icon-caret-down, +.oae-clip .oae-clip-content > button:disabled i.icon-caret-up { + display: none; +} + +.oae-clip .oae-clip-content h1 { + display: inline-block; + font-size: 16px; + line-height: 1; + margin: 0px; + font-weight: 600; + max-width: 500px; + word-wrap: break-word; +} + +.oae-clip .oae-clip-content small { + clear: both; + display: block; + font-size: 12px; + line-height: 1; + font-weight: normal; + white-space: nowrap; +} + +/* Clip actions */ + +.oae-clip .oae-clip-content ul { + list-style: none; + margin: 0 10px; + display: none; +} + +.oae-clip .oae-clip-content ul li { + display: inline; +} + +.oae-clip .oae-clip-content ul li button { + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + font-size: 11px; + min-width: 70px; + padding: 10px; + margin-bottom: 10px; + text-align: center; +} + +.oae-clip .oae-clip-content ul li button i { + display: block; + margin: 0 auto 3px; +} + + +/*********** + ** TILES ** + ***********/ + +/** + * A tile is a combination of a preview image and some entity metadata in a + * polaroid-like appearance. The preview image will take up the bulk of the + * space, with a bar at the bottom overlapping with the image that can show + * metadata. Tiles will adjust in size to the space they have been given by + * their container. + * + * The following HTML structure should be used to create a tile: + * + *
+ * + *
+ * John Librarian + *
+ *
+ *
+ * + *

+ * John Librarian + *

+ * Professor + *
+ *
+ * + * Notes: + * + * - The `oae-thumbnail` element, containing the preview image, is a standard + * `oae-thumbnail` element (See Thumbnail section for full overview). + * - The `oae-threedots` class should be added to metadata elements if you want + * to make sure that `...` is shown when the metadata is longer than the available + * space in the tile. + * - The actual content of the metadata div can be pretty much anything, although an + * h3 should be used for the tile title. + * - The `small` element used to add some additional metadata is optional. + * - The visibility icon can be used as defined in the Visibility icon section, and + * can be floated on the left or right. + */ + +.oae-tile { + position: relative; + overflow: hidden; + border: 1px solid; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +/* Default thumbnail picture positioning */ + +.oae-tile .oae-thumbnail { + -webkit-border-radius: 0px; + -moz-border-radius: 0px; + border-radius: 0px; +} + +.oae-tile .oae-thumbnail:before { + margin-top: -30px; +} + +.oae-tile .oae-thumbnail.oae-thumbnail-large:before { + margin-top: -50px; +} + +/* Tile metadata */ + +.oae-tile > div:last-child { + position: absolute; + bottom: 0px; + right: 0px; + left: 0px; + padding: 7px; +} + +.oae-tile h3, +.oae-tile h3 a { + font-size: 14px; + font-weight: bold; + line-height: 1.3; + margin: 0px; +} + +.oae-tile small { + font-size: 11px; + font-style: italic; + font-weight: normal; + text-transform: uppercase; +} + + +/**************** + ** LIST ITEMS ** + ****************/ + +/* + * A list item is a way of displaying an entity and is a combination of a preview image, + * some entity metadata, a checkbox and actions that can be taken on the entity. A list + * item can be used as part of a larger list, but can also be used outside of a list to + * present a single entity. List items will adjust in size to the space they have been + * given by their container. + * + * The following HTML structure should be used to create a list item: + * + *
+ * + * + *
+ * John Librarian + * + *
+ *
+ *

John Librarian

+ * Professor + *
+ *
+ * + *
+ *
+ * + * Notes: + * + * - A list item is available in an expanded size and a compact size. By default, the larger expanded + * view will be used. In order to use the smaller compact view, the class `oae-listitem-compact` + * should be added to the `oae-listitem` element. + * - A checkbox can be added to the list item for management purposes. This checkbox should have an + * accompanying `oae-aural-text` label for accessibility purposes. + * - An action bar can be added to the list item by adding an `oae-listitem-actions` div to the list + * item. This action bar can contain one or multiple action buttons. + * - The `oae-thumbnail`, `oae-listitem-actions` and checkbox are all optional. + * - The `small` element used to add some additional metadata is optional as well. + * - The `oae-thumbnail` element, containing the preview image, is a standard + * `oae-thumbnail` element (See Thumbnail section for full overview). + */ + +.oae-tile, +.oae-listitem { + -webkit-box-shadow: 0 0 2px 0 rgba(219, 219, 219, 0.8); + -moz-box-shadow: 0 0 2px 0 rgba(219, 219, 219, 0.8); + box-shadow: 0 0 2px 0 rgba(219, 219, 219, 0.8); +} + +.oae-listitem { + padding: 10px; + margin-bottom: 10px; + height: 50px; + border: 1px solid; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +.oae-listitem.oae-listitem-compact { + height: 25px; +} + +.oae-listitem input[type="checkbox"].pull-left { + margin-right: 10px; + margin-top: 20px; +} + +.oae-listitem.oae-listitem-compact input[type="checkbox"].pull-left { + margin-top: 6px; +} + +/* List item thumbnail */ + +.oae-listitem .oae-thumbnail { + float: left; + height: 50px; + width: 50px; + margin-right: 15px; +} + +.oae-listitem.oae-listitem-compact .oae-thumbnail { + height: 25px; + width: 25px; +} + +/* List item metadata */ + +.oae-listitem > div:not(.oae-thumbnail) { + display: table-cell; + vertical-align: middle; + height: 50px; +} + +.oae-listitem.oae-listitem-compact > div:not(.oae-thumbnail) { + height: 25px; + width: auto; +} + +.oae-listitem h3 { + display: inline-block; + font-size: 16px; + font-weight: 500; + line-height: 1.4; + margin: 0; + max-width: 450px; +} + +.oae-listitem small { + line-height: 1; + font-size: 11px; + font-style: italic; + text-transform: uppercase; +} + +.oae-listitem.oae-listitem-compact small { + display: inline-block; + line-height: 1.6; + margin-left: 20px; +} + +/* List item actions */ + +.oae-listitem .oae-listitem-actions { + width: 100%; + text-align: right; +} + +.oae-listitem .oae-listitem-actions i { + font-size: 18px; +} + + +/*********** + ** LISTS ** + ***********/ + +/** + * Lists are used as the core component for multiple widgets (library, membership, participants, + * search, etc.) and present a list of entities that can be viewed in 3 separate view modes (grid, + * details and compact). + * + * The HTML for a list item has been abstracted into a globally available TrimPath template that + * can be used when rendering list view items: + * + * `${listItem(entityData, [pagingKey], [metadata], [showCheckbox])}` + * + * - `entityData` is an object representing a user, group or content item or a search result for a user, group + * or content item + * - `pagingKey` (optional) is the key that should be used for paging through the infinite scroll plugin + * - `metadata` (optional) is a line of metadata information that should be displayed underneath the entity name + * - `showCheckbox` (optional) will determine whether ot not the checkbox should be shown. By default, the checkbox will be shown to all logged in users + * + * The output from this macro represents a single list (li) item, and should be wrapped in a list container (ul) + * element with an `oae-list` class. In order to show the grid view, an `oae-list-grid` class should be added to + * the list, in order to show the details view, an `oae-list-details` class should be added to the list and in order + * to show the compact view, an `oae-list-compact` class should be added to the list: + * + * e.g. + */ + +/* Core list styles */ + +ul.oae-list { + margin: 0; + padding: 0; + clear: both; +} + +ul.oae-list li { + list-style: none; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +ul.oae-list:not(.oae-list-grid) li .oae-list-grid-item, +ul.oae-list:not(.oae-list-details) li .oae-list-details-item, +ul.oae-list:not(.oae-list-compact) li .oae-list-compact-item { + display: none; +} + +/* Grid view */ + +ul.oae-list.oae-list-grid li { + float: left; + margin: 0px 14px 24px 0px; +} + +ul.oae-list.oae-list-grid li .oae-thumbnail { + height: 162px; + width: 162px; +} + +/* Details and compact view */ + +ul.oae-list li .oae-list-details-item, +ul.oae-list li .oae-list-compact-item { + display: table; + width: 100%; +} + + +/****************** + ** LIST OPTIONS ** + ******************/ + +/** + * The list options can be shown at the top of a list, providing a title for the list, as well + * as possibly a list search form, list actions, view mode switching, etc. + * + * Some example HTML for a list options view: + * + *
+ *
+ * + *
+ * + *
+ *
+ *
+ * + * + * + * + *
+ * + * + * + *
+ *
+ *
+ * + * Notes: + * + * - The `oae-list-options-toggle` item is used to show the title of the list, and will also be used to toggle + * the actions bar. This will be enabled automatically by the system. If a list needs to be shown in view-only + * mode, this element should be set to disabled, in which case the dropdown icon will disappear and the toggle + * will no longer work. + * - The `oae-list-options-actions` div represents the action bar that will be toggled when the `oae-list-options-toggle` + * element is clicked. This bar contains all of the action that can be done on the selected list items, and + * can basically be anything. + * - An `oae-list-selectall` class can be applied to the element that should be used to select/deselect all list + * items. This will be enabled automatically by the system. + */ + +.oae-list-options { + border-bottom: 1px solid #EEE; + margin-bottom: 20px; +} + +.oae-list-options > div { + line-height: 30px; + margin-bottom: 15px; + clear: both; +} + +.oae-list-options .oae-list-options-toggle, +.oae-list-options .btn.oae-list-options-toggle, +.oae-list-options .btn.oae-list-options-toggle:hover, +.oae-list-options .btn.oae-list-options-toggle:active, +.oae-list-options .btn.oae-list-options-toggle:focus { + background: none; + border: none; + padding: 1px 0px; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.oae-list-options .oae-list-options-toggle h2 { + margin: 0; + font-size: 20px; + line-height: 1; +} + +.oae-list-options .oae-list-options-toggle h2 .badge { + margin-left: 5px; + top: -4px; +} + +.oae-list-options .oae-list-options-toggle:disabled { + cursor: auto; +} + +.oae-list-options .oae-list-options-toggle:disabled .icon-caret-down, +.oae-list-options .oae-list-options-toggle:disabled .icon-caret-up { + display: none; +} + +.oae-list-options form { + margin-bottom: 0px; +} + +/* Actions bar */ + +.oae-list-options .oae-list-options-actions > input, +.oae-list-options .oae-list-options-actions > button { + margin-right: 7px; +} + +.oae-list-options .oae-list-options-actions .btn i { + font-size: 18px; +} + +.oae-list-options .btn-group .btn i { + font-size: 12px; +} + + + + +/*ul.oae-list li.oae-list-item.oae-list-item-dnd { + border: none; + display: none; +} +ul.oae-list li.oae-list-item.oae-list-item-dnd:first-child { + display: block; +} +ul.oae-list li.oae-list-item.oae-list-item-dnd .oae-list-dnd-container { + border: 1px solid #F5F5F5; + height: 120px; +} +ul.oae-list li.oae-list-item.oae-list-item-dnd .oae-list-dnd-container > div { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + border: 1px dashed #999; + height: 112px; + margin: 4px; +} +ul.oae-list li.oae-list-item.oae-list-item-dnd .oae-list-dnd-container .oae-list-dnd-label { + color: #999; + font-size: 13px; + font-style: italic; + line-height: 1.3; + margin: 10px auto 0; + width: 100px; +} +ul.oae-list li.oae-list-item.oae-list-item-dnd .oae-list-dnd-container .oae-trigger-addcontent, +ul.oae-list li.oae-list-item.oae-list-item-dnd .oae-list-newdocument { + display: block; + margin: 10px auto; +} +ul.oae-list li.oae-list-item.oae-list-item-dnd .oae-list-dnd-container .oae-trigger-addcontent i, +ul.oae-list li.oae-list-item.oae-list-item-dnd .oae-list-newdocument i { + color: #333; + font-size: 18px; +}*/ diff --git a/app/controllers/sdk_controller.rb b/app/controllers/sdk_controller.rb index 81e81fd..123e6c9 100644 --- a/app/controllers/sdk_controller.rb +++ b/app/controllers/sdk_controller.rb @@ -1,8 +1,105 @@ class SdkController < ApplicationController - def index - render :layout => 'application' - end - def sdk_section - render params[:section].split('/').last, :layout => request.xhr? ? 'sdkxhr' : 'lhnavigation' - end + require 'net/http' + require 'open-uri' + require 'redcarpet' + require 'yajl' + include SdkHelper + + # Properties + + @@url_readme_file = 'https://raw.github.com/sakaiproject/Hilary/master/README.md' + @@url_rest_api_doc = 'http://tenant1.oae.com/api/doc/' + @@url_css_file = 'http://tenant1.oae.com/shared/oae/css/oae.components.css' + + # Show index page of SDK + + def index + render :layout => 'application' + end + + # Show section of SDK (e.g. api, faq...) + + def sdk_section + + # Properties + @modules = nil + + # The requested template + template = params[:section] + + # If section is 'api' + if template == 'api' + + # Path to the template + template = "sdk/api/index" + + # Show front or back end + if !params[:subsection].blank? + + # Load the module names + @modules = get_doc_module_names(@@url_rest_api_doc + params[:subsection]) + + # If the modules are not empty + if !@modules.blank? + + # Set module title + @subsection = params[:subsection] + + # Set the url for the HTTPRequest + if !params[:module].blank? + url = params[:module] + @module_title = params[:module] + + # Re-render the lhnavigation + render template, :layout => 'lhnavigation' if request.xhr? + + else + url = @modules.first + @module_title = @modules.first + end + + # Get the module details + @content = get_doc_details(@@url_rest_api_doc + params[:subsection] + '/' + url) + + # Set the variables for rendering the page + locals = { :modules => @modules, :subsection => @subsection, :content => @content, :title => @module_title } + + end + + end + + # If section is 'style-guide' & subsection is 'reusable-css' + elsif template == 'style-guide' && params[:subsection] == 'reusable-css' + + # Path to the template + template = "sdk/style-guide/reusable-css" + + # Get the versions + @versions = get_skins_from_directory + if @versions.length > 0 + + # Check if version is set in the querystring + @version = @versions.first() + if !params[:module].blank? + @version = params[:module] + end + + end + + # Pass the content as a parameter for the view variables + locals = { :version => @version, :versions => @versions } + + # If section is 'development-environment-setup', load the parse the markdown file + elsif template == 'development-environment-setup' + @content = parse_markdown + locals = { :content => @content } + else + template = params[:subsection] if !params[:subsection].blank? + locals = nil + end + + # Render the template + render template, :layout => request.xhr? ? 'sdkxhr' : 'lhnavigation' , :locals => locals + + end end diff --git a/app/helpers/sdk_helper.rb b/app/helpers/sdk_helper.rb new file mode 100644 index 0000000..a01b05f --- /dev/null +++ b/app/helpers/sdk_helper.rb @@ -0,0 +1,195 @@ +module SdkHelper + + # Properties + @@dir_templates = 'public/examples/versions/*' + + # Regular expressions + + @@regex_cat_title = /\/\*{3,}\s*.*\s*\*+\// + @@regex_description = /\/{1}\*{2}\s*(\*?\s.*\s*)*\*{1}\/{1}/ + @@regex_selector = /(\S*\.?\#?[^\s]+\s{1}\{(\s*[^\;]*;+)*\s*\}{1})/ + + + + # Parse the markdown file + # + # @return {String} * The html that will be injected in the template + + def parse_markdown + begin + markdown = open(@@url_readme_file) {|io| io.read} + renderer = Redcarpet::Render::HTML + render = renderer.new(render_extensions = {}) + return Redcarpet::Markdown.new(render, parse_extensions = {}).render(markdown).html_safe + rescue + return nil + end + end + + + + # Reads the skins directory and returns all the versions + # + # @return {Array} versions Array containing all the skin versions + + def get_skins_from_directory + versions = [] + dirs = Dir.glob(@@dir_templates) + dirs.each{|dir| + dir = dir.split('/').last() + versions.push(dir) + } + versions = versions.sort.reverse + return versions + end + + + # Get all the modules from the REST API + # + # @param {String} url The endpoint of the documentation api + # @return {Array} data The array containing all the module names + + def get_doc_module_names(url) + begin + resp = Net::HTTP.get_response(URI.parse(url)) + data = resp.body + if !resp.body.is_a?(Net::HTTPSuccess) + data = ActiveSupport::JSON.decode(resp.body).sort + end + return data + rescue + return nil + end + end + + + # Get the module details from the REST API + # + # @param {String} url The url for the HTTPRequest + # @return {Hash} * The hash containing the module details + + def get_doc_details(url) + begin + resp = Net::HTTP.get_response(URI.parse(url)) + return Yajl::Parser.parse(resp.body) + rescue + return nil + end + end + + + # Remove all the characters from a string (to create a clean title) + # + # @param {Array} chars The characters that need to be replaced + # @param {String} string The given string that needs to be cleaned up + # @return {String} string The cleaned up string + + def replace_all_dirty_chars_from_string(chars, string) + chars.each {|char| string.gsub!(char, "")} + return string + end + + + # Parse a css file + # + # @param {String} url The endpoint of the documentation api + # @return {String} the css dump The hash containing the module details + + def parse_css_file(url) + output = nil + begin + resp = Net::HTTP.get_response(URI.parse(url)) + if resp.body.class == String + + # Create an array to store the categories => create item for each category + categories = [] + resp.body.scan(@@regex_cat_title).collect{|x| categories.push(x)} + + # Loop the categories to get their content + i = 1 + arrCategories = [] + categories.each do |cat| + + # Create an object for each category + obj = {} + obj['title'] = replace_all_dirty_chars_from_string([/\*/, /\//], cat) + obj['content'] = {} + + # To get the content, split on a regex of the type 'title' + # Returns a string with the description and selectors of the 'category' + # Puts each string in an array + splitted = [] + resp.body.split(@@regex_cat_title).each do |item| + splitted.push(item) + end + + # Loop the content for the category and look for other codeblocks + # Splits the string on empty lines + selectors = [] + splitted[i].split(/\n\n/).each do |paragraph| + + # Split the paragraph + if !paragraph.blank? + arrParagraph = paragraph.split('*/') + arrParagraph.each do |item| + + # Create new item object and set as selector by default + objItem = {} + objItem['value'] = item + objItem['type'] = "selector" + + # If the item matches ' /*' + if item.match(/^\/\*/) + + # Override type and set as description + objItem['type'] = "description" + + # Create some arrays for other elements + objItem['examples'] = [] + objItem['snippets'] = [] + objItem['explanations'] = [] + + # First remove all the '*' and the ' \' from the string + val = replace_all_dirty_chars_from_string([/\*/, /^\//], item) + val = val.gsub(/\s<").gsub(/>$/,">").gsub(/\se.g./, "") + + # EXAMPLES: Get all the examples out of the string and remove 'example: ' + val.scan(/example.*\.html/).collect{|example| + example = example.gsub(/example:\s/,"") + objItem['examples'].push(example) + } + + # SNIPPETS: Get all the html snippets out of the string + val.scan(/
.*<\/pre>/).collect{|item|
+                                        snippet = item.gsub(/
/,"").gsub(/<\/pre>/,"")
+                                        objItem['snippets'].push(snippet)
+                                    }
+                                            
+                                    # EXPLANATIONS: Parse comment blocks and remove the examples                        
+                                    val.split(/
.*<\/pre>/).each do |i|
+                                        stripped = i.gsub(/\n/,"").gsub(/example:.*\.html/,"")                                        
+                                        if !stripped.blank? && stripped != ""  
+                                            objItem['explanations'].push(stripped) 
+                                        end
+                                    end                                    
+                                end                       
+                                selectors.push(objItem)
+                            end
+                        end                                      
+        
+                    end           
+                    
+                    # Add the selectors to the content object
+                    obj['content']['selectors'] = selectors
+                    arrCategories.push(obj)
+                    i += 1          
+                end             
+                output = arrCategories                                                                 
+            end                               
+            return output
+        rescue
+            return nil
+        end        
+    end
+
+end
\ No newline at end of file
diff --git a/app/views/sdk/_lhnav.html.erb b/app/views/sdk/_lhnav.html.erb
index 2fbd4ed..419cc61 100644
--- a/app/views/sdk/_lhnav.html.erb
+++ b/app/views/sdk/_lhnav.html.erb
@@ -1,43 +1,83 @@
 
 
diff --git a/app/views/sdk/api.html.erb b/app/views/sdk/api.html.erb deleted file mode 100644 index 70a47a9..0000000 --- a/app/views/sdk/api.html.erb +++ /dev/null @@ -1,34 +0,0 @@ -<% content_for :title do %> - SDK - API & endpoints<% end %> -
-

API & endpoints

-

There is already a lot of functionality build into Sakai OAE.
We show you how you can use that and how you can communicate with the server.

- -
- <%= image_tag "developer_fulldev_icon.png", :alt => "Front-end API", :class => "descriptive_icon" %> -
-

Front-end API

-

Use the build-in JavaScript functionality of Sakai OAE.

- <%= link_to "View", "/sdk/api/frontend", :class => "wl-link-button wl-button wl-header-button blue"%> -
-
- -
- <%= image_tag "developer_quickdev_icon.png", :alt => "Back-end endpoints", :class => "descriptive_icon" %> -
-

Back-end endpoints

-

Communicate with the OAE back-end.

- <%= link_to "View", "/sdk/api/backend", :class => "wl-link-button wl-button wl-header-button blue"%> -
-
- -
- <%= image_tag "developer_interaction_icon.png", :alt => "3rd party libraries", :class => "descriptive_icon" %> -
-

3rd party libraries

-

A list of 3rd party JavaScript libraries that we use in Sakai OAE.

- <%= link_to "View", "/sdk/api/thirdparty", :class => "wl-link-button wl-button wl-header-button blue"%> -
-
- -
-
\ No newline at end of file diff --git a/app/views/sdk/api/_apimoduledetails.html.erb b/app/views/sdk/api/_apimoduledetails.html.erb new file mode 100644 index 0000000..7d82a55 --- /dev/null +++ b/app/views/sdk/api/_apimoduledetails.html.erb @@ -0,0 +1,80 @@ + +

<%= raw @module_title %>

+ + +<% @content.each do |k, v| %> +

<%= k %>

+ + + <% v.each do |x| %> + + + <% next unless !x["isPrivate"] == true && x["ignore"] == false %> +
+ <% if !x["ctx"].blank? %> + + <% if params[:module].blank? %> +

<%= link_to(x["ctx"]["name"], @subsection + '/' + @module_title + '#' + x["ctx"]["name"], :name => x["ctx"]["name"]) %>

+ <% else %> +

<%= link_to(x["ctx"]["name"], @module_title + '#' + x["ctx"]["name"], :name => x["ctx"]["name"]) %>

+ <% end %> + +

+ <%= raw x["ctx"]["value"] %> +

+ <% end %> +
+

<%= raw x["description"]["full"] %>

+
+ + <% if !x["tags"].blank? %> + + <% if !x["ctx"].blank? %> + + + + + + <% end %> + + + + <% x["tags"].each do |tag| %> + + <% if tag["type"] == "param" %> + + <% else %> + + <% end %> + + <% end %> + + + +
Parameters for <%= raw x["ctx"]["name"] %>
+ <%= raw tag["name"] %> + <% if !tag["types"].blank? && tag["types"].length %>: + <% tag["types"].each do |type| %> + <%= raw type %> + <% end %> + <% end %> + +
<%= raw tag["description"] %> +
+ Returns + <% if !tag["types"].blank? && tag["types"].length %>: + <% tag["types"].each do |type| %> + <%= raw type %> + <% end %> + <% end %> + +
<%= raw tag["description"] %> +
+ <% end %> + +
+ + <% end %> + + +<% end %> diff --git a/app/views/sdk/api/_apimodulesnav.html.erb b/app/views/sdk/api/_apimodulesnav.html.erb new file mode 100644 index 0000000..fa85a7c --- /dev/null +++ b/app/views/sdk/api/_apimodulesnav.html.erb @@ -0,0 +1,11 @@ +<% @modules.each do |mod| %> + <% + classname = "wl-regular-link" + if params[:module].eql?(mod) + classname += " selected" + elsif params[:module].blank? && mod == @modules.first + classname += " selected" + end + %> +

<%= link_to(mod, '/sdk/api/' + @subsection + '/' + mod, :title => mod, :class => classname) %>

+<% end %> diff --git a/app/views/sdk/api/index.html.erb b/app/views/sdk/api/index.html.erb new file mode 100644 index 0000000..6d21cc1 --- /dev/null +++ b/app/views/sdk/api/index.html.erb @@ -0,0 +1,30 @@ +<% content_for :title do %> - SDK - API & endpoints<% end %> +
+ +

API

+ +
+ + +
+ <% if !@modules.blank? %> + <%= render :partial => "sdk/api/apimodulesnav", :locals => { :modules => @modules, :subsection => @subsection }%> + <% end %> +
+ + +
+ <% if !@content.blank? %> + <%= render :partial => "sdk/api/apimoduledetails", :locals => { :content => @content }%> + <% else %> +

No results

+ <% end %> +
+ + +
+
+ +
+ +
diff --git a/app/views/sdk/bootstrap-reference.html.erb b/app/views/sdk/bootstrap-reference.html.erb new file mode 100644 index 0000000..81d8e62 --- /dev/null +++ b/app/views/sdk/bootstrap-reference.html.erb @@ -0,0 +1,5 @@ +<% content_for :title do %> - SDK - Style guide & endpoints<% end %> +
+

Bootstrap reference

+
+
diff --git a/app/views/sdk/contact.html.erb b/app/views/sdk/contact.html.erb index 96725f3..34f2600 100644 --- a/app/views/sdk/contact.html.erb +++ b/app/views/sdk/contact.html.erb @@ -1,4 +1,4 @@ -<% content_for :title do %> - SDK - Help<% end %> +<% content_for :title do %> - SDK - Getting help<% end %>

Sakai is a very helpful community

There are a number of ways you can get in touch with members of the community if you need help or want to share your ideas.

@@ -28,4 +28,4 @@
<%= render :partial => "sdk/feedback" %> -
\ No newline at end of file + diff --git a/app/views/sdk/dashes-instead-of-underscore.html.erb b/app/views/sdk/dashes-instead-of-underscore.html.erb new file mode 100644 index 0000000..e336571 --- /dev/null +++ b/app/views/sdk/dashes-instead-of-underscore.html.erb @@ -0,0 +1,5 @@ +<% content_for :title do %> - SDK - Development guide & endpoints<% end %> +
+

Dashes instead of underscore

+
+
diff --git a/app/views/sdk/develop-a-widget.html.erb b/app/views/sdk/develop-a-widget.html.erb new file mode 100644 index 0000000..d9233af --- /dev/null +++ b/app/views/sdk/develop-a-widget.html.erb @@ -0,0 +1,5 @@ +<% content_for :title do %> - SDK - Develop a widget<% end %> +
+

Develop a widget

+
+
diff --git a/app/views/sdk/development-environment-setup.html.erb b/app/views/sdk/development-environment-setup.html.erb new file mode 100644 index 0000000..a755267 --- /dev/null +++ b/app/views/sdk/development-environment-setup.html.erb @@ -0,0 +1,14 @@ +<% content_for :title do %> - SDK - Development environment setup<% end %> +
+
+
+ <% if !@content.blank? %> + <%= raw @content.gsub(/\r/, '
') %> + <% else %> +

Open Academic Environment (OAE Project)

+

No results

+ <% end %> +
+
+
+
diff --git a/app/views/sdk/development-guide.html.erb b/app/views/sdk/development-guide.html.erb new file mode 100644 index 0000000..bc5b616 --- /dev/null +++ b/app/views/sdk/development-guide.html.erb @@ -0,0 +1,5 @@ +<% content_for :title do %> - SDK - Development guide<% end %> +
+

Development guide

+
+
diff --git a/app/views/sdk/getting-help.html.erb b/app/views/sdk/getting-help.html.erb new file mode 100644 index 0000000..34f2600 --- /dev/null +++ b/app/views/sdk/getting-help.html.erb @@ -0,0 +1,31 @@ +<% content_for :title do %> - SDK - Getting help<% end %> +
+

Sakai is a very helpful community

+

There are a number of ways you can get in touch with members of the community if you need help or want to share your ideas.

+ +
+

IRC

+

You can almost always find a 3akai-UX (Sakai OAE front-end codename) Developer or Nakamura (Sakai OAE back-end codename) Developer in the Sakai IRC group chat room. The purpose of this space is to get quick answers to issues you are having and for group discussions on various issues. All are welcome.

+

To join:

+

1. You will need an IRC Client:

+ +

2. Connect to the server: irc.freenode.net (if you're using <%= link_to "Freenode Webchat", "http://webchat.freenode.net/?channels=sakai", :class => "wl-regular-link" %>, you're automatically connected to the right server)

+

3. Use a nickname that describes you

+

4. Once connected to the server, join room (also known as a 'channel'): #sakai

+

This chat room is archived at <%= link_to "http://sakai.iriscouch.com/irc/_design/viewer/index.html", "http://sakai.iriscouch.com/irc/_design/viewer/index.html", :class => "wl-regular-link" %> and the logs for the previous 24 hours are sent to the oae-dev list at midnight UTC.

+

For example widgets that have been heavily documented in this Widget SDK documentation, see the <%= link_to "Widget designs", "/sdk/designguide/widgetdesigns", :class => "wl-regular-link" %> page.

+
+
+

Email

+

The Sakai community relies heavily on email lists for communication. Questions and ideas are welcome from anyone on these lists but you must sign up before you can send to the lists.

+ +
+ <%= render :partial => "sdk/feedback" %> +
diff --git a/app/views/sdk/html-css.html.erb b/app/views/sdk/html-css.html.erb new file mode 100644 index 0000000..aeedbc1 --- /dev/null +++ b/app/views/sdk/html-css.html.erb @@ -0,0 +1,5 @@ +<% content_for :title do %> - SDK - Develop a widget & endpoints<% end %> +
+

HTML/CSS

+
+
diff --git a/app/views/sdk/index.html.erb b/app/views/sdk/index.html.erb index bdc0898..b6460fd 100644 --- a/app/views/sdk/index.html.erb +++ b/app/views/sdk/index.html.erb @@ -55,4 +55,4 @@
- \ No newline at end of file + diff --git a/app/views/sdk/js.html.erb b/app/views/sdk/js.html.erb new file mode 100644 index 0000000..ff822bc --- /dev/null +++ b/app/views/sdk/js.html.erb @@ -0,0 +1,5 @@ +<% content_for :title do %> - SDK - Develop a widget & endpoints<% end %> +
+

JavaScript

+
+
diff --git a/app/views/sdk/more.html.erb b/app/views/sdk/more.html.erb new file mode 100644 index 0000000..6cbe2e9 --- /dev/null +++ b/app/views/sdk/more.html.erb @@ -0,0 +1,5 @@ +<% content_for :title do %> - SDK - Develop a widget & endpoints<% end %> +
+

More

+
+
\ No newline at end of file diff --git a/app/views/sdk/remove-reusable-css.html.erb b/app/views/sdk/remove-reusable-css.html.erb new file mode 100644 index 0000000..d50c934 --- /dev/null +++ b/app/views/sdk/remove-reusable-css.html.erb @@ -0,0 +1,5 @@ +<% content_for :title do %> - SDK - Development guide & endpoints<% end %> +
+

Remove reusable CSS

+
+
diff --git a/app/views/sdk/style-guide.html.erb b/app/views/sdk/style-guide.html.erb new file mode 100644 index 0000000..a270887 --- /dev/null +++ b/app/views/sdk/style-guide.html.erb @@ -0,0 +1,5 @@ +<% content_for :title do %> - SDK - Styleguide<% end %> +
+

Style guide

+
+
diff --git a/app/views/sdk/style-guide/_reusable-css-categories.html.erb b/app/views/sdk/style-guide/_reusable-css-categories.html.erb new file mode 100644 index 0000000..9018e23 --- /dev/null +++ b/app/views/sdk/style-guide/_reusable-css-categories.html.erb @@ -0,0 +1,1013 @@ +
+

accessibility

+
+

Used for accessibility purposes as it allows to put text content for items that might not have text content (e.g. icons) or create additional clues for screenreader users

+

+ + +
+.oae-aural-text {
+    border: 0;
+    clip: rect(0 0 0 0);
+    height: 1px;
+    margin: -1px;
+    overflow: hidden;
+    padding: 0;
+    position: absolute;
+    width: 1px;
+}
+
+

Style that can be used for links if we just want them to have the same color as the text. These links will be underlined when hovering over them.

+

+ + +
+a.oae-plain-link:hover {
+    text-decoration: underline;
+}
+
+
+
+
+

threedots

+
+

Style that can be applied to text elements to make sure that the text in a text element doesn't use more than the space it has available. If the text is shorter than the available space, this will leave the text unchanged. If the text is longer than the available space, it will be cut off at its maximum length and will be appended with `...`. In order for this to work, the text element will need to have a maximum width set.

+

+ + +
.oae-threedots {
+    display: block;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+
+
+
+

panels

+
+

Panels that can be used to show HTML content on top of a background color or background image. Three different panels can be used - `oae-panel-primary`: Panel that contains content that should really stand out - `oae-panel-secondary`: Panel that contains the secondary content - `oae-panel-tertiary`: Other panel content (e.g. search box on the landing page)

+

+ + +
+.oae-panel-primary, .oae-panel-secondary, .oae-panel-tertiary {
+    padding: 15px;
+    -webkit-border-radius: 5px;
+       -moz-border-radius: 5px;
+            border-radius: 5px;
+}
+
+
+
+
+

visibility icons

+
+

These icons are used consistently to indicate the visibility setting for an entity in the system. The available visibility privacy options are `private`, `loggedin` and `public`.

+

+

+

Large icons can be rendered by adding the `large` class to the icon.

+

+

+

Note: - The `oae-aural-text` span is added in for accessibility purposes, but can be left out when necessary.

+ + +
i.icon-oae-private,
+i.icon-oae-loggedin,
+i.icon-oae-public {
+    font-size: 100%;
+    width: 18px;
+    height: 18px;
+}
+
+
i.icon-oae-private:before,
+i.icon-oae-loggedin:before,
+i.icon-oae-public:before {
+    -webkit-border-radius: 500px;
+       -moz-border-radius: 500px;
+            border-radius: 500px;
+    color: #313131;
+    font-size: 15px;
+    width: 18px;
+    height: 16px;
+    padding-top: 1px;
+    text-align: center;
+}
+
+
i.icon-oae-private:before {
+    background-color: #FFBC78;
+    content: "\f023";
+}
+
+
i.icon-oae-loggedin:before {
+    background-color: #C4E6FF;
+    content: "\f041";
+}
+
+
i.icon-oae-public:before {
+    background-color: #A6E0AB;
+    content: "\f0ac";
+}
+
+

Large visibility icons

+
i.icon-oae-private.large:before,
+i.icon-oae-loggedin.large:before,
+i.icon-oae-public.large:before {
+    font-size: 50px;
+    height: 55px;
+    padding-top: 5px;
+    width: 60px;
+}
+
+
+
+
+

visibility toggles

+
+

A Large group of toggle buttons for visibility settings. When an `oae-visibility-choice input` field changes value the `oae-visibility-changed` event is sent out with data: `{'radio': $(input)}`

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+ + +
.oae-visibility-choice-container .oae-visibility-choice {
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+    height: 150px;
+    margin: 0 10px 20px 0;
+    width: 100%;
+}
+
+
.oae-visibility-choice-container label:last-child .oae-visibility-choice {
+    margin-right: 0;
+}
+
+
.oae-visibility-choice-container .oae-visibility-choice input {
+    position: absolute;
+    z-index: -1; /* Adding a z-index of -1 hides the element from the view but still allows for focus of the element 
+
+
+}
+
+
.oae-visibility-choice-container .oae-visibility-choice span {
+    display: block;
+    font-size: 13px;
+    font-weight: bold;
+    margin-top: 7px;
+}
+
+
.oae-visibility-choice-container .oae-visibility-choice.checked {
+    border: 8px solid;
+    padding-top: 12px;
+}
+
+
.oae-visibility-choice-container .oae-visibility-choice + i {
+    display: none;
+}
+
+
.oae-visibility-choice-container .oae-visibility-choice.checked + i {
+    -webkit-border-radius: 100px;
+       -moz-border-radius: 100px;
+            border-radius: 100px;
+    bottom: 26.5%;
+    display: block;
+    margin-left: 65px;
+    position: absolute;
+}
+
+
.oae-visibility-choice-container .oae-visibility-choice.checked + i:before {
+    font-size: 24px;
+    height: 30px;
+    padding-top: 5px;
+    width: 35px;
+}
+
+
+
+
+

successfail icons

+
+

These icons are used in situations where checks for success/failure are done

+
+[class^="icon-"].icon-ok,
+[class*=" icon-"].icon-ok,
+[class^="icon-"].icon-ok:hover,
+[class*=" icon-"].icon-ok:hover {
+    color: #468847;
+}
+
+
[class^="icon-"].icon-warning-sign,
+[class*=" icon-"].icon-warning-sign,
+[class^="icon-"].icon-warning-sign:hover,
+[class*=" icon-"].icon-warning-sign:hover {
+    color: #DD2222;
+}
+
+
+
+
+

thumbnails

+
+

A thumbnail can be used to show a thumbnail picture/profile picture for an entity. It will also attempt to set a default thumbnail in case no actual image is available, and it allows for showing a visibility icon combined with the thumbnail. These thumbnails will adjust in size to the space they have been given by their container.

+

+

+

+

+

+

Next to using the HTML structure, there is also a Trimpath macro that can be used instead from all Trimpath templates: `${renderThumbnail(entityData, [addVisibilityIcon], [large])}` - `entityData` is a standard object representing a user, group or content item or a search result for a user, group or content item as returned by Hilary. Alternatively, a string representing the resourceType or resourceSubType (i.e., 'user', 'group', 'content', 'file', 'link', 'collabdoc') can be passed in for an empty/anonymous entity thumbnail. - `addVisibilityIcon` (optional) will determine whether or not the visibility icon should be shown. By default, the visibility icon will be shown. However, users will not never show a visibility icon. - `large` (optional) determines whether or not a large default thumbnail icon should used. By default, a small icon will be used. Notes: - The actual thumbnail image is optional, and if no image is specified the thumbnail will show a default entity thumbnail. In order to do this, `icon-oae-user` should be added to the `oae-thumbnail` div for users, `icon-oae-group` should be added to the `oae-thumbnail` div for groups, `icon-oae-discussion` should be added to the `oae-thumbnail` div for discussions, `icon-oae-content` should be added to the `oae-thumbnail` div for generic content, `icon-oae-file` should be added to the `oae-thumbnail` div for uploaded files, `icon-oae-link` should be added to the `oae-thumbnail` div for links and `icon-oae-collabdoc` should be added to the `oae-thumbnail` div for collaborative documents. Even when an image is provided, the entity icon class can still be added as it will be used when the image cannot be downloaded. - For large thumbnails (> 100px width/height), the `oae-thumbnail-large` class should be added to the `oae-thumbnail` container. It will cause the default thumbnail to be larger. - An optional visibility icon can be added to the thumbnail as well and will automatically be positioned correctly. The available visibility icons are `icon-oae-private`, `icon-oae-loggedin` and `icon-oae-public` (See Visibility icons section). - The link inside of the thumbnail can be used to link to the entity's profile page. This link is optional and can be left out.

+ + +
div.oae-thumbnail {
+    width: 100%;
+    height: 100%;
+    text-align: center;
+    display: inline-block;
+    position: relative;
+    -webkit-border-radius: 4px;
+       -moz-border-radius: 4px;
+            border-radius: 4px;
+    -webkit-box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.35);
+       -moz-box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.35);
+            box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.35);
+}
+
+
div.oae-thumbnail a,
+div.oae-thumbnail img {
+    position: absolute;
+    left: 0;
+    top: 0;
+    min-width: 100%;
+    height: 100%;
+    font-size: 12px;
+}
+
+
div.oae-thumbnail:before {
+    font-size: 20px;
+    padding-top: 50%;
+    margin-top: -11px;
+}
+
+
div.oae-thumbnail.oae-thumbnail-large:before {
+    font-size: 50px;
+    margin-top: -25px;
+}
+
+

Default entity thumbnails

+
div.oae-thumbnail.icon-oae-content:before, div.oae-thumbnail.icon-oae-file:before {
+    content: "\f016";
+}
+
+
div.oae-thumbnail.icon-oae-link:before {
+    content: "\f0c1";
+}
+
+
div.oae-thumbnail.icon-oae-collabdoc:before {
+    content: "\f044";
+}
+
+
div.oae-thumbnail.icon-oae-discussion:before {
+    content: "\f086";
+}
+
+
div.oae-thumbnail.icon-oae-group:before {
+    content: "\f0c0";
+}
+
+
div.oae-thumbnail.icon-oae-user:before {
+    content: "\f007";
+}
+
+

Visibility icon positioning

+
div.oae-thumbnail i[class^="icon-"] {
+    position: absolute;
+    bottom: -8px;
+    right: -8px;
+}
+
+
+
+
+

clips

+
+

Clips are the elements that are used for page (entity) titles and page actions. They are folded onto the top of a container, which is usually the main page content container. Each clip can have a set of actions associated to it, which will automatically show when opening the clip through the dropdown icon. The HTML structure required for creating a clip is the following:

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

Notes: - A clip needs to be inside of an `oae-clip-container` div. Inside of this container, you can specify the clips that should go on the left by adding them to a `oae-clip-container-left` div. You can specify the clips that should go on the right by adding them to a `oae-clip-container-right div inside of this container. - The fold on a clip can be on the left of the clip or on the right of the clip. By default, the fold will be on the right. When a fold on the left is required, an `oae-clip-flipped` class should be added to the .`oae-clip` element. - Clips are available in two different skinnable styles. By default, the primary style will be used. If the secundary style is needed, this can be done by adding an 'oae-clip-secondary' class to the `.oae-clip` element. - A thumbnail image can be added to the clip by adding an `oae-thumbnail` div as the first element of the main button. This can also show a default entity picture (in case no image is provided) as well as a visibility icon (See the `Thumbnail` section for details on how to create a thumbnail). The thumbnail image is optional and can be left out as well. - The `icon-caret-down` element is optional. If it is not provided, the clip will be shown in view only mode. If it is provided, the clip will be toggleable and the action menu will be shown when clicked. - The `small` tag is used to show some additional clip metadata and is optional. - When a clip should not be clickable (e.g. in non-manager mode of a page), the `disabled` attribute should be added to the button. This will hide any caret icons and will make the clip unclickable.

+ + +

Clip container

+
.oae-clip-container {
+    position: relative;
+    margin-bottom: 55px;
+}
+
+
.oae-clip-container .oae-clip-container-left,
+.oae-clip-container .oae-clip-container-right {
+    position: absolute;
+}
+
+
.oae-clip-container .oae-clip-container-right {
+    margin-right: 55px;
+    right: 0px;
+}
+
+
.oae-clip {
+    float: left;
+    margin: -16px 10px 10px;
+    position: relative;
+    z-index: 100;
+}
+
+

Clip fold

+
.oae-clip .oae-clip-fold {
+    height: 6px;
+    float: right;
+    margin-right: -7px;
+    position: relative;
+    width: 7px;
+    z-index: 10;
+}
+
+
.oae-clip.oae-clip-flipped .oae-clip-fold {
+    float: left;
+    margin-left: -9px;
+}
+
+
.oae-clip .oae-clip-fold .oae-clip-fold-inner {
+    -webkit-border-radius: 50px 50px 0 0;
+       -moz-border-radius: 50px 50px 0 0;
+            border-radius: 50px 50px 0 0;
+    float: left;
+    height: 6px;
+    margin-left: -1px;
+    position: absolute;
+    width: 9px;
+    z-index: 1;
+}
+.oae-clip.oae-clip-flipped .oae-clip-fold .oae-clip-fold-inner {
+    margin-left: 0;
+}
+
+
.oae-clip .oae-clip-fold .oae-clip-fold-outer {
+    float: right;
+    height: 6px;
+    margin-left: -5px;
+    position: absolute;
+    width: 7px;
+    z-index: 0;
+}
+.oae-clip.oae-clip-flipped .oae-clip-fold .oae-clip-fold-outer {
+    margin-left: 4px;
+}
+
+

Clip content

+
.oae-clip .oae-clip-content {
+    -webkit-border-radius: 6px 0 6px 6px;
+       -moz-border-radius: 6px 0 6px 6px;
+            border-radius: 6px 0 6px 6px;
+    -webkit-box-shadow: 0 1px 2px 1px rgba(0, 0, 0, 0.3);
+       -moz-box-shadow: 0 1px 2px 1px rgba(0, 0, 0, 0.3);
+            box-shadow: 0 1px 2px 1px rgba(0, 0, 0, 0.3);
+}
+
+
.oae-clip.oae-clip-flipped .oae-clip-content {
+    -webkit-border-radius: 0 6px 6px;
+       -moz-border-radius: 0 6px 6px;
+            border-radius: 0 6px 6px;
+}
+
+
.oae-clip .oae-clip-content > button,
+.oae-clip .oae-clip-content ul li button {
+    background: none;
+    border: none;
+    font-weight: 600;
+    padding: 14px 20px 14px 14px;
+    text-align: left;
+}
+
+
.oae-clip .oae-clip-content > button:disabled {
+    cursor: default;
+}
+
+
.oae-clip .oae-clip-content > button > div {
+    float: left
+}
+
+
.oae-clip .oae-clip-content > button > div:nth-child(2) > div {
+    display: table-cell;
+    height: 35px;
+    vertical-align: middle;
+}
+
+
.oae-clip .oae-clip-content > button div.oae-thumbnail {
+    height: 35px;
+    width: 35px;
+    margin-right: 12px;
+}
+
+
.oae-clip .oae-clip-content > button i.icon-caret-down,
+.oae-clip .oae-clip-content > button i.icon-caret-up {
+    margin-left: 10px;
+    line-height: 16px;
+    position: relative;
+    top: 2px;
+}
+
+
.oae-clip .oae-clip-content > button:disabled i.icon-caret-down,
+.oae-clip .oae-clip-content > button:disabled i.icon-caret-up {
+    display: none;
+}
+
+
.oae-clip .oae-clip-content h1 {
+    display: inline-block;
+    font-size: 16px;
+    line-height: 1;
+    margin: 0px;
+    font-weight: 600;
+    max-width: 500px;
+    word-wrap: break-word;
+}
+
+
.oae-clip .oae-clip-content small {
+    clear: both;
+    display: block;
+    font-size: 12px;
+    line-height: 1;
+    font-weight: normal;
+    white-space: nowrap;
+}
+
+

Clip actions

+
.oae-clip .oae-clip-content ul {
+    list-style: none;
+    margin: 0 10px;
+    display: none;
+}
+
+
.oae-clip .oae-clip-content ul li {
+    display: inline;
+}
+
+
.oae-clip .oae-clip-content ul li button {
+    -webkit-border-radius: 6px;
+       -moz-border-radius: 6px;
+            border-radius: 6px;
+    font-size: 11px;
+    min-width: 70px;
+    padding: 10px;
+    margin-bottom: 10px;
+    text-align: center;
+}
+
+
.oae-clip .oae-clip-content ul li button i {
+    display: block;
+    margin: 0 auto 3px;
+}
+
+
+
+
+

tiles

+
+

A tile is a combination of a preview image and some entity metadata in a polaroid-like appearance. The preview image will take up the bulk of the space, with a bar at the bottom overlapping with the image that can show metadata. Tiles will adjust in size to the space they have been given by their container. The following HTML structure should be used to create a tile:

+

+

+

+

+

+

+

+

+

+

+

+

+

+

Notes: - The `oae-thumbnail` element, containing the preview image, is a standard `oae-thumbnail` element (See Thumbnail section for full overview). - The `oae-threedots` class should be added to metadata elements if you want to make sure that `...` is shown when the metadata is longer than the available space in the tile. - The actual content of the metadata div can be pretty much anything, although an h3 should be used for the tile title. - The `small` element used to add some additional metadata is optional. - The visibility icon can be used as defined in the Visibility icon section, and can be floated on the left or right.

+ + +
.oae-tile {
+    position: relative;
+    overflow: hidden;
+    border: 1px solid;
+    -webkit-border-radius: 3px;
+       -moz-border-radius: 3px;
+            border-radius: 3px;
+}
+
+

Default thumbnail picture positioning

+
.oae-tile .oae-thumbnail {
+    -webkit-border-radius: 0px;
+       -moz-border-radius: 0px;
+            border-radius: 0px;
+}
+
+
.oae-tile .oae-thumbnail:before {
+    margin-top: -30px;
+}
+
+
.oae-tile .oae-thumbnail.oae-thumbnail-large:before {
+    margin-top: -50px;
+}
+
+

Tile metadata

+
.oae-tile > div:last-child {
+    position: absolute;
+    bottom: 0px;
+    right: 0px;
+    left: 0px;
+    padding: 7px;
+}
+
+
.oae-tile h3,
+.oae-tile h3 a {
+    font-size: 14px;
+    font-weight: bold;
+    line-height: 1.3;
+    margin: 0px;
+}
+
+
.oae-tile small {
+    font-size: 11px;
+    font-style: italic;
+    font-weight: normal;
+    text-transform: uppercase;
+}
+
+
+
+
+

list items

+
+

A list item is a way of displaying an entity and is a combination of a preview image, some entity metadata, a checkbox and actions that can be taken on the entity. A list item can be used as part of a larger list, but can also be used outside of a list to present a single entity. List items will adjust in size to the space they have been given by their container. The following HTML structure should be used to create a list item:

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

Notes: - A list item is available in an expanded size and a compact size. By default, the larger expanded view will be used. In order to use the smaller compact view, the class `oae-listitem-compact` should be added to the `oae-listitem` element. - A checkbox can be added to the list item for management purposes. This checkbox should have an accompanying `oae-aural-text` label for accessibility purposes. - An action bar can be added to the list item by adding an `oae-listitem-actions` div to the list item. This action bar can contain one or multiple action buttons. - The `oae-thumbnail`, `oae-listitem-actions` and checkbox are all optional. - The `small` element used to add some additional metadata is optional as well. - The `oae-thumbnail` element, containing the preview image, is a standard `oae-thumbnail` element (See Thumbnail section for full overview).

+ + +
.oae-tile,
+.oae-listitem {
+    -webkit-box-shadow: 0 0 2px 0 rgba(219, 219, 219, 0.8);
+       -moz-box-shadow: 0 0 2px 0 rgba(219, 219, 219, 0.8);
+            box-shadow: 0 0 2px 0 rgba(219, 219, 219, 0.8);
+}
+
+
.oae-listitem {
+    padding: 10px;
+    margin-bottom: 10px;
+    height: 50px;
+    border: 1px solid;
+    -webkit-border-radius: 3px;
+       -moz-border-radius: 3px;
+            border-radius: 3px;
+}
+
+
.oae-listitem.oae-listitem-compact {
+    height: 25px;
+}
+
+
.oae-listitem input[type="checkbox"].pull-left {
+    margin-right: 10px;
+    margin-top: 20px;
+}
+
+
.oae-listitem.oae-listitem-compact input[type="checkbox"].pull-left {
+    margin-top: 6px;
+}
+
+

List item thumbnail

+
.oae-listitem .oae-thumbnail {
+    float: left;
+    height: 50px;
+    width: 50px;
+    margin-right: 15px;
+}
+
+
.oae-listitem.oae-listitem-compact .oae-thumbnail {
+    height: 25px;
+    width: 25px;
+}
+
+

List item metadata

+
.oae-listitem > div:not(.oae-thumbnail) {
+    display: table-cell;
+    vertical-align: middle;
+    height: 50px;
+}
+
+
.oae-listitem.oae-listitem-compact > div:not(.oae-thumbnail) {
+    height: 25px;
+    width: auto;
+}
+
+
.oae-listitem h3 {
+    display: inline-block;
+    font-size: 16px;
+    font-weight: 500;
+    line-height: 1.4;
+    margin: 0;
+    max-width: 450px;
+}
+
+
.oae-listitem small {
+    line-height: 1;
+    font-size: 11px;
+    font-style: italic;
+    text-transform: uppercase;
+}
+
+
.oae-listitem.oae-listitem-compact small {
+    display: inline-block;
+    line-height: 1.6;
+    margin-left: 20px;
+}
+
+

List item actions

+
.oae-listitem .oae-listitem-actions {
+    width: 100%;
+    text-align: right;
+}
+
+
.oae-listitem .oae-listitem-actions i {
+    font-size: 18px;
+}
+
+
+
+
+

lists

+
+

Lists are used as the core component for multiple widgets (library, membership, participants, search, etc.) and present a list of entities that can be viewed in 3 separate view modes (grid, details and compact). The HTML for a list item has been abstracted into a globally available TrimPath template that can be used when rendering list view items: `${listItem(entityData, [pagingKey], [metadata], [showCheckbox])}` - `entityData` is an object representing a user, group or content item or a search result for a user, group or content item - `pagingKey` (optional) is the key that should be used for paging through the infinite scroll plugin - `metadata` (optional) is a line of metadata information that should be displayed underneath the entity name - `showCheckbox` (optional) will determine whether ot not the checkbox should be shown. By default, the checkbox will be shown to all logged in users The output from this macro represents a single list (li) item, and should be wrapped in a list container (ul) element with an `oae-list` class. In order to show the grid view, an `oae-list-grid` class should be added to the list, in order to show the details view, an `oae-list-details` class should be added to the list and in order to show the compact view, an `oae-list-compact` class should be added to the list:

+

+

+

+ + +

Core list styles

+
ul.oae-list {
+    margin: 0;
+    padding: 0;
+    clear: both;
+}
+
+
ul.oae-list li {
+    list-style: none;
+    -webkit-border-radius: 3px;
+       -moz-border-radius: 3px;
+            border-radius: 3px;
+}
+
+
ul.oae-list:not(.oae-list-grid) li .oae-list-grid-item,
+ul.oae-list:not(.oae-list-details) li .oae-list-details-item,
+ul.oae-list:not(.oae-list-compact) li .oae-list-compact-item {
+    display: none;
+}
+
+

Grid view

+
ul.oae-list.oae-list-grid li {
+    float: left;
+    margin: 0px 14px 24px 0px;
+}
+
+
ul.oae-list.oae-list-grid li .oae-thumbnail {
+    height: 162px;
+    width: 162px;
+}
+
+

Details and compact view

+
ul.oae-list li .oae-list-details-item,
+ul.oae-list li .oae-list-compact-item  {
+    display: table;
+    width: 100%;
+}
+
+
+
+
+

list options

+
+

The list options can be shown at the top of a list, providing a title for the list, as well as possibly a list search form, list actions, view mode switching, etc. Some example HTML for a list options view:

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

Notes: - The `oae-list-options-toggle` item is used to show the title of the list, and will also be used to toggle the actions bar. This will be enabled automatically by the system. If a list needs to be shown in view-only mode, this element should be set to disabled, in which case the dropdown icon will disappear and the toggle will no longer work. - The `oae-list-options-actions` div represents the action bar that will be toggled when the `oae-list-options-toggle` element is clicked. This bar contains all of the action that can be done on the selected list items, and can basically be anything. - An `oae-list-selectall` class can be applied to the element that should be used to select/deselect all list items. This will be enabled automatically by the system.

+ + +
.oae-list-options {
+    border-bottom: 1px solid #EEE;
+    margin-bottom: 20px;
+}
+
+
.oae-list-options > div {
+    line-height: 30px;
+    margin-bottom: 15px;
+    clear: both;
+}
+
+
.oae-list-options .oae-list-options-toggle,
+.oae-list-options .btn.oae-list-options-toggle,
+.oae-list-options .btn.oae-list-options-toggle:hover,
+.oae-list-options .btn.oae-list-options-toggle:active,
+.oae-list-options .btn.oae-list-options-toggle:focus {
+    background: none;
+    border: none;
+    padding: 1px 0px;
+    -webkit-box-shadow: none;
+       -moz-box-shadow: none;
+            box-shadow: none;
+}
+
+
.oae-list-options .oae-list-options-toggle h2 {
+    margin: 0;
+    font-size: 20px;
+    line-height: 1;
+}
+
+
.oae-list-options .oae-list-options-toggle h2 .badge {
+    margin-left: 5px;
+    top: -4px;
+}
+
+
.oae-list-options .oae-list-options-toggle:disabled {
+    cursor: auto;
+}
+
+
.oae-list-options .oae-list-options-toggle:disabled .icon-caret-down,
+.oae-list-options .oae-list-options-toggle:disabled .icon-caret-up {
+    display: none;
+}
+
+
.oae-list-options form {
+    margin-bottom: 0px;
+}
+
+

Actions bar

+
.oae-list-options .oae-list-options-actions > input,
+.oae-list-options .oae-list-options-actions > button {
+    margin-right: 7px;
+}
+
+
.oae-list-options .oae-list-options-actions .btn i {
+    font-size: 18px;
+}
+
+
.oae-list-options .btn-group .btn i {
+    font-size: 12px;
+}
+
+

ul.oae-list li.oae-list-item.oae-list-item-dnd { border: none; display: none;}ul.oae-list li.oae-list-item.oae-list-item-dnd:first-child { display: block;}ul.oae-list li.oae-list-item.oae-list-item-dnd .oae-list-dnd-container { border: 1px solid #F5F5F5; height: 120px;}ul.oae-list li.oae-list-item.oae-list-item-dnd .oae-list-dnd-container > div { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; border: 1px dashed #999; height: 112px; margin: 4px;}ul.oae-list li.oae-list-item.oae-list-item-dnd .oae-list-dnd-container .oae-list-dnd-label { color: #999; font-size: 13px; font-style: italic; line-height: 1.3; margin: 10px auto 0; width: 100px;}ul.oae-list li.oae-list-item.oae-list-item-dnd .oae-list-dnd-container .oae-trigger-addcontent,ul.oae-list li.oae-list-item.oae-list-item-dnd .oae-list-newdocument { display: block; margin: 10px auto;}ul.oae-list li.oae-list-item.oae-list-item-dnd .oae-list-dnd-container .oae-trigger-addcontent i,ul.oae-list li.oae-list-item.oae-list-item-dnd .oae-list-newdocument i { color: #333; font-size: 18px; }

+
+
+
+
+
diff --git a/app/views/sdk/style-guide/res_reusable-css-categories.html.erb b/app/views/sdk/style-guide/res_reusable-css-categories.html.erb new file mode 100644 index 0000000..b1b7986 --- /dev/null +++ b/app/views/sdk/style-guide/res_reusable-css-categories.html.erb @@ -0,0 +1,45 @@ + +<% @content.each do |cat| %> +
+ +

<%= cat['title'] %>

+ +
+ <% cat['content']['selectors'].each do |selector| %> + + + <% if selector['type'] == "description" %> + + + <% if !selector['explanations'].empty? %> + <% selector["explanations"].each do |explanation| %> +

<%= explanation.gsub(/\s-/,'

-').gsub(/\n/,"
").html_safe %>

+ <% end%> + <% end %> + + + <% if !selector['examples'].empty? %> + <% selector['examples'].each do |example| %> + + <% end%> + <% end %> + + + <% if !selector['snippets'].empty? %> + + <% end %> + + + <% else %> +
<%= selector['value'] %>
+ <% end %> + + <% end %> +
+ +
+<% end %> diff --git a/app/views/sdk/style-guide/reusable-css.html.erb b/app/views/sdk/style-guide/reusable-css.html.erb new file mode 100644 index 0000000..3237967 --- /dev/null +++ b/app/views/sdk/style-guide/reusable-css.html.erb @@ -0,0 +1,27 @@ + + +<% content_for :title do %> - SDK - Style guide & endpoints<% end %> +
+ +
+

Reusable CSS pieces/templates

+ <% if !@versions.blank? %> +
+ + +
+ <% end %> +
+ + + <% if !@versions.blank? %> + <%= render :partial => "sdk/style-guide/versions/" + @version, :locals => { :content => @content }%> + <% else %> +

No results

+ <% end %> +
+
diff --git a/app/views/sdk/what-is-a-widget.html.erb b/app/views/sdk/what-is-a-widget.html.erb new file mode 100644 index 0000000..42b61b8 --- /dev/null +++ b/app/views/sdk/what-is-a-widget.html.erb @@ -0,0 +1,5 @@ +<% content_for :title do %> - SDK - Develop a widget & endpoints<% end %> +
+

What is a widget

+
+
diff --git a/app/views/sdk/widget-configuration.html.erb b/app/views/sdk/widget-configuration.html.erb new file mode 100644 index 0000000..0c6fbe1 --- /dev/null +++ b/app/views/sdk/widget-configuration.html.erb @@ -0,0 +1,5 @@ +<% content_for :title do %> - SDK - Develop a widget & endpoints<% end %> +
+

Widget configuration

+
+
diff --git a/app/views/sdk/widget-structure.html.erb b/app/views/sdk/widget-structure.html.erb new file mode 100644 index 0000000..7c68241 --- /dev/null +++ b/app/views/sdk/widget-structure.html.erb @@ -0,0 +1,5 @@ +<% content_for :title do %> - SDK - Develop a widget & endpoints<% end %> +
+

Widget structure

+
+
diff --git a/config/routes.rb b/config/routes.rb index 8a11596..162bd99 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -43,10 +43,9 @@ # SDK match '/sdk' => 'sdk#index', :as => :sdk - match '/sdk/*section' => 'sdk#sdk_section' + match '/sdk/:section(/:subsection)(/:module)' => 'sdk#sdk_section' match '/zippedwidget' => 'widget_generator#zippedwidget' - # Admin section match '/admin/users' => 'admin#users', :as => :admin_users match '/admin/users/admin' => 'admin#adminusers', :as => :admin_admin_users diff --git a/lib/markdown_handler.rb b/lib/markdown_handler.rb new file mode 100644 index 0000000..543f329 --- /dev/null +++ b/lib/markdown_handler.rb @@ -0,0 +1,14 @@ +require 'rdiscount' + +module MarkdownHandler + def self.erb + @erb ||= ActionView::Template.registered_template_handler(:erb) + end + + def self.call(template) + compiled_source = erb.call(template) + "RDiscount.new(begin;#{compiled_source};end).to_html" + end +end + +ActionView::Template.register_template_handler :md, MarkdownHandler \ No newline at end of file diff --git a/public/examples/assets/css/style.css b/public/examples/assets/css/style.css new file mode 100644 index 0000000..c767948 --- /dev/null +++ b/public/examples/assets/css/style.css @@ -0,0 +1,45 @@ +body { + background-color: #F5F5F5; + display: block; + padding: 0; + margin: 0; +} + +.example-container{ + width: 662px; + padding: 10px; + overflow: visible; +} + +/* ACCESSIBILITY */ + +#accessibility1, #accessibility2{ + height: auto; +} + +/* THREEDOTS */ + +#threedots1 span.oae-threedots{ + width: 150px; + height: auto; +} + +/* THUMBNAILS */ + +#thumbnails1 .oae-thumbnail{ + width: 30px; + height: 30px; +} + +/* TILES */ + +#tiles1 .oae-tile{ + width: 150px; + height: 150px; +} + +/* CLIPS */ + +#clips1{ + margin-top: 20px; +} diff --git a/public/examples/assets/img/profile-pic-john-large.jpg b/public/examples/assets/img/profile-pic-john-large.jpg new file mode 100644 index 0000000..b34b5c8 Binary files /dev/null and b/public/examples/assets/img/profile-pic-john-large.jpg differ diff --git a/public/examples/assets/img/profile-pic-john.png b/public/examples/assets/img/profile-pic-john.png new file mode 100644 index 0000000..c711eea Binary files /dev/null and b/public/examples/assets/img/profile-pic-john.png differ diff --git a/public/examples/assets/js/style.js b/public/examples/assets/js/style.js new file mode 100644 index 0000000..6c9b237 --- /dev/null +++ b/public/examples/assets/js/style.js @@ -0,0 +1,10 @@ +$(function(){ + + // Replace all the src attributes for the images from the CSS file + $('#clips1').find('.oae-thumbnail img').attr('src','/examples/assets/img/profile-pic-john.png'); + $('#listitems1').find('.oae-thumbnail img').attr('src','/examples/assets/img/profile-pic-john.png'); + $('#thumbnails1').find('.oae-thumbnail img').attr('src','/examples/assets/img/profile-pic-john.png'); + + $('#tiles1').find('.oae-thumbnail img').attr('src','/examples/assets/img/profile-pic-john-large.jpg'); + +}); diff --git a/script/parser/parser.rb b/script/parser/parser.rb new file mode 100755 index 0000000..bdf8bb1 --- /dev/null +++ b/script/parser/parser.rb @@ -0,0 +1,361 @@ +#!/usr/bin/env ruby +require 'net/http' +require 'open-uri' +require 'timeout' + +# Properties +@regex_cat_title = /\/\*{3,}\s*.*\s*\*+\// + +@dir_public = "../../public/" +@dir_examples = "examples/versions/" +@dir_template_target = "../../app/views/sdk/style-guide/versions/" + +@url_remote_css_file_components = nil +@url_remote_css_file_ui = nil + +# Remove all the characters from a string (to create a clean title) +# +# @param {Array} chars The characters that need to be replaced +# @param {String} string The given string that needs to be cleaned up +# @return {String} string The cleaned up string + +def replace_chars_in_string(chars, string) + chars.each {|char| string.gsub!(char, "")} + return string +end + + + +# Save the file +# +# @param {String} directory The target directory for the new file +# @param {String} filename The name of the HTML file +# @param {String} dump The HTML dump + +def save_file(directory, filename, dump) + + # First check if directory exists => create directory if not + if !File.directory?(directory) + Dir::mkdir(directory) + end + + # Create a new file object and write content + file = File.new(directory + filename, "w") + file.write(dump) + file.close + + puts '-' + directory + filename + ' was created successfully!' +end + + + +# Write the HTML to a file +# +# @param {String} foldername The name that will be used for the new skin file +# @param {String} directory The target directory for the new file +# @param {String} dump The HTML dump + +def prepare_file(foldername, directory, dump) + if foldername != "" + file = "_" + foldername + ".html.erb" + begin + save_file(directory, file, dump) + rescue + print "Saving the HTML file failed. Try again? (y/n): " + answer = gets.chomp + if answer == "y" + save_file(directory, file, dump) + else + exit + puts "Exit" + end + end + else + prepare_file(directory, dump) + end +end + + + +# Prepare an example file before creating +# +# @param {String} directory The target directory for the new file +# @param {String} filename The name for the new file +# @param {Array} lines Array of all the HTML lines + +def prepare_example_file(directory, filename, lines) + if lines.length > 0 + dump = "" + dump << "" + dump << "" + dump << "" + dump << "" + dump << "" + dump << "" + dump << "
" + lines.each{ |line| + dump << line + } + dump << "
" + dump << "" + dump << "" + dump << "" + save_file(directory, filename + ".html", dump) + end +end + + + +# Creates an object for each block +# +# @param {String} dump A string containing a comment or a selector +# @return {Object} obj The returned object + +def create_css_block(dump) + # Create a new object + objBlock = {} + objBlock['value'] = dump + objBlock['type'] = "selector" + + # If the item matches ' /*' + if dump.match(/^\/\*/) + objBlock['type'] = "description" + + # Create some arrays for other elements + objBlock['examples'] = [] + objBlock['snippets'] = [] + objBlock['explanations'] = [] + + # First remove all the '*' and the ' \' from the string + val = replace_chars_in_string([/\*/, /^\//], dump) + val = val.gsub(/\s<").gsub(/>$/,">").gsub(/\se.g./, "") + + # EXAMPLES: extract all the code out of the block + tempval = val + tempval.gsub(/\/?\*\s*[^<]*/,"") + tempval.scan(/
.*<\/pre>/).collect{|item|
+            item = item.gsub(/
/,"").gsub(/<\/pre>/,"").gsub(/^(\s)*/,"")
+            if item.length > 0
+                objBlock['examples'].push(item)                          
+            end
+        }
+                    
+        # SNIPPETS: Get all the html snippets out of the string               
+        val.scan(/
.*<\/pre>/).collect{|item|
+            snippet = item.gsub(/
/,"").gsub(/<\/pre>/,"").gsub(/^(\s)*/,"")            
+            objBlock['snippets'].push(snippet)
+        }
+                             
+        # EXPLANATIONS: Parse comment blocks and remove the examples                        
+        val.split(/
.*<\/pre>/).each{|i|
+            stripped = i.gsub(/\n/,"").gsub(/example:.*\.html/,"")                                        
+            if stripped && stripped != ""  
+                objBlock['explanations'].push(stripped) 
+            end
+        }                                                                
+    end  
+            
+    # Return the object
+    return objBlock  
+end
+
+
+
+# Generate a HTML structure
+#
+# @param    {Array}     categories      The categories
+
+def create_html_output(categories)  
+            
+    # Create a foldername
+    puts "Please enter the name of the skin: "
+    foldername = gets.chomp
+    
+    # Check if foldername is set
+    if(foldername && foldername != "")
+    
+        # Stores the HTML
+        dump = ""
+    
+        # Loop the categories 
+        categories.each{ |category| 
+            
+            # wl-widget-item
+            dump << "
\n" + + # Category title + dump << "

#{category['title']}

\n" + + # Category content + if category['content'] + + dump << "
\n" + + # Loop the category content items + counter = 1 + category['content'].each{ |item| + + # If item is not a selector + if item["type"] != "selector" + + # Create a filename for the example page + filename = category['title'] + counter.to_s + filename = filename.gsub(/\s/,"") + + # If the item has an explanation + if item["explanations"].length > 0 + item["explanations"].each{ |explanation| + dump << "

#{explanation}

\n" + } + end + + # If the item has examples + if item["examples"].length > 0 + dir = @dir_examples + foldername + dump << "\n" + end + + # If the item has snippets + if item["snippets"].length > 0 + arrLines = [] + dump << "
    \n" + item["snippets"].each{ |snippet| + arrLines.push(snippet) + dump << "
  • #{snippet.gsub(//,'>')}
  • \n" + } + dump << "
\n" + + directory = @dir_public + @dir_examples + foldername + "/" + prepare_example_file(directory, filename, arrLines) + + counter += 1 + end + + # If item is a selector + else + dump << "
#{item['value']}\n
\n" + end + } + + dump << "
\n" + + end + + # close wl-widget-item + dump << "
\n" + } + + # Prepare the main HTML file + prepare_file(foldername, @dir_template_target, dump) + + else + create_html_output(foldername, categories) + end +end + + + +# Parse the CSS file +# +# @param {String} file The CSS dump + +def parse_css_file(file) + + # Create an array to store the categories => create item for each category + titles = [] + file.scan(@regex_cat_title){|title| titles.push(title)} + + # If categories is not empty + if !titles.empty? + + # Create a new array to store the categories + arrCategories = [] + + # Create a new object for each title + i = 1 + titles.each{|title| + + # Create a new object for each category + objCategory = {} + objCategory['title'] = replace_chars_in_string([/\*/, /\//, /\s$/, /\n\s*/], title).downcase + objCategory['content'] = [] + + # To get the content, split on a regex of the type 'title' + # Returns a string with the description and selectors of the 'category' + # Puts each string in a temporary array + temp_categories = [] + file.split(@regex_cat_title).each{|category| + temp_categories.push(category) + } + + # Split the content on empty lines + arrParagraphs = [] + temp_categories[i].split(/\n\n/).each{|paragraph| + if paragraph.length > 1 + # Differentiate comment blocks from selectors + paragraph.split('*/').each{|block| + # Create e new object for each item (comment or selector) + arrParagraphs.push(create_css_block(block)) + } + end + } + + # Add all the paragrahps to the category object + objCategory['content'] = arrParagraphs + + # Update counter + i += 1 + + # Add the object to the array + arrCategories.push(objCategory) + } + + # Generate the HTML + create_html_output(arrCategories) + + else + puts "CSS file has no categories" + end +end + + + +# Load the CSS file +# +# @param {String} url The url to the css file + +def load_css_file(url) + begin + res = open(url).read + if res.length && res.class == String + parse_css_file(res) + end + rescue + puts "Loading CSS file failed! Try again? (y/n): " + answer = gets.chomp + if answer == "y" + init + else + puts "Exit" + exit + end + end +end + + + +# Initialize the script, asks for the path to the CSS file that needs to be parsed + +def init + print "Please enter the path to the CSS file: " + name = gets.chomp + if name == "" + puts "Please enter a valid path!" + init + else + load_css_file(name) + end +end + +init + \ No newline at end of file