<commit_before>// ==========================================================================
//                        DG.DocumentArchiver
//
//  Author:   Kirk Swenson
//
//  Copyright (c) 2014 by The Concord Consortium, Inc. All rights reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// ==========================================================================

/** @class

  Coordinating controller for the document.

  @extends SC.Object
*/

/*global CSV: true */

DG.DocumentArchiver = SC.Object.extend(
/** @scope DG.DocumentArchiver.prototype */ {

  /**
    Open the specified document text as a new document, returning the newly-created document.
   */
  openDocument: function( iStore, iDocText) {
    var docArchive = SC.json.decode( iDocText),
        dataSource = DG.ModelStore.create();

    DG.store = dataSource;
    return DG.Document.createDocument(docArchive);
  },

  importCSV: function (iText, iFileName) {

    // trims empty columns from right side of
    function trimTrailingColumns(arr) {
      var newArr = [];
      arr.forEach(function (row) {
        var value;
        if (Array.isArray(row)) {
          do {
            value = row.pop();
          } while(value === '');
          if (value) row.push(value);
        }
        if (row.length) {
          newArr.push(row);
        }
      });
      return newArr;
    }
    function parseText() {
      var tValuesArray,
        tCollectionRow,
        tChildName = 'children',// Child Collection Name: should be first
                                // line of CSV
        tAttrNamesRow,// Column Header Names: should be second row
        tDoc = {
          name: 'DG.Document.defaultDocumentName'.loc(),
          components: [],
          contexts: [
            {
              "type": "DG.DataContext",
              "collections": [
                {
                  "attrs": [],
                  "cases": []
                }
              ],
              "contextStorage": {
                "gameUrl": iFileName
              }
            }
          ],
          appName: DG.APPNAME,
          appVersion: DG.VERSION,
          appBuildNum: DG.BUILD_NUM,
          globalValues: []
        },
        tAttrsArray = tDoc.contexts[0].collections[0].attrs,
        tCasesArray = tDoc.contexts[0].collections[0].cases;

      CSV.RELAXED = true;
      CSV.IGNORE_RECORD_LENGTH = true;
      tValuesArray = CSV.parse(iText);
      if (tValuesArray && tValuesArray.length >= 2) {
        tValuesArray = trimTrailingColumns(tValuesArray);
        tCollectionRow = tValuesArray.shift();
        tAttrNamesRow = tValuesArray[0];

        if (Array.isArray(tCollectionRow)) {
          // check if it looks like name row is missing
          if ((tAttrNamesRow.length === tCollectionRow.length) && (tAttrNamesRow.length > 1)) {
            tAttrNamesRow = tCollectionRow;
          } else {
            tChildName = tCollectionRow[0];
            tValuesArray.shift();
          }
        }
        else {
          tChildName = tCollectionRow;
          tValuesArray.shift();
        }
        tDoc.contexts[0].collections[0].name = tChildName;

        tAttrNamesRow.forEach(function (iName) {
          tAttrsArray.push( {
            name: iName
          });
        });

        tValuesArray.forEach( function( iValues) {
          var tCase = {
            values: {}
          };
          tAttrNamesRow.forEach( function( iName, iIndex) {
            tCase.values[ iName] = iValues[ iIndex];
          });
          tCasesArray.push( tCase);
        });

        return tDoc;
      }
    } // parseText

    var docArchive = parseText( );
    return docArchive;
  },
  /**
   *
   * @param iText - csv or tab-delimited
   * @returns {DG.Document}
   */
  importTextIntoDocument: function( iText, iName) {
    var docArchive = this.importCSV(iText, iName);

    return DG.Document.createDocument(docArchive);
  },

  /**
   *
   * @param iURL - URL of data interactive
   * @returns {DG.Document}
   */
  importURLIntoDocument: function (iURL) {
    var tDoc = {
      name: 'DG.Document.defaultDocumentName'.loc(),
      components: [
        {
          "type": "DG.GameView",
          "componentStorage": {
            "currentGameName": "",
            "currentGameUrl": iURL,
            allowInitGameOverride: true
          }
        }
      ],
      contexts: [
      ],
      appName: DG.APPNAME,
      appVersion: DG.VERSION,
      appBuildNum: DG.BUILD_NUM,
      globalValues: []
    };

    return DG.Document.createDocument(tDoc);
  },

  /**
    Save the specified document in its JSON-text form.
    @param    {DG.Document}   iDocument   The document whose contents are to be archived

    signature of `callback`:
    @param  {Object} docArchive      An object suitable for JSON encoding
   */
  saveDocument: function( iDocument, callback) {

    // Prepare the context-specific storage for saving.
    // Start by saving the state of the current game in the appropriate context.
    // Callback below executes after the state has been saved
    DG.gameSelectionController.saveCurrentGameState(function() {
      var docController = DG.currDocumentController();
      DG.DataContext.forEachContextInMap( iDocument.get('id'),
                                          function( iContextID, iContext) {
                                            iContext.willSaveContext();
                                          });
      if( docController) {
        // Prepare the component-specific storage for saving
        DG.ObjectMap.forEach( docController.componentControllersMap,
                              function( iComponentID, iController) {
                                iController.willSaveComponent();
                              });
      }

      callback(iDocument.toArchive());
    });
  },

  saveDataContexts: function( iDocument, callback, saveAll) {
    var model,
        deferred = $.Deferred();
    DG.gameSelectionController.saveCurrentGameState(function() {
      DG.DataContext.forEachContextInMap( iDocument.get('id'),
                                          function( iContextID, iContext) {
                                            iContext.willSaveContext();
                                            model = iContext.get('model');
                                            if ( saveAll || !SC.none(model.get('externalDocumentId'))) {
                                              callback(model, model.toArchive(true));
                                            }
                                          });
      deferred.resolve();
    });
    return deferred;
  },

  /**
   * Copy the specified document case data in tab-delimited string form
   * @param	{String} iWhichCollection 'parent' or 'child' (TODO: allow 'both' for flatted collection with all attributes)
   * @param {DG.Document}	iDocument   The document whose contents are to be archived
   * @returns {String}	The export string
   */
  exportCaseData: function( iDocument, iWhichCollection ) {
    var caseDataString = '';

    DG.DataContext.forEachContextInMap( iDocument.get('id'),
      function( iContextID, iContext) {
        caseDataString += iContext.exportCaseData( iWhichCollection );
      });
    return caseDataString;
  }

});

<commit_msg>Extend document that wraps a Data Interactive to include an empty context.<commit_after>// ==========================================================================
//                        DG.DocumentArchiver
//
//  Author:   Kirk Swenson
//
//  Copyright (c) 2014 by The Concord Consortium, Inc. All rights reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// ==========================================================================

/** @class

  Coordinating controller for the document.

  @extends SC.Object
*/

/*global CSV: true */

DG.DocumentArchiver = SC.Object.extend(
/** @scope DG.DocumentArchiver.prototype */ {

  /**
    Open the specified document text as a new document, returning the newly-created document.
   */
  openDocument: function( iStore, iDocText) {
    var docArchive = SC.json.decode( iDocText),
        dataSource = DG.ModelStore.create();

    DG.store = dataSource;
    return DG.Document.createDocument(docArchive);
  },

  importCSV: function (iText, iFileName) {

    // trims empty columns from right side of
    function trimTrailingColumns(arr) {
      var newArr = [];
      arr.forEach(function (row) {
        var value;
        if (Array.isArray(row)) {
          do {
            value = row.pop();
          } while(value === '');
          if (value) row.push(value);
        }
        if (row.length) {
          newArr.push(row);
        }
      });
      return newArr;
    }
    function parseText() {
      var tValuesArray,
        tCollectionRow,
        tChildName = 'children',// Child Collection Name: should be first
                                // line of CSV
        tAttrNamesRow,// Column Header Names: should be second row
        tDoc = {
          name: 'DG.Document.defaultDocumentName'.loc(),
          components: [],
          contexts: [
            {
              "type": "DG.DataContext",
              "collections": [
                {
                  "attrs": [],
                  "cases": []
                }
              ],
              "contextStorage": {
                "gameUrl": iFileName
              }
            }
          ],
          appName: DG.APPNAME,
          appVersion: DG.VERSION,
          appBuildNum: DG.BUILD_NUM,
          globalValues: []
        },
        tAttrsArray = tDoc.contexts[0].collections[0].attrs,
        tCasesArray = tDoc.contexts[0].collections[0].cases;

      CSV.RELAXED = true;
      CSV.IGNORE_RECORD_LENGTH = true;
      tValuesArray = CSV.parse(iText);
      if (tValuesArray && tValuesArray.length >= 2) {
        tValuesArray = trimTrailingColumns(tValuesArray);
        tCollectionRow = tValuesArray.shift();
        tAttrNamesRow = tValuesArray[0];

        if (Array.isArray(tCollectionRow)) {
          // check if it looks like name row is missing
          if ((tAttrNamesRow.length === tCollectionRow.length) && (tAttrNamesRow.length > 1)) {
            tAttrNamesRow = tCollectionRow;
          } else {
            tChildName = tCollectionRow[0];
            tValuesArray.shift();
          }
        }
        else {
          tChildName = tCollectionRow;
          tValuesArray.shift();
        }
        tDoc.contexts[0].collections[0].name = tChildName;

        tAttrNamesRow.forEach(function (iName) {
          tAttrsArray.push( {
            name: iName
          });
        });

        tValuesArray.forEach( function( iValues) {
          var tCase = {
            values: {}
          };
          tAttrNamesRow.forEach( function( iName, iIndex) {
            tCase.values[ iName] = iValues[ iIndex];
          });
          tCasesArray.push( tCase);
        });

        return tDoc;
      }
    } // parseText

    var docArchive = parseText( );
    return docArchive;
  },
  /**
   *
   * @param iText - csv or tab-delimited
   * @returns {DG.Document}
   */
  importTextIntoDocument: function( iText, iName) {
    var docArchive = this.importCSV(iText, iName);

    return DG.Document.createDocument(docArchive);
  },

  /**
   *
   * @param iURL - URL of data interactive
   * @returns {DG.Document}
   */
  importURLIntoDocument: function (iURL) {
    var tDoc = {
      name: 'DG.Document.defaultDocumentName'.loc(),
      guid: 1,
      components: [
        {
          "type": "DG.GameView",
          "componentStorage": {
            "currentGameName": "",
            "currentGameUrl": iURL,
            allowInitGameOverride: true,
            "_links_": {
              "context": {
                "type": "DG.DataContextRecord",
                "id": 501
              }
            }
          }
        }
      ],
      contexts: [
        {
          type: 'DG.GameContext',
          guid: 501,
          contextStorage: {}
        }
      ],
      appName: DG.APPNAME,
      appVersion: DG.VERSION,
      appBuildNum: DG.BUILD_NUM,
      globalValues: []
    };

    return DG.Document.createDocument(tDoc);
  },

  /**
    Save the specified document in its JSON-text form.
    @param    {DG.Document}   iDocument   The document whose contents are to be archived

    signature of `callback`:
    @param  {Object} docArchive      An object suitable for JSON encoding
   */
  saveDocument: function( iDocument, callback) {

    // Prepare the context-specific storage for saving.
    // Start by saving the state of the current game in the appropriate context.
    // Callback below executes after the state has been saved
    DG.gameSelectionController.saveCurrentGameState(function() {
      var docController = DG.currDocumentController();
      DG.DataContext.forEachContextInMap( iDocument.get('id'),
                                          function( iContextID, iContext) {
                                            iContext.willSaveContext();
                                          });
      if( docController) {
        // Prepare the component-specific storage for saving
        DG.ObjectMap.forEach( docController.componentControllersMap,
                              function( iComponentID, iController) {
                                iController.willSaveComponent();
                              });
      }

      callback(iDocument.toArchive());
    });
  },

  saveDataContexts: function( iDocument, callback, saveAll) {
    var model,
        deferred = $.Deferred();
    DG.gameSelectionController.saveCurrentGameState(function() {
      DG.DataContext.forEachContextInMap( iDocument.get('id'),
                                          function( iContextID, iContext) {
                                            iContext.willSaveContext();
                                            model = iContext.get('model');
                                            if ( saveAll || !SC.none(model.get('externalDocumentId'))) {
                                              callback(model, model.toArchive(true));
                                            }
                                          });
      deferred.resolve();
    });
    return deferred;
  },

  /**
   * Copy the specified document case data in tab-delimited string form
   * @param	{String} iWhichCollection 'parent' or 'child' (TODO: allow 'both' for flatted collection with all attributes)
   * @param {DG.Document}	iDocument   The document whose contents are to be archived
   * @returns {String}	The export string
   */
  exportCaseData: function( iDocument, iWhichCollection ) {
    var caseDataString = '';

    DG.DataContext.forEachContextInMap( iDocument.get('id'),
      function( iContextID, iContext) {
        caseDataString += iContext.exportCaseData( iWhichCollection );
      });
    return caseDataString;
  }

});

<|endoftext|>


<commit_before>function GloballyPinnedTabs(tabs) {
    this.tabs = tabs;
    this.activeTab = tabs.filter(function(x) { return x.realTab && x.realTab.active; })[0];
}

GloballyPinnedTabs.create = function(serializedTabs) {
    serializedTabs = serializedTabs || [{
        startupUrl: 'https://www.toggl.com/app/timer'
    }, {
        startupUrl: 'https://www.beeminder.com/danielhilgarth'
    }];

    var result = new GloballyPinnedTabs(serializedTabs.map(function(x) {
        return new GloballyPinnedTab(x.startupUrl, x.currentUrl, x.favIconUrl, x.title);
    }));

    var onCloseCallback = function(pinnedTab) {
        result.onPinnedTabClosed(pinnedTab);
    };
    for (var i = 0; i < result.tabs.length; i++)
        result.tabs[i].onCloseCallback = onCloseCallback;

    return result;
};

GloballyPinnedTabs.prototype = {
    serialize: function() {
        return this.tabs.map(GloballyPinnedTab.serialize);
    },

    addTab: function(tab) {
        var self = this;
        var newTab = new GloballyPinnedTab(tab.url, tab.url, tab.favIconUrl, tab.title, function(pinnedTab) {
            self.onPinnedTabClosed(pinnedTab);
        });
        this.tabs.push(newTab);
        Storage.persistData();
        Chrome.getAllWindows(function(windows) { newTab.createTabs(windows); });
    },

    createTabs: function(windows) {
        for (var i = 0; i < this.tabs.length; i++)
            this.tabs[i].createTabs(windows);
    },

    findTab: function(url) {
        return this.tabs.filter(function(x) { return x.startupUrl === url; })[0];
    },

    activateWindow: function(window, callback) {
        if(this.tabs.length === 0) {
            callback();
            return;
        }

        var oldWindowId;
        if(this.tabs[0].realTab)
            oldWindowId = this.tabs[0].realTab.windowId;

        if(oldWindowId === window.id) {
            callback();
            return;
        }

        if(oldWindowId !== undefined)
            this.moveTabs(window, oldWindowId, callback);
        else
            this.recreateTabs(window, callback);
    },

    recreateTabs: function(targetWindow, callback) {
        var dummyTabs = this.getDummyTabsForWindow(targetWindow, false);
        var dummyTabIds = dummyTabs.map(function(x) { return x.id; });
        chrome.tabs.remove(dummyTabIds);
        for (var i = 0; i < this.tabs.length; i++)
            this.tabs[i].createRealTab(targetWindow, callback, true);
    },

    getDummyTabsForWindow: function(window) {
        var result = {
            foundTabs: [],
            missingTabs: []
        };
        for (var i = 0; i < this.tabs.length; i++) {
            var tab = this.tabs[i];
            var dummyTab = tab.dummyTabs[window.id];
            if(!dummyTab)
                result.missingTabs.push(tab);
            else
                result.foundTabs.push(dummyTab);
        }

        return result;
    },

    moveTabs: function(targetWindow, sourceWindowId, callback) {

        var dummyTabs = this.getDummyTabsForWindow(targetWindow);
        var dummyTabIds = [];
        var smallestDummyTabsIndex = 10000;
        var i;
        var tab;
        var tabToActivate;
        for (i = 0; i < dummyTabs.foundTabs.length; i++) {
            tab = dummyTabs.foundTabs[i];
            dummyTabIds.push(tab.id);
            smallestDummyTabsIndex = Math.min(smallestDummyTabsIndex, tab.index);
            if(tab.active) {
                var startupUrl = QueryParameters.getQueryParameters(QueryParameters.getQueryString(tab.url)).startupUrl;
                tabToActivate = this.findTab(startupUrl);
            }
        }

        var realTabIds = [];
        var smallestRealTabsIndex = 10000;
        for (i = 0; i < this.tabs.length; i++) {
            tab = this.tabs[i];
            realTabIds.push(tab.realTab.id);
            smallestRealTabsIndex = Math.min(smallestRealTabsIndex, tab.realTab.index);
        }

        var finished = 0;
        var total = realTabIds.length + dummyTabs.foundTabs.length + dummyTabs.missingTabs.length;
        var self = this;

        var callCallback = function() {
            finished++;
            if(finished === total) {
                if(tabToActivate)
                    tabToActivate.activate(callback);
                else
                    callback();
            }
        };

        Chrome.moveTabs(realTabIds, targetWindow.id, smallestRealTabsIndex, function(tabs) {
            for (var i = 0; i < tabs.length; ++i) {
                self.tabs[i].realTab = tabs[i];
                Chrome.pinTab(tabs[i].id, callCallback);
            }
        });

        if(dummyTabIds.length) {
            Chrome.moveTabs(dummyTabIds, sourceWindowId, smallestDummyTabsIndex, function (tabs) {
                for (var i = 0; i < tabs.length; ++i) {
                    delete self.tabs[i].dummyTabs[targetWindow.id];
                    self.tabs[i].dummyTabs[sourceWindowId] = tabs[i];
                    Chrome.pinTab(tabs[i].id, callCallback);
                }
            });
        }

        if(dummyTabs.missingTabs.length) {
            Chrome.getWindow(sourceWindowId, function (window) {
                for (i = 0; i < dummyTabs.missingTabs.length; i++) {
                    dummyTabs.missingTabs[i].createTabForWindow(window, callCallback);
                }
            });
        }
    },

    updateTab: function(tab) {
        var pinnedTab = this.getTabForIdOfRealTab(tab.id);
        if(pinnedTab) {
            if(pinnedTab.updateRealTab(tab))
                Storage.persistData();
        } else {
            pinnedTab = this.getTabForAnyTabId(tab.id);
            if(pinnedTab)
                pinnedTab.updateDummyTab(tab);
        }
    },

    getTabForIdOfRealTab: function(realTabId) {
        return this.tabs.filter(function(x) { return x.realTab && (x.realTab.id === realTabId); })[0];
    },

    getTabForAnyTabId: function(tabId) {
        return this.tabs.filter(function(x) {
            if (x.realTab && (x.realTab.id === tabId))
                return true;
            for (var key in x.dummyTabs) {
                if (x.dummyTabs[key].id === tabId) {
                    return true;
                }
            }
        })[0];
    },

    handleClosedTab: function(tabId) {
        var tab = this.getTabForAnyTabId(tabId);
        if (tab) {
            if (tab.realTab && (tab.realTab.id === tabId))
                tab.realTab = undefined;
            else {
                for (var key in tab.dummyTabs) {
                    if (tab.dummyTabs[key].id === tabId) {
                        delete tab.dummyTabs[key];
                        break;
                    }
                }
            }
            tab.close();
        }
    },

    handleClosedWindow: function(windowId) {
        for (var i = 0; i < this.tabs.length; i++)
            this.tabs[i].handleClosedWindow(windowId);
    },

    onPinnedTabClosed: function(pinnedTab) {
        this.tabs.remove(pinnedTab);
        console.log(this.tabs);
        Storage.persistData();
    }
};<commit_msg>Fix issue: Window closes when the pinned tabs are the only tabs left in the window.<commit_after>function GloballyPinnedTabs(tabs) {
    this.tabs = tabs;
    this.activeTab = tabs.filter(function(x) { return x.realTab && x.realTab.active; })[0];
}

GloballyPinnedTabs.create = function(serializedTabs) {
    serializedTabs = serializedTabs || [{
        startupUrl: 'https://www.toggl.com/app/timer'
    }, {
        startupUrl: 'https://www.beeminder.com/danielhilgarth'
    }];

    var result = new GloballyPinnedTabs(serializedTabs.map(function(x) {
        return new GloballyPinnedTab(x.startupUrl, x.currentUrl, x.favIconUrl, x.title);
    }));

    var onCloseCallback = function(pinnedTab) {
        result.onPinnedTabClosed(pinnedTab);
    };
    for (var i = 0; i < result.tabs.length; i++)
        result.tabs[i].onCloseCallback = onCloseCallback;

    return result;
};

GloballyPinnedTabs.prototype = {
    serialize: function() {
        return this.tabs.map(GloballyPinnedTab.serialize);
    },

    addTab: function(tab) {
        var self = this;
        var newTab = new GloballyPinnedTab(tab.url, tab.url, tab.favIconUrl, tab.title, function(pinnedTab) {
            self.onPinnedTabClosed(pinnedTab);
        });
        this.tabs.push(newTab);
        Storage.persistData();
        Chrome.getAllWindows(function(windows) { newTab.createTabs(windows); });
    },

    createTabs: function(windows) {
        for (var i = 0; i < this.tabs.length; i++)
            this.tabs[i].createTabs(windows);
    },

    findTab: function(url) {
        return this.tabs.filter(function(x) { return x.startupUrl === url; })[0];
    },

    activateWindow: function(window, callback) {
        if(this.tabs.length === 0) {
            callback();
            return;
        }

        var oldWindowId;
        if(this.tabs[0].realTab)
            oldWindowId = this.tabs[0].realTab.windowId;

        if(oldWindowId === window.id) {
            callback();
            return;
        }

        if(oldWindowId !== undefined) {
            var self = this;
            Chrome.getWindow(oldWindowId, function (oldWindow) {
                self.moveTabs(window, oldWindow, callback);
            });
        }
        else
            this.recreateTabs(window, callback);
    },

    recreateTabs: function(targetWindow, callback) {
        var dummyTabs = this.getDummyTabsForWindow(targetWindow, false);
        var dummyTabIds = dummyTabs.map(function(x) { return x.id; });
        chrome.tabs.remove(dummyTabIds);
        for (var i = 0; i < this.tabs.length; i++)
            this.tabs[i].createRealTab(targetWindow, callback, true); // Bug (callback)
    },

    getDummyTabsForWindow: function(window) {
        var result = {
            foundTabs: [],
            missingTabs: []
        };
        for (var i = 0; i < this.tabs.length; i++) {
            var tab = this.tabs[i];
            var dummyTab = tab.dummyTabs[window.id];
            if(!dummyTab)
                result.missingTabs.push(tab);
            else
                result.foundTabs.push(dummyTab);
        }

        return result;
    },

    moveTabs: function(targetWindow, sourceWindow, callback) {

        var dummyTabs = this.getDummyTabsForWindow(targetWindow);
        var dummyTabIds = [];
        var smallestDummyTabsIndex = 10000;
        var i;
        var tab;
        var tabToActivate;
        for (i = 0; i < dummyTabs.foundTabs.length; i++) {
            tab = dummyTabs.foundTabs[i];
            dummyTabIds.push(tab.id);
            smallestDummyTabsIndex = Math.min(smallestDummyTabsIndex, tab.index);
            if(tab.active) {
                var startupUrl = QueryParameters.getQueryParameters(QueryParameters.getQueryString(tab.url)).startupUrl;
                tabToActivate = this.findTab(startupUrl);
            }
        }

        var realTabIds = [];
        var smallestRealTabsIndex = 10000;
        for (i = 0; i < this.tabs.length; i++) {
            tab = this.tabs[i];
            realTabIds.push(tab.realTab.id);
            smallestRealTabsIndex = Math.min(smallestRealTabsIndex, tab.realTab.index);
        }

        var finished = 0;
        var total = realTabIds.length + dummyTabs.foundTabs.length + dummyTabs.missingTabs.length;
        var self = this;

        var temporaryTabIds = [];

        var callCallback = function() {
            finished++;
            if(finished === total) {
                if(temporaryTabIds.length) {
                    chrome.tabs.remove(temporaryTabIds, function () {
                        if(tabToActivate)
                            tabToActivate.activate(callback);
                        else
                            callback();
                    });
                }
                if(tabToActivate)
                    tabToActivate.activate(callback);
                else
                    callback();
            }
        };

        var performMove = function() {
            Chrome.moveTabs(realTabIds, targetWindow.id, smallestRealTabsIndex, function(tabs) {
                for (var i = 0; i < tabs.length; ++i) {
                    self.tabs[i].realTab = tabs[i];
                    Chrome.pinTab(tabs[i].id, callCallback);
                }
            });

            if(dummyTabIds.length) {
                Chrome.moveTabs(dummyTabIds, sourceWindow.id, smallestDummyTabsIndex, function (tabs) {
                    for (var i = 0; i < tabs.length; ++i) {
                        delete self.tabs[i].dummyTabs[targetWindow.id];
                        self.tabs[i].dummyTabs[sourceWindow.id] = tabs[i];
                        Chrome.pinTab(tabs[i].id, callCallback);
                    }
                });
            }

            if(dummyTabs.missingTabs.length) {
                for (i = 0; i < dummyTabs.missingTabs.length; i++) {
                    dummyTabs.missingTabs[i].createTabForWindow(sourceWindow, callCallback);
                }
            }
        };

        var createPinnedTabInTargetWindow = function() {
            if(targetWindow.tabs.length === self.tabs.length) {
                Chrome.createPinnedTab(targetWindow, 'about:blank', function (tab) {
                    temporaryTabIds.push(tab.id);
                    performMove();
                });
            }
            else
                performMove();
        };

        if(sourceWindow.tabs.length === this.tabs.length) {
            Chrome.createPinnedTab(sourceWindow, 'about:blank', function(tab) {
                temporaryTabIds.push(tab.id);
                createPinnedTabInTargetWindow();
             });
        } else {
            createPinnedTabInTargetWindow();
        }
    },

    updateTab: function(tab) {
        var pinnedTab = this.getTabForIdOfRealTab(tab.id);
        if(pinnedTab) {
            if(pinnedTab.updateRealTab(tab))
                Storage.persistData();
        } else {
            pinnedTab = this.getTabForAnyTabId(tab.id);
            if(pinnedTab)
                pinnedTab.updateDummyTab(tab);
        }
    },

    getTabForIdOfRealTab: function(realTabId) {
        return this.tabs.filter(function(x) { return x.realTab && (x.realTab.id === realTabId); })[0];
    },

    getTabForAnyTabId: function(tabId) {
        return this.tabs.filter(function(x) {
            if (x.realTab && (x.realTab.id === tabId))
                return true;
            for (var key in x.dummyTabs) {
                if (x.dummyTabs[key].id === tabId) {
                    return true;
                }
            }
        })[0];
    },

    handleClosedTab: function(tabId) {
        var tab = this.getTabForAnyTabId(tabId);
        if (tab) {
            if (tab.realTab && (tab.realTab.id === tabId))
                tab.realTab = undefined;
            else {
                for (var key in tab.dummyTabs) {
                    if (tab.dummyTabs[key].id === tabId) {
                        delete tab.dummyTabs[key];
                        break;
                    }
                }
            }
            tab.close();
        }
    },

    handleClosedWindow: function(windowId) {
        for (var i = 0; i < this.tabs.length; i++)
            this.tabs[i].handleClosedWindow(windowId);
    },

    onPinnedTabClosed: function(pinnedTab) {
        this.tabs.remove(pinnedTab);
        console.log(this.tabs);
        Storage.persistData();
    }
};<|endoftext|>


<commit_before>/*======================================================
************   App Init   ************
======================================================*/
app.init = function () {
    // Compile Template7 templates on app load
    if (app.initTemplate7Templates) app.initTemplate7Templates();

    // Init Plugins
    if (app.initPlugins) app.initPlugins();

    // Init Device
    if (app.getDeviceInfo) app.getDeviceInfo();

    // Init Click events
    if (app.initFastClicks && app.params.fastClicks) app.initFastClicks();
    if (app.initClickEvents) app.initClickEvents();

    // Init each page callbacks
    $('.page:not(.cached)').each(function () {
        app.initPageWithCallback(this);
    });

    // Init each navbar callbacks
    $('.navbar:not(.cached)').each(function () {
        app.initNavbarWithCallback(this);
    });

    // Init resize events
    if (app.initResize) app.initResize();

    // Init push state
    if (app.initPushState && app.params.pushState) app.initPushState();

    // Init Live Swipeouts events
    if (app.initSwipeout && app.params.swipeout) app.initSwipeout();

    // Init Live Sortable events
    if (app.initSortable && app.params.sortable) app.initSortable();

    // Init Live Swipe Panels
    if (app.initSwipePanels && (app.params.swipePanel || app.params.swipePanelOnlyClose)) app.initSwipePanels();

    // Init Panels Breakpoints
    if (app.initPanelsBreakpoints && (app.params.panelLeftBreakpoint || app.params.panelRightBreakpoint)) app.initPanelsBreakpoints();

    // Init Material Inputs
    if (app.params.material && app.initMaterialWatchInputs) app.initMaterialWatchInputs();

    // Init Material Tabbar
    if (app.params.material) {
        $('.tabbar').each(function (index, el) {
            if ($(el).parents('.page').length === 0) {
                app.initMaterialTabbar(el);
            }
        });
    }

    // App Init callback
    if (app.params.onAppInit) app.params.onAppInit();

    // Plugin app init hook
    app.pluginHook('appInit');
};
if (app.params.init) app.init();
<commit_msg>Init panels before pages<commit_after>/*======================================================
************   App Init   ************
======================================================*/
app.init = function () {
    // Compile Template7 templates on app load
    if (app.initTemplate7Templates) app.initTemplate7Templates();

    // Init Plugins
    if (app.initPlugins) app.initPlugins();

    // Init Device
    if (app.getDeviceInfo) app.getDeviceInfo();

    // Init Panels Breakpoints
    if (app.initPanelsBreakpoints && (app.params.panelLeftBreakpoint || app.params.panelRightBreakpoint)) app.initPanelsBreakpoints();

    // Init Click events
    if (app.initFastClicks && app.params.fastClicks) app.initFastClicks();
    if (app.initClickEvents) app.initClickEvents();

    // Init each page callbacks
    $('.page:not(.cached)').each(function () {
        app.initPageWithCallback(this);
    });

    // Init each navbar callbacks
    $('.navbar:not(.cached)').each(function () {
        app.initNavbarWithCallback(this);
    });

    // Init resize events
    if (app.initResize) app.initResize();

    // Init push state
    if (app.initPushState && app.params.pushState) app.initPushState();

    // Init Live Swipeouts events
    if (app.initSwipeout && app.params.swipeout) app.initSwipeout();

    // Init Live Sortable events
    if (app.initSortable && app.params.sortable) app.initSortable();

    // Init Live Swipe Panels
    if (app.initSwipePanels && (app.params.swipePanel || app.params.swipePanelOnlyClose)) app.initSwipePanels();

    // Init Material Inputs
    if (app.params.material && app.initMaterialWatchInputs) app.initMaterialWatchInputs();

    // Init Material Tabbar
    if (app.params.material) {
        $('.tabbar').each(function (index, el) {
            if ($(el).parents('.page').length === 0) {
                app.initMaterialTabbar(el);
            }
        });
    }

    // App Init callback
    if (app.params.onAppInit) app.params.onAppInit();

    // Plugin app init hook
    app.pluginHook('appInit');
};
if (app.params.init) app.init();
<|endoftext|>


<commit_before>/**
 * Handlebars helpers ready to be used both on client&server side
 * @src http://www.codyrushing.com/using-handlebars-helpers-on-both-client-and-server/
 */
var register = function (Handlebars, isClient) {

    var helpers = {

        /**
         * Print how long time ago an input date is from/until now or a given input date
         * @param {string} date to check against
         * @param {boolean}
         *
         * Usage example
         * {{ago "01/02/03" format="DD/MM/YY" checkDate="01/02/04"}}
         * where `format` and `checkDate` are optional parameters
         */
        ago: function (date, options) {

            //the format of the input date variable, with date.month.year as standard
            var inputFormat = (options.hash !== undefined && options.hash.format !== undefined) ? options.hash.format : "DD.MM.YYYY";

            //date to check input date against
            var checkDate = null;

            //check if a checkDate is set..
            if (options.hash !== undefined && options.hash.checkDate !== undefined)
                checkDate = moment(options.hash.checkDate, inputFormat); //use input date to compare against input date
            else
                checkDate = moment(); //.. or use today as compare date

            var output = moment(date, inputFormat);

            return output.from(checkDate);
        },

        /**
         * Retrieve a date string on the given output format
         * @param {string} date string to format
         * @param {string} outputFormat the format which the output date should be converted to
         * @returns {string} output string
         *
         * Usage example
         * {{dateFormat "01/02/03" "DD.MM.YYYY" format="DD/MM/YY"}}
         * where `format` is an optional parameter
         */
        dateFormat: function (date, outputFormat, options) {

            //the format of the input date variable, with date.month.year as standard
            var inputFormat = (options.hash !== undefined && options.hash.format !== undefined) ? options.hash.format : "DD.MM.YYYY";
            var output = moment(date, inputFormat);

            return output.format(outputFormat);
        },

        /**
         * Retrieve a url for a header image
         * @param {string} img name of picture to return path to
         * @returns {string} uri for header image
         *
         *  Usage example
         * {{headerImg image}}
         * where `image` is a image residing in the given
         * path defined in config.path.featureImg
         */
        headerImg: function (img, options) {
            var size = (options.hash !== undefined && options.hash.size !== undefined) ? options.hash.size : "";

            return config.path.baseurl + config.path.featureImg + "/" + img + size + ".jpg";
        },

        /**
         * Get the first enabled item of a list..
         * @param items An array of items.
         * @return A subset of items.
         * @src http://webercoder.com/journal/2015/05/12/building-an-assembleio-blog-part-2.html
         */
        getLatestEntries: function (items, sortBy, limit, options) {
            var rv = "";
            var count = 0;

            //the format of the input date variable, with date.month.year as standard
            var inputFormat = (options.hash !== undefined && options.hash.format !== undefined) ? options.hash.format : "DD.MM.YYYY";

            // Sort items by date
            var sortedItems = items.sort(function (a, b) {
                var momentA = moment(a[sortBy], inputFormat);
                var momentB = moment(b[sortBy], inputFormat);
                return momentB.diff(momentA);
            });

            if (!limit) {
                limit = 10;
            }
            // Pull out the most recent
            for (var i = 0; i < sortedItems.length && count++ < limit; i++) {
                if ("exclude" in sortedItems[i] && sortedItems[i].exclude === true) {
                    continue;
                }
                rv += options.fn(sortedItems[i]);
            }

            return rv;
        },

        /**
         * Retrieve a uri link to a post given its category and basename
         * @param {string} category which the post resides in
         * @param {string} basename if the file to link to
         * @returns {string} link to post
         *
         *  Usage example
         * {{link programming hello-world}}
         */
        link: function (category, basename, options) {
            return config.path.baseurl + "/posts/" + category + "/" + basename + ".html";
        },

        /**
         *
         */
        categoryList: function (pages, options) {
            if (isClient === true)
                return;

            var obj = {};
            var validImageExts = [".png", ".jpg", ".jpeg"];//valid pictures to be used with categories

            pages.forEach(function (page, index) {
                var value = page.category;
                if (value !== undefined && obj[value] === undefined) {
                    var image = config.path.baseurl + config.path.img + "/categories/_default.png";//TODO: insert default category picture

                    validImageExts.forEach(function (ext, index) {
                        try {
                            var filename = config.path.img + "/categories/" + value + ext;
                            var file = fs.statSync("./dist" + filename);

                            if (file.isFile())
                                image = config.path.baseurl + filename;
                        }
                        catch (e) {/*couldn't find picture, continue search or us defaukt*/ }
                    });

                    obj[value] = { category: value, link: config.path.baseurl + value, image: image }
                }
            });

            return obj;
        },

        /**
         * Generates a text-cloud on all categories. The input should be
         * a collection of pages which has a category attribute. Each
         * category is counted and stored into an object, which is
         * later used for generating the npm text-cloud.
         * @param {array} pages the pages to retrieve category from
         * @returns {string} generated html code of tag cloud
         *
         * Usage example
         * {{{categoryCloud posts}}}
         * Note: need three brackets to output html successfully
         */
        categoryCloud: function (pages, options) {
            if (isClient === true)
                return;

            var obj = {};
            var total = 0;

            pages.forEach(function (page, index) {

                var value = page.category;

                if (value !== undefined) {
                    ++total;
                    if (obj[value] === undefined)
                        obj[value] = 1;
                    else
                        obj[value]++;
                }
            });

            var words = [];

            for (var key in obj) {
                if (obj.hasOwnProperty(key)) {

                    words.push({
                        tagName: key,
                        count: obj[key],
                        //weight: (10 / (100 / ((obj[key] / total) * 100))),
                        href: "http://vg.no"
                    });

                }
            }
            var html = null;
            tagCloud.tagCloud(words, function (err, data) {
                html = data;
            }, {
                    additionalAttributes: {
                        href: 'http://google.com?q={{tag}}'
                    },
                    htmlTag: 'a',
                    randomize: true
                });

            return html;
        },

        /**
         * Generates a text-cloud on all categories. The input should be
         * a collection of pages which has a category attribute. Each
         * category is counted and stored into an object, which is
         * later used for generating the npm text-cloud.
         * @param {array} pages the pages to retrieve category from
         * @returns {string} generated html code of tag cloud
         *
         * Usage example
         * {{{categoryCloud posts}}}
         * Note: need three brackets to output html successfully
         */
        tagCloud: function (pages, options) {
            if (isClient === true)
                return;

            var obj = {};
            var total = 0;

            //retrieve all tags from each page to create an object
            //with a count for each tag occurent
            pages.forEach(function (page, i) {

                var tags = page.tags;
                console.log(tags);

                tags.forEach(function (tag, j) {
                    ++total;
                    if (obj[tag] === undefined)
                        obj[tag] = 1;
                    else
                        obj[tag]++;
                });
            });
            console.log(obj);

            var tags = [];
            for (var tag in obj) {
                if (obj.hasOwnProperty(tag)) {
                    tags.push({
                        tagName: tag,
                        count: obj[tag],
                        href: "http://jonastn.com"
                    });
                }
            }

            console.log(tags);

            var html = null;
            tagCloud.tagCloud(tags, function (error, data) {
                html = data;
            }, {
                    additionalAttributes: {
                        href: config.path.baseurl + "tags/{{tag}}"
                    },
                    htmlTag: 'a',
                    randomize: true,
                    classPrefix: "tag"
                });

            return html;
        }

    };

    if (Handlebars && typeof Handlebars.registerHelper === "function") {
        // register helpers
        for (var prop in helpers) {
            Handlebars.registerHelper(prop, helpers[prop]);
        }
    } else {
        // just return helpers object if we can't register helpers here
        return helpers;
    }

};

// client
if (typeof window !== "undefined") {
    var config = Data.config;
    register(Handlebars, true);
}
// server
else {
    var moment = require("moment");
    var fs = require('fs');
    var config = require("../../../config.json");
    var tagCloud = require('tag-cloud');
    module.exports.register = register;
    module.exports.helpers = register(null, false);
}<commit_msg>feat: category list<commit_after>/**
 * Handlebars helpers ready to be used both on client&server side
 * @src http://www.codyrushing.com/using-handlebars-helpers-on-both-client-and-server/
 */
var register = function (Handlebars, isClient) {

    var helpers = {

        /**
         * Print how long time ago an input date is from/until now or a given input date
         * @param {string} date to check against
         * @param {boolean}
         *
         * Usage example
         * {{ago "01/02/03" format="DD/MM/YY" checkDate="01/02/04"}}
         * where `format` and `checkDate` are optional parameters
         */
        ago: function (date, options) {

            //the format of the input date variable, with date.month.year as standard
            var inputFormat = (options.hash !== undefined && options.hash.format !== undefined) ? options.hash.format : "DD.MM.YYYY";

            //date to check input date against
            var checkDate = null;

            //check if a checkDate is set..
            if (options.hash !== undefined && options.hash.checkDate !== undefined)
                checkDate = moment(options.hash.checkDate, inputFormat); //use input date to compare against input date
            else
                checkDate = moment(); //.. or use today as compare date

            var output = moment(date, inputFormat);

            return output.from(checkDate);
        },

        /**
         * Retrieve a date string on the given output format
         * @param {string} date string to format
         * @param {string} outputFormat the format which the output date should be converted to
         * @returns {string} output string
         *
         * Usage example
         * {{dateFormat "01/02/03" "DD.MM.YYYY" format="DD/MM/YY"}}
         * where `format` is an optional parameter
         */
        dateFormat: function (date, outputFormat, options) {

            //the format of the input date variable, with date.month.year as standard
            var inputFormat = (options.hash !== undefined && options.hash.format !== undefined) ? options.hash.format : "DD.MM.YYYY";
            var output = moment(date, inputFormat);

            return output.format(outputFormat);
        },

        /**
         * Retrieve a url for a header image
         * @param {string} img name of picture to return path to
         * @returns {string} uri for header image
         *
         *  Usage example
         * {{headerImg image}}
         * where `image` is a image residing in the given
         * path defined in config.path.featureImg
         */
        headerImg: function (img, options) {
            var size = (options.hash !== undefined && options.hash.size !== undefined) ? options.hash.size : "";

            return config.path.baseurl + config.path.featureImg + "/" + img + size + ".jpg";
        },

        /**
         * Get the first enabled item of a list..
         * @param items An array of items.
         * @return A subset of items.
         * @src http://webercoder.com/journal/2015/05/12/building-an-assembleio-blog-part-2.html
         */
        getLatestEntries: function (items, sortBy, limit, options) {
            var rv = "";
            var count = 0;

            //the format of the input date variable, with date.month.year as standard
            var inputFormat = (options.hash !== undefined && options.hash.format !== undefined) ? options.hash.format : "DD.MM.YYYY";

            // Sort items by date
            var sortedItems = items.sort(function (a, b) {
                var momentA = moment(a[sortBy], inputFormat);
                var momentB = moment(b[sortBy], inputFormat);
                return momentB.diff(momentA);
            });

            if (!limit) {
                limit = 10;
            }
            // Pull out the most recent
            for (var i = 0; i < sortedItems.length && count++ < limit; i++) {
                if ("exclude" in sortedItems[i] && sortedItems[i].exclude === true) {
                    continue;
                }
                rv += options.fn(sortedItems[i]);
            }

            return rv;
        },

        /**
         * Retrieve a uri link to a post given its category and basename
         * @param {string} category which the post resides in
         * @param {string} basename if the file to link to
         * @returns {string} link to post
         *
         *  Usage example
         * {{link programming hello-world}}
         */
        link: function (category, basename, options) {
            return config.path.baseurl + "/posts/" + category + "/" + basename + ".html";
        },

    /**
      * Generates a list of all categories. The input should be
      * a collection of pages which has a category attribute. Each
      * category is stored into an object, which is
      * later used for creating list information fore ach category,
      including its href, image and title
      * @param {array} pages the pages to retrieve category from
      * @returns {arrat} generated list of categories
      *
      * Usage example
      * {{{categoryList posts}}}
      * Note: wrap inside '(' ')' to loop through each element in handlebars
      */
        categoryList: function (pages, options) {
            if (isClient === true)
                return;

            var obj = {};
            var validImageExts = [".png", ".jpg", ".jpeg"];//valid pictures to be used with categories

            pages.forEach(function (page, index) {
                var value = page.category;
                if (value !== undefined && obj[value] === undefined) {
                    var image = config.path.baseurl + config.path.img + "/categories/_default.png";//TODO: insert default category picture

                    validImageExts.forEach(function (ext, index) {
                        try {
                            var filename = config.path.img + "/categories/" + value + ext;
                            var file = fs.statSync("./dist" + filename);

                            if (file.isFile())
                                image = config.path.baseurl + filename;
                        }
                        catch (e) {/*couldn't find picture, continue search or us defaukt*/ }
                    });
                    //TODO: change link when functionality for category filter is supported
                    obj[value] = { category: value, categoryLink: "#"/*config.path.baseurl + "/"+value*/, image: image }
                }
            });

            return obj;
        },

        /**
         * Generates a text-cloud on all categories. The input should be
         * a collection of pages which has a category attribute. Each
         * category is counted and stored into an object, which is
         * later used for generating the npm text-cloud.
         * @param {array} pages the pages to retrieve category from
         * @returns {string} generated html code of tag cloud
         *
         * Usage example
         * {{{categoryCloud posts}}}
         * Note: need three brackets to output html successfully
         */
        tagCloud: function (pages, options) {
            if (isClient === true)
                return;

            var obj = {};
            var total = 0;

            //retrieve all tags from each page to create an object
            //with a count for each tag occurent
            pages.forEach(function (page, i) {

                var tags = page.tags;
                console.log(tags);

                tags.forEach(function (tag, j) {
                    ++total;
                    if (obj[tag] === undefined)
                        obj[tag] = 1;
                    else
                        obj[tag]++;
                });
            });
            console.log(obj);

            var tags = [];
            for (var tag in obj) {
                if (obj.hasOwnProperty(tag)) {
                    tags.push({
                        tagName: tag,
                        count: obj[tag]
                        //TODO: see below for explanation why this is removed
                        //href: "http://jonastn.com"
                    });
                }
            }

            console.log(tags);

            var html = null;
            tagCloud.tagCloud(tags, function (error, data) {
                html = data;
            }, {
                    /*TODO: provide href to tags when functionality for tag filtering is supported
                        additionalAttributes: {
                            href: config.path.baseurl + "tags/{{tag}}"
                        },*/
                    htmlTag: 'a',
                    randomize: true,
                    classPrefix: "tag"
                });

            return html;
        }

    };

    if (Handlebars && typeof Handlebars.registerHelper === "function") {
        // register helpers
        for (var prop in helpers) {
            Handlebars.registerHelper(prop, helpers[prop]);
        }
    } else {
        // just return helpers object if we can't register helpers here
        return helpers;
    }

};

// client
if (typeof window !== "undefined") {
    var config = Data.config;
    register(Handlebars, true);
}
// server
else {
    var moment = require("moment");
    var fs = require('fs');
    var config = require("../../../config.json");
    var tagCloud = require('tag-cloud');
    module.exports.register = register;
    module.exports.helpers = register(null, false);
}<|endoftext|>


<commit_before>$(document).ready(function() {
  // This is called after the document has loaded in its entirety
  // This guarantees that any elements we bind to will exist on the page
  // when we try to bind to them

  // See: http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
});
<commit_msg>started the ajax request, prevented default and starting to work with data<commit_after>$(document).ready(function() {

  $('#new_survey_form').on('click', function(event){
    event.preventDefault();
    var method = this.attr('method');
    var target_url = this.attr('action');
    var form_data = this.target.serialize();
    $.ajax({
      type: method,
      url: target_url,
      data: form_data
    }).done(function(response){

    }).fail(function(deffered){

    })
  })

});
<|endoftext|>


<commit_before>$(document).ready(function() {
  // console.log("document ready");

  createGame();
  loadEventListener(); // for button to reload the game
});

var currentTurn = "X"; // where X is always human player, and O is always AI
var blankCells = 9;
var game; // 3x3 array
var gameClone; //for AI to explore possibilities on
var currentTurnInPossibilities; //declare AI / "O" as default later?

function reloadGame() {
  currentTurn = "X";
  blankCells = 9;
  clearTable();
  createGame();
}

// initialize game with empty 3x3 board
function createGame() {
  game = new Array(3);
  for (var i = 0; i < game.length; i++) {
    game[i] = new Array(3);
    for (var j = 0; j < game[i].length; j++) {
      game[i][j] = "";
    }
  }
}

function clearTable() {
  $("td").empty();
}

function loadEventListener() {
  $("#reload").click(function() {
    reloadGame();
    $(".dynamic_text").html('
Start whenever you\'re ready
');
    $(".check").html("");
  });
}

function switchTurn() {
  if (currentTurn === "X") {
    currentTurn = "O";
  } else {
    currentTurn = "X";
  }
}

// accessed from onclick attribute in view.html
function humansMove(id,row,column) {
  // debugger;
  if (blankCells === 9) {
    $(".start_text").fadeOut("slow");
  }

  // if cell is already occupied, the move is invalid
  var content = $("#"+id).text();
  if (content.length > 0) {
    $(".dynamic_text").html("
Invalid move
");
    return;
  }
  $("#"+id).addClass("x").html("X");

  // populate 2d game array with corresponding tile
  game[row][column] = "X";

  // decrement number of blank cells
  blankCells -= 1;
  console.log("blank cells left - " + blankCells); //check if blank cells decrementing

  var result = checkForWinner(game);
  if (result !== "continue") {
    endTheGame(result);
  }
  switchTurn();
  // console.log("the current turn - " + currentTurn);
  aiMove(); //undefined still
  result = checkForWinner(game);
  if (result !== "continue") {
    endTheGame(result);
  }
}

function aiMove() {
  // debugger;
  // console.log("ai move");
  // return if it's not the ai's turn -- maybe get rid of this later
  // console.log("current turn - letter " + currentTurn)
  if (currentTurn !== "O") {
    return;
  }
  // return if there are no turns left / no blank cells available
  if (blankCells === 0) {
    return;
  }
  // debugger;
  createGameClone();
  currentTurnInPossibilities = "O";
  var possibleResult, row, col, choice = -1000;
  // for each blank cell, plop in "O"
  // debugger;
  for (var i = 0; i < gameClone.length; i++) {
    for (var j = 0; j < gameClone[i].length; j++) {
      if (gameClone[i][j] === "") {
        // debugger;
        gameClone[i][j] = currentTurnInPossibilities;
        // console.log("gameClone[i][j]" + "[" +i+ "][" +j+ "] tile - " + gameClone[i][j]);
        // console.log("game[i][j] - " + game[i][j]);

        blankCells -= 1; // decrementing unnecessarily currently blah
        // console.log("blankCells - " + blankCells);

        switchTurnInPossibilities();
        // console.log("switch turn in possibilities - first turn should be x - " + currentTurnInPossibilities);

        possibleResult = searchThroughDepths(1);
        // debugger;
        $(".check").append("row " + i + " column " + j + " possibleResult " + possibleResult + "
");
        gameClone[i][j] = "";
        blankCells +=1;
        console.log("choice in aiMove() - " + choice);
        console.log("possibleResult in aiMove() - " + possibleResult);
        console.log("[ " +row+ " ][" +col+ "]");
        if (choice === -1000) {
          choice = possibleResult;
          row = i;
          col = j;
        } else if (possibleResult > choice) {
          choice = possibleResult;
          row = i;
          col = j;
        }
        switchTurnInPossibilities();
      }
    }
  }
  $(".check").append("return -- choice "+ choice + " row " + row + " col " + col);
  game[row][col] = "O";
  blankCells -= 1;
  // console.log("blankCells - " + blankCells);
  populateTable(row, col);
  switchTurn();
}

function populateTable(row, col) {
  var elemId = row*3 + col + 1;
  $("#"+elemId).html("O"); //CONTINUE HERE
}

function searchThroughDepths(level) {
  console.log(level);
  var possibleResult = checkForWinner(gameClone);
  // console.log("searchThroughDepths - possibleResult is - "+ possibleResult);
  if (possibleResult === "O") { // AI wins
    return 100 - level;
  } else if (possibleResult === "X") { // human player wins
    return level - 100;
  } else if (possibleResult === "draw") {
    return 0;
  }
  console.log("searchThroughDepths ------");
  var choice = -1000;
  var otherOptions;

  for (var i = 0; i < gameClone.length; i++) {
    for (var j = 0; j < gameClone[i].length; j++) {
      if (gameClone[i][j] === "") {
        // console.log("per blank cell in searchThroughDepths");

        gameClone[i][j] = currentTurnInPossibilities;
        // console.log("gameClone[i][j]" + "[" +i+ "][" +j+ "] tile - " + gameClone[i][j]);
        // console.log("game[i][j] - " + game[i][j]);

        switchTurnInPossibilities();

        blankCells -= 1;
        otherOptions = searchThroughDepths(level+1);
        console.log("searchthrudepths - choice blah - " + choice);
        console.log("searchthrudepths - otherOptions blah - " + otherOptions);
        switchTurnInPossibilities();
        gameClone[i][j] = "";
        blankCells += 1;
        if (choice === -1000) {
          choice = otherOptions;
        } else if (currentTurnInPossibilities === "O") {
            if (otherOptions > choice) {
              choice = otherOptions;
            }
        } else if (currentTurnInPossibilities === "X") {
            if (otherOptions < choice) {
              choice = otherOptions;
            }
        }
      }
    }
  }
  console.log("searchthrudepths - choice blah being returned - " + choice);
  return choice;
}

function createGameClone() {
  gameClone = new Array(3);
  for (var k = 0; k < gameClone.length; k++) {
    gameClone[k] = new Array(3);
  }

  for (var i = 0; i < gameClone.length; i++) {
    for (var j = 0; j < gameClone[i].length; j++) {
      gameClone[i][j] = game[i][j];
    }
  }
}

function switchTurnInPossibilities() {
  if (currentTurnInPossibilities === "O") {
    currentTurnInPossibilities = "X"; //switch to human player
  } else {
    currentTurnInPossibilities = "O";
  }
}

// when a draw happens or a winner has been found
function endTheGame(result) {
  if (result === "draw") {
    $(".dynamic_text").html("
Draw!
");
  } else if (result === "X") {
    // just to check if human can win --hopefully not!
      $(".dynamic_text").html("
You win!
");
  } else {
      $(".dynamic_text").html("
I win!
");
  }
  // reloadGame(); //allow user to reload game manually by pressing start over button
  return;
}

function checkForWinner(game) {
  // check for horizontal wins, left to right
  for (var row = 0; row < game.length; row++) {
    if (game[row][0] === game[row][1] && game[row][1] === game[row][2]) {
      if (game[row][0] !== "") {
        return game[row][0]; // returns either X or O depending on winning combo
      }
    }
  }
  // check for vertical wins, top to bottom
  for (var col = 0; col < game.length; col++) {
    if (game[0][col] === game[1][col] && game[1][col] === game[2][col]) {
      if (game[0][col] !== "") {
        return game[0][col]; // returns either X or O depending on winning combo
      }
    }
  }
 // check for diagonal wins, top left to bottom right and bottom left to top right
 if ((game[0][0] === game[1][1] && game[1][1] === game[2][2]) || (game[2][0] === game[1][1] && game[1][1] === game[0][2])) {
    if (game[1][1] !== "") {
      return game[1][1]; // returns either X or O depending on winning combo
    }
 }
 // return draw when all cells are filled and no winner is found
 if (blankCells === 0) {
    return "draw";
 }
 // resume playing until game ends in a draw or a winner is found
 return "continue";
}

<commit_msg>ITS WORKING AHHHH. dang it, semicolons ruining alls the thaaangs. but yayyy<commit_after>$(document).ready(function() {

  createGame();
  loadEventListener(); // for button to reload the game
});

var currentTurn = "X"; // where X is always human player, and O is always AI
var blankCells = 9;
var game; // 3x3 array
var gameClone; //for AI to explore possibilities on
var currentTurnInPossibilities; //declare AI / "O" as default later?

function reloadGame() {
  currentTurn = "X";
  blankCells = 9;
  clearTable();
  createGame();
}

// initialize game with empty 3x3 board
function createGame() {
  game = new Array(3);
  for (var i = 0; i < game.length; i++) {
    game[i] = new Array(3);
    for (var j = 0; j < game[i].length; j++) {
      game[i][j] = "";
    }
  }
}

function clearTable() {
  $("td").empty();
}

function loadEventListener() {
  $("#reload").click(function() {
    reloadGame();
    $(".dynamic_text").html('
Start whenever you\'re ready
');
    $(".check").html("");
  });
}

function switchTurn() {
  if (currentTurn === "X") {
    currentTurn = "O";
  } else {
    currentTurn = "X";
  }
}

// accessed from onclick attribute in view.html
function humansMove(id,row,column) {
  if (blankCells === 9) {
    $(".start_text").fadeOut("slow");
  }

  // if cell is already occupied, the move is invalid
  var content = $("#"+id).text();
  if (content.length > 0) {
    $(".dynamic_text").html("
Invalid move
");
    return;
  }
  $("#"+id).addClass("x").html("X");

  // populate 2d game array with corresponding tile
  game[row][column] = "X";

  // decrement number of blank cells
  blankCells -= 1;
  console.log("blank cells left - " + blankCells); //check if blank cells decrementing

  var result = checkForWinner(game);
  if (result !== "continue") {
    endTheGame(result);
  }
  switchTurn();
  // console.log("the current turn - " + currentTurn);
  aiMove(); //undefined still
  result = checkForWinner(game);
  if (result !== "continue") {
    endTheGame(result);
  }
}

function aiMove() {
  // debugger;
  // console.log("ai move");
  // return if it's not the ai's turn -- maybe get rid of this later
  // console.log("current turn - letter " + currentTurn)
  if (currentTurn !== "O") {
    return;
  }
  // return if there are no turns left / no blank cells available
  if (blankCells === 0) {
    return;
  }
  // debugger;
  createGameClone();
  currentTurnInPossibilities = "O";
  var possibleResult, row, col, choice = -1000;
  // for each blank cell, plop in "O"
  // debugger;
  for (var i = 0; i < gameClone.length; i++) {
    for (var j = 0; j < gameClone[i].length; j++) {
      if (gameClone[i][j] === "") {
        // debugger;
        gameClone[i][j] = currentTurnInPossibilities;
        // console.log("gameClone[i][j]" + "[" +i+ "][" +j+ "] tile - " + gameClone[i][j]);
        // console.log("game[i][j] - " + game[i][j]);

        blankCells -= 1; // decrementing unnecessarily currently blah
        // console.log("blankCells - " + blankCells);

        switchTurnInPossibilities();
        // console.log("switch turn in possibilities - first turn should be x - " + currentTurnInPossibilities);

        possibleResult = searchThroughDepths(1);
        // debugger;
        $(".check").append("row " + i + " column " + j + " possibleResult " + possibleResult + "
");
        gameClone[i][j] = "";
        blankCells +=1;
        console.log("choice in aiMove() - " + choice);
        console.log("possibleResult in aiMove() - " + possibleResult);
        console.log("[ " +row+ " ][" +col+ "]");
        if (choice === -1000) {
          choice = possibleResult;
          row = i;
          col = j;
        } else if (possibleResult > choice) {
          choice = possibleResult;
          row = i;
          col = j;
        }
        switchTurnInPossibilities();
      }
    }
  }
  $(".check").append("return -- choice "+ choice + " row " + row + " col " + col);
  game[row][col] = "O";
  blankCells -= 1;
  // console.log("blankCells - " + blankCells);
  populateTable(row, col);
  switchTurn();
}

function populateTable(row, col) {
  var elemId = row*3 + col + 1;
  $("#"+elemId).html("O"); //CONTINUE HERE
}

function searchThroughDepths(level) {
  console.log(level);
  var possibleResult = checkForWinner(gameClone);
  // console.log("searchThroughDepths - possibleResult is - "+ possibleResult);
  if (possibleResult === "O") { // AI wins
    return 100 - level;
  } else if (possibleResult === "X") { // human player wins
    return level - 100;
  } else if (possibleResult === "draw") {
    return 0;
  }
  console.log("searchThroughDepths ------");
  var choice = -1000;
  var otherOptions;

  for (var i = 0; i < gameClone.length; i++) {
    for (var j = 0; j < gameClone[i].length; j++) {
      if (gameClone[i][j] === "") {
        // console.log("per blank cell in searchThroughDepths");

        gameClone[i][j] = currentTurnInPossibilities;
        // console.log("gameClone[i][j]" + "[" +i+ "][" +j+ "] tile - " + gameClone[i][j]);
        // console.log("game[i][j] - " + game[i][j]);

        switchTurnInPossibilities();

        blankCells -= 1;
        otherOptions = searchThroughDepths(level+1);
        console.log("searchthrudepths - choice blah - " + choice);
        console.log("searchthrudepths - otherOptions blah - " + otherOptions);
        switchTurnInPossibilities();
        gameClone[i][j] = "";
        blankCells += 1;
        if (choice === -1000) {
          choice = otherOptions;
        } else if (currentTurnInPossibilities === "O") {
            if (otherOptions > choice) {
              choice = otherOptions;
            }
        } else if (currentTurnInPossibilities === "X") {
            if (otherOptions < choice) {
              choice = otherOptions;
            }
        }
      }
    }
  }
  console.log("searchthrudepths - choice blah being returned - " + choice);
  return choice;
}

function createGameClone() {
  gameClone = new Array(3);
  for (var k = 0; k < gameClone.length; k++) {
    gameClone[k] = new Array(3);
  }

  for (var i = 0; i < gameClone.length; i++) {
    for (var j = 0; j < gameClone[i].length; j++) {
      gameClone[i][j] = game[i][j];
    }
  }
}

function switchTurnInPossibilities() {
  if (currentTurnInPossibilities === "O") {
    currentTurnInPossibilities = "X"; //switch to human player
  } else {
    currentTurnInPossibilities = "O";
  }
}

// when a draw happens or a winner has been found
function endTheGame(result) {
  if (result === "draw") {
    $(".dynamic_text").html("
Draw!
");
  } else if (result === "X") {
    // just to check if human can win --hopefully not!
      $(".dynamic_text").html("
You win!
");
  } else {
      $(".dynamic_text").html("
I win!
");
  }
  // reloadGame(); //allow user to reload game manually by pressing start over button
  return;
}

function checkForWinner(game) {
  // check for horizontal wins, left to right
  for (var row = 0; row < game.length; row++) {
    if (game[row][0] === game[row][1] && game[row][1] === game[row][2]) {
      if (game[row][0] !== "") {
        return game[row][0]; // returns either X or O depending on winning combo
      }
    }
  }
  // check for vertical wins, top to bottom
  for (var col = 0; col < game.length; col++) {
    if (game[0][col] === game[1][col] && game[1][col] === game[2][col]) {
      if (game[0][col] !== "") {
        return game[0][col]; // returns either X or O depending on winning combo
      }
    }
  }
 // check for diagonal wins, top left to bottom right and bottom left to top right
 if ((game[0][0] === game[1][1] && game[1][1] === game[2][2]) || (game[2][0] === game[1][1] && game[1][1] === game[0][2])) {
    if (game[1][1] !== "") {
      return game[1][1]; // returns either X or O depending on winning combo
    }
 }
 // return draw when all cells are filled and no winner is found
 if (blankCells === 0) {
    return "draw";
 }
 // resume playing until game ends in a draw or a winner is found
 return "continue";
}

<|endoftext|>


<commit_before>import {$$, addClass, Animation, assign, css, fastdom, hasAttr, hasClass, height, includes, isBoolean, isFunction, isVisible, noop, Promise, removeClass, toFloat, toggleClass, toNodes, Transition, trigger} from 'uikit-util';

export default {

    props: {
        cls: Boolean,
        animation: 'list',
        duration: Number,
        origin: String,
        transition: String
    },

    data: {
        cls: false,
        animation: [false],
        duration: 200,
        origin: false,
        transition: 'linear',
        clsEnter: 'uk-togglabe-enter',
        clsLeave: 'uk-togglabe-leave',

        initProps: {
            overflow: '',
            height: '',
            paddingTop: '',
            paddingBottom: '',
            marginTop: '',
            marginBottom: ''
        },

        hideProps: {
            overflow: 'hidden',
            height: 0,
            paddingTop: 0,
            paddingBottom: 0,
            marginTop: 0,
            marginBottom: 0
        }

    },

    computed: {

        hasAnimation({animation}) {
            return !!animation[0];
        },

        hasTransition({animation}) {
            return this.hasAnimation && animation[0] === true;
        }

    },

    methods: {

        toggleElement(targets, toggle, animate) {
            return new Promise(resolve =>
                Promise.all(toNodes(targets).map(el => {

                    const show = isBoolean(toggle) ? toggle : !this.isToggled(el);

                    if (!trigger(el, `before${show ? 'show' : 'hide'}`, [this])) {
                        return Promise.reject();
                    }

                    const promise = (
                        isFunction(animate)
                            ? animate
                            : animate === false || !this.hasAnimation
                            ? this._toggle
                            : this.hasTransition
                                ? toggleHeight(this)
                                : toggleAnimation(this)
                    )(el, show) || Promise.resolve();

                    addClass(el, show ? this.clsEnter : this.clsLeave);

                    trigger(el, show ? 'show' : 'hide', [this]);

                    promise
                        .catch(noop)
                        .then(() => removeClass(el, show ? this.clsEnter : this.clsLeave));

                    return promise.then(() => {
                        removeClass(el, show ? this.clsEnter : this.clsLeave);
                        trigger(el, show ? 'shown' : 'hidden', [this]);
                        this.$update(el);
                    });
                })).then(resolve, noop)
            );
        },

        isToggled(el = this.$el) {
            return hasClass(el, this.clsEnter)
                ? true
                : hasClass(el, this.clsLeave)
                    ? false
                    : this.cls
                        ? hasClass(el, this.cls.split(' ')[0])
                        : !hasAttr(el, 'hidden');
        },

        _toggle(el, toggled) {

            if (!el) {
                return;
            }

            toggled = Boolean(toggled);

            let changed;
            if (this.cls) {
                changed = includes(this.cls, ' ') || toggled !== hasClass(el, this.cls);
                changed && toggleClass(el, this.cls, includes(this.cls, ' ') ? undefined : toggled);
            } else {
                changed = toggled === el.hidden;
                changed && (el.hidden = !toggled);
            }

            $$('[autofocus]', el).some(el => isVisible(el) ? el.focus() || true : el.blur());

            if (changed) {
                trigger(el, 'toggled', [toggled, this]);
                this.$update(el);
            }
        }

    }

};

export function toggleHeight({isToggled, duration, initProps, hideProps, transition, _toggle}) {
    return (el, show) => {

        const inProgress = Transition.inProgress(el);
        const inner = el.hasChildNodes ? toFloat(css(el.firstElementChild, 'marginTop')) + toFloat(css(el.lastElementChild, 'marginBottom')) : 0;
        const currentHeight = isVisible(el) ? height(el) + (inProgress ? 0 : inner) : 0;

        Transition.cancel(el);

        if (!isToggled(el)) {
            _toggle(el, true);
        }

        height(el, '');

        // Update child components first
        fastdom.flush();

        const endHeight = height(el) + (inProgress ? 0 : inner);
        height(el, currentHeight);

        return (show
            ? Transition.start(el, assign({}, initProps, {overflow: 'hidden', height: endHeight}), Math.round(duration * (1 - currentHeight / endHeight)), transition)
            : Transition.start(el, hideProps, Math.round(duration * (currentHeight / endHeight)), transition).then(() => _toggle(el, false))
        ).then(() => css(el, initProps));

    };
}

function toggleAnimation(cmp) {
    return (el, show) => {

        Animation.cancel(el);

        const {animation, duration, _toggle} = cmp;

        if (show) {
            _toggle(el, true);
            return Animation.in(el, animation[0], duration, cmp.origin);
        }

        return Animation.out(el, animation[1] || animation[0], duration, cmp.origin).then(() => _toggle(el, false));
    };
}
<commit_msg>refactor: make toggleElement fire 'shown/hidden' immediately if animate is set to false Resolves #4390<commit_after>import {$$, addClass, Animation, assign, css, fastdom, hasAttr, hasClass, height, includes, isBoolean, isFunction, isVisible, noop, Promise, removeClass, toFloat, toggleClass, toNodes, Transition, trigger} from 'uikit-util';

export default {

    props: {
        cls: Boolean,
        animation: 'list',
        duration: Number,
        origin: String,
        transition: String
    },

    data: {
        cls: false,
        animation: [false],
        duration: 200,
        origin: false,
        transition: 'linear',
        clsEnter: 'uk-togglabe-enter',
        clsLeave: 'uk-togglabe-leave',

        initProps: {
            overflow: '',
            height: '',
            paddingTop: '',
            paddingBottom: '',
            marginTop: '',
            marginBottom: ''
        },

        hideProps: {
            overflow: 'hidden',
            height: 0,
            paddingTop: 0,
            paddingBottom: 0,
            marginTop: 0,
            marginBottom: 0
        }

    },

    computed: {

        hasAnimation({animation}) {
            return !!animation[0];
        },

        hasTransition({animation}) {
            return this.hasAnimation && animation[0] === true;
        }

    },

    methods: {

        toggleElement(targets, toggle, animate) {
            return new Promise(resolve =>
                Promise.all(toNodes(targets).map(el => {

                    const show = isBoolean(toggle) ? toggle : !this.isToggled(el);

                    if (!trigger(el, `before${show ? 'show' : 'hide'}`, [this])) {
                        return Promise.reject();
                    }

                    const promise = (
                        isFunction(animate)
                            ? animate
                            : animate === false || !this.hasAnimation
                            ? this._toggle
                            : this.hasTransition
                                ? toggleHeight(this)
                                : toggleAnimation(this)
                    )(el, show);

                    const cls = show ? this.clsEnter : this.clsLeave;

                    addClass(el, cls);

                    trigger(el, show ? 'show' : 'hide', [this]);

                    const done = () => {
                        removeClass(el, cls);
                        trigger(el, show ? 'shown' : 'hidden', [this]);
                        this.$update(el);
                    };

                    return promise ? promise.then(done, () => {
                        removeClass(el, cls);
                        return Promise.reject();
                    }) : done();

                })).then(resolve, noop)
            );
        },

        isToggled(el = this.$el) {
            return hasClass(el, this.clsEnter)
                ? true
                : hasClass(el, this.clsLeave)
                    ? false
                    : this.cls
                        ? hasClass(el, this.cls.split(' ')[0])
                        : !hasAttr(el, 'hidden');
        },

        _toggle(el, toggled) {

            if (!el) {
                return;
            }

            toggled = Boolean(toggled);

            let changed;
            if (this.cls) {
                changed = includes(this.cls, ' ') || toggled !== hasClass(el, this.cls);
                changed && toggleClass(el, this.cls, includes(this.cls, ' ') ? undefined : toggled);
            } else {
                changed = toggled === el.hidden;
                changed && (el.hidden = !toggled);
            }

            $$('[autofocus]', el).some(el => isVisible(el) ? el.focus() || true : el.blur());

            if (changed) {
                trigger(el, 'toggled', [toggled, this]);
                this.$update(el);
            }
        }

    }

};

export function toggleHeight({isToggled, duration, initProps, hideProps, transition, _toggle}) {
    return (el, show) => {

        const inProgress = Transition.inProgress(el);
        const inner = el.hasChildNodes ? toFloat(css(el.firstElementChild, 'marginTop')) + toFloat(css(el.lastElementChild, 'marginBottom')) : 0;
        const currentHeight = isVisible(el) ? height(el) + (inProgress ? 0 : inner) : 0;

        Transition.cancel(el);

        if (!isToggled(el)) {
            _toggle(el, true);
        }

        height(el, '');

        // Update child components first
        fastdom.flush();

        const endHeight = height(el) + (inProgress ? 0 : inner);
        height(el, currentHeight);

        return (show
            ? Transition.start(el, assign({}, initProps, {overflow: 'hidden', height: endHeight}), Math.round(duration * (1 - currentHeight / endHeight)), transition)
            : Transition.start(el, hideProps, Math.round(duration * (currentHeight / endHeight)), transition).then(() => _toggle(el, false))
        ).then(() => css(el, initProps));

    };
}

function toggleAnimation(cmp) {
    return (el, show) => {

        Animation.cancel(el);

        const {animation, duration, _toggle} = cmp;

        if (show) {
            _toggle(el, true);
            return Animation.in(el, animation[0], duration, cmp.origin);
        }

        return Animation.out(el, animation[1] || animation[0], duration, cmp.origin).then(() => _toggle(el, false));
    };
}
<|endoftext|>


<commit_before>$(document).ready(function() {
  var turnCounter = 0
  $('.space').click(function(){
    if ( turnCounter % 2 === 0 ) {
      $(this).css('background-color', 'red')
      turnCounter += 1
    } else {
      $(this).css('background-color', 'black')
      turnCounter += 1
    }
  })
});

<commit_msg>Prevent changing a filled space<commit_after>$(document).ready(function() {

  var turnCounter = 0

  $('.space').click(function(){

    var row = $(this).attr('class').split(" ")[1]
    var column = $(this).attr('class').split(" ")[2]

    if ($(this).hasClass('empty')) {
      if ( turnCounter % 2 === 0 ) {
        $(this).css('background-color', 'red')
        $(this).removeClass('empty')
        $(this).addClass('filled')
        turnCounter += 1
      } else {
        $(this).css('background-color', 'black')
        $(this).removeClass('empty')
        $(this).addClass('filled')
        turnCounter += 1
      }
    }

  })
});

<|endoftext|>


<commit_before>import React, { PropTypes, Component } from 'react';
const ReactLink = require('react/lib/ReactLink');
const ReactStateSetters = require('react/lib/ReactStateSetters');
import RegularTopNavbar from '../components/ui/RegularTopNavbar';
import TextInput from '../components/ui/TextInput';
import PasswordInput from '../components/ui/PasswordInput';
import FullWidthButton from '../components/ui/FullWidthButton';
import LoginActionCreators from '../actions/LoginActionCreators';
import connectToStores from '../utils/connectToStores';
import LoginStore from '../stores/LoginStore';

function getState(props) {

    const error = LoginStore.error;
    const requesting = LoginStore.requesting();

    return {
        error,
        requesting
    };
}

@connectToStores([LoginStore], getState)
export default class LoginPage extends Component {

    static propTypes = {
        // Injected by @connectToStores:
        error     : PropTypes.object,
        requesting: PropTypes.bool.isRequired
    };

    constructor() {
        super();
        this.state = {
            user    : '',
            password: ''
        };
    }

    login(e) {
        e.preventDefault();
        LoginActionCreators.loginUser(this.state.user, this.state.password);
    }

    linkState(key) {
        return new ReactLink(this.state[key], ReactStateSetters.createStateKeySetter(this, key));
    }

    render() {
        const {
            error,
            requesting
            } = this.props;
        return (

                <RegularTopNavbar leftText={'Cancelar'} centerText={'Iniciar sesión'}/>

                                <TextInput placeholder={'Usuario o email'} valueLink={this.linkState('user')}/>
                                <PasswordInput placeholder={'Contraseña'} valueLink={this.linkState('password')}/>

                        <FullWidthButton type="submit" onClick={this.login.bind(this)}>Iniciar Sesión</FullWidthButton>

{ requesting ? 'Enviando...' : ''}

{ error ? error.error : ''}

        );
    }
}
<commit_msg>QS-908: Login on keydown enter<commit_after>import React, { PropTypes, Component } from 'react';
const ReactLink = require('react/lib/ReactLink');
const ReactStateSetters = require('react/lib/ReactStateSetters');
import RegularTopNavbar from '../components/ui/RegularTopNavbar';
import TextInput from '../components/ui/TextInput';
import PasswordInput from '../components/ui/PasswordInput';
import FullWidthButton from '../components/ui/FullWidthButton';
import LoginActionCreators from '../actions/LoginActionCreators';
import connectToStores from '../utils/connectToStores';
import LoginStore from '../stores/LoginStore';

function getState(props) {

    const error = LoginStore.error;
    const requesting = LoginStore.requesting();

    return {
        error,
        requesting
    };
}

@connectToStores([LoginStore], getState)
export default class LoginPage extends Component {

    static propTypes = {
        // Injected by @connectToStores:
        error     : PropTypes.object,
        requesting: PropTypes.bool.isRequired
    };

    constructor() {
        super();
        this.login = this.login.bind(this);
        this._onKeyDown = this._onKeyDown.bind(this);
        this.state = {
            user    : '',
            password: ''
        };
    }

    login() {
        LoginActionCreators.loginUser(this.state.user, this.state.password);
    }

    _onKeyDown(event) {
        let ENTER_KEY_CODE = 13;
        if (event.keyCode === ENTER_KEY_CODE) {
            event.preventDefault();
            this.login();
        }
    }

    linkState(key) {
        return new ReactLink(this.state[key], ReactStateSetters.createStateKeySetter(this, key));
    }

    render() {
        const {
            error,
            requesting
            } = this.props;
        return (

                <RegularTopNavbar leftText={'Cancelar'} centerText={'Iniciar sesión'}/>

                                <TextInput placeholder={'Usuario o email'} valueLink={this.linkState('user')} onKeyDown={this._onKeyDown}/>
                                <PasswordInput placeholder={'Contraseña'} valueLink={this.linkState('password')} onKeyDown={this._onKeyDown}/>

                        <FullWidthButton type="submit" onClick={this.login}>Iniciar Sesión</FullWidthButton>

{ requesting ? 'Enviando...' : ''}

{ error ? error.error : ''}

        );
    }
}
<|endoftext|>


<commit_before>$('document').ready( function(){

  // Fix Broken Image
// function imageCheck() {
  var image_el = $('.poster')
  for (i = 0; i < image_el.length; i++) {
    if (image_el[i].width < 1 || image_el[1].src.search(/.N\/A/)) {
      console.log("No Image!");
      image_el.innerHTML = '
No Image!
';
    } else {
      console.log("Image loaded!")
    }
  }
// }

  // Footer Date
  var today = new Date();
  var date = today.toDateString();
  var footer_el = document.getElementById('footer');
  footer_el.innerHTML = '
Copyright © ' + date + '

Anthony Ng | Crafted lovingly in San Francisco, California.
';

// Google Map API
function initialize() {

  var markers = [];
  var map = new google.maps.Map(document.getElementById('map-canvas'), {
    mapTypeId: google.maps.MapTypeId.ROADMAP
  });

  var defaultBounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(37.773493, -122.423864),
    new google.maps.LatLng(37.790147, -122.388974));
  map.fitBounds(defaultBounds);

  // Create the search box and link it to the UI element.
  var input = /** @type {HTMLInputElement} */(
    document.getElementById('pac-input'));
  map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

  var searchBox = new google.maps.places.SearchBox((input));

  // [START region_getplaces]
  // Listen for the event fired when the user selects an item from the
  // pick list. Retrieve the matching places for that item.
  google.maps.event.addListener(searchBox, 'places_changed', function() {
    var places = searchBox.getPlaces();

    if (places.length == 0) {
      return;
    }
    for (var i = 0, marker; marker = markers[i]; i++) {
      marker.setMap(null);
    }

    // For each place, get the icon, place name, and location.
    markers = [];
    var bounds = new google.maps.LatLngBounds();
    for (var i = 0, place; place = places[i]; i++) {
      var image = {
        url: place.icon,
        size: new google.maps.Size(71, 71),
        origin: new google.maps.Point(0, 0),
        anchor: new google.maps.Point(17, 34),
        scaledSize: new google.maps.Size(25, 25)
      };

      // Create a marker for each place.
      var marker = new google.maps.Marker({
        map: map,
        icon: image,
        title: place.name,
        position: place.geometry.location
      });

      markers.push(marker);

      bounds.extend(place.geometry.location);
    }

    map.fitBounds(bounds);
  });
  // [END region_getplaces]

  // Bias the SearchBox results towards places that are within the bounds of the
  // current map's viewport.
  google.maps.event.addListener(map, 'bounds_changed', function() {
    var bounds = map.getBounds();
    searchBox.setBounds(bounds);
  });
}

google.maps.event.addDomListener(window, 'load', initialize);

// background Video Button
var vid = document.getElementById("bgvid");
var pauseButton = document.getElementById("vidpause");
function vidFade() {
vid.classList.add("stopfade");
}
vid.addEventListener('ended', function() {
// only functional if "loop" is removed
vid.pause();
// to capture IE10
vidFade();
});
pauseButton.addEventListener("click", function() {
vid.classList.toggle("stopfade");
if (vid.paused) {
vid.play();
pauseButton.innerHTML = "Pause";
} else {
vid.pause();
pauseButton.innerHTML = "Paused";
}
})

  // $('form').on('submit', function(event){
  //   event.preventDefault()
  //   $('form').nextAll().remove()
  //   $.ajax({
  //     type: 'GET',
  //     url: $(this).attr('action'),
  //     data: $(this).serialize()
  //   }).done(function(data) {
  //     $(".container").append(data)
  //   })
  // })
})
<commit_msg>fixed broken link with image<commit_after>$('document').ready( function(){

  // Fix Broken Image
// function imageCheck() {
  var image_el = $('.poster')
  for (i = 0; i < image_el.length; i++) {
    if (image_el[i].src.search(/.N\/A/) !== -1) {
      console.log("No Image!");
      image_el[i].setAttribute("src", "../images/oscar.jpg");;
    } else {
      console.log("Image loaded!")
    }
  }
// }

  // Footer Date
  var today = new Date();
  var date = today.toDateString();
  var footer_el = document.getElementById('footer');
  footer_el.innerHTML = '
Copyright © ' + date + '

Anthony Ng | Crafted lovingly in San Francisco, California.
';

// Google Map API
function initialize() {

  var markers = [];
  var map = new google.maps.Map(document.getElementById('map-canvas'), {
    mapTypeId: google.maps.MapTypeId.ROADMAP
  });

  var defaultBounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(37.773493, -122.423864),
    new google.maps.LatLng(37.790147, -122.388974));
  map.fitBounds(defaultBounds);

  // Create the search box and link it to the UI element.
  var input = /** @type {HTMLInputElement} */(
    document.getElementById('pac-input'));
  map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

  var searchBox = new google.maps.places.SearchBox((input));

  // [START region_getplaces]
  // Listen for the event fired when the user selects an item from the
  // pick list. Retrieve the matching places for that item.
  google.maps.event.addListener(searchBox, 'places_changed', function() {
    var places = searchBox.getPlaces();

    if (places.length == 0) {
      return;
    }
    for (var i = 0, marker; marker = markers[i]; i++) {
      marker.setMap(null);
    }

    // For each place, get the icon, place name, and location.
    markers = [];
    var bounds = new google.maps.LatLngBounds();
    for (var i = 0, place; place = places[i]; i++) {
      var image = {
        url: place.icon,
        size: new google.maps.Size(71, 71),
        origin: new google.maps.Point(0, 0),
        anchor: new google.maps.Point(17, 34),
        scaledSize: new google.maps.Size(25, 25)
      };

      // Create a marker for each place.
      var marker = new google.maps.Marker({
        map: map,
        icon: image,
        title: place.name,
        position: place.geometry.location
      });

      markers.push(marker);

      bounds.extend(place.geometry.location);
    }

    map.fitBounds(bounds);
  });
  // [END region_getplaces]

  // Bias the SearchBox results towards places that are within the bounds of the
  // current map's viewport.
  google.maps.event.addListener(map, 'bounds_changed', function() {
    var bounds = map.getBounds();
    searchBox.setBounds(bounds);
  });
}

google.maps.event.addDomListener(window, 'load', initialize);

// background Video Button
var vid = document.getElementById("bgvid");
var pauseButton = document.getElementById("vidpause");
function vidFade() {
vid.classList.add("stopfade");
}
vid.addEventListener('ended', function() {
// only functional if "loop" is removed
vid.pause();
// to capture IE10
vidFade();
});
pauseButton.addEventListener("click", function() {
vid.classList.toggle("stopfade");
if (vid.paused) {
vid.play();
pauseButton.innerHTML = "Pause";
} else {
vid.pause();
pauseButton.innerHTML = "Paused";
}
})

  // $('form').on('submit', function(event){
  //   event.preventDefault()
  //   $('form').nextAll().remove()
  //   $.ajax({
  //     type: 'GET',
  //     url: $(this).attr('action'),
  //     data: $(this).serialize()
  //   }).done(function(data) {
  //     $(".container").append(data)
  //   })
  // })
})
<|endoftext|>