<commit_before>define([
    "jquery",
    "moments",
    "mustache",
    "underscore",
    "backbone",
    "../../../js/collections/profile-collection",
    "../../../js/collection-views/profile-collection-view"
], function($, Moments, Mustache, _, Backbone, ProfileCollection, ProfileCollectionView) {

        var PageView = Backbone.View.extend({

            initialize: function(options) {
                // Initiliaze ProfileCollections
                console.log("initializing new collection");
                var profileCollection = new ProfileCollection({});
                // Fetch from our server the new data
                // Async XHR might be depricated in vanilla js, so becareful
                // Could toggle the loading gif now
                profileCollection.fetch({async: false});
                // Could untoggle it now or on success
                console.log(profileCollection);
                // Initialize Profile-CollectionView
            }

        });

        // Instantiate our Page View
        var pageView = new PageView({el: $('body')});

});

/*
    // kick off the app
    $(document).ready(function() {
        $('#spinner').show();
        $.ajax({
            type: "GET",
            url: '/geet',
        })
        .done(function(data) {
            $('#container').empty();
            // TODO use map instead
            for (var i in data) {
                if (data[i].eventData.pushEvents ) {
                    console.log(data[i]);
                    // Throwing error since some commits didn't have specifc data
                    if (data[i].eventData.pushEvents.payload.commits[0]) {
                        var commit = data[i].eventData.pushEvents.payload.commits.length ? data[i].eventData.pushEvents.payload.commits[0].message : " ";
                        var commitMsg = data[i].eventData.pushEvents.payload.commits.length ? data[i].eventData.pushEvents.payload.commits[0].sha.slice(0 ,5) : "";
                        var commitSha = data[i].eventData.pushEvents.payload.commits[0].sha.slice(0,5);
                        var commitUrl ='http://github.com/'+data[i].eventData.pushEvents.repo.name+'/commit/'+data[i].eventData.pushEvents.payload.commits[0].sha;
                    } else {
                        var commit = "";
                        var commitMsg = "";
                        var commitSha = "";
                        var commitUrl = "";
                    }

                    // Create a new gitCard Model
                    var gitCard = new GitCard({
                        imgUrl: data[i].eventData.pushEvents.actor.avatar_url,
                        user: data[i].eventData.pushEvents.actor.login,
                        userID: data[i].eventData.pushEvents.actor.login.toLowerCase(),
                        repoName: data[i].eventData.pushEvents.repo.name,
                        commitMsg: commit,
                        commitSha: commitSha,
                        commitUrl: commitUrl,
                        date: "Last pushed "+Moments(data[i].eventData.pushEvents.created_at).fromNow(),
                        dateString: data[i].eventData.pushEvents.created_at
                    });

                    if (data[i].eventData.watchEvents) {
                        // If a user has watched events (stars) set them
                        gitCard.set({
                            watch: data[i].eventData.watchEvents.repo.name,
                            watchUrl: 'http://www.github.com/'+data[i].eventData.watchEvents.repo.name
                        });
                    }

                    profileCollection.add(gitCard);
                    //var view = new ProfileView({model: gitCard});
                } if(data[i].contributions) {
                    gitCard.set({
                        currentStreak: data[i].contributions.currentStreaks,
                        longestStreak: data[i].contributions.longestStreaks,
                        totalContributions: data[i].contributions.totals
                    });
                } if(data[i].personalData) {
                    gitCard.set({
                        company: data[i].personalData.personalData.company,
                        location: data[i].personalData.personalData.location,
                        //TODO add these to the view
                        blog: data[i].personalData.personalData.blog

                    });
                }
            }

            // User has friends, initial render
            if(profileCollection.length) {
                $('#spinner').hide();
                profileCollection.sort();
                var profileCollectionView = new ProfileCollectionView({collection: profileCollection});
                profileCollectionView.render();
            } else {
                // User has no Friends, display message
                $("#spinner").hide();
                $("#img-spinner").attr("src", "../assets/help.gif");
                $("#img-spinner").attr("id", "no-friends");
                $("#info").append("Looks like you don't have any friends on Github, try adding some and come back! <3</span");
                $("#spinner").show();
            }

        })

        // 404 error
        .fail(function() {
            $("#img-spinner").attr("src", "../assets/404.gif");
            $("#info").append("404 Opps! Something went wrong... ");
        });

    });
});*/
<commit_msg>refactoring bit by bit<commit_after>define([
    "jquery",
    "moments",
    "mustache",
    "underscore",
    "backbone",
    "../../../js/collections/profile-collection",
    "../../../js/collection-views/profile-collection-view"
], function($, Moments, Mustache, _, Backbone, ProfileCollection, ProfileCollectionView) {

        var PageView = Backbone.View.extend({

            initialize: function(options) {
                _.bindAll(this, 'toggleLoader', 'toggleEmptyView');

                //
                // Initiliaze ProfileCollections
                //
                console.log("initializing new collection");
                this.profileCollection = new ProfileCollection();
                this.toggleLoader({init: true});

                /*this.listenTo(this.profileCollection, 'collectionUpdated',
                    _.bind(function() {
                        console.log("collection has been updated");
                        this.toggleLoader()
                    })
                );*/

                //
                // Fetch from our server the new data
                //
                this.profileCollection.fetch({
                    reset: true,
                    success: _.bind(function() {
                        // Can trigger an update event here if we want
                    }, this)
                    // Can also include a fail event.
                });

                //
                // Initialize Profile-CollectionView
                //

            },

            toggleLoader: function(options) {
                //TODO Might want these to be properties of the collection-view, not the page view
                options = (options || {});
                if (!this.profileCollection.length && options.init) {
                    // Toggle has been called, but it's the initial call
                    $('#spinner').show();
                } else if (!this.profileCollection.length && !options.init) {
                    // Collection has fetched, but it's empty
                    this.toggleEmptyView();
                } else {
                    // We have a colletion to render that is NOT Empty
                    $('#spinner').hide();
                }
            },

            toggleEmptyView : function() {
                // TODO REFACTOR THIS TO RENDER AN EMPTY TEMPLATE
                // TODO Might want these to be properties of the collection-view, not the page view
                $("#spinner").hide();
                $("#img-spinner").attr("src", "../assets/help.gif");
                $("#img-spinner").attr("id", "no-friends");
                $("#info").append("Looks like you don't have any friends on Github, try adding some and come back! <3</span");
                $("#spinner").show();
            }

        });

        // Instantiate our Page View
        var pageView = new PageView({el: $('body')});

});

/*
    // kick off the app
    $(document).ready(function() {
        $('#spinner').show();
        $.ajax({
            type: "GET",
            url: '/geet',
        })
        .done(function(data) {
            $('#container').empty();
            // TODO use map instead
            for (var i in data) {
                if (data[i].eventData.pushEvents ) {
                    console.log(data[i]);
                    // Throwing error since some commits didn't have specifc data
                    if (data[i].eventData.pushEvents.payload.commits[0]) {
                        var commit = data[i].eventData.pushEvents.payload.commits.length ? data[i].eventData.pushEvents.payload.commits[0].message : " ";
                        var commitMsg = data[i].eventData.pushEvents.payload.commits.length ? data[i].eventData.pushEvents.payload.commits[0].sha.slice(0 ,5) : "";
                        var commitSha = data[i].eventData.pushEvents.payload.commits[0].sha.slice(0,5);
                        var commitUrl ='http://github.com/'+data[i].eventData.pushEvents.repo.name+'/commit/'+data[i].eventData.pushEvents.payload.commits[0].sha;
                    } else {
                        var commit = "";
                        var commitMsg = "";
                        var commitSha = "";
                        var commitUrl = "";
                    }

                    // Create a new gitCard Model
                    var gitCard = new GitCard({
                        imgUrl: data[i].eventData.pushEvents.actor.avatar_url,
                        user: data[i].eventData.pushEvents.actor.login,
                        userID: data[i].eventData.pushEvents.actor.login.toLowerCase(),
                        repoName: data[i].eventData.pushEvents.repo.name,
                        commitMsg: commit,
                        commitSha: commitSha,
                        commitUrl: commitUrl,
                        date: "Last pushed "+Moments(data[i].eventData.pushEvents.created_at).fromNow(),
                        dateString: data[i].eventData.pushEvents.created_at
                    });

                    if (data[i].eventData.watchEvents) {
                        // If a user has watched events (stars) set them
                        gitCard.set({
                            watch: data[i].eventData.watchEvents.repo.name,
                            watchUrl: 'http://www.github.com/'+data[i].eventData.watchEvents.repo.name
                        });
                    }

                    profileCollection.add(gitCard);
                    //var view = new ProfileView({model: gitCard});
                } if(data[i].contributions) {
                    gitCard.set({
                        currentStreak: data[i].contributions.currentStreaks,
                        longestStreak: data[i].contributions.longestStreaks,
                        totalContributions: data[i].contributions.totals
                    });
                } if(data[i].personalData) {
                    gitCard.set({
                        company: data[i].personalData.personalData.company,
                        location: data[i].personalData.personalData.location,
                        //TODO add these to the view
                        blog: data[i].personalData.personalData.blog

                    });
                }
            }

            // User has friends, initial render
            if(profileCollection.length) {
                $('#spinner').hide();
                profileCollection.sort();
                var profileCollectionView = new ProfileCollectionView({collection: profileCollection});
                profileCollectionView.render();
            } else {
                // User has no Friends, display message
                $("#spinner").hide();
                $("#img-spinner").attr("src", "../assets/help.gif");
                $("#img-spinner").attr("id", "no-friends");
                $("#info").append("Looks like you don't have any friends on Github, try adding some and come back! <3</span");
                $("#spinner").show();
            }

        })

        // 404 error
        .fail(function() {
            $("#img-spinner").attr("src", "../assets/404.gif");
            $("#info").append("404 Opps! Something went wrong... ");
        });

    });
});*/
<|endoftext|>


<commit_before>

var CLIENT_ID = '109310418708-u9pbu42qpmbke340qscbs9e69jcbhns6.apps.googleusercontent.com';
// var CLIENT_ID = '9b419356804c88acf0b53d4b5dde50750182c269';

// Array of API discovery doc URLs for APIs used by the quickstart
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"];

// Authorization scopes required by the API; multiple scopes can be
// included, separated by spaces.
var SCOPES = "https://www.googleapis.com/auth/calendar";

/**
*  On load, called to load the auth2 library and API client library.
*/
function handleClientLoad() {
  gapi.load('client:auth2', initClient);
}

/**
*  Initializes the API client library and sets up sign-in state
*  listeners.
*/
function initClient() {
  gapi.client.init({
    discoveryDocs: DISCOVERY_DOCS,
    clientId: CLIENT_ID,
    scope: SCOPES
  }).then(function () {
    // Listen for sign-in state changes.
    gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);

    // Handle the initial sign-in state.
    updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
    //authorizeButton.onclick = handleAuthClick;
    //signoutButton.onclick = handleSignoutClick;
    handleAuthClick();
  });
}

/**
*  Called when the signed in status changes, to update the UI
*  appropriately. After a sign-in, the API is called.
*/
function updateSigninStatus(isSignedIn) {
  if (isSignedIn) {
    //listUpcomingEvents();
    insertEvent();
  } else {
  }
}

/**
*  Sign in the user upon button click.
*/
function handleAuthClick() {
  gapi.auth2.getAuthInstance().signIn();
}

/**
*  Sign out the user upon button click.
*/
function handleSignoutClick(event) {
  gapi.auth2.getAuthInstance().signOut();
}

/**
* Append a pre element to the body containing the given message
* as its text node. Used to display the results of the API call.
*
* @param {string} message Text to be placed in pre element.
*/
function appendPre(message) {
  var pre = document.getElementById('content');
  var textContent = document.createTextNode(message + '\n');
  pre.appendChild(textContent);
}

/**
* Print the summary and start datetime/date of the next ten events in
* the authorized user's calendar. If no events are found an
* appropriate message is printed.
*/
function listUpcomingEvents() {
  gapi.client.calendar.events.list({
    'calendarId': 'sk3u2tr3dhradfgd7t4j4ie690@group.calendar.google.com',
    'timeMin': (new Date()).toISOString(),
    'showDeleted': false,
    'singleEvents': true,
    'maxResults': 10,
    'orderBy': 'startTime'
  }).then(function(response) {
    var events = response.result.items;
    appendPre('Upcoming events:');

    if (events.length > 0) {
    for (i = 0; i < events.length; i++) {
      var event = events[i];
      var when = event.start.dateTime;
      if (!when) {
        when = event.start.date;
      }
      appendPre(event.summary + ' (' + when + ')')
    }
    } else {
      appendPre('No upcoming events found.');
    }
  });
}

var newEvent = {
  'summary': 'Google I/O 2015',
  'start': {
    'dateTime': '2017-02-25T09:00:00-07:00',
    'timeZone': 'America/Los_Angeles'
  },
  'end': {
    'dateTime': '2017-02-25T17:00:00-07:00',
    'timeZone': 'America/Los_Angeles'
  }
};

function insertEvent() {

  var request = gapi.client.calendar.events.insert({
    'calendarId': 'sk3u2tr3dhradfgd7t4j4ie690@group.calendar.google.com',
    'resource': newEvent
  });

  request.execute(function(event) {
    appendPre('Event created: ' + event.htmlLink);
    appendPre('event is: ' + event.summary);
  });

  appendPre("insereting");
/*
  gapi.client.calendar.events.insert({
      'calendarId': 'sk3u2tr3dhradfgd7t4j4ie690@group.calendar.google.com',
      'resource': newEvent
    }).then(function(response) {
      appendPre("response: " + response);
      var events = response.result.items;
      appendPre("the events is: " + events + "\n");
      appendPre('Upcoming events:');

      if (events.length > 0) {
        for (i = 0; i < events.length; i++) {
          var event = events[i];
          var when = event.start.dateTime;
          if (!when) {
            when = event.start.date;
          }
          appendPre(event.summary + ' (' + when + ')')
        }
      } else {
        appendPre('No upcoming events found.');
      }
    }); */
}<commit_msg>Fixed typos<commit_after>

var CLIENT_ID = '109310418708-u9pbu42qpmbke340qscbs9e69jcbhns6.apps.googleusercontent.com';
// var CLIENT_ID = '9b419356804c88acf0b53d4b5dde50750182c269';

// Array of API discovery doc URLs for APIs used by the quickstart
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"];

// Authorization scopes required by the API; multiple scopes can be
// included, separated by spaces.
var SCOPES = "https://www.googleapis.com/auth/calendar";

/**
*  On load, called to load the auth2 library and API client library.
*/
function handleClientLoad() {
  gapi.load('client:auth2', initClient);
}

/**
*  Initializes the API client library and sets up sign-in state
*  listeners.
*/
function initClient() {
  gapi.client.init({
    discoveryDocs: DISCOVERY_DOCS,
    clientId: CLIENT_ID,
    scope: SCOPES
  }).then(function () {
    // Listen for sign-in state changes.
    gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);

    // Handle the initial sign-in state.
    updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
    //authorizeButton.onclick = handleAuthClick;
    //signoutButton.onclick = handleSignoutClick;
    handleAuthClick();
  });
}

/**
*  Called when the signed in status changes, to update the UI
*  appropriately. After a sign-in, the API is called.
*/
function updateSigninStatus(isSignedIn) {
  if (isSignedIn) {
    //listUpcomingEvents();
    insertEvent();
  } else {
  }
}

/**
*  Sign in the user upon button click.
*/
function handleAuthClick() {
  gapi.auth2.getAuthInstance().signIn();
}

/**
*  Sign out the user upon button click.
*/
function handleSignoutClick(event) {
  gapi.auth2.getAuthInstance().signOut();
}

/**
* Append a pre element to the body containing the given message
* as its text node. Used to display the results of the API call.
*
* @param {string} message Text to be placed in pre element.
*/
function appendPre(message) {
  var pre = document.getElementById('content');
  var textContent = document.createTextNode(message + '\n');
  pre.appendChild(textContent);
}

/**
* Print the summary and start datetime/date of the next ten events in
* the authorized user's calendar. If no events are found an
* appropriate message is printed.
*/
function listUpcomingEvents() {
  gapi.client.calendar.events.list({
    'calendarId': 'sk3u2tr3dhradfgd7t4j4ie690@group.calendar.google.com',
    'timeMin': (new Date()).toISOString(),
    'showDeleted': false,
    'singleEvents': true,
    'maxResults': 10,
    'orderBy': 'startTime'
  }).then(function(response) {
    var events = response.result.items;
    appendPre('Upcoming events:');

    if (events.length > 0) {
    for (i = 0; i < events.length; i++) {
      var event = events[i];
      var when = event.start.dateTime;
      if (!when) {
        when = event.start.date;
      }
      appendPre(event.summary + ' (' + when + ')')
    }
    } else {
      appendPre('No upcoming events found.');
    }
  });
}

var newEvent = {
  'summary': 'Prototype Event',
  'start': {
    'dateTime': '2017-02-25T09:00:00-07:00',
    'timeZone': 'America/Los_Angeles'
  },
  'end': {
    'dateTime': '2017-02-25T17:00:00-07:00',
    'timeZone': 'America/Los_Angeles'
  }
};

function insertEvent() {

  /*
  var sectionnames = [];
  $("#Assignment1").each(function(){ sectionnames.push($("#Assignment1").text()); });
  //appendPre("section names: " + sectionnames[0]);
  //appendPre("section names 1: " + $("#Assignment1").text());
  appendPre("section names 2: " + $("#Assignment1")[0].text());
  */

  var request = gapi.client.calendar.events.insert({
    'calendarId': 'sk3u2tr3dhradfgd7t4j4ie690@group.calendar.google.com',
    'resource': newEvent
  });

  request.execute(function(event) {
    appendPre('Event Created: ' + event.htmlLink);
    appendPre('Event is: ' + event.summary);
  });

  appendPre("Currently Inserting");
/*
  gapi.client.calendar.events.insert({
      'calendarId': 'sk3u2tr3dhradfgd7t4j4ie690@group.calendar.google.com',
      'resource': newEvent
    }).then(function(response) {
      appendPre("response: " + response);
      var events = response.result.items;
      appendPre("the events is: " + events + "\n");
      appendPre('Upcoming events:');

      if (events.length > 0) {
        for (i = 0; i < events.length; i++) {
          var event = events[i];
          var when = event.start.dateTime;
          if (!when) {
            when = event.start.date;
          }
          appendPre(event.summary + ' (' + when + ')')
        }
      } else {
        appendPre('No upcoming events found.');
      }
    }); */
}<|endoftext|>


<commit_before>  var drawingManager;
  var selectedShape;
  var selectedMarker;
  var colors = ['#1E90FF', '#FF1493', '#32CD32', '#FF8C00', '#4B0082'];
  var selectedColor;
  var colorButtons = {};

  function clearSelection() {
    if (selectedShape) {
      selectedShape.setEditable(false);
      selectedShape = null;
    }
  }

  function clearMarker() {
    if (selectedMarker) {
      selectedMarker.setEditable(false);
      selectedMarker = null;
    }
  }

  function setSelection(shape) {
    clearSelection();
    selectedShape = shape;
    shape.setEditable(true);
    selectColor(shape.get('fillColor') || shape.get('strokeColor'));
  }

  function setSelection(marker) {
    selectedMarker = marker;
  }

  function deleteSelectedShape() {
    if (selectedShape) {
      selectedShape.setMap(null);
    }
    // To show:
     drawingManager.setOptions({
       drawingControl: true
     });
  }

  function deleteSelectedMarker() {
    if (selectedMarker) {
      selectedMarker.setMap(null);
    }
    // To show:
    drawingManager.setOptions({
      drawingControl: true
    });
  }

  function selectColor(color) {
    selectedColor = color;
    for (var i = 0; i < colors.length; ++i) {
      var currColor = colors[i];
      colorButtons[currColor].style.border = currColor == color ? '2px solid #789' : '2px solid #fff';
    }

    // Retrieves the current options from the drawing manager and replaces the
    // stroke or fill color as appropriate.
    var polylineOptions = drawingManager.get('polylineOptions');
    polylineOptions.strokeColor = color;
    drawingManager.set('polylineOptions', polylineOptions);

    var rectangleOptions = drawingManager.get('rectangleOptions');
    rectangleOptions.fillColor = color;
    drawingManager.set('rectangleOptions', rectangleOptions);

    var circleOptions = drawingManager.get('circleOptions');
    circleOptions.fillColor = color;
    drawingManager.set('circleOptions', circleOptions);

    var polygonOptions = drawingManager.get('polygonOptions');
    polygonOptions.fillColor = color;
    drawingManager.set('polygonOptions', polygonOptions);
  }

  function setSelectedShapeColor(color) {
    if (selectedShape) {
      if (selectedShape.type == google.maps.drawing.OverlayType.POLYLINE) {
        selectedShape.set('strokeColor', color);
      } else {
        selectedShape.set('fillColor', color);
      }
    }
  }

  function makeColorButton(color) {
    var button = document.createElement('span');
    button.className = 'color-button';
    button.style.backgroundColor = color;
    google.maps.event.addDomListener(button, 'click', function() {
      selectColor(color);
      setSelectedShapeColor(color);
    });

    return button;
  }

   function buildColorPalette() {
     var colorPalette = document.getElementById('color-palette');
     for (var i = 0; i < colors.length; ++i) {
       var currColor = colors[i];
       var colorButton = makeColorButton(currColor);
       colorPalette.appendChild(colorButton);
       colorButtons[currColor] = colorButton;
     }
     selectColor(colors[0]);
   }

  function initialize() {
    var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 10,
      center: new google.maps.LatLng(54.12555975898535, 21.68217234313488),
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      disableDefaultUI: true,
      zoomControl: true
    });

    var polyOptions = {
      strokeWeight: 0,
      fillOpacity: 0.45,
      editable: true
    };
    // Creates a drawing manager attached to the map that allows the user to draw
    // markers, lines, and shapes.
    drawingManager = new google.maps.drawing.DrawingManager({
      drawingMode: google.maps.drawing.OverlayType.POLYGON,
      drawingControlOptions: {
        drawingModes: [
          google.maps.drawing.OverlayType.POLYGON
        ]
      },
      markerOptions: {
        draggable: true
      },
      polylineOptions: {
        editable: true
      },
      rectangleOptions: polyOptions,
      circleOptions: polyOptions,
      polygonOptions: polyOptions,
      map: map
    });

    function overlayClickListener(overlay) {
      google.maps.event.addListener(overlay, "mouseup", function(event){
        $('#coords').val(overlay.getPath().getArray());
      });
    }

    google.maps.event.addListener(drawingManager, 'overlaycomplete', function(event) {
      if (event.type == google.maps.drawing.OverlayType.CIRCLE) {
        var radius = event.overlay.getRadius();
      }
    });
    google.maps.event.addListener(drawingManager, 'overlaycomplete', function(event) {
      if (event.type != google.maps.drawing.OverlayType.MARKER) {
        // Switch back to non-drawing mode after drawing a shape or putting marker on the map
        drawingManager.setDrawingMode(null);
        // To hide:
        drawingManager.setOptions({
          drawingControl: false
        });

        // Add an event listener that selects the newly-drawn shape when the user mouses down on it.
        var newShape = event.overlay;
        newShape.type = event.type;
        google.maps.event.addListener(newShape, 'click', function() {
          setSelection(newShape);
        });
        setSelection(newShape);
        overlayClickListener(newShape);
      } else {
        // Switch back to non-drawing mode after putting marker on the map
        drawingManager.setDrawingMode(null);
        // To hide:
        drawingManager.setOptions({
          drawingControl: false
        });

        // Add an event listener that selects the newly-drawn shape when the user mouses down on it.
        var newMarker = event.overlay;
        newMarker.type = event.type;
        google.maps.event.addListener(newMarker, 'dragend', function(event) {
          console.log(event, 'event');
          console.log(newMarker.position.toString(), 'position');
          setSelection(newMarker);
          $('#coords').val(newMarker.position.toString());
        });
        setSelection(newMarker);
        $('#coords').val(newMarker.position.toString());
      }
    });

    // Clear the current selection when the drawing mode is changed, or when the
    // map is clicked.
    google.maps.event.addListener(drawingManager, 'drawingmode_changed', clearSelection);
    google.maps.event.addListener(map, 'click', clearSelection);
    google.maps.event.addDomListener(document.getElementById('delete-button'), 'click', deleteSelectedShape);

    buildColorPalette();
  }
  google.maps.event.addDomListener(window, 'load', initialize);<commit_msg>- Added JavaScript function on path modification event<commit_after>  var drawingManager;
  var selectedShape;
  var selectedMarker;
  var colors = ['#1E90FF', '#FF1493', '#32CD32', '#FF8C00', '#4B0082'];
  var selectedColor;
  var colorButtons = {};

  function clearSelection() {
    if (selectedShape) {
      selectedShape.setEditable(false);
      selectedShape = null;
    }
  }

  function clearMarker() {
    if (selectedMarker) {
      selectedMarker.setEditable(false);
      selectedMarker = null;
    }
  }

  function setSelection(shape) {
    clearSelection();
    selectedShape = shape;
    shape.setEditable(true);
    selectColor(shape.get('fillColor') || shape.get('strokeColor'));
  }

  function setSelection(marker) {
    selectedMarker = marker;
  }

  function deleteSelectedShape() {
    if (selectedShape) {
      selectedShape.setMap(null);
    }
    // To show:
     drawingManager.setOptions({
       drawingControl: true
     });
  }

  function deleteSelectedMarker() {
    if (selectedMarker) {
      selectedMarker.setMap(null);
    }
    // To show:
    drawingManager.setOptions({
      drawingControl: true
    });
  }

  function selectColor(color) {
    selectedColor = color;
    for (var i = 0; i < colors.length; ++i) {
      var currColor = colors[i];
      colorButtons[currColor].style.border = currColor == color ? '2px solid #789' : '2px solid #fff';
    }

    // Retrieves the current options from the drawing manager and replaces the
    // stroke or fill color as appropriate.
    var polylineOptions = drawingManager.get('polylineOptions');
    polylineOptions.strokeColor = color;
    drawingManager.set('polylineOptions', polylineOptions);

    var rectangleOptions = drawingManager.get('rectangleOptions');
    rectangleOptions.fillColor = color;
    drawingManager.set('rectangleOptions', rectangleOptions);

    var circleOptions = drawingManager.get('circleOptions');
    circleOptions.fillColor = color;
    drawingManager.set('circleOptions', circleOptions);

    var polygonOptions = drawingManager.get('polygonOptions');
    polygonOptions.fillColor = color;
    drawingManager.set('polygonOptions', polygonOptions);
  }

  function setSelectedShapeColor(color) {
    if (selectedShape) {
      if (selectedShape.type == google.maps.drawing.OverlayType.POLYLINE) {
        selectedShape.set('strokeColor', color);
      } else {
        selectedShape.set('fillColor', color);
      }
    }
  }

  function makeColorButton(color) {
    var button = document.createElement('span');
    button.className = 'color-button';
    button.style.backgroundColor = color;
    google.maps.event.addDomListener(button, 'click', function() {
      selectColor(color);
      setSelectedShapeColor(color);
    });

    return button;
  }

   function buildColorPalette() {
     var colorPalette = document.getElementById('color-palette');
     for (var i = 0; i < colors.length; ++i) {
       var currColor = colors[i];
       var colorButton = makeColorButton(currColor);
       colorPalette.appendChild(colorButton);
       colorButtons[currColor] = colorButton;
     }
     selectColor(colors[0]);
   }

  function initialize() {
    var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 10,
      center: new google.maps.LatLng(54.12555975898535, 21.68217234313488),
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      disableDefaultUI: true,
      zoomControl: true
    });

    var polyOptions = {
      strokeWeight: 0,
      fillOpacity: 0.45,
      editable: true
    };
    // Creates a drawing manager attached to the map that allows the user to draw
    // markers, lines, and shapes.
    drawingManager = new google.maps.drawing.DrawingManager({
      drawingMode: google.maps.drawing.OverlayType.POLYGON,
      drawingControlOptions: {
        drawingModes: [
          google.maps.drawing.OverlayType.POLYGON
        ]
      },
      markerOptions: {
        draggable: true
      },
      polylineOptions: {
        editable: true
      },
      rectangleOptions: polyOptions,
      circleOptions: polyOptions,
      polygonOptions: polyOptions,
      map: map
    });

    function overlayClickListener(overlay) {
      google.maps.event.addListener(overlay, "mouseup", function(event){
        $('#coords').val(overlay.getPath().getArray().join());
      });
      $('#coords').val(overlay.getPath().getArray().join());
    }

    google.maps.event.addListener(drawingManager, 'overlaycomplete', function(event) {
      if (event.type == google.maps.drawing.OverlayType.CIRCLE) {
        var radius = event.overlay.getRadius();
      }
    });
    google.maps.event.addListener(drawingManager, 'overlaycomplete', function(event) {
      if (event.type != google.maps.drawing.OverlayType.MARKER) {
        // Switch back to non-drawing mode after drawing a shape or putting marker on the map
        drawingManager.setDrawingMode(null);
        // To hide:
        drawingManager.setOptions({
          drawingControl: false
        });

        // Add an event listener that selects the newly-drawn shape when the user mouses down on it.
        var newShape = event.overlay;
        newShape.type = event.type;
        google.maps.event.addListener(newShape, 'click', function() {
          setSelection(newShape);
        });
        setSelection(newShape);
        overlayClickListener(newShape);
        // update coords after shape modification
        google.maps.event.addListener(newShape.getPath(), 'set_at', function() {
          console.log('Vertex moved on outer path.');
          $('#coords').val(this.getArray().join());
        });
        google.maps.event.addListener(newShape.getPath(), 'insert_at', function() {
          console.log('Vertex added to inner path.');
          $('#coords').val(this.getArray().join());
        });
      } else {
        // Switch back to non-drawing mode after putting marker on the map
        drawingManager.setDrawingMode(null);
        // To hide:
        drawingManager.setOptions({
          drawingControl: false
        });

        // Add an event listener that selects the newly-drawn shape when the user mouses down on it.
        var newMarker = event.overlay;
        newMarker.type = event.type;
        google.maps.event.addListener(newMarker, 'dragend', function(event) {
          console.log(event, 'event');
          console.log(newMarker.position.toString(), 'position');
          setSelection(newMarker);
          $('#coords').val(newMarker.position.toString());
        });
        setSelection(newMarker);
        $('#coords').val(newMarker.position.toString());
      }
    });

    // Clear the current selection when the drawing mode is changed, or when the
    // map is clicked.
    google.maps.event.addListener(drawingManager, 'drawingmode_changed', clearSelection);
    google.maps.event.addListener(map, 'click', clearSelection);
    google.maps.event.addDomListener(document.getElementById('delete-button'), 'click', deleteSelectedShape);

    buildColorPalette();
  }
  google.maps.event.addDomListener(window, 'load', initialize);<|endoftext|>


<commit_before>require([
   "jquery", "underscore", "backbone", "validate", "client-models", "auth",
   // plugins
   "backbone.marionette", "bootstrap", "underscore-template-config"
], function($, _, Backbone, validate, models, auth) {

$(document).ready(function() {

	var users = new models.UserList(USER_DATA);
	var events = new models.EventList(EVENT_DATA);

	var adminsToBeRemoved = [];

	var modalAdminAdder;
	var modalAdminRemover;
	var modalConfirmAdminRemoval;

	var EventRowView = Backbone.Marionette.ItemView.extend({
	    tagName: 'tr',
	    template: '#event-row',

	    events: {
	        'click .btn-add-admin': 'invokeAddAdminModal',
	        'click .btn-remove-admin': 'invokeRemoveAdminModal'
    	},

    	modelEvents: {
	        'change': 'render'
	    },

	    ui: {
	    	eventAdmins: '.event-admins',
	    	eventDate: '.event-date',
	    },

    	invokeAddAdminModal: function(jqevt) {
    		jqevt.preventDefault();

	        var event = this.model;

	        modalAdminAdder = new EventAdminAdder({event: event});
	        modalAdminAdder.render();
    	},

    	invokeRemoveAdminModal: function(jqevt) {
	    	jqevt.preventDefault();

	        var event = this.model;

	        modalAdminRemover = new EventAdminRemover({event: event});
	        modalAdminRemover.render();
	    },

    	onRender: function() {
  			var event = this.model;

  			//Building the date and time
  			var dateFragment = document.createDocumentFragment();

  			var date = event.get("dateAndTime");

  			if(date) {
  				dateP = document.createElement("p");
  				dateP.innerHTML = moment(date).format("D MMM YYYY"); ;
  				dateFragment.appendChild(dateP);
  			}

  			//Now add the event date fragment to the layout and display it
        	this.ui.eventDate.html(dateFragment);

  			//Build the list of event admins
  			var adminFragment = document.createDocumentFragment();

  			var drawAdmin = _.bind(function (admin) {
	            imgEl = document.createElement("img");
	            var user = event.findAdminAsUser(admin, users);
	            imgEl.src = user.get("picture");
	            adminFragment.appendChild(imgEl);

	        }, this);  //drawAdmin

        	_.each(this.model.get("admins"), function(admin) {
        		drawAdmin(admin);
        	});

        	//Now add the event admins fragment to the layout
        	//and display it
        	this.ui.eventAdmins.html(adminFragment);

	    },
    });

    var EventAdminAdder = Backbone.View.extend({
	    template: _.template($('#event-admin-adder').html()),

	    events: {
	        'click .close, .cancel': 'close',
	        'click .add': 'add',
	        'keydown .filter-email': 'removeInputErrors',
	        'click .send-invite': 'sendLoginInvite'
	    },

	    ui: {
	        'filterEmail': 'input.filter-email',
	    },

	    initialize: function(options) {
	        _.bindAll(this, "add", "close", "render");
	        this.event = options.event;
	    },

	    add: function() {
	    	var email = this.$el.find(".filter-email").val();
	    	addAdminToEvent(email, this.event);

	        this.close();
	    },

	    sendLoginInvite: function() {
	    	var adminInviteeEmail = this.$el.find(".filter-email").val();
	    	var adminInviterName  = USER.displayName;
	    	var eventTitle = this.event.get("title");

	    	$.ajax({
                url:"/myevents/admin-login-invite/",
                type:"POST",
                data: {adminInviterName: adminInviterName,
						eventTitle: eventTitle, adminInviteeEmail: adminInviteeEmail}
            }).done(function() {
            	this.$el.modal("hide");

                //content changes for this modal later
                $('#invite-sent-modal').modal('show');

            }).fail(function() {
                alert("Server error.. please try later.");
            });

	    },

	    close: function() {
	        this.$el.on("hidden", this.remove);
	        this.$el.modal("hide");
	    },

	    removeInputErrors: function() {
    		$(".filter-email").addClass("success");
    		$(".filter-email").removeClass("error");

    		$(".email-validate-error").addClass("hide");
           	$(".email-validate-error").removeClass("show");

           	$(".send-invite").removeClass("show");
       		$(".send-invite").addClass("hide");
    	},

	    render: function() {
	        this.$el.addClass("modal fade");
	        this.$el.html(this.template({
	            event: this.event,
	        }));

	        this.$el.modal("show");

	    },
	});

	var EventAdminRemover = Backbone.View.extend({
	    template: _.template($('#event-admin-remover').html()),

	    events: {
	        'click .close, .cancel': 'close',
	        'click .remove': 'remove',
	        'click .close-alert': 'closeAlert',
	        'click .confirm-removal': 'confirmAdminRemoval'
	    },

	    initialize: function(options) {
	        _.bindAll(this, "close", "render", "remove");
	        this.event = options.event;
	    },

	    remove: function(jqevt) {
	    	jqevt.preventDefault();

	    	$(".alert-confirm-removal").removeClass("hide");
       		$(".alert-confirm-removal").addClass("show");

       		$(".alert-confirm-removal").find("p").text("Are you sure you would \
       			like to remove " + adminsToBeRemoved.length+ " admin(s)?");
	    },

	    closeAlert: function(jqevt) {
	    	jqevt.preventDefault();

	    	$(".alert-confirm-removal").removeClass("show");
       		$(".alert-confirm-removal").addClass("hide");
	    },

	    close: function() {
	        this.$el.on("hidden", this.remove);
	        this.$el.modal("hide");
	    },

	    confirmAdminRemoval: function() {
	    	removeAdminFromEvent(this.event);
	    },

	    render: function() {
	        this.$el.addClass("modal fade");

	        //Initially show the remove class and modal body
	        this.$el.find(".modal-body").html("");
	        this.$el.find(".remove").removeClass("hide");
        	this.$el.find(".remove").addClass("show");
        	$(".alert-confirm-removal").removeClass("show");
       		$(".alert-confirm-removal").addClass("hide");

	        this.$el.html(this.template({
	            event: this.event,
	        }));

	        this.$el.modal("show");

	        adminsToBeRemoved = [];

	        //remove the admin row select classes
	        $(this).removeClass("admin-row-selected");
	        $(this).removeClass("admin-row-unselected");

	        //Build the list of event admins to be shown for removal
  			var adminFragment = document.createDocumentFragment();

  			var drawAdminRow = _.bind(function (admin) {
  				divEl = document.createElement("div");
	            imgEl = document.createElement("img");

	            var user = this.event.findAdminAsUser(admin, users);

	            pElName = document.createTextNode(user.get("displayName"));
	            pElEmail = document.createElement("span");
	            pElEmail.innerHTML = "  " + user.get("emails")[0].value +  "";

	            imgEl.src = user.get("picture");
	            divEl.id = user.get("id");

	            divEl.appendChild(imgEl);
	            divEl.appendChild(pElName)
	            divEl.appendChild(pElEmail);

	            divEl.onclick = selectAdminRow;
	            adminFragment.appendChild(divEl);

	            function selectAdminRow() {
	            	if(this.className == undefined || this.className == "") {
	            		$(this).addClass("admin-row-selected");
	            		$(this).removeClass("admin-row-unselected");

	            		listOfAdminsForRemoval(this.id, "add");

	            	} else if(this.className == "admin-row-selected") {
	            		$(this).addClass("admin-row-unselected");
	            		$(this).removeClass("admin-row-selected");

	            		listOfAdminsForRemoval(this.id, "remove");

	            	} else if (this.className == "admin-row-unselected") {
	            		$(this).addClass("admin-row-selected");
	            		$(this).removeClass("admin-row-unselected");

	            		listOfAdminsForRemoval(this.id, "add");
	            	}
	            }

	            function listOfAdminsForRemoval(id, action) {
	            	if(action == "add") {
	            		adminsToBeRemoved.push(id);
	            	} else if (action == "remove") {
	            		if(adminsToBeRemoved && adminsToBeRemoved.indexOf(id) > -1) {

	            			for(var c = 0; c< adminsToBeRemoved.length; c++) {
	            				if(adminsToBeRemoved[c] == id) {
	            					adminsToBeRemoved.splice(c, 1);
	            					break;
	            				}
	            			}

	            		}
	            	}

	            }

	        }, this);  //drawAdmin

        	_.each(this.event.get("admins"), function(admin) {
        		drawAdminRow(admin);
        	});

        	this.$el.find(".event-admins").html(adminFragment);

        	if(this.event.get("admins").length == 0) {
        		this.$el.find(".modal-body").html("Currently, there are no admins for this event");
        		this.$el.find(".remove").addClass("hide");
        		this.$el.find(".remove").removeClass("show");
        	}
	    },
	});

	var EventTableView = Backbone.Marionette.CompositeView.extend({

	    template: '#event-table',
	    itemView: EventRowView,
	    itemViewContainer: 'tbody',

	    initialize: function(options) {
	    	this.collection = events;
	    },

	    serializeData: function() {
	    	var context = Backbone.Marionette.CompositeView.prototype.serializeData.apply(this);

	        context.adminEvents = [];

	        events.each(function(event) {
	 			context.adminEvents.push(event.toJSON());
	        });

	        return context;
	    },

	});

	/* -------------------   App initialization ---------------- */

	var app = new Backbone.Marionette.Application();

	app.addRegions({
	    main: "#main"
	});

	app.addInitializer(function(options) {
	    var eventTable = new EventTableView({model: events});
	    this.main.show(eventTable);
	});

	app.start();

	function addAdminToEvent(email, event) {
		// check if the email is blank
		if(email == "") {
			var message = "Email cannot be left blank";
			showInputErrors(message);
		}

		// check if the email is an invalid address
		if(email && !validate.validateEmail(email)) {
			var message = "Please enter a valid email address";
			showInputErrors(message);
		}

       	var userFilter = getUserForEmailFilter(email);

       	// check if the user for the email address does not
       	// exists in the user directory
       	if(userFilter == "") {
       		$(".send-invite").addClass("show");
       		$(".send-invite").removeClass("hide");

       		modalAdminAdder.addClass("show");
			return;
       	}

       	var user = users.find(function(user) {
			if(user.get("id") ==  userFilter.get("id") ) {
				return user;
			}
		});

		// check if the user is already an admin
		if(event.userIsAdmin(user)) {
			var message = 'User with this email address is already an admin';
			showInputErrors(message);
		}

		var admins = [];
		admins.push(user.get("id"));

       	postUserData({
            action: "add-event-admin",
            eventId: event.get("id"),
            admins: admins,
        }, function() {
        	event.addAdmin(userFilter);
            userFilter.trigger("change", userFilter);
        }, function(error) {
            alert("Server error");
            console.error(error);
        });
	}

	function removeAdminFromEvent(event) {
       	postUserData({
            action: "remove-event-admin",
            admins: adminsToBeRemoved,
            eventId: event.get("id"),
        }, function() {

        	for(var i = 0; i < adminsToBeRemoved.length; i++) {
        		var user = users.find(function(user) {
					if(user.get("id") ==  adminsToBeRemoved[i] ) {
						return user;
					}
				});

				event.removeAdmin(user);
				user.trigger("change", user);

        	}

        }, function(error) {
            alert("Server error");
            console.error(error);
        }, function(success) {
        	console.log("success");
        });

	}

	function postUserData(data, success, error) {

		var post = _.extend({eventId: data.eventId}, data);

        $.ajax({
            type: 'POST',
            url: '/myevents/',
            data: post,
            success: success,
            error: error
        });
	}

	function getUserForEmailFilter(email) {

		userFilter = [];

		_.filter(users.models, _.bind(function(user) {

       		if(email) {
       			var tokens = email.toLowerCase().split(" ");

       			var search = (user.get("displayName") + " " +
                _.pluck(user.get("emails"), "value").join(" ")).toLowerCase();

                for (var i = 0; i < tokens.length; i++) {

                    if (search.indexOf(tokens[i]) >= 0) { //matched
                    	userFilter = user;
                    	return false;
                    }

                }

       		}

     		})

     	);

     	return userFilter;
    }

	function showInputErrors(msg) {
		$(".email-validate-error").removeClass("hide");
   		$(".email-validate-error").addClass("show");

		$(".email-validate-error").text(msg);

		$(".filter-email").addClass("error");
		$(".filter-email").removeClass("success");

		modalAdminAdder.addClass("show");
		return;
    }

}); //document ready

$("[rel=popover]").popover({container: "body", placement: "left"});
$("[title]").not("[rel=popover]").tooltip({container: "body"});

});
<commit_msg>data attribute property for user ids and tooltip to display admins username on myevents page<commit_after>require([
   "jquery", "underscore", "backbone", "validate", "client-models", "auth",
   // plugins
   "backbone.marionette", "bootstrap", "underscore-template-config"
], function($, _, Backbone, validate, models, auth) {

$(document).ready(function() {

	var users = new models.UserList(USER_DATA);
	var events = new models.EventList(EVENT_DATA);

	var adminsToBeRemoved = [];

	var modalAdminAdder;
	var modalAdminRemover;
	var modalConfirmAdminRemoval;

	var EventRowView = Backbone.Marionette.ItemView.extend({
	    tagName: 'tr',
	    template: '#event-row',

	    events: {
	        'click .btn-add-admin': 'invokeAddAdminModal',
	        'click .btn-remove-admin': 'invokeRemoveAdminModal'
    	},

    	modelEvents: {
	        'change': 'render'
	    },

	    ui: {
	    	eventAdmins: '.event-admins',
	    	eventDate: '.event-date',
	    },

    	invokeAddAdminModal: function(jqevt) {
    		jqevt.preventDefault();

	        var event = this.model;

	        modalAdminAdder = new EventAdminAdder({event: event});
	        modalAdminAdder.render();
    	},

    	invokeRemoveAdminModal: function(jqevt) {
	    	jqevt.preventDefault();

	        var event = this.model;

	        modalAdminRemover = new EventAdminRemover({event: event});
	        modalAdminRemover.render();
	    },

    	onRender: function() {
  			var event = this.model;

  			//Building the date and time
  			var dateFragment = document.createDocumentFragment();

  			var date = event.get("dateAndTime");

  			if(date) {
  				dateP = document.createElement("p");
  				dateP.innerHTML = moment(date).format("D MMM YYYY"); ;
  				dateFragment.appendChild(dateP);
  			}

  			//Now add the event date fragment to the layout and display it
        	this.ui.eventDate.html(dateFragment);

  			//Build the list of event admins
  			var adminFragment = document.createDocumentFragment();

  			var drawAdmin = _.bind(function (admin) {
	            imgEl = document.createElement("img");
	            var user = event.findAdminAsUser(admin, users);
	            imgEl.src = user.get("picture");
	            imgEl.dataset.id = user.get("id");
	            imgEl.dataset.name = user.get("displayName");
	            adminFragment.appendChild(imgEl);
	            imgEl.onmouseover = showUsernameTooltip;
	            imgEl.alt = user.get("displayName");

	        }, this);  //drawAdmin

        	_.each(this.model.get("admins"), function(admin) {
        		drawAdmin(admin);
        	});

        	//Now add the event admins fragment to the layout
        	//and display it
        	this.ui.eventAdmins.html(adminFragment);

        	function showUsernameTooltip() {
        		console.log(this.dataset.id);

        		$(this).attr("data-toggle", "tooltip")
        			   .attr("title", this.dataset.name)
        			   .tooltip("show");
        	}

	    },
    });

    var EventAdminAdder = Backbone.View.extend({
	    template: _.template($('#event-admin-adder').html()),

	    events: {
	        'click .close, .cancel': 'close',
	        'click .add': 'add',
	        'keydown .filter-email': 'removeInputErrors',
	        'click .send-invite': 'sendLoginInvite'
	    },

	    ui: {
	        'filterEmail': 'input.filter-email',
	    },

	    initialize: function(options) {
	        _.bindAll(this, "add", "close", "render");
	        this.event = options.event;
	    },

	    add: function() {
	    	var email = this.$el.find(".filter-email").val();
	    	addAdminToEvent(email, this.event);

	        this.close();
	    },

	    sendLoginInvite: function() {
	    	var adminInviteeEmail = this.$el.find(".filter-email").val();
	    	var adminInviterName  = USER.displayName;
	    	var eventTitle = this.event.get("title");

	    	$.ajax({
                url:"/myevents/admin-login-invite/",
                type:"POST",
                data: {adminInviterName: adminInviterName,
						eventTitle: eventTitle, adminInviteeEmail: adminInviteeEmail}
            }).done(function() {
            	this.$el.modal("hide");

                //content changes for this modal later
                $('#invite-sent-modal').modal('show');

            }).fail(function() {
                alert("Server error.. please try later.");
            });

	    },

	    close: function() {
	        this.$el.on("hidden", this.remove);
	        this.$el.modal("hide");
	    },

	    removeInputErrors: function() {
    		$(".filter-email").addClass("success");
    		$(".filter-email").removeClass("error");

    		$(".email-validate-error").addClass("hide");
           	$(".email-validate-error").removeClass("show");

           	$(".send-invite").removeClass("show");
       		$(".send-invite").addClass("hide");
    	},

	    render: function() {
	        this.$el.addClass("modal fade");
	        this.$el.html(this.template({
	            event: this.event,
	        }));

	        this.$el.modal("show");

	    },
	});

	var EventAdminRemover = Backbone.View.extend({
	    template: _.template($('#event-admin-remover').html()),

	    events: {
	        'click .close, .cancel': 'close',
	        'click .remove': 'remove',
	        'click .close-alert': 'closeAlert',
	        'click .confirm-removal': 'confirmAdminRemoval'
	    },

	    initialize: function(options) {
	        _.bindAll(this, "close", "render", "remove");
	        this.event = options.event;
	    },

	    remove: function(jqevt) {
	    	jqevt.preventDefault();

	    	$(".alert-confirm-removal").removeClass("hide");
       		$(".alert-confirm-removal").addClass("show");

       		$(".alert-confirm-removal").find("p").text("Are you sure you would \
       			like to remove " + adminsToBeRemoved.length+ " admin(s)?");
	    },

	    closeAlert: function(jqevt) {
	    	jqevt.preventDefault();

	    	$(".alert-confirm-removal").removeClass("show");
       		$(".alert-confirm-removal").addClass("hide");
	    },

	    close: function() {
	        this.$el.on("hidden", this.remove);
	        this.$el.modal("hide");
	    },

	    confirmAdminRemoval: function() {
	    	removeAdminFromEvent(this.event);
	    },

	    render: function() {
	        this.$el.addClass("modal fade");

	        //Initially show the remove class and modal body
	        this.$el.find(".modal-body").html("");
	        this.$el.find(".remove").removeClass("hide");
        	this.$el.find(".remove").addClass("show");
        	$(".alert-confirm-removal").removeClass("show");
       		$(".alert-confirm-removal").addClass("hide");

	        this.$el.html(this.template({
	            event: this.event,
	        }));

	        this.$el.modal("show");

	        adminsToBeRemoved = [];

	        //remove the admin row select classes
	        $(this).removeClass("admin-row-selected");
	        $(this).removeClass("admin-row-unselected");

	        //Build the list of event admins to be shown for removal
  			var adminFragment = document.createDocumentFragment();

  			var drawAdminRow = _.bind(function (admin) {
  				divEl = document.createElement("div");
	            imgEl = document.createElement("img");

	            var user = this.event.findAdminAsUser(admin, users);

	            pElName = document.createTextNode(user.get("displayName"));
	            pElEmail = document.createElement("span");
	            pElEmail.innerHTML = "  " + user.get("emails")[0].value +  "";

	            imgEl.src = user.get("picture");
	            divEl.dataset.id = user.get("id");

	            divEl.appendChild(imgEl);
	            divEl.appendChild(pElName)
	            divEl.appendChild(pElEmail);

	            divEl.onclick = selectAdminRow;
	            adminFragment.appendChild(divEl);

	            function selectAdminRow() {
	            	if(this.className == undefined || this.className == "") {
	            		$(this).addClass("admin-row-selected");
	            		$(this).removeClass("admin-row-unselected");

	            		listOfAdminsForRemoval(this.dataset.id, "add");

	            	} else if(this.className == "admin-row-selected") {
	            		$(this).addClass("admin-row-unselected");
	            		$(this).removeClass("admin-row-selected");

	            		listOfAdminsForRemoval(this.dataset.id, "remove");

	            	} else if (this.className == "admin-row-unselected") {
	            		$(this).addClass("admin-row-selected");
	            		$(this).removeClass("admin-row-unselected");

	            		listOfAdminsForRemoval(this.dataset.id, "add");
	            	}
	            }

	            function listOfAdminsForRemoval(id, action) {
	            	if(action == "add") {
	            		adminsToBeRemoved.push(id);
	            	} else if (action == "remove") {
	            		if(adminsToBeRemoved && adminsToBeRemoved.indexOf(id) > -1) {

	            			for(var c = 0; c< adminsToBeRemoved.length; c++) {
	            				if(adminsToBeRemoved[c] == id) {
	            					adminsToBeRemoved.splice(c, 1);
	            					break;
	            				}
	            			}

	            		}
	            	}

	            }

	        }, this);  //drawAdmin

        	_.each(this.event.get("admins"), function(admin) {
        		drawAdminRow(admin);
        	});

        	this.$el.find(".event-admins").html(adminFragment);

        	if(this.event.get("admins").length == 0) {
        		this.$el.find(".modal-body").html("Currently, there are no admins for this event");
        		this.$el.find(".remove").addClass("hide");
        		this.$el.find(".remove").removeClass("show");
        	}
	    },
	});

	var EventTableView = Backbone.Marionette.CompositeView.extend({

	    template: '#event-table',
	    itemView: EventRowView,
	    itemViewContainer: 'tbody',

	    initialize: function(options) {
	    	this.collection = events;
	    },

	    serializeData: function() {
	    	var context = Backbone.Marionette.CompositeView.prototype.serializeData.apply(this);

	        context.adminEvents = [];

	        events.each(function(event) {
	 			context.adminEvents.push(event.toJSON());
	        });

	        return context;
	    },

	});

	/* -------------------   App initialization ---------------- */

	var app = new Backbone.Marionette.Application();

	app.addRegions({
	    main: "#main"
	});

	app.addInitializer(function(options) {
	    var eventTable = new EventTableView({model: events});
	    this.main.show(eventTable);
	});

	app.start();

	function addAdminToEvent(email, event) {
		// check if the email is blank
		if(email == "") {
			var message = "Email cannot be left blank";
			showInputErrors(message);
		}

		// check if the email is an invalid address
		if(email && !validate.validateEmail(email)) {
			var message = "Please enter a valid email address";
			showInputErrors(message);
		}

       	var userFilter = getUserForEmailFilter(email);

       	// check if the user for the email address does not
       	// exists in the user directory
       	if(userFilter == "") {
       		$(".send-invite").addClass("show");
       		$(".send-invite").removeClass("hide");

       		modalAdminAdder.addClass("show");
			return;
       	}

       	var user = users.find(function(user) {
			if(user.get("id") ==  userFilter.get("id") ) {
				return user;
			}
		});

		// check if the user is already an admin
		if(event.userIsAdmin(user)) {
			var message = 'User with this email address is already an admin';
			showInputErrors(message);
		}

		var admins = [];
		admins.push(user.get("id"));

       	postUserData({
            action: "add-event-admin",
            eventId: event.get("id"),
            admins: admins,
        }, function() {
        	event.addAdmin(userFilter);
            userFilter.trigger("change", userFilter);
        }, function(error) {
            alert("Server error");
            console.error(error);
        });
	}

	function removeAdminFromEvent(event) {
       	postUserData({
            action: "remove-event-admin",
            admins: adminsToBeRemoved,
            eventId: event.get("id"),
        }, function() {

        	for(var i = 0; i < adminsToBeRemoved.length; i++) {
        		var user = users.find(function(user) {
					if(user.get("id") ==  adminsToBeRemoved[i] ) {
						return user;
					}
				});

				event.removeAdmin(user);
				user.trigger("change", user);

        	}

        }, function(error) {
            alert("Server error");
            console.error(error);
        }, function(success) {
        	console.log("success");
        });

	}

	function postUserData(data, success, error) {

		var post = _.extend({eventId: data.eventId}, data);

        $.ajax({
            type: 'POST',
            url: '/myevents/',
            data: post,
            success: success,
            error: error
        });
	}

	function getUserForEmailFilter(email) {

		userFilter = [];

		_.filter(users.models, _.bind(function(user) {

       		if(email) {
       			var tokens = email.toLowerCase().split(" ");

       			var search = (user.get("displayName") + " " +
                _.pluck(user.get("emails"), "value").join(" ")).toLowerCase();

                for (var i = 0; i < tokens.length; i++) {

                    if (search.indexOf(tokens[i]) >= 0) { //matched
                    	userFilter = user;
                    	return false;
                    }

                }

       		}

     		})

     	);

     	return userFilter;
    }

	function showInputErrors(msg) {
		$(".email-validate-error").removeClass("hide");
   		$(".email-validate-error").addClass("show");

		$(".email-validate-error").text(msg);

		$(".filter-email").addClass("error");
		$(".filter-email").removeClass("success");

		modalAdminAdder.addClass("show");
		return;
    }

}); //document ready

$("[rel=popover]").popover({container: "body", placement: "left"});
$("[title]").not("[rel=popover]").tooltip({container: "body"});

});
<|endoftext|>


<commit_before>'use strict';

var startTime = new Date().getTime();

// Call this function when the page loads (the "ready" event)
$(document).ready(function() {
	initializePage();

	$(".folded").each(function() {
		new FoldedList($(this));
	});
	$("#submit").click(searchVideo);
	$("#query").on('keyup', textfieldListener);
	$("#query").on('keypress', stopRKey);

	$(".preview").css("top", $(window).height()/2 - 160);

	$("#backToFullList").css("display", "none");

	$(".grid-videoitem").click(function() {
		$(this).next().fadeIn();
	});

	$(".goback").click(function() {
		$(this).parent().css("display", "none");
	})

    $(".description-button").click(function() {
    	ga("send", "event", "Show Description", "click");
        console.log("hello");
        $(this).fadeOut(function() {
            $(this).next().fadeIn();
        });
    });

    $("#recently").trigger("click");

    $(".thumbnails, .preview-thumbnails, .play").click(function() {
    	var id = $(this).attr("id");
    	playVideo(id);
    });
})

function playVideo(id) {
	console.log(id);
	var endTime = new Date().getTime();
	console.log(endTime - startTime);
	var label = "unk";
	if (id == "4bfa81198cf5fc1002a42b93") label = "salsa";
	if (id == "4bfa81198cf5fc1002a42b91") label = "dougie";
	if (id == "4bfa81198cf5fc1002a42b92") label = "shuffle";
	console.log(label);
	ga('send', {
		  'hitType': 'event',          // Required.
		  'eventCategory': 'Time Spent',   // Required.
		  'eventAction': 'click',      // Required.
		  'eventLabel': label,
		  'eventValue': endTime - startTime
	});
	window.location = '/video/' + id;
}

function textfieldListener() {
	console.log($(this).val());
	if ($(this).val() == "") {
		toDefaultView();
	}
}

function stopRKey(evt) {
   var evt = (evt) ? evt : ((event) ? event : null);
   var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
   if ((evt.keyCode == 13) && (node.type=="text")) {
   		searchVideo();
   		return false;
   }
}

function searchVideo() {
	var query = $("#query").val();
	if (query == "" || query == "Search your videos...") {
		$(".warning .message").html("Type keywords to search for");
		$(".warning").fadeIn(function() {
			setTimeout(function() {
				$(".warning").fadeOut();
			}, 1500);
		});
	} else {
		var jqxhr = $.post("/playlist", { 'query': query })
			.done(function(data) {
				$("#backToFullList").css("display", "");
				$(".default").css("display", "none");
	  			$(".searchlist").css("display", "");

				var html = ""
				if (data.length == 0) {
					html = "
No video found
"
				} else {
					for (var i=0; i < data.length; i++) {
						var video = data[i];
						var newitem = '
\
						\

\

\

\
						\

'+video.title+'
\

 Show Description
 \

'+video.description+'
\

';
						html += newitem;
					}
				}
				$(".searchlist").html(html);

			    $(".description-button").click(function() {
			        console.log("hello");
			        $(this).fadeOut(function() {
			            $(this).next().fadeIn();
			        });
			    });

				$('
', {
				    text: 'Search results:',
				    class: 'searchresulttitle'
				}).prependTo('.searchlist');
				$(".searchlist").slideDown();
				$("#back").attr("href","/playlist");
		  	})
			.fail(function() {
				alert( "error" );
			});
	}
}

function toDefaultView(event) {
	if (event) {
		event.preventDefault();
		$("#query").val("");
	}
	$(".default").css("display", "");
	$(".searchlist").html("");
	$(".searchlist").css("display", "none");
	$("#back").attr("href","/");
	$("#backToFullList").css("display", "none");
}

function FoldedList(button){
	var open = false;

	button.click(function() {
		if(!open) {
			$(this).next().slideDown('slow');
			open = true;
		} else {
			$(this).next().slideUp('slow');
			open = false;
		}
	});

	button.next().find(".foldbutton").click(function() {
		$(this).parent().slideUp();
		open = false;
	})
}

/*
 * Function that is called when the document is ready.
 */
function initializePage() {
	var searched = false;
	$("#query").click(function() {
		if (!searched) {
			$("#query").css("font-style","normal");
			$("#query").css("color","black");
			$("#query").css("font-size", "13pt");
			$("#query").val("");
			searched = true;
		}
	});
}

<commit_msg>eliminated test code<commit_after>'use strict';

var startTime = new Date().getTime();

// Call this function when the page loads (the "ready" event)
$(document).ready(function() {
	initializePage();

	$(".folded").each(function() {
		new FoldedList($(this));
	});
	$("#submit").click(searchVideo);
	$("#query").on('keyup', textfieldListener);
	$("#query").on('keypress', stopRKey);

	$(".preview").css("top", $(window).height()/2 - 160);

	$("#backToFullList").css("display", "none");

	$(".grid-videoitem").click(function() {
		$(this).next().fadeIn();
	});

	$(".goback").click(function() {
		$(this).parent().css("display", "none");
	})

    $(".description-button").click(function() {
        $(this).fadeOut(function() {
            $(this).next().fadeIn();
        });
    });

    $("#recently").trigger("click");

    $(".thumbnails, .preview-thumbnails, .play").click(function() {
    	var id = $(this).attr("id");
    	playVideo(id);
    });
})

function playVideo(id) {
	console.log(id);
	var endTime = new Date().getTime();
	console.log(endTime - startTime);
	var label = "unk";
	if (id == "4bfa81198cf5fc1002a42b93") label = "salsa";
	if (id == "4bfa81198cf5fc1002a42b91") label = "dougie";
	if (id == "4bfa81198cf5fc1002a42b92") label = "shuffle";
	console.log(label);
	window.location = '/video/' + id;
}

function textfieldListener() {
	console.log($(this).val());
	if ($(this).val() == "") {
		toDefaultView();
	}
}

function stopRKey(evt) {
   var evt = (evt) ? evt : ((event) ? event : null);
   var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
   if ((evt.keyCode == 13) && (node.type=="text")) {
   		searchVideo();
   		return false;
   }
}

function searchVideo() {
	var query = $("#query").val();
	if (query == "" || query == "Search your videos...") {
		$(".warning .message").html("Type keywords to search for");
		$(".warning").fadeIn(function() {
			setTimeout(function() {
				$(".warning").fadeOut();
			}, 1500);
		});
	} else {
		var jqxhr = $.post("/playlist", { 'query': query })
			.done(function(data) {
				$("#backToFullList").css("display", "");
				$(".default").css("display", "none");
	  			$(".searchlist").css("display", "");

				var html = ""
				if (data.length == 0) {
					html = "
No video found
"
				} else {
					for (var i=0; i < data.length; i++) {
						var video = data[i];
						var newitem = '
\
						\

\

\

\
						\

'+video.title+'
\

 Show Description
 \

'+video.description+'
\

';
						html += newitem;
					}
				}
				$(".searchlist").html(html);

			    $(".description-button").click(function() {
			        console.log("hello");
			        $(this).fadeOut(function() {
			            $(this).next().fadeIn();
			        });
			    });

				$('
', {
				    text: 'Search results:',
				    class: 'searchresulttitle'
				}).prependTo('.searchlist');
				$(".searchlist").slideDown();
				$("#back").attr("href","/playlist");
		  	})
			.fail(function() {
				alert( "error" );
			});
	}
}

function toDefaultView(event) {
	if (event) {
		event.preventDefault();
		$("#query").val("");
	}
	$(".default").css("display", "");
	$(".searchlist").html("");
	$(".searchlist").css("display", "none");
	$("#back").attr("href","/");
	$("#backToFullList").css("display", "none");
}

function FoldedList(button){
	var open = false;

	button.click(function() {
		if(!open) {
			$(this).next().slideDown('slow');
			open = true;
		} else {
			$(this).next().slideUp('slow');
			open = false;
		}
	});

	button.next().find(".foldbutton").click(function() {
		$(this).parent().slideUp();
		open = false;
	})
}

/*
 * Function that is called when the document is ready.
 */
function initializePage() {
	var searched = false;
	$("#query").click(function() {
		if (!searched) {
			$("#query").css("font-style","normal");
			$("#query").css("color","black");
			$("#query").css("font-size", "13pt");
			$("#query").val("");
			searched = true;
		}
	});
}

<|endoftext|>


<commit_before>/**
 * Practice view blocks for jsSART
 */

(function() {
  var practice = [];
  var participant_id = getParticipantId();
  var practice_condition = generatePracticeCondition();
  var practice_trials = {
    'BLOCK_1_STIMULI': generateStimuli(18, 2),
    'BLOCK_2_STIMULI': generateStimuli(72, 8)
  };

  // baseline evaluation questions
  var baseline_notice = createTextBlock("
Before we get started, we would like to ask you a couple of questions about how you're feeling right now.
");
  var baseline_questions = generateMultiChoiceSurvey(
      jsSART.QUESTIONS.AROUSAL, true  // randomized order
  );
  practice.push(
    baseline_notice,
    baseline_questions
  );

  // practice block 1
  // ----------------------------
  // notice
  var practice_block_1_notice_text = "
Thank you!

Now, for the first practice block, you will be given feedback after each item so that you know how you performed the task.

When you're ready to continue, the practice block will begin.
";
  var practice_block_1_notice = createTextBlock(practice_block_1_notice_text);
  // practice block 1
  var practice_block_1 = createSartBlock(practice_trials.BLOCK_1_STIMULI, {
    give_feedback: true
  });
  practice.push(
    practice_block_1_notice,
    fixation_trial,
    practice_block_1
  );

  // practice block 2
  // ----------------------------
  // instructions
  var practice_num_items = practice_trials.BLOCK_2_STIMULI.length;
  // NOTE: participants must get a minimum number of items correct
  var practice_min_correct = getPracticeMinCorrect(
    practice_num_items, jsSART.PRACTICE.MAX_ERROR_RATE);

  var practice_block_2_instructions = {
    type: "instructions",
    pages: [
      "
OK, you should be getting the hang of it.

Before continuing, let the experimenter know if you have any questions.

You will now continue with a second block of practice trials; however, you will no longer receive any feedback on how you are doing.
",

      "
Remember: Whenever there is a digit other than " + jsSART.STIMULI.NO_GO_VALUE + " (e.g. 1, 2, 4, 5, 6, 7, 8, 9), press the " + spacebar_html + " as fast as you can. However, if digit " + jsSART.STIMULI.NO_GO_VALUE + " is presented, don’t do anything. Just wait for the next digit.

Use the index finger of your dominant hand when responding (e.g. if you are left-handed, use your left index finger to press the " + spacebar_html + ".

It’s important to be accurate and fast in this study.
",

      "
Now we are going to try some more practice but this time the numbers will be presented at a rate of 1 every ~" + (sum(jsSART.STIMULI.DISPLAY_TIMINGS) / 1000) + " seconds. You will be shown " + practice_num_items + " numbers.

We want to be sure that you understand the task that is ahead of you, so if you get fewer than " + practice_min_correct + " right, don't worry, the practice will repeat and you can try again!
"
    ],
    show_clickable_nav: true,
    allow_backward: false
  };
  practice.push(practice_block_2_instructions);

  // practice block 2
  // NOTE: repeats if error rate threshold is eclipsed, or 3 failed trials
  var practice_block_2_attempts = 0;
  var skip_experiment = false;
  var practice_block_2_notice_text = "
OK, let's practice the task once more, just as it will be in the experiment...
";
  var practice_block_2_notice = createTextBlock(practice_block_2_notice_text);
  var practice_block_2 = createSartBlock(practice_trials.BLOCK_2_STIMULI);

  var practice_2_chunk = {
    chunk_type: 'while',
    timeline: [practice_block_2_notice, fixation_trial, practice_block_2],
    loop_function: function(data) {
      practice_block_2_attempts++;
      // total number of correct problems
      var num_correct = 0;
      for (var i in data) {
        if (data[i].correct) {
          num_correct++;
        }
      }

      if (num_correct >= practice_min_correct) {
        // end the practice loop
        return false;
      } else if (practice_block_2_attempts >= jsSART.PRACTICE.MAX_ATTEMPTS) {
        // end the practice loop
        // also skip the experiment in order to go straight to demographics
        skip_experiment = true;
        return false;
      } else {
        // keep going until enough problems are correctly answered
        return true;
      }
    }
  };
  practice.push(practice_2_chunk);

  // post-practice notice
  // note: skipped if practice block 2 not understood
  var post_practice_notice_block = createTextBlock(
    "
OK, looks like you've got it!

Do you have any questions at all? Remember, this is a challenging task. If you make a mistake, just jump right back in.

Also note that, at several points during the task, you will pause briefly and be asked to report your experience before continuing on.
"
  );
  var post_practice_notice = {
    chunk_type: 'if',
    timeline: [post_practice_notice_block],
    conditional_function: function() { return !skip_experiment; }
  };
  practice.push(post_practice_notice);

  // end practice notice
  var end_practice_notice = createTextBlock(
    "You have now completed the practice blocks."
  );
  practice.push(end_practice_notice);

  // add generated experiment settings to saved data
  jsPsych.data.addProperties({
    participant_id: participant_id,
    practice_condition: practice_condition
  });

  jsPsych.init({
    display_element: $('#jspsych-target'),
    timeline: practice,
    on_finish: function() {
      var url_params = {pid: participant_id};
      var url_path = 'experiment';
      // NOTE: different params and URL if practice block 2 not understood
      if (skip_experiment) {
        url_params = _.extend(url_params, {skip_experiment: skip_experiment});
        url_path = 'follow_up';
      }

      var redirect_url = url_path + '?' + $.param(url_params);
      postDataToDb(jsPsych.data.getData(), participant_id, redirect_url);
    }
  });
})();
<commit_msg>Reduce number of trials in practice block 2<commit_after>/**
 * Practice view blocks for jsSART
 */

(function() {
  var practice = [];
  var participant_id = getParticipantId();
  var practice_condition = generatePracticeCondition();
  var practice_trials = {
    'BLOCK_1_STIMULI': generateStimuli(18, 2),
    'BLOCK_2_STIMULI': generateStimuli(27, 3)
  };

  // baseline evaluation questions
  var baseline_notice = createTextBlock("
Before we get started, we would like to ask you a couple of questions about how you're feeling right now.
");
  var baseline_questions = generateMultiChoiceSurvey(
      jsSART.QUESTIONS.AROUSAL, true  // randomized order
  );
  practice.push(
    baseline_notice,
    baseline_questions
  );

  // practice block 1
  // ----------------------------
  // notice
  var practice_block_1_notice_text = "
Thank you!

Now, for the first practice block, you will be given feedback after each item so that you know how you performed the task.

When you're ready to continue, the practice block will begin.
";
  var practice_block_1_notice = createTextBlock(practice_block_1_notice_text);
  // practice block 1
  var practice_block_1 = createSartBlock(practice_trials.BLOCK_1_STIMULI, {
    give_feedback: true
  });
  practice.push(
    practice_block_1_notice,
    fixation_trial,
    practice_block_1
  );

  // practice block 2
  // ----------------------------
  // instructions
  var practice_num_items = practice_trials.BLOCK_2_STIMULI.length;
  // NOTE: participants must get a minimum number of items correct
  var practice_min_correct = getPracticeMinCorrect(
    practice_num_items, jsSART.PRACTICE.MAX_ERROR_RATE);

  var practice_block_2_instructions = {
    type: "instructions",
    pages: [
      "
OK, you should be getting the hang of it.

Before continuing, let the experimenter know if you have any questions.

You will now continue with a second block of practice trials; however, you will no longer receive any feedback on how you are doing.
",

      "
Remember: Whenever there is a digit other than " + jsSART.STIMULI.NO_GO_VALUE + " (e.g. 1, 2, 4, 5, 6, 7, 8, 9), press the " + spacebar_html + " as fast as you can. However, if digit " + jsSART.STIMULI.NO_GO_VALUE + " is presented, don’t do anything. Just wait for the next digit.

Use the index finger of your dominant hand when responding (e.g. if you are left-handed, use your left index finger to press the " + spacebar_html + ".

It’s important to be accurate and fast in this study.
",

      "
Now we are going to try some more practice but this time the numbers will be presented at a rate of 1 every ~" + (sum(jsSART.STIMULI.DISPLAY_TIMINGS) / 1000) + " seconds. You will be shown " + practice_num_items + " numbers.

We want to be sure that you understand the task that is ahead of you, so if you get fewer than " + practice_min_correct + " right, don't worry, the practice will repeat and you can try again!
"
    ],
    show_clickable_nav: true,
    allow_backward: false
  };
  practice.push(practice_block_2_instructions);

  // practice block 2
  // NOTE: repeats if error rate threshold is eclipsed, or 3 failed trials
  var practice_block_2_attempts = 0;
  var skip_experiment = false;
  var practice_block_2_notice_text = "
OK, let's practice the task once more, just as it will be in the experiment...
";
  var practice_block_2_notice = createTextBlock(practice_block_2_notice_text);
  var practice_block_2 = createSartBlock(practice_trials.BLOCK_2_STIMULI);

  var practice_2_chunk = {
    chunk_type: 'while',
    timeline: [practice_block_2_notice, fixation_trial, practice_block_2],
    loop_function: function(data) {
      practice_block_2_attempts++;
      // total number of correct problems
      var num_correct = 0;
      for (var i in data) {
        if (data[i].correct) {
          num_correct++;
        }
      }

      if (num_correct >= practice_min_correct) {
        // end the practice loop
        return false;
      } else if (practice_block_2_attempts >= jsSART.PRACTICE.MAX_ATTEMPTS) {
        // end the practice loop
        // also skip the experiment in order to go straight to demographics
        skip_experiment = true;
        return false;
      } else {
        // keep going until enough problems are correctly answered
        return true;
      }
    }
  };
  practice.push(practice_2_chunk);

  // post-practice notice
  // note: skipped if practice block 2 not understood
  var post_practice_notice_block = createTextBlock(
    "
OK, looks like you've got it!

Do you have any questions at all? Remember, this is a challenging task. If you make a mistake, just jump right back in.

Also note that, at several points during the task, you will pause briefly and be asked to report your experience before continuing on.
"
  );
  var post_practice_notice = {
    chunk_type: 'if',
    timeline: [post_practice_notice_block],
    conditional_function: function() { return !skip_experiment; }
  };
  practice.push(post_practice_notice);

  // end practice notice
  var end_practice_notice = createTextBlock(
    "You have now completed the practice blocks."
  );
  practice.push(end_practice_notice);

  // add generated experiment settings to saved data
  jsPsych.data.addProperties({
    participant_id: participant_id,
    practice_condition: practice_condition
  });

  jsPsych.init({
    display_element: $('#jspsych-target'),
    timeline: practice,
    on_finish: function() {
      var url_params = {pid: participant_id};
      var url_path = 'experiment';
      // NOTE: different params and URL if practice block 2 not understood
      if (skip_experiment) {
        url_params = _.extend(url_params, {skip_experiment: skip_experiment});
        url_path = 'follow_up';
      }

      var redirect_url = url_path + '?' + $.param(url_params);
      postDataToDb(jsPsych.data.getData(), participant_id, redirect_url);
    }
  });
})();
<|endoftext|>


<commit_before>require('regenerator/runtime');
require('serviceworker-cache-polyfill');
var wikipedia = require('../shared/wikipedia');
var storage = require('../shared/storage');

var version = '24';
var prefix = 'wikioffline';
var staticCacheName = `${prefix}-static-v${version}`;

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(staticCacheName).then(cache => {
      return cache.addAll([
        '/',
        '/shell.html',
        '/js/page.js',
        '/js/page-framework.js', // yeahhhh, we're caching waayyyyy more than we need, but keeps the request tests fair
        '/css/head-wiki.css', // don't need this when it's inlined, but helps when rendered with blocking CSS in settings
        '/css/wiki.css'
      ]).then(() => cache.match('/shell.html')).then(response => {
        // bit hacky, making the shell start & end from the shell just fetched
        return response.text().then(text => {
          const headerEnd = text.indexOf('
');
          const articleEnd = text.indexOf('
');
          return Promise.all([
            cache.put('/shell-start.html', new Response(text.slice(0, headerEnd), response)),
            cache.put('/shell-end.html', new Response(text.slice(articleEnd), response))
          ]);
        });
      });
    })
  );
});

var expectedCaches = [
  staticCacheName
];

self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(keys => {
      return Promise.all(
        keys.map(key => {
          if (key.startsWith(prefix + '-')
            && !key.startsWith(`${prefix}-article-`)
            && expectedCaches.indexOf(key) == -1) {
            return caches.delete(key);
          }
        })
      );
    })
  );
});

// This will vanish when the ServiceWorker closes,
// but that's cool, I want that.
var dataTmpCache = {};

self.addEventListener('fetch', event => {
  var requestURL = new URL(event.request.url);

  // catch the root request
  if (requestURL.origin == location.origin) {
    if (requestURL.pathname == '/') {
      event.respondWith(caches.match('/'));
      return;
    }
    if (requestURL.pathname.startsWith('/wiki/')) {
      if (/\.(middle.inc)$/.test(requestURL.pathname)) {
        return;
      }

      if (/\.(json|inc)$/.test(requestURL.pathname)) {
        if (dataTmpCache[requestURL.href]) {
          var response = dataTmpCache[requestURL.href];
          delete dataTmpCache[requestURL.href];
          event.respondWith(response);
        }
        return;
      }

      if (requestURL.search.includes('sw-stream')) {
        event.respondWith(streamArticle(requestURL));
        return;
      }

      // Get ahead of the pack by starting the json request now
      var jsonURL = new URL(requestURL);
      jsonURL.pathname += '.json';
      jsonURL.search = '';
      var incURL = new URL(requestURL);
      incURL.pathname += '.inc';
      incURL.search = '';
      dataTmpCache[jsonURL.href] = fetch(jsonURL, {
        credentials: 'include' // needed for flag cookies
      });
      dataTmpCache[incURL.href] = fetch(incURL, {
        credentials: 'include' // needed for flag cookies
      });

      event.respondWith(caches.match('/shell.html'));
      return;
    }
  }

  // default fetch behaviour
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    })
  );
});

function streamArticle(url) {
  try {
    new ReadableStream({});
  }
  catch(e) {
    return new Response("Streams not supported");
  }
  const stream = new ReadableStream({
    start(controller) {
      const contentURL = new URL(url);
      contentURL.pathname += '.middle.inc';
      const startFetch = caches.match('/shell-start.html')
      const contentFetch = fetch(contentURL).catch(() => new Response("Failed, soz"));
      const endFetch = caches.match('/shell-end.html')

      function pushStream(stream) {
        const reader = stream.getReader();
        function read() {
          return reader.read().then(result => {
            if (result.done) return;
            controller.enqueue(result.value);
            return read();
          });
        }
        return read();
      }

      startFetch
        .then(response => pushStream(response.body))
        .then(() => contentFetch)
        .then(response => pushStream(response.body))
        .then(() => endFetch)
        .then(response => pushStream(response.body))
        .then(() => controller.close());
    }
  });

  return new Response(stream, {
    headers: {'Content-Type': 'text/html'}
  })
}

self.addEventListener('sync', event => {
  // My use of storage here has race conditions. Meh.
  console.log("Good lord, a sync event");

  event.waitUntil(
    storage.get('to-bg-cache').then(toCache => {
      toCache = toCache || [];

      return Promise.all(toCache.map(async articleName => {
        var article = await wikipedia.article(articleName);
        await article.cache();
        registration.showNotification((await article.meta).title + " ready!", {
          icon: "/imgs/wikipedia-192.png",
          body: "View the article",
          data: (await article.meta).urlId
        });
      }));
    }).then(_ => {
      storage.set('to-bg-cache', []);
    })
  );
});

self.addEventListener('notificationclick', function(event) {
  // assuming only one type of notification right now
  event.notification.close();
  clients.openWindow(`${location.origin}/wiki/${event.notification.data}`);
});

self.addEventListener('message', event => {
  if (event.data == 'skipWaiting') {
    self.skipWaiting();
  }
});<commit_msg>Allow opt-out of prefetch<commit_after>require('regenerator/runtime');
require('serviceworker-cache-polyfill');
var wikipedia = require('../shared/wikipedia');
var storage = require('../shared/storage');

var version = '24';
var prefix = 'wikioffline';
var staticCacheName = `${prefix}-static-v${version}`;

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(staticCacheName).then(cache => {
      return cache.addAll([
        '/',
        '/shell.html',
        '/js/page.js',
        '/js/page-framework.js', // yeahhhh, we're caching waayyyyy more than we need, but keeps the request tests fair
        '/css/head-wiki.css', // don't need this when it's inlined, but helps when rendered with blocking CSS in settings
        '/css/wiki.css'
      ]).then(() => cache.match('/shell.html')).then(response => {
        // bit hacky, making the shell start & end from the shell just fetched
        return response.text().then(text => {
          const headerEnd = text.indexOf('
');
          const articleEnd = text.indexOf('
');
          return Promise.all([
            cache.put('/shell-start.html', new Response(text.slice(0, headerEnd), response)),
            cache.put('/shell-end.html', new Response(text.slice(articleEnd), response))
          ]);
        });
      });
    })
  );
});

var expectedCaches = [
  staticCacheName
];

self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(keys => {
      return Promise.all(
        keys.map(key => {
          if (key.startsWith(prefix + '-')
            && !key.startsWith(`${prefix}-article-`)
            && expectedCaches.indexOf(key) == -1) {
            return caches.delete(key);
          }
        })
      );
    })
  );
});

// This will vanish when the ServiceWorker closes,
// but that's cool, I want that.
var dataTmpCache = {};

self.addEventListener('fetch', event => {
  var requestURL = new URL(event.request.url);

  // catch the root request
  if (requestURL.origin == location.origin) {
    if (requestURL.pathname == '/') {
      event.respondWith(caches.match('/'));
      return;
    }
    if (requestURL.pathname.startsWith('/wiki/')) {
      if (/\.(middle.inc)$/.test(requestURL.pathname)) {
        return;
      }

      if (/\.(json|inc)$/.test(requestURL.pathname)) {
        if (dataTmpCache[requestURL.href]) {
          var response = dataTmpCache[requestURL.href];
          delete dataTmpCache[requestURL.href];
          event.respondWith(response);
        }
        return;
      }

      if (requestURL.search.includes('sw-stream')) {
        event.respondWith(streamArticle(requestURL));
        return;
      }

      // Get ahead of the pack by starting the json request now
      if (!requestURL.search.includes('no-prefetch')) {
        var jsonURL = new URL(requestURL);
        jsonURL.pathname += '.json';
        jsonURL.search = '';
        var incURL = new URL(requestURL);
        incURL.pathname += '.inc';
        incURL.search = '';
        dataTmpCache[jsonURL.href] = fetch(jsonURL, {
          credentials: 'include' // needed for flag cookies
        });
        dataTmpCache[incURL.href] = fetch(incURL, {
          credentials: 'include' // needed for flag cookies
        });
      }

      event.respondWith(caches.match('/shell.html'));
      return;
    }
  }

  // default fetch behaviour
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    })
  );
});

function streamArticle(url) {
  try {
    new ReadableStream({});
  }
  catch(e) {
    return new Response("Streams not supported");
  }
  const stream = new ReadableStream({
    start(controller) {
      const contentURL = new URL(url);
      contentURL.pathname += '.middle.inc';
      const startFetch = caches.match('/shell-start.html');
      const contentFetch = fetch(contentURL).catch(() => new Response("Failed, soz"));
      const endFetch = caches.match('/shell-end.html');

      function pushStream(stream) {
        const reader = stream.getReader();
        function read() {
          return reader.read().then(result => {
            if (result.done) return;
            controller.enqueue(result.value);
            return read();
          });
        }
        return read();
      }

      startFetch
        .then(response => pushStream(response.body))
        .then(() => contentFetch)
        .then(response => pushStream(response.body))
        .then(() => endFetch)
        .then(response => pushStream(response.body))
        .then(() => controller.close());
    }
  });

  return new Response(stream, {
    headers: {'Content-Type': 'text/html'}
  })
}

self.addEventListener('sync', event => {
  // My use of storage here has race conditions. Meh.
  console.log("Good lord, a sync event");

  event.waitUntil(
    storage.get('to-bg-cache').then(toCache => {
      toCache = toCache || [];

      return Promise.all(toCache.map(async articleName => {
        var article = await wikipedia.article(articleName);
        await article.cache();
        registration.showNotification((await article.meta).title + " ready!", {
          icon: "/imgs/wikipedia-192.png",
          body: "View the article",
          data: (await article.meta).urlId
        });
      }));
    }).then(_ => {
      storage.set('to-bg-cache', []);
    })
  );
});

self.addEventListener('notificationclick', function(event) {
  // assuming only one type of notification right now
  event.notification.close();
  clients.openWindow(`${location.origin}/wiki/${event.notification.data}`);
});

self.addEventListener('message', event => {
  if (event.data == 'skipWaiting') {
    self.skipWaiting();
  }
});<|endoftext|>


<commit_before>var error = [];
var u = 0;

function un_val() {
  var error1 = document.getElementById("error1");
  var un = document.forms["Register"]["username"].value;
  var un_l = document.forms["Register"]["username"].value.length;
  var format = /^[0-9a-zA-Z,_-]+$/;
  if (un_l == 0) {
    error1.innerHTML = "This is a required field";
    error.push('0');
    u = u +1;
  } else if (un_l < 3 || un_l > 29) {
    error1.innerHTML = "Min length of 3 characters, max length of 29 characters";
    error.push('0');
    u = u +1;
  } else if (!format.test(un)) {
    error1.innerHTML = "Can only contain letters, numbers and underscore _ or dash -.";
    error.push('0');
    u = u +1;
  } else {
    error1.innerHTML = "";
    remove('0', u);
  }
}

function remove(x, y){
  var i = error.indexOf(x);
  if (i >= 0){
    error.sort();
    error.splice(i, y);
  }
}

function val() {
  un_val();
  if(error.length > 0) {
    event.preventDefault();
  }
}
<commit_msg>Road to Socialize 0.7.0<commit_after>var error = [];
var u = 0;
var e = 0;

function un_val() {
  var error1 = document.getElementById("error1");
  var un = document.forms["Register"]["username"].value;
  var un_l = document.forms["Register"]["username"].value.length;
  var format = /^[0-9a-zA-Z,_-]+$/;
  if (un_l == 0) {
    error1.innerHTML = "This is a required field";
    error.push('0');
    u = u +1;
  } else if (un_l < 3 || un_l > 29) {
    error1.innerHTML = "Min length of 3 characters, max length of 29 characters";
    error.push('0');
    u = u +1;
  } else if (!format.test(un)) {
    error1.innerHTML = "Can only contain letters, numbers and underscore _ or dash -.";
    error.push('0');
    u = u +1;
  } else {
    error1.innerHTML = "";
    remove('0', u);
  }
}

  function mail_val(){
    var error2 = document.getElementById("error2");
    var mail_l = document.forms["Register"]["email"].value.length;
    var email = document.forms["Register"]["email"].value;
    var mailformat = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
    if(mailformat.test(email)){
      error2.innerHTML = "";
      remove('1', e);
    }	else if (mail_l == 0) {
      error2.innerHTML = "This is a required field";
      error.push('1');
      e = e +1;
    } else {
      error2.innerHTML = "This email address is not valid";
      error.push('1');
      e = e +1;
    }
  }

function remove(x, y){
  var i = error.indexOf(x);
  if (i >= 0){
    error.sort();
    error.splice(i, y);
  }
}

function val() {
  un_val();
  mail_val();
  if(error.length > 0) {
    event.preventDefault();
  }
}
<|endoftext|>