Browse Source

Merge branch 'AngelFQC-7279' into 1.9.x

Yannick Warnier 10 years ago
parent
commit
2cd07a55d9

+ 26 - 0
plugin/tour/README.md

@@ -0,0 +1,26 @@
+Chamilo Tour Plugin
+===================
+
+Shows people how to use your Chamilo LMS
+
+# Set the blocks for the tour
+
+Edit the `plugin/tour/config/tour.json` file adding the page classes and steps
+
+To set the steps in a page, add a object like this:
+```
+{
+    "pageClass": "page unique class selector",
+    "steps": [
+        {
+            "elementSelector": "element class or id",
+            "message": "LanguageVariable"
+        },
+        {
+            "elementSelector": "element class or id",
+            "message": "LanguageVariable"
+        },
+    ]
+}
+```
+Then set the language variables inside the `plugin/tour/lang/$language.php` file

+ 23 - 0
plugin/tour/ajax/save.ajax.php

@@ -0,0 +1,23 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * Get the intro steps for the web page
+ * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ * @package chamilo.plugin.tour
+ */
+/**
+ * Init
+ */
+require_once __DIR__ . '/../../../main/inc/global.inc.php';
+require_once __DIR__ . '/../config.php';
+
+if (!api_is_anonymous()) {
+    $currentPageClass = isset($_POST['page_class']) ? $_POST['page_class'] : '';
+
+    if (!empty($currentPageClass)) {
+        $userId = api_get_user_id();
+
+        $tourPlugin = Tour::create();
+        $tourPlugin->saveCompletedTour($currentPageClass, $userId);
+    }
+}

+ 37 - 0
plugin/tour/ajax/steps.ajax.php

@@ -0,0 +1,37 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * Get the intro steps for the web page
+ * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ * @package chamilo.plugin.tour
+ */
+require_once __DIR__.'/../../../main/inc/global.inc.php';
+require_once api_get_path(LIBRARY_PATH) . 'plugin.class.php';
+require_once api_get_path(PLUGIN_PATH) . 'tour/src/tour_plugin.class.php';
+
+if (!api_is_anonymous()) {
+    $currentPageClass = isset($_GET['page_class']) ? $_GET['page_class'] : '';
+
+    $tourPlugin = Tour::create();
+
+    $json = $tourPlugin->getTourConfig();
+
+    $currentPageSteps = array();
+
+    foreach ($json as $pageContent) {
+        if ($pageContent['pageClass'] == $currentPageClass) {
+            foreach ($pageContent['steps'] as $step) {
+                $currentPageSteps[] = array(
+                    'element' => $step['elementSelector'],
+                    'intro' => $tourPlugin->get_lang($step['message'])
+                );
+            }
+
+            break;
+        }
+    }
+
+    if (!empty($currentPageSteps)) {
+        echo json_encode($currentPageSteps);
+    }
+}

+ 14 - 0
plugin/tour/config.php

@@ -0,0 +1,14 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * Config the plugin
+ * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ * @package chamilo.plugin.tour
+ */
+//require_once '../../main/inc/global.inc.php';
+
+define('TABLE_TOUR_LOG', 'plugin_tour_log');
+
+require_once api_get_path(SYS_PATH) . 'main/inc/global.inc.php';
+require_once api_get_path(LIBRARY_PATH) . 'plugin.class.php';
+require_once api_get_path(PLUGIN_PATH) . 'tour/src/tour_plugin.class.php';

+ 31 - 0
plugin/tour/config/tour.json

@@ -0,0 +1,31 @@
+[
+    {
+        "pageClass": ".section-mycampus",
+        "steps": [
+            {
+                "elementSelector": "#logo",
+                "message": "TheLogoStep"
+            },
+            {
+                "elementSelector": ".navbar",
+                "message": "TheNavbarStep"
+            },
+            {
+                "elementSelector": "div.span3:nth-child(1)",
+                "message": "TheRightPanelStep"
+            },
+            {
+                "elementSelector": "#user_image_block",
+                "message": "TheUserImageBlock"
+            },
+            {
+                "elementSelector": "#profile_block",
+                "message": "TheProfileBlock"
+            },
+            {
+                "elementSelector": "#homepage",
+                "message": "TheHomePageStep"
+            }
+        ]
+    }
+]

+ 46 - 0
plugin/tour/index.php

@@ -0,0 +1,46 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * Config the plugin
+ * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ * @package chamilo.plugin.tour
+ */
+require_once __DIR__ . '/config.php';
+
+$pluginPath = api_get_path(PLUGIN_PATH) . 'tour/';
+$pluginWebPath = api_get_path(WEB_PLUGIN_PATH) . 'tour/';
+
+$userId = api_get_user_id();
+
+$tourPlugin = Tour::create();
+$config = $tourPlugin->getTourConfig();
+$showTour = $tourPlugin->get('show_tour') === 'true';
+
+if ($showTour) {
+    $pages = array();
+
+    foreach ($config as $pageContent) {
+        $pages[] = array(
+            'pageClass' => $pageContent['pageClass'],
+            'show' => $tourPlugin->checkTourForUser($pageContent['pageClass'], $userId)
+        );
+    }
+
+    $theme = $tourPlugin->get('theme');
+
+    $_template['show_tour'] = $showTour;
+
+    $_template['pages'] = json_encode($pages);
+
+    $_template['web_path'] = array(
+        'intro_css' => "{$pluginWebPath}intro.js/introjs.min.css",
+        'intro_theme_css' => null,
+        'intro_js' => "{$pluginWebPath}intro.js/intro.min.js",
+        'steps_ajax' => "{$pluginWebPath}ajax/steps.ajax.php",
+        'save_ajax' => "{$pluginWebPath}ajax/save.ajax.php"
+    );
+
+    if (file_exists("{$pluginPath}intro.js/introjs-$theme.css")) {
+        $_template['web_path']['intro_theme_css'] = "{$pluginWebPath}intro.js/introjs-$theme.css";
+    }
+}

+ 10 - 0
plugin/tour/install.php

@@ -0,0 +1,10 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * Initialization install
+ * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ * @package chamilo.plugin.tour
+ */
+require_once __DIR__ . '/config.php';
+
+Tour::create()->install();

+ 27 - 0
plugin/tour/intro.js/intro.min.js

@@ -0,0 +1,27 @@
+(function(p,f){"object"===typeof exports?f(exports):"function"===typeof define&&define.amd?define(["exports"],f):f(p)})(this,function(p){function f(a){this._targetElement=a;this._options={nextLabel:"Next &rarr;",prevLabel:"&larr; Back",skipLabel:"Skip",doneLabel:"Done",tooltipPosition:"bottom",tooltipClass:"",exitOnEsc:!0,exitOnOverlayClick:!0,showStepNumbers:!0,keyboardNavigation:!0,showButtons:!0,showBullets:!0,scrollToElement:!0,overlayOpacity:0.8}}function r(a){if(null==a||"object"!=typeof a||
+"undefined"!=typeof a.nodeType)return a;var b={},c;for(c in a)b[c]=r(a[c]);return b}function s(){this._direction="forward";"undefined"===typeof this._currentStep?this._currentStep=0:++this._currentStep;if(this._introItems.length<=this._currentStep)"function"===typeof this._introCompleteCallback&&this._introCompleteCallback.call(this),t.call(this,this._targetElement);else{var a=this._introItems[this._currentStep];"undefined"!==typeof this._introBeforeChangeCallback&&this._introBeforeChangeCallback.call(this,
+a.element);A.call(this,a)}}function x(){this._direction="backward";if(0===this._currentStep)return!1;var a=this._introItems[--this._currentStep];"undefined"!==typeof this._introBeforeChangeCallback&&this._introBeforeChangeCallback.call(this,a.element);A.call(this,a)}function t(a){var b=a.querySelector(".introjs-overlay");if(null!=b){b.style.opacity=0;setTimeout(function(){b.parentNode&&b.parentNode.removeChild(b)},500);(a=a.querySelector(".introjs-helperLayer"))&&a.parentNode.removeChild(a);(a=document.querySelector(".introjsFloatingElement"))&&
+a.parentNode.removeChild(a);if(a=document.querySelector(".introjs-showElement"))a.className=a.className.replace(/introjs-[a-zA-Z]+/g,"").replace(/^\s+|\s+$/g,"");if((a=document.querySelectorAll(".introjs-fixParent"))&&0<a.length)for(var c=a.length-1;0<=c;c--)a[c].className=a[c].className.replace(/introjs-fixParent/g,"").replace(/^\s+|\s+$/g,"");window.removeEventListener?window.removeEventListener("keydown",this._onKeyDown,!0):document.detachEvent&&document.detachEvent("onkeydown",this._onKeyDown);
+this._currentStep=void 0}}function B(a,b,c,d){var e="";b.style.top=null;b.style.right=null;b.style.bottom=null;b.style.left=null;b.style.marginLeft=null;b.style.marginTop=null;c.style.display="inherit";"undefined"!=typeof d&&null!=d&&(d.style.top=null,d.style.left=null);if(this._introItems[this._currentStep])switch(e=this._introItems[this._currentStep],e="string"===typeof e.tooltipClass?e.tooltipClass:this._options.tooltipClass,b.className=("introjs-tooltip "+e).replace(/^\s+|\s+$/g,""),currentTooltipPosition=
+this._introItems[this._currentStep].position,currentTooltipPosition){case "top":b.style.left="15px";b.style.top="-"+(h(b).height+10)+"px";c.className="introjs-arrow bottom";break;case "right":b.style.left=h(a).width+20+"px";c.className="introjs-arrow left";break;case "left":!0==this._options.showStepNumbers&&(b.style.top="15px");b.style.right=h(a).width+20+"px";c.className="introjs-arrow right";break;case "floating":c.style.display="none";a=h(b);b.style.left="50%";b.style.top="50%";b.style.marginLeft=
+"-"+a.width/2+"px";b.style.marginTop="-"+a.height/2+"px";"undefined"!=typeof d&&null!=d&&(d.style.left="-"+(a.width/2+18)+"px",d.style.top="-"+(a.height/2+18)+"px");break;case "bottom-right-aligned":c.className="introjs-arrow top-right";b.style.right="0px";b.style.bottom="-"+(h(b).height+10)+"px";break;case "bottom-middle-aligned":d=h(a);a=h(b);c.className="introjs-arrow top-middle";b.style.left=d.width/2-a.width/2+"px";b.style.bottom="-"+(a.height+10)+"px";break;default:b.style.bottom="-"+(h(b).height+
+10)+"px",c.className="introjs-arrow top"}}function v(a){if(a&&this._introItems[this._currentStep]){var b=this._introItems[this._currentStep],c=h(b.element),d=10;"floating"==b.position&&(d=0);a.setAttribute("style","width: "+(c.width+d)+"px; height:"+(c.height+d)+"px; top:"+(c.top-5)+"px;left: "+(c.left-5)+"px;")}}function A(a){var b;"undefined"!==typeof this._introChangeCallback&&this._introChangeCallback.call(this,a.element);var c=this,d=document.querySelector(".introjs-helperLayer");h(a.element);
+if(null!=d){var e=d.querySelector(".introjs-helperNumberLayer"),C=d.querySelector(".introjs-tooltiptext"),g=d.querySelector(".introjs-arrow"),y=d.querySelector(".introjs-tooltip"),k=d.querySelector(".introjs-skipbutton"),n=d.querySelector(".introjs-prevbutton"),l=d.querySelector(".introjs-nextbutton");y.style.opacity=0;if(null!=e&&(b=this._introItems[0<=a.step-2?a.step-2:0],null!=b&&"forward"==this._direction&&"floating"==b.position||"backward"==this._direction&&"floating"==a.position))e.style.opacity=
+0;v.call(c,d);var m=document.querySelectorAll(".introjs-fixParent");if(m&&0<m.length)for(b=m.length-1;0<=b;b--)m[b].className=m[b].className.replace(/introjs-fixParent/g,"").replace(/^\s+|\s+$/g,"");b=document.querySelector(".introjs-showElement");b.className=b.className.replace(/introjs-[a-zA-Z]+/g,"").replace(/^\s+|\s+$/g,"");c._lastShowElementTimer&&clearTimeout(c._lastShowElementTimer);c._lastShowElementTimer=setTimeout(function(){null!=e&&(e.innerHTML=a.step);C.innerHTML=a.intro;B.call(c,a.element,
+y,g,e);d.querySelector(".introjs-bullets li > a.active").className="";d.querySelector('.introjs-bullets li > a[data-stepnumber="'+a.step+'"]').className="active";y.style.opacity=1;e&&(e.style.opacity=1)},350)}else{var k=document.createElement("div"),m=document.createElement("div"),j=document.createElement("div"),n=document.createElement("div"),l=document.createElement("div"),f=document.createElement("div");k.className="introjs-helperLayer";v.call(c,k);this._targetElement.appendChild(k);m.className=
+"introjs-arrow";n.className="introjs-tooltiptext";n.innerHTML=a.intro;l.className="introjs-bullets";!1===this._options.showBullets&&(l.style.display="none");var p=document.createElement("ul");b=0;for(var u=this._introItems.length;b<u;b++){var r=document.createElement("li"),q=document.createElement("a");q.onclick=function(){c.goToStep(this.getAttribute("data-stepnumber"))};0===b&&(q.className="active");q.href="javascript:void(0);";q.innerHTML="&nbsp;";q.setAttribute("data-stepnumber",this._introItems[b].step);
+r.appendChild(q);p.appendChild(r)}l.appendChild(p);f.className="introjs-tooltipbuttons";!1===this._options.showButtons&&(f.style.display="none");j.className="introjs-tooltip";j.appendChild(n);j.appendChild(l);if(!0==this._options.showStepNumbers){var w=document.createElement("span");w.className="introjs-helperNumberLayer";w.innerHTML=a.step;k.appendChild(w)}j.appendChild(m);k.appendChild(j);l=document.createElement("a");l.onclick=function(){c._introItems.length-1!=c._currentStep&&s.call(c)};l.href=
+"javascript:void(0);";l.innerHTML=this._options.nextLabel;n=document.createElement("a");n.onclick=function(){0!=c._currentStep&&x.call(c)};n.href="javascript:void(0);";n.innerHTML=this._options.prevLabel;k=document.createElement("a");k.className="introjs-button introjs-skipbutton";k.href="javascript:void(0);";k.innerHTML=this._options.skipLabel;k.onclick=function(){c._introItems.length-1==c._currentStep&&"function"===typeof c._introCompleteCallback&&c._introCompleteCallback.call(c);c._introItems.length-
+1!=c._currentStep&&"function"===typeof c._introExitCallback&&c._introExitCallback.call(c);t.call(c,c._targetElement)};f.appendChild(k);1<this._introItems.length&&(f.appendChild(n),f.appendChild(l));j.appendChild(f);B.call(c,a.element,j,m,w)}0==this._currentStep&&1<this._introItems.length?(n.className="introjs-button introjs-prevbutton introjs-disabled",l.className="introjs-button introjs-nextbutton",k.innerHTML=this._options.skipLabel):this._introItems.length-1==this._currentStep||1==this._introItems.length?
+(k.innerHTML=this._options.doneLabel,n.className="introjs-button introjs-prevbutton",l.className="introjs-button introjs-nextbutton introjs-disabled"):(n.className="introjs-button introjs-prevbutton",l.className="introjs-button introjs-nextbutton",k.innerHTML=this._options.skipLabel);l.focus();a.element.className+=" introjs-showElement";b=z(a.element,"position");"absolute"!==b&&"relative"!==b&&(a.element.className+=" introjs-relativePosition");for(b=a.element.parentNode;null!=b&&"body"!==b.tagName.toLowerCase();){m=
+z(b,"z-index");j=parseFloat(z(b,"opacity"));if(/[0-9]+/.test(m)||1>j)b.className+=" introjs-fixParent";b=b.parentNode}b=a.element.getBoundingClientRect();!(0<=b.top&&0<=b.left&&b.bottom+80<=window.innerHeight&&b.right<=window.innerWidth)&&!0===this._options.scrollToElement&&(j=a.element.getBoundingClientRect(),b=void 0!=window.innerWidth?window.innerHeight:document.documentElement.clientHeight,m=j.bottom-(j.bottom-j.top),j=j.bottom-b,0>m||a.element.clientHeight>b?window.scrollBy(0,m-30):window.scrollBy(0,
+j+100));"undefined"!==typeof this._introAfterChangeCallback&&this._introAfterChangeCallback.call(this,a.element)}function z(a,b){var c="";a.currentStyle?c=a.currentStyle[b]:document.defaultView&&document.defaultView.getComputedStyle&&(c=document.defaultView.getComputedStyle(a,null).getPropertyValue(b));return c&&c.toLowerCase?c.toLowerCase():c}function D(a){var b=document.createElement("div"),c="",d=this;b.className="introjs-overlay";if("body"===a.tagName.toLowerCase())c+="top: 0;bottom: 0; left: 0;right: 0;position: fixed;",
+b.setAttribute("style",c);else{var e=h(a);e&&(c+="width: "+e.width+"px; height:"+e.height+"px; top:"+e.top+"px;left: "+e.left+"px;",b.setAttribute("style",c))}a.appendChild(b);b.onclick=function(){!0==d._options.exitOnOverlayClick&&(t.call(d,a),void 0!=d._introExitCallback&&d._introExitCallback.call(d))};setTimeout(function(){c+="opacity: "+d._options.overlayOpacity.toString()+";";b.setAttribute("style",c)},10);return!0}function h(a){var b={};b.width=a.offsetWidth;b.height=a.offsetHeight;for(var c=
+0,d=0;a&&!isNaN(a.offsetLeft)&&!isNaN(a.offsetTop);)c+=a.offsetLeft,d+=a.offsetTop,a=a.offsetParent;b.top=d;b.left=c;return b}var u=function(a){if("object"===typeof a)return new f(a);if("string"===typeof a){if(a=document.querySelector(a))return new f(a);throw Error("There is no element with given selector.");}return new f(document.body)};u.version="0.9.0";u.fn=f.prototype={clone:function(){return new f(this)},setOption:function(a,b){this._options[a]=b;return this},setOptions:function(a){var b=this._options,
+c={},d;for(d in b)c[d]=b[d];for(d in a)c[d]=a[d];this._options=c;return this},start:function(){a:{var a=this._targetElement,b=[],c=this;if(this._options.steps)for(var d=[],e=0,d=this._options.steps.length;e<d;e++){var f=r(this._options.steps[e]);f.step=b.length+1;"string"===typeof f.element&&(f.element=document.querySelector(f.element));if("undefined"===typeof f.element||null==f.element){var g=document.querySelector(".introjsFloatingElement");null==g&&(g=document.createElement("div"),g.className=
+"introjsFloatingElement",document.body.appendChild(g));f.element=g;f.position="floating"}null!=f.element&&b.push(f)}else{d=a.querySelectorAll("*[data-intro]");if(1>d.length)break a;e=0;for(f=d.length;e<f;e++){var g=d[e],h=parseInt(g.getAttribute("data-step"),10);0<h&&(b[h-1]={element:g,intro:g.getAttribute("data-intro"),step:parseInt(g.getAttribute("data-step"),10),tooltipClass:g.getAttribute("data-tooltipClass"),position:g.getAttribute("data-position")||this._options.tooltipPosition})}e=h=0;for(f=
+d.length;e<f;e++)if(g=d[e],null==g.getAttribute("data-step")){for(;"undefined"!=typeof b[h];)h++;b[h]={element:g,intro:g.getAttribute("data-intro"),step:h+1,tooltipClass:g.getAttribute("data-tooltipClass"),position:g.getAttribute("data-position")||this._options.tooltipPosition}}}e=[];for(d=0;d<b.length;d++)b[d]&&e.push(b[d]);b=e;b.sort(function(a,b){return a.step-b.step});c._introItems=b;D.call(c,a)&&(s.call(c),a.querySelector(".introjs-skipbutton"),a.querySelector(".introjs-nextbutton"),c._onKeyDown=
+function(b){if(27===b.keyCode&&!0==c._options.exitOnEsc)t.call(c,a),void 0!=c._introExitCallback&&c._introExitCallback.call(c);else if(37===b.keyCode)x.call(c);else if(39===b.keyCode||13===b.keyCode)s.call(c),b.preventDefault?b.preventDefault():b.returnValue=!1},c._onResize=function(){v.call(c,document.querySelector(".introjs-helperLayer"))},window.addEventListener?(this._options.keyboardNavigation&&window.addEventListener("keydown",c._onKeyDown,!0),window.addEventListener("resize",c._onResize,!0)):
+document.attachEvent&&(this._options.keyboardNavigation&&document.attachEvent("onkeydown",c._onKeyDown),document.attachEvent("onresize",c._onResize)))}return this},goToStep:function(a){this._currentStep=a-2;"undefined"!==typeof this._introItems&&s.call(this);return this},nextStep:function(){s.call(this);return this},previousStep:function(){x.call(this);return this},exit:function(){t.call(this,this._targetElement)},refresh:function(){v.call(this,document.querySelector(".introjs-helperLayer"));return this},
+onbeforechange:function(a){if("function"===typeof a)this._introBeforeChangeCallback=a;else throw Error("Provided callback for onbeforechange was not a function");return this},onchange:function(a){if("function"===typeof a)this._introChangeCallback=a;else throw Error("Provided callback for onchange was not a function.");return this},onafterchange:function(a){if("function"===typeof a)this._introAfterChangeCallback=a;else throw Error("Provided callback for onafterchange was not a function");return this},
+oncomplete:function(a){if("function"===typeof a)this._introCompleteCallback=a;else throw Error("Provided callback for oncomplete was not a function.");return this},onexit:function(a){if("function"===typeof a)this._introExitCallback=a;else throw Error("Provided callback for onexit was not a function.");return this}};return p.introJs=u});

+ 288 - 0
plugin/tour/intro.js/introjs-nassim.css

@@ -0,0 +1,288 @@
+.introjs-overlay {
+  position: absolute;
+  z-index: 999999;
+  background: #181818;
+  opacity: 0;
+  
+  -webkit-transition: all 0.3s ease-out;
+     -moz-transition: all 0.3s ease-out;
+      -ms-transition: all 0.3s ease-out;
+       -o-transition: all 0.3s ease-out;
+          transition: all 0.3s ease-out;
+}
+
+.introjs-fixParent {
+  z-index: auto !important;
+  opacity: 1.0 !important;
+}
+
+.introjs-showElement {
+  z-index: 9999999 !important;
+}
+
+.introjs-relativePosition {
+  position: relative;
+}
+
+.introjs-helperLayer {
+  position: absolute;
+  z-index: 9999998;
+  background-color: #FFF;
+  background-color: rgba(255,255,255,.9);
+  border: 1px solid #777;
+  border: 2px solid rgba(117, 117, 117, 1);
+  border-radius: 4px;
+  box-shadow: 0 5px 8px -3px rgba(0,0,0,.6);
+  -webkit-transition: all 0.3s ease-out;
+     -moz-transition: all 0.3s ease-out;
+      -ms-transition: all 0.3s ease-out;
+       -o-transition: all 0.3s ease-out;
+          transition: all 0.3s ease-out;
+}
+
+.introjs-helperNumberLayer {
+  position: absolute;
+  top: -16px;
+  left: -9px;
+  z-index: 9999999999 !important;
+  padding: 2px;
+  font-family: Arial, verdana, tahoma;
+  font-size: 13px;
+  font-weight: bold;
+  color: #fff; /* Old browsers */ /* Chrome10+,Safari5.1+ */
+  background: #DA4433;
+  width: 20px;
+  box-shadow: 0 1px 1px rgba(0,0,0,.35);
+  height:20px;
+  text-align: center;
+  line-height: 20px;
+  border: 2px solid #DA4433;
+  border-radius: 0; /* IE6-9 */  /* IE10 text shadows */
+}
+
+.introjs-helperNumberLayer:after {
+  content:"";
+  width:0;
+  height:0;
+  position:absolute;
+  content:0;
+  left:-3px;
+  bottom:-10px;
+  border:4px solid transparent;
+  border-right-color:#900;
+  border-top-color:#900;
+}
+
+.introjs-arrow {
+  border: 5px solid white;
+  content:'';
+  position: absolute;
+}
+.introjs-arrow.top {
+  top: -10px;
+  border-top-color:transparent;
+  border-right-color:transparent;
+  border-bottom-color: #ecf0f1;
+  border-left-color:transparent;
+}
+.introjs-arrow.right {
+  right: -10px;
+  top: 10px;
+  border-top-color:transparent;
+  border-right-color:transparent;
+  border-bottom-color:transparent;
+  border-left-color:#ecf0f1;
+}
+.introjs-arrow.bottom {
+  bottom: -10px;
+  border-top-color:#ecf0f1;
+  border-right-color:transparent;
+  border-bottom-color:transparent;
+  border-left-color:transparent;
+}
+.introjs-arrow.left {
+  left: -10px;
+  top: 10px;
+  border-top-color:transparent;
+  border-right-color: #ecf0f1;
+  border-bottom-color:transparent;
+  border-left-color:transparent;
+}
+
+.introjs-tooltip {
+  position: absolute;
+  padding: 10px 10px;
+  background-color: #ecf0f1;
+  min-width: 200px;
+  max-width: 300px;
+  border-radius: 3px;
+  /* border-radius: 3px; */
+  /* box-shadow: 0 6px 7px -4px rgba(0,0,0,.4); */
+  -webkit-transition: opacity 0.1s ease-out;
+     -moz-transition: opacity 0.1s ease-out;
+      -ms-transition: opacity 0.1s ease-out;
+       -o-transition: opacity 0.1s ease-out;
+          transition: opacity 0.1s ease-out;
+  /* border: 5px double #0787AF; */
+}
+
+.introjs-tooltiptext {
+    margin-left: -10px;
+  
+    margin-right: -10px;
+    /* border-top: 1px solid #FFFFFF; */
+    /* background: #FAFAFA; */
+    color: #2c3e50;
+    padding: 25px 30px 15px;
+    /* border-bottom: 1px solid #FFFFFF; */
+}
+
+.introjs-tooltipbuttons {
+  text-align: center;
+  /* background: rgba(0, 0, 0, 0.06); */
+  border-radius: 0 0 8px 8px;
+  padding-bottom: 10px;
+}
+
+/* 
+ Buttons style by http://nicolasgallagher.com/lab/css3-github-buttons/ 
+ Changed by Afshin Mehrabani
+*/
+.introjs-button {
+  position: relative;
+  overflow: visible;
+  display: inline-block;
+  padding: 0.5em 0.8em;
+  /* box-shadow: 0 2px 0px -0px #306588; */
+  margin: 0;
+  outline: none;
+  border: 2px solid;
+  background: transparent;
+  text-decoration: none;
+  font: 11px/normal sans-serif;
+  color: #2980b9 !important;
+  white-space: nowrap;
+  cursor: pointer;
+  outline: none !important;
+  -webkit-background-clip: padding;
+  -moz-background-clip: padding;
+  -o-background-clip: padding-box;
+  /*background-clip: padding-box;*/ /* commented out due to Opera 11.10 bug */
+  -webkit-border-radius: 0.2em;
+  -moz-border-radius: 0.2em;
+  border-radius: 0.2em;
+  /* IE hacks */
+  zoom: 1;
+  *display: inline;
+  margin-top: 10px;
+  transition:all 0.25s ease;
+  -webkit-transition:all 0.25s ease;
+  -moz-transition:all 0.25s ease;
+  -ms-transition:all 0.25s ease;
+  -o-transition:all 0.25s ease;
+}
+
+.introjs-button:hover {
+  color: #fff;
+  background: #2671A2;
+  text-decoration: none; 
+  border-color: #235677;
+}
+
+.introjs-button:focus,
+.introjs-button:active {
+    background: #23587A;  text-decoration: none;  
+    color: #fff;
+    /* bottom: -1px; */
+    box-shadow: none;
+    border-color: #173B53;
+}
+
+/* overrides extra padding on button elements in Firefox */
+.introjs-button::-moz-focus-inner {
+  padding: 0;
+  border: 0;
+}
+
+.introjs-skipbutton {
+  margin-right: 5px;
+  color: #c00;
+  background: transparent;
+}
+
+.introjs-skipbutton:hover {
+    background: #EB1540;  
+    border-color: #B91D0D;
+  
+}
+
+.introjs-skipbutton:active, .introjs-skipbutton:focus {
+    background: #C02312;  
+    /* box-shadow: 0 1px 0px -0px #6F1309; */
+  
+}
+
+.introjs-prevbutton {
+  -webkit-border-radius: 0.2em 0 0 0.2em;
+  -moz-border-radius: 0.2em 0 0 0.2em;
+  border-radius: 0.2em 0 0 0.2em;
+  border-right: none;
+}
+
+.introjs-nextbutton {
+  -webkit-border-radius: 0 0.2em 0.2em 0;
+  -moz-border-radius: 0 0.2em 0.2em 0;
+  border-radius: 0 0.2em 0.2em 0;
+}
+
+.introjs-disabled, .introjs-disabled:hover, .introjs-disabled:focus {
+  color: #C2C2C2 !important;
+  border-color: #d4d4d4;
+  cursor: default;
+  /* box-shadow: 0 2px 0px -0px #CACED1; */
+  background-color: #E6E6E6;
+  background-image: none;
+  text-decoration: none;
+}
+
+.introjs-bullets {
+  text-align: center;
+  position: absolute;
+  left: 0;
+  right: 0;
+  top: -5px;
+}
+.introjs-bullets ul {
+  clear: both;
+  margin: 15px auto 0;
+  padding: 0;
+  display: inline-block;
+}
+.introjs-bullets ul li {
+  list-style: none;
+  float: left;
+  margin: 0 2px;
+}
+.introjs-bullets ul li a {
+  display: block;
+  width: 6px;
+  height: 6px;
+  background: #ccc;
+  border-radius: 10px;
+  -moz-border-radius: 10px;
+  -webkit-border-radius: 10px;
+  text-decoration: none;
+}
+.introjs-bullets ul li a:hover {
+  background: #999;
+}
+.introjs-bullets ul li a.active {
+  background: #999;
+}
+.introjsFloatingElement {
+  position: absolute;
+  height: 0;
+  width: 0;
+  left: 50%;
+  top: 50%;
+}

+ 257 - 0
plugin/tour/intro.js/introjs-nazanin.css

@@ -0,0 +1,257 @@
+.introjs-overlay {
+  position: absolute;
+  z-index: 999999;
+  background: #525252;
+  opacity: 0;
+  
+  -webkit-transition: all 0.3s ease-out;
+     -moz-transition: all 0.3s ease-out;
+      -ms-transition: all 0.3s ease-out;
+       -o-transition: all 0.3s ease-out;
+          transition: all 0.3s ease-out;
+}
+
+.introjs-fixParent {
+  z-index: auto !important;
+  opacity: 1.0 !important;
+}
+
+.introjs-showElement {
+  z-index: 9999999 !important;
+}
+
+.introjs-relativePosition {
+  position: relative;
+}
+
+.introjs-helperLayer {
+  position: absolute;
+  z-index: 9999998;
+  background-color: #FFF;
+  background-color: rgba(255,255,255,.9);
+  border: 1px solid #777;
+  border: 3px solid rgba(211, 214, 209, 1);
+  border-radius: 0;
+  box-shadow: 0 5px 8px -3px rgba(0,0,0,.6);
+  -webkit-transition: all 0.3s ease-out;
+     -moz-transition: all 0.3s ease-out;
+      -ms-transition: all 0.3s ease-out;
+       -o-transition: all 0.3s ease-out;
+          transition: all 0.3s ease-out;
+}
+
+.introjs-helperNumberLayer {
+  position: absolute;
+  top: -16px;
+  left: -16px;
+  z-index: 9999999999 !important;
+  padding: 2px;
+  font-family: Arial, verdana, tahoma;
+  font-size: 13px;
+  font-weight: bold;
+  color: white; /* Old browsers */ /* Chrome10+,Safari5.1+ */
+  background:#ff3019 ;
+  width: 20px;
+  height:20px;
+  text-align: center;
+  line-height: 20px;
+  border: 3px solid #DA4433;
+  border-radius: 10px 10px 0; /* IE6-9 */  /* IE10 text shadows */
+}
+
+.introjs-arrow {
+  border: 5px solid white;
+  content:'';
+  position: absolute;
+}
+.introjs-arrow.top {
+  top: -10px;
+  border-top-color:transparent;
+  border-right-color:transparent;
+  border-bottom-color: #ecf0f1;
+  border-left-color:transparent;
+}
+.introjs-arrow.right {
+  right: -10px;
+  top: 10px;
+  border-top-color:transparent;
+  border-right-color:transparent;
+  border-bottom-color:transparent;
+  border-left-color:#ecf0f1;
+}
+.introjs-arrow.bottom {
+  bottom: -10px;
+  border-top-color:#ecf0f1;
+  border-right-color:transparent;
+  border-bottom-color:transparent;
+  border-left-color:transparent;
+}
+.introjs-arrow.left {
+  left: -10px;
+  top: 10px;
+  border-top-color:transparent;
+  border-right-color: #ecf0f1;
+  border-bottom-color:transparent;
+  border-left-color:transparent;
+}
+
+.introjs-tooltip {
+  position: absolute;
+  padding: 10px;
+  background-color: #ecf0f1;
+  min-width: 200px;
+  max-width: 300px;
+  /* border-radius: 3px; */
+  box-shadow: 0 6px 7px -4px rgba(0,0,0,.4);
+  -webkit-transition: opacity 0.1s ease-out;
+     -moz-transition: opacity 0.1s ease-out;
+      -ms-transition: opacity 0.1s ease-out;
+       -o-transition: opacity 0.1s ease-out;
+          transition: opacity 0.1s ease-out;
+}
+
+.introjs-tooltiptext {
+    margin-left: -10px;
+  
+    margin-right: -10px;
+    border-top: 1px solid #FFFFFF;
+    background: #FAFAFA;
+    color: #2c3e50;
+    padding: 5px 10px;
+    border-bottom: 1px solid #FFFFFF;
+}
+
+.introjs-tooltipbuttons {
+  text-align: center;
+}
+
+/* 
+ Buttons style by http://nicolasgallagher.com/lab/css3-github-buttons/ 
+ Changed by Afshin Mehrabani
+*/
+.introjs-button {
+  position: relative;
+  overflow: visible;
+  display: inline-block;
+  padding: 0.5em 0.8em;
+  box-shadow: 0 2px 0px -0px #306588;
+  margin: 0;
+  outline: none;
+  background: #2980b9;
+  text-decoration: none;
+  font: 11px/normal sans-serif;
+  color: #fff !important;
+  white-space: nowrap;
+  cursor: pointer;
+  outline: none !important;
+  -webkit-background-clip: padding;
+  -moz-background-clip: padding;
+  -o-background-clip: padding-box;
+  /*background-clip: padding-box;*/ /* commented out due to Opera 11.10 bug */
+  -webkit-border-radius: 0.2em;
+  -moz-border-radius: 0.2em;
+  border-radius: 0.2em;
+  /* IE hacks */
+  zoom: 1;
+  *display: inline;
+  margin-top: 10px;
+}
+
+.introjs-button:hover {
+  color: #fff;
+  background: #2671A2;
+  text-decoration: none; 
+  box-shadow: 0 2px 0px -0px #235677;
+}
+
+.introjs-button:focus,
+.introjs-button:active {
+    background: #23587A;  text-decoration: none;  
+    /* bottom: -1px; */
+    box-shadow: 0 2px 0px 0px #173B53;
+}
+
+/* overrides extra padding on button elements in Firefox */
+.introjs-button::-moz-focus-inner {
+  padding: 0;
+  border: 0;
+}
+
+.introjs-skipbutton {
+  margin-right: 5px;
+  color: #fff;
+  background: #e74c3c;
+  box-shadow: 0 2px 0px -0px #B91D0D;
+}
+
+.introjs-skipbutton:hover {
+    background: #EB1540;  box-shadow: 0 2px 0px -0px #B91D0D;
+  
+}
+
+.introjs-skipbutton:active, .introjs-skipbutton:focus {
+    background: #C02312;  
+    box-shadow: 0 1px 0px -0px #6F1309;
+  
+}
+
+.introjs-prevbutton {
+  -webkit-border-radius: 0.2em 0 0 0.2em;
+  -moz-border-radius: 0.2em 0 0 0.2em;
+  border-radius: 0.2em 0 0 0.2em;
+  border-right: none;
+}
+
+.introjs-nextbutton {
+  -webkit-border-radius: 0 0.2em 0.2em 0;
+  -moz-border-radius: 0 0.2em 0.2em 0;
+  border-radius: 0 0.2em 0.2em 0;
+}
+
+.introjs-disabled, .introjs-disabled:hover, .introjs-disabled:focus {
+  color: #C2C2C2 !important;
+  border-color: #d4d4d4;
+  cursor: default;
+  box-shadow: 0 2px 0px -0px #CACED1;
+  background-color: #E6E6E6;
+  background-image: none;
+  text-decoration: none;
+}
+
+.introjs-bullets {
+  text-align: center;
+}
+.introjs-bullets ul {
+  clear: both;
+  margin: 15px auto 0;
+  padding: 0;
+  display: inline-block;
+}
+.introjs-bullets ul li {
+  list-style: none;
+  float: left;
+  margin: 0 2px;
+}
+.introjs-bullets ul li a {
+  display: block;
+  width: 6px;
+  height: 6px;
+  background: #ccc;
+  border-radius: 10px;
+  -moz-border-radius: 10px;
+  -webkit-border-radius: 10px;
+  text-decoration: none;
+}
+.introjs-bullets ul li a:hover {
+  background: #999;
+}
+.introjs-bullets ul li a.active {
+  background: #999;
+}
+.introjsFloatingElement {
+  position: absolute;
+  height: 0;
+  width: 0;
+  left: 50%;
+  top: 50%;
+}

+ 274 - 0
plugin/tour/intro.js/introjs-royal.css

@@ -0,0 +1,274 @@
+.introjs-overlay {
+  position: absolute;
+  z-index: 999999;
+  background: #525252;
+  opacity: 0;
+  
+  -webkit-transition: all 0.3s ease-out;
+     -moz-transition: all 0.3s ease-out;
+      -ms-transition: all 0.3s ease-out;
+       -o-transition: all 0.3s ease-out;
+          transition: all 0.3s ease-out;
+}
+
+.introjs-fixParent {
+  z-index: auto !important;
+  opacity: 1.0 !important;
+}
+
+.introjs-showElement {
+  z-index: 9999999 !important;
+}
+
+.introjs-relativePosition {
+  position: relative;
+}
+
+.introjs-helperLayer {
+  position: absolute;
+  z-index: 9999998;
+  background-color: #FFF;
+  background-color: rgba(255,255,255,.9);
+  border: 1px solid #777;
+  border: 3px solid rgba(255, 255, 255, 1);
+  border-radius: 0;
+  box-shadow: 0 8px 50px -10px rgba(0,0,0,.6);
+  -webkit-transition: all 0.3s ease-out;
+     -moz-transition: all 0.3s ease-out;
+      -ms-transition: all 0.3s ease-out;
+       -o-transition: all 0.3s ease-out;
+          transition: all 0.3s ease-out;
+}
+
+.introjs-helperNumberLayer {
+  position: absolute;
+  top: -29px;
+  left: -29px;
+  z-index: 9999999999 !important;
+  padding: 3px;
+  font-family: Arial, verdana, tahoma;
+  font-size: 13px;
+  font-weight: bold;
+  color: #DA4433; /* Old browsers */ /* Chrome10+,Safari5.1+ */
+  background: #FFFFFF;
+  width: 20px;
+  height:20px;
+  text-align: center;
+  line-height: 20px;
+  border: 3px solid #DA4433;
+  border-right: none;
+  border-bottom: none; /* IE6-9 */  /* IE10 text shadows */
+  border-radius: 10px 0 0 0;
+}
+
+.introjs-arrow {
+  border: 5px solid white;
+  content:'';
+  position: absolute;
+}
+.introjs-arrow.top {
+  top: -10px;
+  border-top-color:transparent;
+  border-right-color:transparent;
+  border-bottom-color: #ecf0f1;
+  border-left-color:transparent;
+  display: none !important;
+}
+.introjs-arrow.right {
+  right: -10px;
+  top: 10px;
+  border-top-color:transparent;
+  border-right-color:transparent;
+  border-bottom-color:transparent;
+  border-left-color:#ecf0f1;
+}
+.introjs-arrow.bottom {
+  bottom: -10px;
+  border-top-color:#ecf0f1;
+  border-right-color:transparent;
+  border-bottom-color:transparent;
+  border-left-color:transparent;
+}
+.introjs-arrow.left {
+  left: -10px;
+  top: 10px;
+  border-top-color:transparent;
+  border-right-color: #ecf0f1;
+  border-bottom-color:transparent;
+  border-left-color:transparent;
+}
+
+.introjs-tooltip {
+  position: fixed;
+  padding: 10px 170px 30px 10px;
+  background-color: #ecf0f1;
+  min-width: 200px;
+  max-width: 300px;
+  /* border-radius: 3px; */
+  border-top: 3px solid #236591;
+  box-shadow: 0 -6px 50px -4px rgba(0,0,0,.4);
+  -webkit-transition: opacity 0.1s ease-out;
+     -moz-transition: opacity 0.1s ease-out;
+      -ms-transition: opacity 0.1s ease-out;
+       -o-transition: opacity 0.1s ease-out;
+          transition: opacity 0.1s ease-out;
+  bottom: 0 !important;
+  left: 0 !Important;
+  top: initial !important;
+  right: 0 !Important;
+  max-width: initial;
+  width: auto !important;
+}
+
+.introjs-tooltiptext {
+    margin-left: -10px;
+  
+    margin-right: -10px;
+    /* border-top: 1px solid #FFFFFF; */
+    /* background: #FAFAFA; */
+    color: #2c3e50;
+    padding: 5px 10px;
+    /* border-bottom: 1px solid #FFFFFF; */
+}
+
+.introjs-tooltipbuttons {
+  text-align: center;
+  position: absolute;
+  right: 10px;
+  top: 0;
+}
+
+/* 
+ Buttons style by http://nicolasgallagher.com/lab/css3-github-buttons/ 
+ Changed by Afshin Mehrabani
+*/
+.introjs-button {
+  position: relative;
+  overflow: visible;
+  display: inline-block;
+  padding: 0.5em 0.8em;
+  box-shadow: 0 2px 0px -0px #306588;
+  margin: 0;
+  outline: none;
+  background: #2980b9;
+  text-decoration: none;
+  font: 11px/normal sans-serif;
+  color: #fff !important;
+  white-space: nowrap;
+  cursor: pointer;
+  outline: none !important;
+  -webkit-background-clip: padding;
+  -moz-background-clip: padding;
+  -o-background-clip: padding-box;
+  /*background-clip: padding-box;*/ /* commented out due to Opera 11.10 bug */
+  -webkit-border-radius: 0.2em;
+  -moz-border-radius: 0.2em;
+  border-radius: 0.2em;
+  /* IE hacks */
+  zoom: 1;
+  *display: inline;
+  margin-top: 10px;
+}
+
+.introjs-button:hover {
+  color: #fff;
+  background: #2671A2;
+  text-decoration: none; 
+  box-shadow: 0 2px 0px -0px #235677;
+}
+
+.introjs-button:focus,
+.introjs-button:active {
+    background: #23587A;  text-decoration: none;  
+    /* bottom: -1px; */
+    box-shadow: 0 2px 0px 0px #173B53;
+}
+
+/* overrides extra padding on button elements in Firefox */
+.introjs-button::-moz-focus-inner {
+  padding: 0;
+  border: 0;
+}
+
+.introjs-skipbutton {
+  margin-right: 5px;
+  color: #fff;
+  background: #e74c3c;
+  box-shadow: 0 2px 0px -0px #B91D0D;
+}
+
+.introjs-skipbutton:hover {
+    background: #EB1540;  box-shadow: 0 2px 0px -0px #B91D0D;
+  
+}
+
+.introjs-skipbutton:active, .introjs-skipbutton:focus {
+    background: #C02312;  
+    box-shadow: 0 1px 0px -0px #6F1309;
+  
+}
+
+.introjs-prevbutton {
+  -webkit-border-radius: 0.2em 0 0 0.2em;
+  -moz-border-radius: 0.2em 0 0 0.2em;
+  border-radius: 0.2em 0 0 0.2em;
+  border-right: none;
+}
+
+.introjs-nextbutton {
+  -webkit-border-radius: 0 0.2em 0.2em 0;
+  -moz-border-radius: 0 0.2em 0.2em 0;
+  border-radius: 0 0.2em 0.2em 0;
+}
+
+.introjs-disabled, .introjs-disabled:hover, .introjs-disabled:focus {
+  color: #C2C2C2 !important;
+  border-color: #d4d4d4;
+  cursor: default;
+  box-shadow: 0 2px 0px -0px #CACED1;
+  background-color: #E6E6E6;
+  background-image: none;
+  text-decoration: none;
+}
+
+.introjs-bullets {
+  text-align: center;
+  float: right;
+  position: absolute;
+  right: 10px;
+  bottom: 10px;
+}
+.introjs-bullets ul {
+  clear: both;
+  margin: 15px auto 0;
+  padding: 0;
+  display: inline-block;
+}
+.introjs-bullets ul li {
+  list-style: none;
+  float: left;
+  margin: 0 2px;
+}
+.introjs-bullets ul li a {
+  display: block;
+  width: 6px;
+  height: 6px;
+  background: #ccc;
+  border-radius: 10px;
+  -moz-border-radius: 10px;
+  -webkit-border-radius: 10px;
+  text-decoration: none;
+}
+.introjs-bullets ul li a:hover {
+  background: #999;
+}
+.introjs-bullets ul li a.active {
+  background: #999;
+}
+.introjsFloatingElement {
+  position: absolute;
+  height: 0;
+  width: 0;
+  left: 50%;
+  top: 50%;
+}

+ 1 - 0
plugin/tour/intro.js/introjs-rtl.min.css

@@ -0,0 +1 @@
+.introjs-tooltipbuttons{text-align:left}.introjs-skipbutton{margin-left:5px}.introjs-tooltip{direction:rtl}.introjs-prevbutton{border:1px solid #d4d4d4;border-left:0;-webkit-border-radius:0 .2em .2em 0;-moz-border-radius:0 .2em .2em 0;border-radius:0 .2em .2em 0}.introjs-nextbutton{border:1px solid #d4d4d4;-webkit-border-radius:.2em 0 0 .2em;-moz-border-radius:.2em 0 0 .2em;border-radius:.2em 0 0 .2em}

File diff suppressed because it is too large
+ 0 - 0
plugin/tour/intro.js/introjs.min.css


+ 35 - 0
plugin/tour/lang/english.php

@@ -0,0 +1,35 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * Strings to english L10n
+ * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ * @package chamilo.plugin.tour
+ */
+$strings['plugin_title'] = 'Tour';
+$strings['plugin_comment'] = 'This plugin shows people how to use your Chamilo LMS';
+
+/* Strings for settings */
+$strings['show_tour'] = 'Show the tour';
+
+$showTourHelpLine01 = 'The necessary configuration to show the help blocks, in JSON format, is located in the %splugin/tour/config/tour.json%s file.';
+$showTourHelpLine02 = 'See README file for more information.';
+
+$strings['show_tour_help'] = sprintf("$showTourHelpLine01 %s $showTourHelpLine02", "<strong>", "</strong>", "<br>");
+
+$strings['theme'] = 'Theme';
+$strings['theme_help'] = 'Chose <i>nassim</i>, <i>nazanin</i>, <i>royal</i>. Empty to use the default theme.';
+
+/* Strings for plugin UI */
+$strings['Skip'] = 'Skip';
+$strings['Next'] = 'Next';
+$strings['Prev'] = 'Prev';
+$strings['Done'] = 'Done';
+$strings['StartButtonText'] = 'Start the tour';
+
+/* String for the steps */
+$strings['TheLogoStep'] = 'Welcome to <b>Chamilo LMS 1.9.x</b>';
+$strings['TheNavbarStep'] = 'Menu bar with main tools.';
+$strings['TheRightPanelStep'] = 'Sidebar panel.';
+$strings['TheUserImageBlock'] = 'Your profile photo.';
+$strings['TheProfileBlock'] = 'Your profile tools: <i>Inbox</i>, <i>Compose</i>, <i>Pending invitations</i>, <i>Edit</i>.';
+$strings['TheHomePageStep'] = 'This is the initial homepage.';

+ 35 - 0
plugin/tour/lang/spanish.php

@@ -0,0 +1,35 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * Strings to spanish L10n
+ * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ * @package chamilo.plugin.tour
+ */
+$strings['plugin_title'] = 'Tour';
+$strings['plugin_comment'] = 'Este plugin muestra a la gente cómo usar tu LMS';
+
+/* Strings for settings */
+$strings['show_tour'] = 'Mostrar el tour';
+
+$showTourHelpLine01 = 'La configuración necesaria para mostrar los bloques de ayuda, en formato JSON, están localizadas en el archivo %splugin/tour/config/tour.json%s.';
+$showTourHelpLine02 = 'Ver el archivo README para más información.';
+
+$strings['show_tour_help'] = sprintf("$showTourHelpLine01 %s $showTourHelpLine02", "<strong>", "</strong>", "<br>");
+
+$strings['theme'] = 'Tema';
+$strings['theme_help'] = 'Elegir entre <i>nassim</i>, <i>nazanin</i>, <i>royal</i>. Vacío para usar el tema por defecto.';
+
+/* Strings for plugin UI */
+$strings['Skip'] = 'Saltar';
+$strings['Next'] = 'Siguiente';
+$strings['Prev'] = 'Anterior';
+$strings['Done'] = 'Hecho';
+$strings['StartButtonText'] = 'Empezar el recorrido';
+
+/* String for the steps */
+$strings['TheLogoStep'] = 'Bienvenido a <b>Chamilo LMS 1.9.x</b>.';
+$strings['TheNavbarStep'] = 'Barra de herramientas con principales herramientas.';
+$strings['TheRightPanelStep'] = 'Pane lateral.';
+$strings['TheUserImageBlock'] = 'Tu foto de perfil.';
+$strings['TheProfileBlock'] = 'Herramientas de perfil: <i>Bandeja de entrada</i>, <i>Nuevo mensaje</i>, <i>Invitaciones pendientes</i>, <i>Editar perfil</i>.';
+$strings['TheHomePageStep'] = 'Esta es la página de inicio.';

+ 12 - 0
plugin/tour/plugin.php

@@ -0,0 +1,12 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * Show the JavaScript template in the web pages
+ * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ * @package chamilo.plugin.tour
+ */
+require_once 'config.php';
+
+$plugin_info = Tour::create()->get_info();
+
+$plugin_info['templates'] = array('views/script.tpl');

+ 22 - 0
plugin/tour/readme.txt

@@ -0,0 +1,22 @@
+<h1>Chamilo Tour Plugin</h1>
+<p>Shows people how to use your Chamilo LMS</p>
+<h2>Set the blocks for the tour</h2>
+<p>Edit the plugin/tour/config/tour.json file adding the page classes and steps</p>
+<p>To set the steps in a page, add an object like this:</p>
+<pre>
+{
+    "pageClass": "page unique class selector",
+    "steps": [
+        {
+            "elementSelector": "element class or id",
+            "message": "LanguageVariable"
+        },
+        {
+            "elementSelector": "element class or id",
+            "message": "LanguageVariable"
+        },
+    ]
+}
+</pre>
+Then set the language variables inside the `plugin/tour/lang/$language.php` file<br>
+<br>

+ 141 - 0
plugin/tour/src/tour_plugin.class.php

@@ -0,0 +1,141 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * The Tour class allows a guided tour in HTML5 of the Chamilo interface
+ * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ * @package chamilo.plugin.tour
+ */
+class Tour extends Plugin
+{
+    /**
+     * Class constructor
+     */
+    protected function __construct()
+    {
+        $parameters = array(
+            'show_tour' => 'boolean',
+            'theme' => 'text'
+        );
+
+        parent::__construct('1.0', 'Angel Fernando Quiroz Campos', $parameters);
+    }
+
+    /**
+     * Instance the plugin
+     * @staticvar null $result
+     * @return Tour
+     */
+    static function create()
+    {
+        static $result = null;
+
+        return $result ? $result : $result = new self();
+    }
+
+    /**
+     * Install the plugin
+     * @return void
+     */
+    public function install()
+    {
+        $this->installDatabase();
+    }
+
+    /**
+     * Uninstall the plugin
+     * @return void
+     */
+    public function uninstall()
+    {
+        $this->unistallDatabase();
+    }
+
+    /**
+     * Create the database tables for the plugin
+     * @return void
+     */
+    private function installDatabase()
+    {
+        $pluginTourLogTable = Database::get_main_table(TABLE_TOUR_LOG);
+
+        $sql = "CREATE TABLE IF NOT EXISTS $pluginTourLogTable ("
+                . "id int UNSIGNED NOT NULL AUTO_INCREMENT, "
+                . "page_class varchar(255) NOT NULL, "
+                . "user_id int UNSIGNED NOT NULL, "
+                . "visualization_datetime datetime NOT NULL, "
+                . "PRIMARY KEY PK_tour_log (id))";
+
+        Database::query($sql);
+    }
+
+    /**
+     * Drop the database tables for the plugin
+     * @return void
+     */
+    private function unistallDatabase()
+    {
+        $pluginTourLogTable = Database::get_main_table(TABLE_TOUR_LOG);
+
+        $sql = "DROP TABLE IF EXISTS $pluginTourLogTable";
+
+        Database::query($sql);
+    }
+
+    /**
+     * Check whether the tour should be displayed to the user
+     * @param string $currentPageClass The class of the current page
+     * @param int $userId The user id
+     * @return boolean If the user has seen the tour return false, otherwise return true
+     */
+    public function checkTourForUser($currentPageClass, $userId)
+    {
+        $pluginTourLogTable = Database::get_main_table(TABLE_TOUR_LOG);
+
+        $checkResult = Database::select('count(1) as qty', $pluginTourLogTable, array(
+                    'where' => array(
+                        "page_class = '?' AND " => $currentPageClass,
+                        "user_id = ?" => intval($userId)
+                    )), 'first');
+
+        if ($checkResult !== false) {
+            if ($checkResult['qty'] > 0) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Set the tour as seen
+     * @param string $currentPageClass The class of the current page
+     * @param int $userId The user id
+     * @return void
+     */
+    public function saveCompletedTour($currentPageClass, $userId)
+    {
+        $pluginTourLogTable = Database::get_main_table(TABLE_TOUR_LOG);
+
+        Database::insert($pluginTourLogTable, array(
+            'page_class' => $currentPageClass,
+            'user_id' => intval($userId),
+            'visualization_datetime' => api_get_utc_datetime()
+        ));
+    }
+
+    /**
+     * Get the configuration to show the tour in pages
+     * @return array The config data
+     */
+    public function getTourConfig()
+    {
+        $pluginPath = api_get_path(PLUGIN_PATH) . 'tour/';
+
+        $jsonContent = file_get_contents($pluginPath . 'config/tour.json');
+
+        $jsonData = json_decode($jsonContent, true);
+
+        return $jsonData;
+    }
+
+}

+ 10 - 0
plugin/tour/uninstall.php

@@ -0,0 +1,10 @@
+<?php
+/* For licensing terms, see /license.txt */
+/**
+ * Initialization uninstall
+ * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ * @package chamilo.plugin.tour
+ */
+require_once __DIR__ . '/config.php';
+
+Tour::create()->uninstall();

+ 88 - 0
plugin/tour/views/script.tpl

@@ -0,0 +1,88 @@
+{% if tour.show_tour %}
+    <script type="text/javascript">
+        var chamiloTour = (function() {
+            var intro = null;
+            var $btnStart = null;
+
+            var setSteps = function (stepsData) {
+                var steps = new Array();
+
+                $.each(stepsData, function () {
+                    var step = this;
+
+                    if (step.element) {
+                        if ($(step.element).length > 0) {
+                            steps.push(step);
+                        }
+                    } else {
+                        steps.push(step);
+                    }
+                });
+
+                return steps;
+            };
+
+            return {
+                init: function(pageClass) {
+                    $.getJSON('{{ tour.web_path.steps_ajax }}', {
+                        'page_class': pageClass
+                    }, function(response) {
+                        intro = introJs();
+                        intro.setOptions({
+                            steps: setSteps(response),
+                            nextLabel: '{{ 'Next' | get_lang }}',
+                            prevLabel: '{{ 'Prev' | get_lang }}',
+                            skipLabel: '{{ 'Skip' | get_lang }}',
+                            doneLabel: '{{ 'Done' | get_lang }}'
+                        });
+                        intro.oncomplete(function () {
+                            $.post('{{ tour.web_path.save_ajax }}', {
+                                page_class: pageClass
+                            }, function () {
+                                $btnStart.remove();
+                            });
+                        });
+
+                        $btnStart = $('<button>', {
+                            class: 'btn btn-primary btn-large',
+                            text: '{{ 'StartButtonText' | get_lang }}',
+                            click: function(e) {
+                                e.preventDefault();
+
+                                intro.start();
+                            }
+                        }).appendTo('#tour-button-cotainer');
+                    });
+                }
+            };
+        })();
+
+        $(document).on('ready', function() {
+            var pages = {{ tour.pages }};
+
+            $.each(pages, function(index, page) {
+                var thereIsSelectedPage = $(page.pageClass).length > 0;
+
+                if (thereIsSelectedPage && page.show) {
+                    $('<link>', {
+                        href: '{{ tour.web_path.intro_css }}',
+                        rel: 'stylesheet'
+                    }).appendTo('head');
+
+                    {% if tour.web_path.intro_theme_css is not null %}
+                        $('<link>', {
+                            href: '{{ tour.web_path.intro_theme_css }}',
+                            rel: 'stylesheet'
+                        }).appendTo('head');
+                    {% endif %}
+
+                    $.getScript('{{ tour.web_path.intro_js }}', function() {
+                        chamiloTour.init(page.pageClass);
+                    });
+                }
+            });
+        });
+    </script>
+
+    <div id="tour-button-cotainer"></div>
+{% endif %}

Some files were not shown because too many files changed in this diff