Add buttons in header
authorCharles Connell <charles@connells.org>
Fri, 13 Dec 2013 20:34:18 +0000 (15:34 -0500)
committerCharles Connell <charles@connells.org>
Fri, 13 Dec 2013 20:34:29 +0000 (15:34 -0500)
karmaworld/apps/courses/views.py
karmaworld/assets/img/global_header_pluscourse.png [new file with mode: 0644]
karmaworld/assets/js/add-course.js [new file with mode: 0644]
karmaworld/assets/js/jquery-scrollto.js [new file with mode: 0644]
karmaworld/assets/js/lightbox-add-course.js [deleted file]
karmaworld/templates/base.html
karmaworld/templates/courses/course_list.html
karmaworld/templates/header.html
karmaworld/templates/partial/add_course.html

index 4b0023fafc61363905ccb771bf8b26e5328ec34e..717e24595493426d37bc0174170bf13c02b0b587 100644 (file)
@@ -36,6 +36,9 @@ class CourseListView(ListView, ModelFormMixin, ProcessFormView):
             # if there was an error in the form
             context['jump_to_form'] = True
 
+        # Include "Add Course" button in header
+        context['display_add_course'] = True
+
         return context
 
     def get_success_url(self):
@@ -64,6 +67,10 @@ class CourseDetailView(DetailView):
         """ filter the Course.note_set to return no Drafts """
         kwargs = super(CourseDetailView, self).get_context_data()
         kwargs['note_set'] = self.object.note_set.filter(is_hidden=False)
+
+        # Include "Add Note" button in header
+        kwargs['display_add_note'] = True
+
         return kwargs
 
 
diff --git a/karmaworld/assets/img/global_header_pluscourse.png b/karmaworld/assets/img/global_header_pluscourse.png
new file mode 100644 (file)
index 0000000..d4482b5
Binary files /dev/null and b/karmaworld/assets/img/global_header_pluscourse.png differ
diff --git a/karmaworld/assets/js/add-course.js b/karmaworld/assets/js/add-course.js
new file mode 100644 (file)
index 0000000..5aec010
--- /dev/null
@@ -0,0 +1,86 @@
+// Setup all the javascript stuff we need for the various
+// incarnations of the Add Course form
+$(function() {
+
+  // Set up the "Add Course" button at bottom
+  // of page
+  $('#add-course-btn').click(function() {
+    // Show the add a course form
+    $('#add-course-form').show();
+    // Hide the add a course button
+    $('#add-course-btn').hide();
+  });
+
+  // Set up the "Add Course" button in the
+  // page header
+  $('#add_course_header_button').click(function() {
+    // Show the add a course form
+    $('#add-course-form').show();
+    // Hide the add a course button
+    $('#add-course-btn').hide();
+    // Scroll the user's page to here
+    $('#add-course-divider').ScrollTo();
+    $('#str_school').focus();
+  });
+
+  // Dismiss on exit x click FIXME
+  $(".lightbox_close").click(function() {
+    $(".modal_content").hide();
+  });
+
+  function setupAjax(){
+    // Assumes variable csrf_token is made available
+    // by embedding document
+    $.ajaxSetup({
+      beforeSend: function(xhr, settings) {
+        if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
+          // Only send the token to relative URLs i.e. locally.
+          xhr.setRequestHeader("X-CSRFToken", csrf_token);
+        }
+      }
+    });
+  }
+
+  setupAjax();
+
+  $("#str_school").autocomplete({
+    source: function(request, response){
+      $.ajax({
+        url: json_course_list,
+        data: {q: request.term},
+        success: function(data) {
+          console.log(data);
+          if (data['status'] === 'success') {
+            response($.map(data['schools'], function(item) {
+              return {
+                  value: item.name,
+                  real_value: item.id,
+                  label: item.name,
+              };
+            }));
+          } else {
+            // FIXME: do something if school not found
+            $('#create_school_link').show();
+          }
+        },
+        dataType: "json",
+        type: 'POST'
+      });
+    },
+    select: function(event, ui) { 
+      console.log("select func");
+      console.log("id");
+      console.log(ui.item.value);
+      console.log("name");
+      console.log(ui.item.label);
+      // don't let the user edit the field anymore
+      //$('#str_school').attr('readonly', true);
+
+      // set the school id as the value of the hidden field
+      $('#id_school').val(ui.item.real_value);
+      // set the School name as the textbox field
+      //$('#str_school').val(ui.item.label);
+    },
+    minLength: 3
+  });
+});
diff --git a/karmaworld/assets/js/jquery-scrollto.js b/karmaworld/assets/js/jquery-scrollto.js
new file mode 100644 (file)
index 0000000..26b2bd9
--- /dev/null
@@ -0,0 +1,261 @@
+/*global define:false require:false */
+(function (name, context, definition) {
+       if (typeof module != 'undefined' && module.exports) module.exports = definition();
+       else if (typeof define == 'function' && define.amd) define(definition);
+       else context[name] = definition();
+})('jquery-scrollto', this, function(){
+       // Prepare
+       var jQuery, $, ScrollTo;
+       jQuery = $ = window.jQuery || require('jquery');
+
+       // Fix scrolling animations on html/body on safari
+       $.propHooks.scrollTop = $.propHooks.scrollLeft = {
+               get: function(elem,prop) {
+                       var result = null;
+                       if ( elem.tagName === 'HTML' || elem.tagName === 'BODY' ) {
+                               if ( prop === 'scrollLeft' ) {
+                                       result = window.scrollX;
+                               } else if ( prop === 'scrollTop' ) {
+                                       result = window.scrollY;
+                               }
+                       }
+                       if ( result == null ) {
+                               result = elem[prop];
+                       }
+                       return result;
+               }
+       };
+       $.Tween.propHooks.scrollTop = $.Tween.propHooks.scrollLeft = {
+               get: function(tween) {
+                       return $.propHooks.scrollTop.get(tween.elem, tween.prop);
+               },
+               set: function(tween) {
+                       // Our safari fix
+                       if ( tween.elem.tagName === 'HTML' || tween.elem.tagName === 'BODY' ) {
+                               // Defaults
+                               tween.options.bodyScrollLeft = (tween.options.bodyScrollLeft || window.scrollX);
+                               tween.options.bodyScrollTop = (tween.options.bodyScrollTop || window.scrollY);
+
+                               // Apply
+                               if ( tween.prop === 'scrollLeft' ) {
+                                       tween.options.bodyScrollLeft = Math.round(tween.now);
+                               }
+                               else if ( tween.prop === 'scrollTop' ) {
+                                       tween.options.bodyScrollTop = Math.round(tween.now);
+                               }
+
+                               // Apply
+                               window.scrollTo(tween.options.bodyScrollLeft, tween.options.bodyScrollTop);
+                       }
+                       // jQuery's IE8 Fix
+                       else if ( tween.elem.nodeType && tween.elem.parentNode ) {
+                               tween.elem[ tween.prop ] = tween.now;
+                       }
+               }
+       };
+
+       // jQuery ScrollTo
+       ScrollTo = {
+               // Configuration
+               config: {
+                       duration: 400,
+                       easing: 'swing',
+                       callback: undefined,
+                       durationMode: 'each',
+                       offsetTop: 0,
+                       offsetLeft: 0
+               },
+
+               // Set Configuration
+               configure: function(options){
+                       // Apply Options to Config
+                       $.extend(ScrollTo.config, options||{});
+
+                       // Chain
+                       return this;
+               },
+
+               // Perform the Scroll Animation for the Collections
+               // We use $inline here, so we can determine the actual offset start for each overflow:scroll item
+               // Each collection is for each overflow:scroll item
+               scroll: function(collections, config){
+                       // Prepare
+                       var collection, $container, container, $target, $inline, position, containerTagName,
+                               containerScrollTop, containerScrollLeft,
+                               containerScrollTopEnd, containerScrollLeftEnd,
+                               startOffsetTop, targetOffsetTop, targetOffsetTopAdjusted,
+                               startOffsetLeft, targetOffsetLeft, targetOffsetLeftAdjusted,
+                               scrollOptions,
+                               callback;
+
+                       // Determine the Scroll
+                       collection = collections.pop();
+                       $container = collection.$container;
+                       $target = collection.$target;
+                       containerTagName = $container.prop('tagName');
+
+                       // Prepare the Inline Element of the Container
+                       $inline = $('<span/>').css({
+                               'position': 'absolute',
+                               'top': '0px',
+                               'left': '0px'
+                       });
+                       position = $container.css('position');
+
+                       // Insert the Inline Element of the Container
+                       $container.css({position:'relative'});
+                       $inline.appendTo($container);
+
+                       // Determine the top offset
+                       startOffsetTop = $inline.offset().top;
+                       targetOffsetTop = $target.offset().top;
+                       targetOffsetTopAdjusted = targetOffsetTop - startOffsetTop - parseInt(config.offsetTop,10);
+
+                       // Determine the left offset
+                       startOffsetLeft = $inline.offset().left;
+                       targetOffsetLeft = $target.offset().left;
+                       targetOffsetLeftAdjusted = targetOffsetLeft - startOffsetLeft - parseInt(config.offsetLeft,10);
+
+                       // Determine current scroll positions
+                       containerScrollTop = $container.prop('scrollTop');
+                       containerScrollLeft = $container.prop('scrollLeft');
+
+                       // Reset the Inline Element of the Container
+                       $inline.remove();
+                       $container.css({position:position});
+
+                       // Prepare the scroll options
+                       scrollOptions = {};
+
+                       // Prepare the callback
+                       callback = function(event){
+                               // Check
+                               if ( collections.length === 0 ) {
+                                       // Callback
+                                       if ( typeof config.callback === 'function' ) {
+                                               config.callback();
+                                       }
+                               }
+                               else {
+                                       // Recurse
+                                       ScrollTo.scroll(collections,config);
+                               }
+                               // Return true
+                               return true;
+                       };
+
+                       // Handle if we only want to scroll if we are outside the viewport
+                       if ( config.onlyIfOutside ) {
+                               // Determine current scroll positions
+                               containerScrollTopEnd = containerScrollTop + $container.height();
+                               containerScrollLeftEnd = containerScrollLeft + $container.width();
+
+                               // Check if we are in the range of the visible area of the container
+                               if ( containerScrollTop < targetOffsetTopAdjusted && targetOffsetTopAdjusted < containerScrollTopEnd ) {
+                                       targetOffsetTopAdjusted = containerScrollTop;
+                               }
+                               if ( containerScrollLeft < targetOffsetLeftAdjusted && targetOffsetLeftAdjusted < containerScrollLeftEnd ) {
+                                       targetOffsetLeftAdjusted = containerScrollLeft;
+                               }
+                       }
+
+                       // Determine the scroll options
+                       if ( targetOffsetTopAdjusted !== containerScrollTop ) {
+                               scrollOptions.scrollTop = targetOffsetTopAdjusted;
+                       }
+                       if ( targetOffsetLeftAdjusted !== containerScrollLeft ) {
+                               scrollOptions.scrollLeft = targetOffsetLeftAdjusted;
+                       }
+
+                       // Check to see if the scroll is necessary
+                       if ( $container.prop('scrollHeight') === $container.width() ) {
+                               delete scrollOptions.scrollTop;
+                       }
+                       if ( $container.prop('scrollWidth') === $container.width() ) {
+                               delete scrollOptions.scrollLeft;
+                       }
+
+                       // Perform the scroll
+                       if ( scrollOptions.scrollTop != null || scrollOptions.scrollLeft != null ) {
+                               $container.animate(scrollOptions, {
+                                       duration: config.duration,
+                                       easing: config.easing,
+                                       complete: callback
+                               });
+                       }
+                       else {
+                               callback();
+                       }
+
+                       // Return true
+                       return true;
+               },
+
+               // ScrollTo the Element using the Options
+               fn: function(options){
+                       // Prepare
+                       var collections, config, $container, container;
+                       collections = [];
+
+                       // Prepare
+                       var     $target = $(this);
+                       if ( $target.length === 0 ) {
+                               // Chain
+                               return this;
+                       }
+
+                       // Handle Options
+                       config = $.extend({},ScrollTo.config,options);
+
+                       // Fetch
+                       $container = $target.parent();
+                       container = $container.get(0);
+
+                       // Cycle through the containers
+                       while ( ($container.length === 1) && (container !== document.body) && (container !== document) ) {
+                               // Check Container for scroll differences
+                               var containerScrollTop, containerScrollLeft;
+                               containerScrollTop = $container.css('overflow-y') !== 'visible' && container.scrollHeight !== container.clientHeight;
+                               containerScrollLeft =  $container.css('overflow-x') !== 'visible' && container.scrollWidth !== container.clientWidth;
+                               if ( containerScrollTop || containerScrollLeft ) {
+                                       // Push the Collection
+                                       collections.push({
+                                               '$container': $container,
+                                               '$target': $target
+                                       });
+                                       // Update the Target
+                                       $target = $container;
+                               }
+                               // Update the Container
+                               $container = $container.parent();
+                               container = $container.get(0);
+                       }
+
+                       // Add the final collection
+                       collections.push({
+                               '$container': $('html'),
+                               // document.body doesn't work in firefox, html works for all
+                               // internet explorer starts at the beggining
+                               '$target': $target
+                       });
+
+                       // Adjust the Config
+                       if ( config.durationMode === 'all' ) {
+                               config.duration /= collections.length;
+                       }
+
+                       // Handle
+                       ScrollTo.scroll(collections,config);
+
+                       // Chain
+                       return this;
+               }
+       };
+
+       // Apply our extensions to jQuery
+       $.ScrollTo = $.ScrollTo || ScrollTo;
+       $.fn.ScrollTo = $.fn.ScrollTo || ScrollTo.fn;
+
+       // Export
+       return ScrollTo;
+});
\ No newline at end of file
diff --git a/karmaworld/assets/js/lightbox-add-course.js b/karmaworld/assets/js/lightbox-add-course.js
deleted file mode 100644 (file)
index 1639f2b..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// setup ajax based autocomplete for the school field in the add course lightbox
-$(function() {
-
-  // Show the add-course-form
-  $('#add-course-btn').click(function() {
-    // Show the add a course form
-    $('#add-course-form').show();
-    // Hide the add a course button
-    $('#add-course-btn').hide();
-  });
-
-  // Dismiss on exit x click FIXME
-  $(".lightbox_close").click(function() {
-    $(".modal_content").hide();
-  });
-
-  function setupAjax(){
-    // Assumes variable csrf_token is made available
-    // by embedding document
-    $.ajaxSetup({
-      beforeSend: function(xhr, settings) {
-        if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
-          // Only send the token to relative URLs i.e. locally.
-          xhr.setRequestHeader("X-CSRFToken", csrf_token);
-        }
-      }
-    });
-  }
-
-  setupAjax();
-
-  $("#str_school").autocomplete({
-    source: function(request, response){
-      $.ajax({
-        url: json_course_list,
-        data: {q: request.term},
-        success: function(data) {
-          console.log(data);
-          if (data['status'] === 'success') {
-            response($.map(data['schools'], function(item) {
-              return {
-                  value: item.name,
-                  real_value: item.id,
-                  label: item.name,
-              };
-            }));
-          } else {
-            // FIXME: do something if school not found
-            $('#create_school_link').show();
-          }
-        },
-        dataType: "json",
-        type: 'POST'
-      });
-    },
-    select: function(event, ui) { 
-      console.log("select func");
-      console.log("id");
-      console.log(ui.item.value);
-      console.log("name");
-      console.log(ui.item.label);
-      // don't let the user edit the field anymore
-      //$('#str_school').attr('readonly', true);
-
-      // set the school id as the value of the hidden field
-      $('#id_school').val(ui.item.real_value);
-      // set the School name as the textbox field
-      //$('#str_school').val(ui.item.label);
-    },
-    minLength: 3
-  });
-});
index 549b0366d1173119b112740141f4aaddde5a0ee2..6a1ed281a94ba242d7c83549410d8345f6063101 100644 (file)
@@ -20,6 +20,7 @@
   <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
   <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
   <script src="{{ STATIC_URL }}ajaxuploader/js/fileuploader.js" ></script>
+  <script src="{{ STATIC_URL }}js/jquery-scrollto.js" ></script>
 
   <!-- block pagescripts -->
   {% block pagescripts %}
index 1858c2a69258604cb39951aaca9b630fb90c3355..00f44dc1d3533f82cb96ad97ac2c2360b76f5932 100644 (file)
@@ -136,7 +136,7 @@ $(document).ready(function() {
   </div> <!-- .row -->
 
   <div class="row">
-    <div class="small-10 columns small-offset-1"> <hr/> </div>
+    <div id="add-course-divider" class="small-10 columns small-offset-1"> <hr/> </div>
   </div>
 
   <div class="row">
@@ -152,7 +152,6 @@ $(document).ready(function() {
     <div class="small-10 columns small-offset-1"> <hr/> </div>
   </div>
 
-
 </section> <!-- #results_content -->
 
 {% endblock %}
index 3e91f4c2ed5621cfe004c2f7ff9b88e645f54c21..b8385c60fad9ed4419f5bc893f6e22d53b1e532a 100644 (file)
@@ -9,7 +9,20 @@
         </a>
       </div><!--/logo container-->
 
-      <div id="login_container" class="small-2 columns small-offset-4">
+      {% if display_add_course %}
+        <div class="small-2 columns small-offset-3 show-for-medium-up">
+          <a id="add_course_header_button" href="#"><img src="{{ STATIC_URL }}img/global_header_pluscourse.png" /></a>
+        </div>
+      {% endif %}
+
+      {% if display_add_note %}
+        <div class="small-2 columns small-offset-3 show-for-medium-up">
+          <a id="add_note_header_button" href="#" onclick="$('.add-note-btn').click();">
+            <img src="{{ STATIC_URL }}img/global_header_plusnote.png" /></a>
+        </div>
+      {% endif %}
+
+      <div id="login_container" class="small-1 columns">
         <a class=white href="{% url 'about' %}">About</a>
       </div>
 
index e0ef993f721de73b821bc36f7410021e0ae7bb03..99af04d39044ba72f0e910d767f91169310c5f8b 100644 (file)
@@ -3,7 +3,7 @@
   var json_course_list = "{% url 'json_school_list' %}"
   var csrf_token = "{{ csrf_token }}";
 </script>
-<script src="{{ STATIC_URL }}js/lightbox-add-course.js"></script>
+<script src="{{ STATIC_URL }}js/add-course.js"></script>
 
 <section id="add-course-form">
   <form method="POST" action="{% url 'home' %}">