<commit_before>function pathinfo(path, options) {
  //  discuss at: http://phpjs.org/functions/pathinfo/
  // original by: Nate
  //  revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // improved by: Brett Zamir (http://brett-zamir.me)
  //    input by: Timo
  //        note: Inspired by actual PHP source: php5-5.2.6/ext/standard/string.c line #1559
  //        note: The way the bitwise arguments are handled allows for greater flexibility
  //        note: & compatability. We might even standardize this code and use a similar approach for
  //        note: other bitwise PHP functions
  //        note: php.js tries very hard to stay away from a core.js file with global dependencies, because we like
  //        note: that you can just take a couple of functions and be on your way.
  //        note: But by way we implemented this function, if you want you can still declare the PATHINFO_*
  //        note: yourself, and then you can use: pathinfo('/www/index.html', PATHINFO_BASENAME | PATHINFO_EXTENSION);
  //        note: which makes it fully compliant with PHP syntax.
  //  depends on: basename
  //   example 1: pathinfo('/www/htdocs/index.html', 1);
  //   returns 1: '/www/htdocs'
  //   example 2: pathinfo('/www/htdocs/index.html', 'PATHINFO_BASENAME');
  //   returns 2: 'index.html'
  //   example 3: pathinfo('/www/htdocs/index.html', 'PATHINFO_EXTENSION');
  //   returns 3: 'html'
  //   example 4: pathinfo('/www/htdocs/index.html', 'PATHINFO_FILENAME');
  //   returns 4: 'index'
  //   example 5: pathinfo('/www/htdocs/index.html', 2 | 4);
  //   returns 5: {basename: 'index.html', extension: 'html'}
  //   example 6: pathinfo('/www/htdocs/index.html', 'PATHINFO_ALL');
  //   returns 6: {dirname: '/www/htdocs', basename: 'index.html', extension: 'html', filename: 'index'}
  //   example 7: pathinfo('/www/htdocs/index.html');
  //   returns 7: {dirname: '/www/htdocs', basename: 'index.html', extension: 'html', filename: 'index'}

  var opt = '',
    optName = '',
    optTemp = 0,
    tmp_arr = {},
    cnt = 0,
    i = 0;
  var have_basename = false,
    have_extension = false,
    have_filename = false;

  // Input defaulting & sanitation
  if (!path) {
    return false;
  }
  if (!options) {
    options = 'PATHINFO_ALL';
  }

  // Initialize binary arguments. Both the string & integer (constant) input is
  // allowed
  var OPTS = {
    'PATHINFO_DIRNAME': 1,
    'PATHINFO_BASENAME': 2,
    'PATHINFO_EXTENSION': 4,
    'PATHINFO_FILENAME': 8,
    'PATHINFO_ALL': 0
  };
  // PATHINFO_ALL sums up all previously defined PATHINFOs (could just pre-calculate)
  for (optName in OPTS) {
    OPTS.PATHINFO_ALL = OPTS.PATHINFO_ALL | OPTS[optName];
  }
  if (typeof options !== 'number') {
    // Allow for a single string or an array of string flags
    options = [].concat(options);
    for (i = 0; i < options.length; i++) {
      // Resolve string input to bitwise e.g. 'PATHINFO_EXTENSION' becomes 4
      if (OPTS[options[i]]) {
        optTemp = optTemp | OPTS[options[i]];
      }
    }
    options = optTemp;
  }

  // Internal Functions
  var __getExt = function (path) {
    var str = path + '';
    var dotP = str.lastIndexOf('.') + 1;
    return !dotP ? false : dotP !== str.length ? str.substr(dotP) : '';
  };

  // Gather path infos
  if (options & OPTS.PATHINFO_DIRNAME) {
    var dirName = path.replace(/\\/g, '/')
      .replace(/\/[^\/]*\/?$/, ''); // dirname
    tmp_arr.dirname = dirName === path ? '.' : dirName;
  }

  if (options & OPTS.PATHINFO_BASENAME) {
    if (false === have_basename) {
      have_basename = this.basename(path);
    }
    tmp_arr.basename = have_basename;
  }

  if (options & OPTS.PATHINFO_EXTENSION) {
    if (false === have_basename) {
      have_basename = this.basename(path);
    }
    if (false === have_extension) {
      have_extension = __getExt(have_basename);
    }
    if (false !== have_extension) {
      tmp_arr.extension = have_extension;
    }
  }

  if (options & OPTS.PATHINFO_FILENAME) {
    if (false === have_basename) {
      have_basename = this.basename(path);
    }
    if (false === have_extension) {
      have_extension = __getExt(have_basename);
    }
    if (false === have_filename) {
      have_filename = have_basename.slice(0, have_basename.length - (have_extension ? have_extension.length + 1 :
        have_extension === false ? 0 : 1));
    }

    tmp_arr.filename = have_filename;
  }

  // If array contains only 1 element: return string
  cnt = 0;
  for (opt in tmp_arr) {
    cnt++;
  }
  if (cnt == 1) {
    return tmp_arr[opt];
  }

  // Return full-blown array
  return tmp_arr;
}<commit_msg>"for each" fix, for modified prototypes<commit_after>function pathinfo(path, options) {
  //  discuss at: http://phpjs.org/functions/pathinfo/
  // original by: Nate
  //  revised by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // improved by: Brett Zamir (http://brett-zamir.me)
  // improved by: Dmitry Gorelenkov
  //    input by: Timo
  //        note: Inspired by actual PHP source: php5-5.2.6/ext/standard/string.c line #1559
  //        note: The way the bitwise arguments are handled allows for greater flexibility
  //        note: & compatability. We might even standardize this code and use a similar approach for
  //        note: other bitwise PHP functions
  //        note: php.js tries very hard to stay away from a core.js file with global dependencies, because we like
  //        note: that you can just take a couple of functions and be on your way.
  //        note: But by way we implemented this function, if you want you can still declare the PATHINFO_*
  //        note: yourself, and then you can use: pathinfo('/www/index.html', PATHINFO_BASENAME | PATHINFO_EXTENSION);
  //        note: which makes it fully compliant with PHP syntax.
  //  depends on: basename
  //   example 1: pathinfo('/www/htdocs/index.html', 1);
  //   returns 1: '/www/htdocs'
  //   example 2: pathinfo('/www/htdocs/index.html', 'PATHINFO_BASENAME');
  //   returns 2: 'index.html'
  //   example 3: pathinfo('/www/htdocs/index.html', 'PATHINFO_EXTENSION');
  //   returns 3: 'html'
  //   example 4: pathinfo('/www/htdocs/index.html', 'PATHINFO_FILENAME');
  //   returns 4: 'index'
  //   example 5: pathinfo('/www/htdocs/index.html', 2 | 4);
  //   returns 5: {basename: 'index.html', extension: 'html'}
  //   example 6: pathinfo('/www/htdocs/index.html', 'PATHINFO_ALL');
  //   returns 6: {dirname: '/www/htdocs', basename: 'index.html', extension: 'html', filename: 'index'}
  //   example 7: pathinfo('/www/htdocs/index.html');
  //   returns 7: {dirname: '/www/htdocs', basename: 'index.html', extension: 'html', filename: 'index'}

  var opt = '',
    optName = '',
    optTemp = 0,
    tmp_arr = {},
    cnt = 0,
    i = 0;
  var have_basename = false,
    have_extension = false,
    have_filename = false;

  // Input defaulting & sanitation
  if (!path) {
    return false;
  }
  if (!options) {
    options = 'PATHINFO_ALL';
  }

  // Initialize binary arguments. Both the string & integer (constant) input is
  // allowed
  var OPTS = {
    'PATHINFO_DIRNAME': 1,
    'PATHINFO_BASENAME': 2,
    'PATHINFO_EXTENSION': 4,
    'PATHINFO_FILENAME': 8,
    'PATHINFO_ALL': 0
  };
  // PATHINFO_ALL sums up all previously defined PATHINFOs (could just pre-calculate)
  for (optName in OPTS) {
    if(OPTS.hasOwnProperty(optName)){
      OPTS.PATHINFO_ALL = OPTS.PATHINFO_ALL | OPTS[optName];
    }
  }
  if (typeof options !== 'number') {
    // Allow for a single string or an array of string flags
    options = [].concat(options);
    for (i = 0; i < options.length; i++) {
      // Resolve string input to bitwise e.g. 'PATHINFO_EXTENSION' becomes 4
      if (OPTS[options[i]]) {
        optTemp = optTemp | OPTS[options[i]];
      }
    }
    options = optTemp;
  }

  // Internal Functions
  var __getExt = function (path) {
    var str = path + '';
    var dotP = str.lastIndexOf('.') + 1;
    return !dotP ? false : dotP !== str.length ? str.substr(dotP) : '';
  };

  // Gather path infos
  if (options & OPTS.PATHINFO_DIRNAME) {
    var dirName = path.replace(/\\/g, '/')
      .replace(/\/[^\/]*\/?$/, ''); // dirname
    tmp_arr.dirname = dirName === path ? '.' : dirName;
  }

  if (options & OPTS.PATHINFO_BASENAME) {
    if (false === have_basename) {
      have_basename = this.basename(path);
    }
    tmp_arr.basename = have_basename;
  }

  if (options & OPTS.PATHINFO_EXTENSION) {
    if (false === have_basename) {
      have_basename = this.basename(path);
    }
    if (false === have_extension) {
      have_extension = __getExt(have_basename);
    }
    if (false !== have_extension) {
      tmp_arr.extension = have_extension;
    }
  }

  if (options & OPTS.PATHINFO_FILENAME) {
    if (false === have_basename) {
      have_basename = this.basename(path);
    }
    if (false === have_extension) {
      have_extension = __getExt(have_basename);
    }
    if (false === have_filename) {
      have_filename = have_basename.slice(0, have_basename.length - (have_extension ? have_extension.length + 1 :
        have_extension === false ? 0 : 1));
    }

    tmp_arr.filename = have_filename;
  }

  // If array contains only 1 element: return string
  cnt = 0;
  for (opt in tmp_arr) {
    if(tmp_arr.hasOwnProperty(opt)){
      cnt++;
    }
  }
  if (cnt == 1) {
    return tmp_arr[opt];
  }

  // Return full-blown array
  return tmp_arr;
}
<|endoftext|>


<commit_before>/**
 * Copyright 2017 Google 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.
 */
'use strict';

/**
 * Initializes the Functions Web quickstart app.
 */
function FunctionsQuickstart() {
  this.signInButton = document.getElementById('sign-in-button');
  this.signOutButton = document.getElementById('sign-out-button');
  this.splashPage = document.getElementById('page-splash');
  this.messageText = document.getElementById('message-text');
  this.addMessageButton = document.getElementById('add-message-button');
  this.firstNumber = document.getElementById('first-number');
  this.secondNumber = document.getElementById('second-number');
  this.addNumbersButton = document.getElementById('send-addition-button');
  this.messageContainer = document.getElementById('message-container');

  // Add Click events to buttons.
  this.signInButton.addEventListener('click', this.signIn);
  this.signOutButton.addEventListener('click', this.signOut);
  this.addMessageButton.addEventListener('click', this.addMessage.bind(this));
  this.addNumbersButton.addEventListener('click', this.addNumbers.bind(this));
  // Listen for auth state changes.
  firebase.auth().onAuthStateChanged(this.onAuthStateChanged.bind(this));
  // Listen for new Messages to be displayed.
  firebase.database().ref('/messages').limitToLast(10).on('child_added', this.onNewMessage.bind(this));
}

// Adds two numbers by calling the `addNumbers` server-side function.
FunctionsQuickstart.prototype.addNumbers = function() {
  var firstNumber = parseFloat(this.firstNumber.value);
  var secondNumber = parseFloat(this.secondNumber.value);
  var addNumbersButton = this.addNumbersButton;
  addNumbersButton.disabled = true;
  // [START callAddFunction]
  var sendNotification = firebase.functions().callable('addNumbers');
  sendNotification({firstNumber: firstNumber, secondNumber: secondNumber}).then(function(result) {
    console.log('Cloud Function called successfully.', result);
    // Read results of the Cloud Function.
    var firstNumber = result.data.firstNumber;
    var secondNumber = result.data.secondNumber;
    var operationResult = result.data.operationResult;
    var operator = result.data.operator;
    // [START_EXCLUDE]
    window.alert('Here is the result of the formula: ' + firstNumber + ' '
        + operator + ' ' + secondNumber + ' = ' + operationResult);
    addNumbersButton.disabled = false;
    // [END_EXCLUDE]
  }).catch(function(error) {
    // Getting the Error details.
    var code = error.code;
    var message = error.message;
    var details = error.details;
    // [START_EXCLUDE]
    console.error('There was an error when calling the Cloud Function', error);
    window.alert('There was an error when calling the Cloud Function:\n\nError Code: '
        + code + '\nError Message:' + message + '\nError Details:' + details);
    addNumbersButton.disabled = false;
    // [END_EXCLUDE]
  });
  // [END callAddFunction]
};

// Adds a message to the Realtime Database by calling the `addMessage` server-side function.
FunctionsQuickstart.prototype.addMessage = function() {
  var messageTextInput = this.messageText;
  var messageText = messageTextInput.value
  var addMessageButton = this.addMessageButton;
  addMessageButton.disabled = true;
  // [START callAddMessageFunction]
  var addMessage = firebase.functions().callable('addMessage');
  addMessage({text: messageText}).then(function(result) {
    // Read result of the Cloud Function.
    var sanitizedMessage = result.data.text;
    // [START_EXCLUDE]
    if (messageText !== sanitizedMessage) {
      window.alert('You were naughty. Your message was sanitized to:\n\n' + sanitizedMessage);
    }
    messageTextInput.value = '';
    addMessageButton.disabled = false;
  // [START catchError]
  }).catch(function(error) {
    // Getting the Error details.
    var code = error.code;
    var message = error.message;
    var details = error.details;
    // [START_EXCLUDE]
    console.error('There was an error when calling the Cloud Function', error);
    window.alert('There was an error when calling the Cloud Function:\n\nError Code: '
        + code + '\nError Message:' + message + '\nError Details:' + details);
    addMessageButton.disabled = false;
    // [END_EXCLUDE]
  // [END catchError]
    // [END_EXCLUDE]
  });
  // [END callAddMessageFunction]
};

// Start the Firebase signs-in flow via Google account.
FunctionsQuickstart.prototype.signIn = function() {
  var provider = new firebase.auth.GoogleAuthProvider();
  firebase.auth().signInWithPopup(provider);
};

// The user signs-out his Firebase account.
FunctionsQuickstart.prototype.signOut = function() {
  firebase.auth().signOut();
};

// This is called when the Firebase auth state has changed. i.e. the User has signed-in or signed-out.
FunctionsQuickstart.prototype.onAuthStateChanged = function(user) {
  if (user) {
    // When a user signs-in we remove the sign-in splash page.
    this.splashPage.style.display = 'none';
  } else {
    // Display the splash page where you can sign-in.
    this.splashPage.style.display = '';
  }
};

// This is called when a new Message has been added to the realtime Database.
FunctionsQuickstart.prototype.onNewMessage = function(snap) {
  var text = snap.val().text;
  var name = snap.val().author.name;
  var messageElement = document.createElement('div');
  messageElement.classList.add('message-element');
  var authorContainer = document.createElement('div');
  authorContainer.innerText = name;
  authorContainer.classList.add('author-container');
  var textContainer = document.createElement('div');
  textContainer.innerText = text;
  messageElement.appendChild(authorContainer);
  messageElement.appendChild(textContainer);
  this.messageContainer.insertBefore(messageElement, this.messageContainer.firstChild);
};

window.onload = function() {
  window.app = new FunctionsQuickstart();
};
<commit_msg>Fixing error include code<commit_after>/**
 * Copyright 2017 Google 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.
 */
'use strict';

/**
 * Initializes the Functions Web quickstart app.
 */
function FunctionsQuickstart() {
  this.signInButton = document.getElementById('sign-in-button');
  this.signOutButton = document.getElementById('sign-out-button');
  this.splashPage = document.getElementById('page-splash');
  this.messageText = document.getElementById('message-text');
  this.addMessageButton = document.getElementById('add-message-button');
  this.firstNumber = document.getElementById('first-number');
  this.secondNumber = document.getElementById('second-number');
  this.addNumbersButton = document.getElementById('send-addition-button');
  this.messageContainer = document.getElementById('message-container');

  // Add Click events to buttons.
  this.signInButton.addEventListener('click', this.signIn);
  this.signOutButton.addEventListener('click', this.signOut);
  this.addMessageButton.addEventListener('click', this.addMessage.bind(this));
  this.addNumbersButton.addEventListener('click', this.addNumbers.bind(this));
  // Listen for auth state changes.
  firebase.auth().onAuthStateChanged(this.onAuthStateChanged.bind(this));
  // Listen for new Messages to be displayed.
  firebase.database().ref('/messages').limitToLast(10).on('child_added', this.onNewMessage.bind(this));
}

// Adds two numbers by calling the `addNumbers` server-side function.
FunctionsQuickstart.prototype.addNumbers = function() {
  var firstNumber = parseFloat(this.firstNumber.value);
  var secondNumber = parseFloat(this.secondNumber.value);
  var addNumbersButton = this.addNumbersButton;
  addNumbersButton.disabled = true;
  // [START callAddFunction]
  var sendNotification = firebase.functions().callable('addNumbers');
  sendNotification({firstNumber: firstNumber, secondNumber: secondNumber}).then(function(result) {
    console.log('Cloud Function called successfully.', result);
    // Read results of the Cloud Function.
    var firstNumber = result.data.firstNumber;
    var secondNumber = result.data.secondNumber;
    var operationResult = result.data.operationResult;
    var operator = result.data.operator;
    // [START_EXCLUDE]
    window.alert('Here is the result of the formula: ' + firstNumber + ' '
        + operator + ' ' + secondNumber + ' = ' + operationResult);
    addNumbersButton.disabled = false;
    // [END_EXCLUDE]
  }).catch(function(error) {
    // Getting the Error details.
    var code = error.code;
    var message = error.message;
    var details = error.details;
    // [START_EXCLUDE]
    console.error('There was an error when calling the Cloud Function', error);
    window.alert('There was an error when calling the Cloud Function:\n\nError Code: '
        + code + '\nError Message:' + message + '\nError Details:' + details);
    addNumbersButton.disabled = false;
    // [END_EXCLUDE]
  });
  // [END callAddFunction]
};

// Adds a message to the Realtime Database by calling the `addMessage` server-side function.
FunctionsQuickstart.prototype.addMessage = function() {
  var messageTextInput = this.messageText;
  var messageText = messageTextInput.value;
  var addMessageButton = this.addMessageButton;
  addMessageButton.disabled = true;
  // [START callAddMessageFunction]
  // [START callAddMessageFunctionWithError]
  var addMessage = firebase.functions().callable('addMessage');
  addMessage({text: messageText}).then(function(result) {
    // Read result of the Cloud Function.
    var sanitizedMessage = result.data.text;
    // [END callAddMessageFunctionWithError]
    // [START_EXCLUDE]
    if (messageText !== sanitizedMessage) {
      window.alert('You were naughty. Your message was sanitized to:\n\n' + sanitizedMessage);
    }
    messageTextInput.value = '';
    addMessageButton.disabled = false;
  // [START catchError]
  }).catch(function(error) {
    // Getting the Error details.
    var code = error.code;
    var message = error.message;
    var details = error.details;
    // [START_EXCLUDE]
    console.error('There was an error when calling the Cloud Function', error);
    window.alert('There was an error when calling the Cloud Function:\n\nError Code: '
        + code + '\nError Message:' + message + '\nError Details:' + details);
    addMessageButton.disabled = false;
    // [END_EXCLUDE]
    // [END_EXCLUDE]
  });
  // [END catchError]
  // [END callAddMessageFunction]
};

// Start the Firebase signs-in flow via Google account.
FunctionsQuickstart.prototype.signIn = function() {
  var provider = new firebase.auth.GoogleAuthProvider();
  firebase.auth().signInWithPopup(provider);
};

// The user signs-out his Firebase account.
FunctionsQuickstart.prototype.signOut = function() {
  firebase.auth().signOut();
};

// This is called when the Firebase auth state has changed. i.e. the User has signed-in or signed-out.
FunctionsQuickstart.prototype.onAuthStateChanged = function(user) {
  if (user) {
    // When a user signs-in we remove the sign-in splash page.
    this.splashPage.style.display = 'none';
  } else {
    // Display the splash page where you can sign-in.
    this.splashPage.style.display = '';
  }
};

// This is called when a new Message has been added to the realtime Database.
FunctionsQuickstart.prototype.onNewMessage = function(snap) {
  var text = snap.val().text;
  var name = snap.val().author.name;
  var messageElement = document.createElement('div');
  messageElement.classList.add('message-element');
  var authorContainer = document.createElement('div');
  authorContainer.innerText = name;
  authorContainer.classList.add('author-container');
  var textContainer = document.createElement('div');
  textContainer.innerText = text;
  messageElement.appendChild(authorContainer);
  messageElement.appendChild(textContainer);
  this.messageContainer.insertBefore(messageElement, this.messageContainer.firstChild);
};

window.onload = function() {
  window.app = new FunctionsQuickstart();
};
<|endoftext|>


<commit_before>var mout = require('mout');
var RegistryClient = require('bower-registry-client');
var ResolveCache = require('./ResolveCache');
var resolverFactory = require('./resolverFactory');
var createError = require('../util/createError');

function PackageRepository(config, logger) {
    var registryOptions;

    this._config = config;
    this._logger = logger;

    // Instantiate the registry
    registryOptions = mout.object.deepMixIn({}, this._config);
    registryOptions.cache = this._config.storage.registry;
    this._registryClient = new RegistryClient(registryOptions);

    // Instantiate the resolve cache
    this._resolveCache = new ResolveCache(this._config);
}

// -----------------

PackageRepository.prototype.fetch = function (decEndpoint) {
    var logger;
    var that = this;
    var info = {
        decEndpoint: decEndpoint
    };

    // Create a new logger that pipes everything to ours that will be
    // used to fetch
    logger = this._logger.geminate();
    // Intercept all logs, adding additional information
    logger.intercept(function (log) {
        that._extendLog(log, info);
    });

    // Get the appropriate resolver
    return resolverFactory(decEndpoint, this._config, logger, this._registryClient)
    // Decide if we retrieve from the cache or not
    // Also decide if we validate the cached entry or not
    .then(function (resolver) {
        info.resolver = resolver;

        // If force flag is used, bypass cache
        if (that._config.force) {
            logger.action('resolve', resolver.getSource() + '#' + resolver.getTarget());
            return that._resolve(resolver, logger);
        }

        // Note that we use the resolver methods to query the
        // cache because transformations/normalisations can occur
        return that._resolveCache.retrieve(resolver.getSource(), resolver.getTarget())
        // Decide if we can use the one from the resolve cache
        .spread(function (canonicalDir, pkgMeta) {
            // If there's no package in the cache
            if (!canonicalDir) {
                // And the offline flag is passed, error out
                if (that._config.offline) {
                    throw createError('No cached version for ' + resolver.getSource() + '#' + resolver.getTarget(), 'ENOCACHE', {
                        resolver: resolver
                    });
                }

                // Otherwise, we have to resolve it
                logger.info('not-cached', resolver.getSource() + (resolver.getTarget() ? '#' + resolver.getTarget() : ''));
                logger.action('resolve', resolver.getSource() + '#' + resolver.getTarget());

                return that._resolve(resolver, logger);
            }

            info.canonicalDir = canonicalDir;
            info.pkgMeta = pkgMeta;

            logger.info('cached', resolver.getSource() + (pkgMeta._release ? '#' + pkgMeta._release : ''));

            // If offline flag is used, use directly the cached one
            if (that._config.offline) {
                return [canonicalDir, pkgMeta];
            }

            // Otherwise check for new contents
            logger.action('validate', (pkgMeta._release ? pkgMeta._release + ' against ': '') +
                                      resolver.getSource() + (resolver.getTarget() ? '#' + resolver.getTarget() : ''));

            return resolver.hasNew(canonicalDir, pkgMeta)
            .then(function (hasNew) {
                // If there are no new contents, resolve to
                // the cached one
                if (!hasNew) {
                    return [canonicalDir, pkgMeta];
                }

                // Otherwise resolve to the newest one
                logger.info('new', 'version for ' + resolver.getSource() + '#' + resolver.getTarget());
                logger.action('resolve', resolver.getSource() + '#' + resolver.getTarget());

                return that._resolve(resolver, logger);
            });
        });
    })
    // If something went wrong, also extend the error
    .fail(function (err) {
        that._extendLog(err, info);
        throw err;
    });
};

PackageRepository.prototype.versions = function (source) {
    // Resolve the source using the factory because the
    // source can actually be a registry name
    return resolverFactory.getConstructor(source, this._config, this._registryClient)
    .spread(function (ConcreteResolver, source) {
        // If offline, resolve using the cached versions
        if (this._config.offline) {
            return this._resolveCache.versions(source);
        }

        // Otherwise, fetch remotely
        return ConcreteResolver.versions(source);
    }.bind(this));
};

PackageRepository.prototype.eliminate = function (pkgMeta) {
    return this._resolveCache.eliminate(pkgMeta);
};

PackageRepository.prototype.clear = function () {
    return this._resolveCache.clear();
};

PackageRepository.prototype.list = function () {
    return this._resolveCache.list();
};

PackageRepository.clearRuntimeCache = function () {
    ResolveCache.clearRuntimeCache();
    RegistryClient.clearRuntimeCache();
    resolverFactory.clearRuntimeCache();
};

// ---------------------

PackageRepository.prototype._resolve = function (resolver, logger) {
    // Resolve the resolver
    return resolver.resolve()
    // Store in the cache
    .then(function (canonicalDir) {
        return this._resolveCache.store(canonicalDir, resolver.getPkgMeta());
    }.bind(this))
    // Resolve promise with canonical dir and package meta
    .then(function (dir) {
        var pkgMeta = resolver.getPkgMeta();
        logger.info('resolved', resolver.getSource() + (pkgMeta._release ? '#' + pkgMeta._release : ''));
        return [dir, pkgMeta];
    }.bind(this));
};

PackageRepository.prototype._extendLog = function (log, info) {
    log.data = log.data || {};

    // Store endpoint info in each log
    if (info.decEndpoint) {
        log.data.endpoint = mout.object.pick(info.decEndpoint, ['name', 'source', 'target']);
    }

    // Store the resolver info in each log
    if (info.resolver) {
        log.data.resolver = {
            name: info.resolver.getName(),
            source: info.resolver.getSource(),
            target: info.resolver.getTarget()
        };
    }

    // Store the canonical dir and its meta in each log
    if (info.canonicalDir) {
        log.data.canonicalDir = info.canonicalDir;
        log.data.pkgMeta = info.pkgMeta;
    }

    return log;
};

module.exports = PackageRepository;
<commit_msg>Also call registry client methods related to eliminate, clear and reset.<commit_after>var mout = require('mout');
var Q = require('q');
var RegistryClient = require('bower-registry-client');
var ResolveCache = require('./ResolveCache');
var resolverFactory = require('./resolverFactory');
var createError = require('../util/createError');

function PackageRepository(config, logger) {
    var registryOptions;

    this._config = config;
    this._logger = logger;

    // Instantiate the registry
    registryOptions = mout.object.deepMixIn({}, this._config);
    registryOptions.cache = this._config.storage.registry;
    this._registryClient = new RegistryClient(registryOptions);

    // Instantiate the resolve cache
    this._resolveCache = new ResolveCache(this._config);
}

// -----------------

PackageRepository.prototype.fetch = function (decEndpoint) {
    var logger;
    var that = this;
    var info = {
        decEndpoint: decEndpoint
    };

    // Create a new logger that pipes everything to ours that will be
    // used to fetch
    logger = this._logger.geminate();
    // Intercept all logs, adding additional information
    logger.intercept(function (log) {
        that._extendLog(log, info);
    });

    // Get the appropriate resolver
    return resolverFactory(decEndpoint, this._config, logger, this._registryClient)
    // Decide if we retrieve from the cache or not
    // Also decide if we validate the cached entry or not
    .then(function (resolver) {
        info.resolver = resolver;

        // If force flag is used, bypass cache
        if (that._config.force) {
            logger.action('resolve', resolver.getSource() + '#' + resolver.getTarget());
            return that._resolve(resolver, logger);
        }

        // Note that we use the resolver methods to query the
        // cache because transformations/normalisations can occur
        return that._resolveCache.retrieve(resolver.getSource(), resolver.getTarget())
        // Decide if we can use the one from the resolve cache
        .spread(function (canonicalDir, pkgMeta) {
            // If there's no package in the cache
            if (!canonicalDir) {
                // And the offline flag is passed, error out
                if (that._config.offline) {
                    throw createError('No cached version for ' + resolver.getSource() + '#' + resolver.getTarget(), 'ENOCACHE', {
                        resolver: resolver
                    });
                }

                // Otherwise, we have to resolve it
                logger.info('not-cached', resolver.getSource() + (resolver.getTarget() ? '#' + resolver.getTarget() : ''));
                logger.action('resolve', resolver.getSource() + '#' + resolver.getTarget());

                return that._resolve(resolver, logger);
            }

            info.canonicalDir = canonicalDir;
            info.pkgMeta = pkgMeta;

            logger.info('cached', resolver.getSource() + (pkgMeta._release ? '#' + pkgMeta._release : ''));

            // If offline flag is used, use directly the cached one
            if (that._config.offline) {
                return [canonicalDir, pkgMeta];
            }

            // Otherwise check for new contents
            logger.action('validate', (pkgMeta._release ? pkgMeta._release + ' against ': '') +
                                      resolver.getSource() + (resolver.getTarget() ? '#' + resolver.getTarget() : ''));

            return resolver.hasNew(canonicalDir, pkgMeta)
            .then(function (hasNew) {
                // If there are no new contents, resolve to
                // the cached one
                if (!hasNew) {
                    return [canonicalDir, pkgMeta];
                }

                // Otherwise resolve to the newest one
                logger.info('new', 'version for ' + resolver.getSource() + '#' + resolver.getTarget());
                logger.action('resolve', resolver.getSource() + '#' + resolver.getTarget());

                return that._resolve(resolver, logger);
            });
        });
    })
    // If something went wrong, also extend the error
    .fail(function (err) {
        that._extendLog(err, info);
        throw err;
    });
};

PackageRepository.prototype.versions = function (source) {
    // Resolve the source using the factory because the
    // source can actually be a registry name
    return resolverFactory.getConstructor(source, this._config, this._registryClient)
    .spread(function (ConcreteResolver, source) {
        // If offline, resolve using the cached versions
        if (this._config.offline) {
            return this._resolveCache.versions(source);
        }

        // Otherwise, fetch remotely
        return ConcreteResolver.versions(source);
    }.bind(this));
};

PackageRepository.prototype.eliminate = function (pkgMeta) {
    return Q.all([
        this._resolveCache.eliminate(pkgMeta),
        Q.nfcall(this._registryClient.clearCache.bind(this._registryClient), pkgMeta.name)
    ]);
};

PackageRepository.prototype.clear = function () {
    return Q.all([
        this._resolveCache.clear(),
        Q.nfcall(this._registryClient.clearCache.bind(this._registryClient))
    ]);
};

PackageRepository.prototype.reset = function () {
    this._resolveCache.reset();
    this._registryClient.resetCache();
};

PackageRepository.prototype.list = function () {
    return this._resolveCache.list();
};

PackageRepository.clearRuntimeCache = function () {
    ResolveCache.clearRuntimeCache();
    RegistryClient.clearRuntimeCache();
    resolverFactory.clearRuntimeCache();
};

// ---------------------

PackageRepository.prototype._resolve = function (resolver, logger) {
    // Resolve the resolver
    return resolver.resolve()
    // Store in the cache
    .then(function (canonicalDir) {
        return this._resolveCache.store(canonicalDir, resolver.getPkgMeta());
    }.bind(this))
    // Resolve promise with canonical dir and package meta
    .then(function (dir) {
        var pkgMeta = resolver.getPkgMeta();
        logger.info('resolved', resolver.getSource() + (pkgMeta._release ? '#' + pkgMeta._release : ''));
        return [dir, pkgMeta];
    }.bind(this));
};

PackageRepository.prototype._extendLog = function (log, info) {
    log.data = log.data || {};

    // Store endpoint info in each log
    if (info.decEndpoint) {
        log.data.endpoint = mout.object.pick(info.decEndpoint, ['name', 'source', 'target']);
    }

    // Store the resolver info in each log
    if (info.resolver) {
        log.data.resolver = {
            name: info.resolver.getName(),
            source: info.resolver.getSource(),
            target: info.resolver.getTarget()
        };
    }

    // Store the canonical dir and its meta in each log
    if (info.canonicalDir) {
        log.data.canonicalDir = info.canonicalDir;
        log.data.pkgMeta = info.pkgMeta;
    }

    return log;
};

module.exports = PackageRepository;
<|endoftext|>


<commit_before>"use strict";

//https://github.com/flatiron/nconf
var nconf = require("nconf"),
    path = require("path"),
    fs = require("fs"),
    _ = require("underscore");

var defaultConfig = require("../defaults/defaultConfig.json"),
    extractConfig = require("./extractConfig.js");

/**
 * Hierarchical load config from 1. ARGV, 2. ENV, 3. CWD/config.json or 4. default config
 * If you pass --config via ARGV or ENV, this file will be loaded as config.json instead of the default
 * Only values defined in config.json and default-alamid values can be overwritten by env
 *
 * **Examples:**
 * alamid --port 1234 : load default-config but overwrite port
 * alamid --config /your/path/to/config.json : load your own config json
 * alamid --config /your/path/to/config.json --port 1234 : load your own config.json but overwrite the port
 *
 * @return {Object} config
 */
function readConfig(part) {

    var conf = {},
        configDir,
        configFileName = "config.json",
        envConfigPath,
        configPath,
        log = readConfig.log,
        activeConfig;

    //working together with process.env.NODE_ENV
    if(process.env.env === undefined && process.env.NODE_ENV !== undefined) {
        process.env.env = process.env.NODE_ENV;
    }

    //parse args & env first
    nconf.argv()
        .env();

    //we prefer appDir, but use process.cwd as a fallback
    //TODO look at appDir, __dirname and process.cwd
    //TODO make this whole thing less messy
    //TODO add notification about which config was loaded
    configDir = nconf.get("server:appDir") || process.cwd();

    //load default config file if none is set
    if (nconf.get("server:config") === undefined) {

        configPath = configFileName;

        //load env-specific config if env is set
        if(nconf.get("env") !== undefined) {

            envConfigPath = "config/" + nconf.get("env") + "." + configFileName;

            //fallback to default config file if env-file doesn't exist
            if(fs.existsSync(envConfigPath)) {
                log("loading env-specific default config for env '" + nconf.get("env") + "'");
                configPath = envConfigPath;
            }
        }
    }
    //check if path to custom config was passed and load if set
    else {
        log("loading custom config as defined '" + nconf.get("server:config") + "'");
        configPath = path.normalize(nconf.get("server:config"));
    }

    log("trying to read config-file from CWD: " + configPath);
    configPath = path.normalize(configDir + "/" + configPath);

    if (fs.existsSync(configPath)) {

        log("config-file found");

        //we need this file to extract the keys from nconf
        activeConfig = JSON.parse(fs.readFileSync(configPath, "utf-8"));
        //at least the default config values have to be set.
        _(activeConfig).extend(defaultConfig);

        nconf.file({ file: configPath });
    }
    else {
        log("Config-file not found. Loading default config");
        activeConfig = defaultConfig;
    }

    //set defaults from included config.json
    nconf.defaults(defaultConfig);

    //Setting the node-env for other modules
    if(nconf.get("env") !== undefined && process.env.NODE_ENV === undefined){
        process.env.NODE_ENV = nconf.get("env");
    }

    //read each value from the passedConfig (merged with default config)
    //this way we can hide env values that are not really wanted
    _(activeConfig).forEach(function forEachDefaultConfig(value, key) {

        //Boolean-String to REAL boolean cast
        if(nconf.get(key) === "true") {
            conf[key] = true;
        }
        else if(nconf.get(key) === "false") {
            conf[key] = false;
        }
        else {
            conf[key] = nconf.get(key);
        }

    });

    if(part) {
        conf = extractConfig(conf, part);
    }

    //type was only needed for nconf
    delete conf.type;

    return conf;
}

readConfig.log = console.log;   // expose log-property so the logging behaviour can be changed externally

module.exports = readConfig;<commit_msg>- added todo<commit_after>"use strict";

//https://github.com/flatiron/nconf
var nconf = require("nconf"),
    path = require("path"),
    fs = require("fs"),
    _ = require("underscore");

var defaultConfig = require("../defaults/defaultConfig.json"),
    extractConfig = require("./extractConfig.js");

/**
 * Hierarchical load config from 1. ARGV, 2. ENV, 3. CWD/config.json or 4. default config
 * If you pass --config via ARGV or ENV, this file will be loaded as config.json instead of the default
 * Only values defined in config.json and default-alamid values can be overwritten by env
 *
 * **Examples:**
 * alamid --port 1234 : load default-config but overwrite port
 * alamid --config /your/path/to/config.json : load your own config json
 * alamid --config /your/path/to/config.json --port 1234 : load your own config.json but overwrite the port
 *
 * @return {Object} config
 */
function readConfig(part) {

    var conf = {},
        configDir,
        configFileName = "config.json",
        envConfigPath,
        configPath,
        log = readConfig.log,
        activeConfig;

    //working together with process.env.NODE_ENV
    if (process.env.env === undefined && process.env.NODE_ENV !== undefined) {
        process.env.env = process.env.NODE_ENV;
    }

    //parse args & env first
    nconf.argv()
        .env();

    //we prefer appDir, but use process.cwd as a fallback
    //TODO look at appDir, __dirname and process.cwd
    //TODO make this whole thing less messy
    //TODO add notification about which config was loaded
    configDir = nconf.get("server:appDir") || process.cwd();

    //load default config file if none is set
    if (nconf.get("server:config") === undefined) {

        configPath = configFileName;

        //load env-specific config if env is set
        if (nconf.get("env") !== undefined) {

            envConfigPath = "config/" + nconf.get("env") + "." + configFileName;

            //fallback to default config file if env-file doesn't exist
            if (fs.existsSync(envConfigPath)) {
                log("loading env-specific default config for env '" + nconf.get("env") + "'");
                configPath = envConfigPath;
            }
        }
    }
    //check if path to custom config was passed and load if set
    else {
        log("loading custom config as defined '" + nconf.get("server:config") + "'");
        configPath = path.normalize(nconf.get("server:config"));
    }

    log("trying to read config-file from CWD: " + configPath);
    configPath = path.normalize(configDir + "/" + configPath);

    if (fs.existsSync(configPath)) {

        log("config-file found");

        //we need this file to extract the keys from nconf
        activeConfig = JSON.parse(fs.readFileSync(configPath, "utf-8"));
        //at least the default config values have to be set.
        _(activeConfig).extend(defaultConfig);

        nconf.file({ file : configPath });
    }
    else {
        log("Config-file not found. Loading default config");
        activeConfig = defaultConfig;
    }

    //set defaults from included config.json
    nconf.defaults(defaultConfig);

    //Setting the node-env for other modules
    if (nconf.get("env") !== undefined && process.env.NODE_ENV === undefined) {
        process.env.NODE_ENV = nconf.get("env");
    }

    //read each value from the passedConfig (merged with default config)
    //this way we can hide env values that are not really wanted
    _(activeConfig).forEach(function forEachDefaultConfig(value, key) {

        //Boolean-String to REAL boolean cast
        if (nconf.get(key) === "true") {
            conf[key] = true;
        }
        else if (nconf.get(key) === "false") {
            conf[key] = false;
        }
        else {
            conf[key] = nconf.get(key);
        }

    });

    if (part) {
        conf = extractConfig(conf, part);
    }

    //type was only needed for nconf
    delete conf.type;

    //TODO: maybe sanitize here
    //define sanitize for client & server
    //i.e. for routes
    return conf;
}

readConfig.log = console.log;   // expose log-property so the logging behaviour can be changed externally

module.exports = readConfig;<|endoftext|>


<commit_before>var express = require('express');

function createMethodWrapper(app, verb) {
    var original = app[verb];

    return function (route, handler) {
        original.call(app, route, function (req, res, next) {
            // must be places here in order that it is cleared on every request
            var hasSentResponse = false;

            handler(req, {
                setHeader: function () {
                    // empty
                },
                send: function(statusCode, body) {
                    if (hasSentResponse) {
                        return;
                    }

                    hasSentResponse = true;

                    res.send(statusCode, body);
                }
            }, function _next(err) {
                if (hasSentResponse) {
                    return;
                }

                hasSentResponse = true;

                next(err);
            });
        });
    };
}

module.exports = function createMockCouchAdapter() {
    var app = express();
    var deferred;
    var original;

    ['del', 'head', 'get', 'post'].forEach(function(verb) {
        var expressVerb = (verb === 'del' ? 'delete' : verb);

        app[verb] = createMethodWrapper(app, expressVerb);
    });

    // store the put method
    app.put = function (route, handler) {
        deferred = handler;
    };

    original = createMethodWrapper(app, 'use');
    app.use = function (middleware) {
        original('/:db', middleware);

        // now add the put method
        createMethodWrapper(app, 'put')('/:db', deferred);
    };

    return app;
};
<commit_msg>Wrap PUT and use the deferred trick for only the first such handler.<commit_after>var express = require('express');

function createMethodWrapper(app, verb) {
    var original = app[verb];

    return function (route, handler) {
        original.call(app, route, function (req, res, next) {
            // must be places here in order that it is cleared on every request
            var hasSentResponse = false;

            handler(req, {
                setHeader: function () {
                    // empty
                },
                send: function(statusCode, body) {
                    if (hasSentResponse) {
                        return;
                    }

                    hasSentResponse = true;

                    res.send(statusCode, body);
                }
            }, function _next(err) {
                if (hasSentResponse) {
                    return;
                }

                hasSentResponse = true;

                next(err);
            });
        });
    };
}

module.exports = function createMockCouchAdapter() {
    var app = express();
    var deferred;
    var original;
    var put;

    ['del', 'head', 'get', 'post'].forEach(function(verb) {
        var expressVerb = (verb === 'del' ? 'delete' : verb);

        app[verb] = createMethodWrapper(app, expressVerb);
    });

    put = createMethodWrapper(app, 'put');
    app.put = function (route, handler) {
        if (!deferred) {
            return put(route, handler);
        }

        deferred = handler;
    };

    original = createMethodWrapper(app, 'use');
    app.use = function (middleware) {
        original('/:db', middleware);

        // now add the put method
        put('/:db', deferred);
    };

    return app;
};
<|endoftext|>


<commit_before>/**
 * The Button Utility
 *
 * @module aui-button
 */

var Lang = A.Lang,

	getClassName = A.ClassNameManager.getClassName,

	NAME = 'button',

	ICON = 'icon',
	STATE = 'state',

	CSS_BUTTON = getClassName(NAME),
	CSS_BUTTON_ICON = getClassName(NAME, 'icon'),
	CSS_BUTTON_LABEL = getClassName(NAME, 'label'),

	CSS_BUTTON_ICON_LABEL = getClassName(NAME, 'icon', 'label'),

	CSS_ICON = getClassName(ICON),

	TPL_BUTTON = '<button></button>',
	TPL_ICON = '',
	TPL_LABEL = '';

	/**
	 * A base class for Button, providing:
	 *

	 *
Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)

	 *
An optional icon or label

	 *
Managed user interaction states (default, active, hover)

	 *
Keyboard accessible

	 *

	 *
	 * Quick Example:

	 *
	 *
var instance = new A.Button({
	 *	icon: 'gear',
	 * label: 'Configuration'
	 * }).render();
	 *

	 *
	 * Check the list of Configuration Attributes available for
	 * Button.
	 *
	 * @param config {Object} Object literal specifying widget configuration properties.
	 *
	 * @class Button
	 * @constructor
	 * @extends Component
	 * @uses WidgetChild
	 */

var Button = function(config) {
	if (Lang.isString(config)) {
		config = {
			icon: config
		};
	}

	Button.superclass.constructor.call(this, config);
};

/**
 * Static property provides a string to identify the class.
 *
 * @property Button.NAME
 * @type String
 * @static
 */

Button.NAME = NAME;

/**
 * Static property used to define the default attribute
 * configuration for the Button.
 *
 * @property Button.ATTRS
 * @type Object
 * @static
 */

Button.ATTRS = {
	/**
	 * Whether to track the active state of the button.
	 *
	 * @attribute activeState
	 * @default false
	 * @type Boolean
	 */
	activeState: {
		value: false
	},

	/**
	 * An object map of the CSS class names to use for the different interaction states.
	 *
	 * @attribute classNames
	 * @type Object
	 */
	classNames: {},

	/**
	 * Whether to apply the default interaction state to the button
	 *
	 * @attribute defaultState
	 * @default true
	 * @type Boolean
	 */
	defaultState: {},

	/**
	 * An event callback to handle when a user interacts with the button.
	 * This can either be a function that will be attached on click, or
	 * an object map that accepts the following keys:
	 * {fn: // The function to execute
	 * context: // The context to execute the function in
	 * type: // The type of event to listen for (defaults to "click")
	 * }
	 *
	 * @attribute handler
	 * @default false
	 * @type Function | Object
	 */
	handler: {
		lazyAdd: false,
		value: null,
		setter: function(value) {
			var instance = this;

			var fn = value;
			var context = instance;
			var args = instance;
			var type = 'click';

			if (Lang.isObject(fn)) {
				var handlerConfig = fn;

				fn = handlerConfig.fn || fn;
				context = handlerConfig.context || context;
				type = handlerConfig.type || type;
			}

			if (Lang.isFunction(fn)) {
				instance.on(type, A.rbind(fn, context, args, handlerConfig.args));
			}

			return value;
		}
	},

	/**
	 * Whether to track the hover interaction state of the button.
	 *
	 * @attribute hoverState
	 * @default true
	 * @type Boolean
	 */
	hoverState: {},

	/**
	 * The icon to use inside of the button. Possible values are:
	 *
	 * @attribute icon
	 * @type String
	 */
	icon: {
		value: ''
	},

	/**
	 * An id that can be used to identify a button.
	 *
	 * @attribute hoverState
	 * @type Boolean
	 */
	id: {
		valueFn: function() {
			return A.guid();
		}
	},

	/**
	 * Text to use inside of the button.
	 *
	 * @attribute label
	 * @type String
	 */
	label: {
		value: ''
	}
};

A.extend(
	Button,
	A.Component,
	{
		BOUNDING_TEMPLATE: TPL_BUTTON,
		CONTENT_TEMPLATE: null,

		/**
		 * Create the DOM structure for the Button. Lifecycle.
		 *
		 * @method renderUI
		 * @protected
		 */
		renderUI: function() {
			var instance = this;

			instance._renderStates();
		},

		/**
		 * Bind the events on the Button UI. Lifecycle.
		 *
		 * @method bindUI
		 * @protected
		 */
		bindUI: function() {
			var instance = this;

			instance.after('iconChange', instance._afterIconChange);
			instance.after('labelChange', instance._afterLabelChange);
		},

		/**
		 * Sync the Button UI. Lifecycle.
		 *
		 * @method syncUI
		 * @protected
		 */
		syncUI: function() {
			var instance = this;

			var icon = instance.get('icon');
			var label = instance.get('label');

			if (icon) {
				instance._uiSetIcon(icon)
			}

			if (label) {
				instance._uiSetLabel(label);
			}

		},

		/**
		 * Fires after the value of the
		 * icon attribute change.
		 *
		 * @method
		 * @param {EventFacade} event
		 * @protected
		 */
		_afterIconChange: function(event) {
			var instance = this;

			instance._uiSetIcon(event.newVal, event.prevVal);
		},

		/**
		 * Fires after the value of the
		 * label attribute change.
		 *
		 * @method
		 * @param {EventFacade} event
		 * @protected
		 */
		_afterLabelChange: function(event) {
			var instance = this;

			instance._uiSetLabel(event.newVal);
		},

		/**
		 * Get's a reference to the private icon node, or if not created,
		 * renders its and returns it.
		 *
		 * @method _getIconNode
		 * @protected
		 * @return {Node}
		 */
		_getIconNode: function() {
			var instance = this;

			return instance._iconNode || instance._renderIcon();
		},

		/**
		 * Get's a reference to the private label node, or if not created,
		 * renders its and returns it.
		 *
		 * @method _getLabelNode
		 * @protected
		 * @return {Node}
		 */
		_getLabelNode: function() {
			var instance = this;

			return instance._labelNode || instance._renderLabel();
		},

		/**
		 * Renders the underlying markup for the icon.
		 *
		 * @method _renderIcon
		 * @protected
		 * @return {Node}
		 */
		_renderIcon: function() {
			var instance = this;

			var iconNode = A.Node.create(TPL_ICON);

			instance._iconNode = iconNode;

			instance.get('boundingBox').appendChild(iconNode);

			return iconNode;
		},

		/**
		 * Renders the underlying markup for the label.
		 *
		 * @method _renderLabel
		 * @protected
		 * @return {Node}
		 */
		_renderLabel: function() {
			var instance = this;

			var labelNode = A.Node.create(TPL_LABEL);

			instance._labelNode = labelNode;

			instance.get('boundingBox').appendChild(labelNode);

			return labelNode;
		},

		/**
		 * Retrieves the state value from either the current instance, or if defined, the
		 * parent widget.
		 *
		 * @method _getState
		 * @param {String} key The state name to retrieve
		 * @param {Object} parent The parent widget to attempt to retrieve the state from
		 * @protected
		 * @return {Object}
		 */
		_getState: function(key, parent) {
			var instance = this;

			var value = instance.get(key);

			var state = value;

			if (parent) {
				value = parent.get(key);

				if (!Lang.isUndefined(value)) {
					state = value;
				}
			}

			return state;
		},

		/**
		 * Attaches state interaction management to the widget.
		 *
		 * @method _renderStates
		 * @param {EventFacade} event
		 * @protected
		 */
		_renderStates: function(event) {
			var instance = this;

			var parent = instance.get('parent');

			var activeState = instance._getState('activeState', parent);
			var classNames = instance._getState('classNames', parent);
			var defaultState = instance._getState('defaultState', parent);
			var hoverState = instance._getState('hoverState', parent);

			instance.plug(
				A.StateInteractionPlugin,
				{
					activeState: activeState,
					classNames: classNames,
					defaultState: defaultState,
					hoverState: hoverState
				}
			);
		},

		/**
		 * Updates the UI for the icon in response to the iconChange event.
		 *
		 * @method _uiSetIcon
		 * @param {String} newVal The new value
		 * @param {String} prevVal The previous value
		 * @protected
		 */
		_uiSetIcon: function(newVal, prevVal) {
			var instance = this;

			var iconNode = instance._getIconNode();

			var action = 'show';

			if (!newVal) {
				action = 'hide';
			}

			newVal = getClassName(ICON, newVal);

			if (prevVal) {
				prevVal = getClassName(ICON, prevVal);
			}

			iconNode.replaceClass(prevVal, newVal);

			var hasIconAndLabel = (newVal && instance.get('label'));

			iconNode[action]();

			instance.get('boundingBox').toggleClass(CSS_BUTTON_ICON_LABEL, hasIconAndLabel);
		},

		/**
		 * Updates the UI for the label in response to the labelChange event.
		 *
		 * @method _uiSetLabel
		 * @param {String} newVal The new value
		 * @protected
		 */
		_uiSetLabel: function(newVal) {
			var instance = this;

			var labelNode = instance._getLabelNode();

			var action = 'show';

			if (!newVal) {
				action = 'hide';
			}

			labelNode.text(newVal);

			labelNode[action]();

			var hasIconAndLabel = (newVal && instance.get('icon'));

			instance.get('boundingBox').toggleClass(CSS_BUTTON_ICON_LABEL, hasIconAndLabel);
		}
	}
);

A.Button = A.Base.build(NAME, Button, [A.WidgetChild], { dynamic: false });<commit_msg>Add type="button" on the buttons to prevent the button native submit<commit_after>/**
 * The Button Utility
 *
 * @module aui-button
 */

var Lang = A.Lang,

	getClassName = A.ClassNameManager.getClassName,

	NAME = 'button',

	ICON = 'icon',
	STATE = 'state',

	CSS_BUTTON = getClassName(NAME),
	CSS_BUTTON_ICON = getClassName(NAME, 'icon'),
	CSS_BUTTON_LABEL = getClassName(NAME, 'label'),

	CSS_BUTTON_ICON_LABEL = getClassName(NAME, 'icon', 'label'),

	CSS_ICON = getClassName(ICON),

	TPL_BUTTON = '<button type="button"></button>',
	TPL_ICON = '',
	TPL_LABEL = '';

	/**
	 * A base class for Button, providing:
	 *

	 *
Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)

	 *
An optional icon or label

	 *
Managed user interaction states (default, active, hover)

	 *
Keyboard accessible

	 *

	 *
	 * Quick Example:

	 *
	 *
var instance = new A.Button({
	 *	icon: 'gear',
	 * label: 'Configuration'
	 * }).render();
	 *

	 *
	 * Check the list of Configuration Attributes available for
	 * Button.
	 *
	 * @param config {Object} Object literal specifying widget configuration properties.
	 *
	 * @class Button
	 * @constructor
	 * @extends Component
	 * @uses WidgetChild
	 */

var Button = function(config) {
	if (Lang.isString(config)) {
		config = {
			icon: config
		};
	}

	Button.superclass.constructor.call(this, config);
};

/**
 * Static property provides a string to identify the class.
 *
 * @property Button.NAME
 * @type String
 * @static
 */

Button.NAME = NAME;

/**
 * Static property used to define the default attribute
 * configuration for the Button.
 *
 * @property Button.ATTRS
 * @type Object
 * @static
 */

Button.ATTRS = {
	/**
	 * Whether to track the active state of the button.
	 *
	 * @attribute activeState
	 * @default false
	 * @type Boolean
	 */
	activeState: {
		value: false
	},

	/**
	 * An object map of the CSS class names to use for the different interaction states.
	 *
	 * @attribute classNames
	 * @type Object
	 */
	classNames: {},

	/**
	 * Whether to apply the default interaction state to the button
	 *
	 * @attribute defaultState
	 * @default true
	 * @type Boolean
	 */
	defaultState: {},

	/**
	 * An event callback to handle when a user interacts with the button.
	 * This can either be a function that will be attached on click, or
	 * an object map that accepts the following keys:
	 * {fn: // The function to execute
	 * context: // The context to execute the function in
	 * type: // The type of event to listen for (defaults to "click")
	 * }
	 *
	 * @attribute handler
	 * @default false
	 * @type Function | Object
	 */
	handler: {
		lazyAdd: false,
		value: null,
		setter: function(value) {
			var instance = this;

			var fn = value;
			var context = instance;
			var args = instance;
			var type = 'click';

			if (Lang.isObject(fn)) {
				var handlerConfig = fn;

				fn = handlerConfig.fn || fn;
				context = handlerConfig.context || context;
				type = handlerConfig.type || type;
			}

			if (Lang.isFunction(fn)) {
				instance.on(type, A.rbind(fn, context, args, handlerConfig.args));
			}

			return value;
		}
	},

	/**
	 * Whether to track the hover interaction state of the button.
	 *
	 * @attribute hoverState
	 * @default true
	 * @type Boolean
	 */
	hoverState: {},

	/**
	 * The icon to use inside of the button. Possible values are:
	 *
	 * @attribute icon
	 * @type String
	 */
	icon: {
		value: ''
	},

	/**
	 * An id that can be used to identify a button.
	 *
	 * @attribute hoverState
	 * @type Boolean
	 */
	id: {
		valueFn: function() {
			return A.guid();
		}
	},

	/**
	 * Text to use inside of the button.
	 *
	 * @attribute label
	 * @type String
	 */
	label: {
		value: ''
	}
};

A.extend(
	Button,
	A.Component,
	{
		BOUNDING_TEMPLATE: TPL_BUTTON,
		CONTENT_TEMPLATE: null,

		/**
		 * Create the DOM structure for the Button. Lifecycle.
		 *
		 * @method renderUI
		 * @protected
		 */
		renderUI: function() {
			var instance = this;

			instance._renderStates();
		},

		/**
		 * Bind the events on the Button UI. Lifecycle.
		 *
		 * @method bindUI
		 * @protected
		 */
		bindUI: function() {
			var instance = this;

			instance.after('iconChange', instance._afterIconChange);
			instance.after('labelChange', instance._afterLabelChange);
		},

		/**
		 * Sync the Button UI. Lifecycle.
		 *
		 * @method syncUI
		 * @protected
		 */
		syncUI: function() {
			var instance = this;

			var icon = instance.get('icon');
			var label = instance.get('label');

			if (icon) {
				instance._uiSetIcon(icon)
			}

			if (label) {
				instance._uiSetLabel(label);
			}

		},

		/**
		 * Fires after the value of the
		 * icon attribute change.
		 *
		 * @method
		 * @param {EventFacade} event
		 * @protected
		 */
		_afterIconChange: function(event) {
			var instance = this;

			instance._uiSetIcon(event.newVal, event.prevVal);
		},

		/**
		 * Fires after the value of the
		 * label attribute change.
		 *
		 * @method
		 * @param {EventFacade} event
		 * @protected
		 */
		_afterLabelChange: function(event) {
			var instance = this;

			instance._uiSetLabel(event.newVal);
		},

		/**
		 * Get's a reference to the private icon node, or if not created,
		 * renders its and returns it.
		 *
		 * @method _getIconNode
		 * @protected
		 * @return {Node}
		 */
		_getIconNode: function() {
			var instance = this;

			return instance._iconNode || instance._renderIcon();
		},

		/**
		 * Get's a reference to the private label node, or if not created,
		 * renders its and returns it.
		 *
		 * @method _getLabelNode
		 * @protected
		 * @return {Node}
		 */
		_getLabelNode: function() {
			var instance = this;

			return instance._labelNode || instance._renderLabel();
		},

		/**
		 * Renders the underlying markup for the icon.
		 *
		 * @method _renderIcon
		 * @protected
		 * @return {Node}
		 */
		_renderIcon: function() {
			var instance = this;

			var iconNode = A.Node.create(TPL_ICON);

			instance._iconNode = iconNode;

			instance.get('boundingBox').appendChild(iconNode);

			return iconNode;
		},

		/**
		 * Renders the underlying markup for the label.
		 *
		 * @method _renderLabel
		 * @protected
		 * @return {Node}
		 */
		_renderLabel: function() {
			var instance = this;

			var labelNode = A.Node.create(TPL_LABEL);

			instance._labelNode = labelNode;

			instance.get('boundingBox').appendChild(labelNode);

			return labelNode;
		},

		/**
		 * Retrieves the state value from either the current instance, or if defined, the
		 * parent widget.
		 *
		 * @method _getState
		 * @param {String} key The state name to retrieve
		 * @param {Object} parent The parent widget to attempt to retrieve the state from
		 * @protected
		 * @return {Object}
		 */
		_getState: function(key, parent) {
			var instance = this;

			var value = instance.get(key);

			var state = value;

			if (parent) {
				value = parent.get(key);

				if (!Lang.isUndefined(value)) {
					state = value;
				}
			}

			return state;
		},

		/**
		 * Attaches state interaction management to the widget.
		 *
		 * @method _renderStates
		 * @param {EventFacade} event
		 * @protected
		 */
		_renderStates: function(event) {
			var instance = this;

			var parent = instance.get('parent');

			var activeState = instance._getState('activeState', parent);
			var classNames = instance._getState('classNames', parent);
			var defaultState = instance._getState('defaultState', parent);
			var hoverState = instance._getState('hoverState', parent);

			instance.plug(
				A.StateInteractionPlugin,
				{
					activeState: activeState,
					classNames: classNames,
					defaultState: defaultState,
					hoverState: hoverState
				}
			);
		},

		/**
		 * Updates the UI for the icon in response to the iconChange event.
		 *
		 * @method _uiSetIcon
		 * @param {String} newVal The new value
		 * @param {String} prevVal The previous value
		 * @protected
		 */
		_uiSetIcon: function(newVal, prevVal) {
			var instance = this;

			var iconNode = instance._getIconNode();

			var action = 'show';

			if (!newVal) {
				action = 'hide';
			}

			newVal = getClassName(ICON, newVal);

			if (prevVal) {
				prevVal = getClassName(ICON, prevVal);
			}

			iconNode.replaceClass(prevVal, newVal);

			var hasIconAndLabel = (newVal && instance.get('label'));

			iconNode[action]();

			instance.get('boundingBox').toggleClass(CSS_BUTTON_ICON_LABEL, hasIconAndLabel);
		},

		/**
		 * Updates the UI for the label in response to the labelChange event.
		 *
		 * @method _uiSetLabel
		 * @param {String} newVal The new value
		 * @protected
		 */
		_uiSetLabel: function(newVal) {
			var instance = this;

			var labelNode = instance._getLabelNode();

			var action = 'show';

			if (!newVal) {
				action = 'hide';
			}

			labelNode.text(newVal);

			labelNode[action]();

			var hasIconAndLabel = (newVal && instance.get('icon'));

			instance.get('boundingBox').toggleClass(CSS_BUTTON_ICON_LABEL, hasIconAndLabel);
		}
	}
);

A.Button = A.Base.build(NAME, Button, [A.WidgetChild], { dynamic: false });<|endoftext|>


<commit_before>import React from 'react';
import { Formik, Field, ErrorMessage } from 'formik';
import { Debug } from './Debug';

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

const required = value => (value ? undefined : 'Required');

class Wizard extends React.Component {
  static Page = ({ children }) => children;

  constructor(props) {
    super(props);
    this.state = {
      page: 0,
      values: props.initialValues,
    };
  }

  next = values =>
    this.setState(state => ({
      page: Math.min(state.page + 1, this.props.children.length - 1),
      values,
    }));

  previous = () =>
    this.setState(state => ({
      page: Math.max(state.page - 1, 0),
    }));

  validate = values => {
    const activePage = React.Children.toArray(this.props.children)[
      this.state.page
    ];
    return activePage.props.validate ? activePage.props.validate(values) : {};
  };

  handleSubmit = (values, bag) => {
    const { children, onSubmit } = this.props;
    const { page } = this.state;
    const isLastPage = page === React.Children.count(children) - 1;
    if (isLastPage) {
      return onSubmit(values, bag);
    } else {
      this.next(values);
      bag.setSubmitting(false);
    }
  };

  render() {
    const { children } = this.props;
    const { page, values } = this.state;
    const activePage = React.Children.toArray(children)[page];
    const isLastPage = page === React.Children.count(children) - 1;
    return (
      <Formik
        initialValues={values}
        enableReinitialize={false}
        validate={this.validate}
        onSubmit={this.handleSubmit}
        render={({ values, handleSubmit, isSubmitting, handleReset }) => (
          <form onSubmit={handleSubmit}>
            {activePage}

              {page > 0 && (
                <button
                  type="button"
                  className="secondary"
                  onClick={this.previous}
                >
                  « Previous
                </button>
              )}

              {!isLastPage && <button type="submit">Next »</button>}
              {isLastPage && (
                <button type="submit" disabled={isSubmitting}>
                  Submit
                </button>
              )}

            <Debug />
          </form>
        )}
      />
    );
  }
}

const App = () => (

Multistep / Form Wizard

    <Wizard
      initialValues={{
        firstName: '',
        lastName: '',
        email: '',
        favoriteColor: '',
      }}
      onSubmit={(values, actions) => {
        sleep(300).then(() => {
          window.alert(JSON.stringify(values, null, 2));
          actions.setSubmitting(false);
        });
      }}
    >
      <Wizard.Page>

          First Name
          <Field
            name="firstName"
            component="input"
            type="text"
            placeholder="First Name"
            validate={required}
          />
          <ErrorMessage
            name="firstName"
            component="div"
            className="field-error"
          />

          Last Name
          <Field
            name="lastName"
            component="input"
            type="text"
            placeholder="Last Name"
            validate={required}
          />
          <ErrorMessage
            name="lastName"
            component="div"
            className="field-error"
          />

      </Wizard.Page>
      <Wizard.Page
        validate={values => {
          const errors = {};
          if (!values.email) {
            errors.email = 'Required';
          }
          if (!values.favoriteColor) {
            errors.favoriteColor = 'Required';
          }
          return errors;
        }}
      >

          Email
          <Field
            name="email"
            component="input"
            type="email"
            placeholder="Email"
          />
          <ErrorMessage name="email" component="div" className="field-error" />

          Favorite Color
          <Field name="favoriteColor" component="select">
            <option value="">Select a Color</option>
            <option value="#ff0000">❤ Red</option>
            <option value="#00ff00">💚 Green</option>
            <option value="#0000ff">💙 Blue</option>
          </Field>
          <ErrorMessage
            name="favoriteColor"
            component="div"
            className="field-error"
          />

      </Wizard.Page>
    </Wizard>

);

export default App;
<commit_msg>update MultistepWizard to reset touched object on navigating to next page of a multistep form (#928)<commit_after>import React from 'react';
import { Formik, Field, ErrorMessage } from 'formik';
import { Debug } from './Debug';

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

const required = value => (value ? undefined : 'Required');

class Wizard extends React.Component {
  static Page = ({ children }) => children;

  constructor(props) {
    super(props);
    this.state = {
      page: 0,
      values: props.initialValues,
    };
  }

  next = values =>
    this.setState(state => ({
      page: Math.min(state.page + 1, this.props.children.length - 1),
      values,
    }));

  previous = () =>
    this.setState(state => ({
      page: Math.max(state.page - 1, 0),
    }));

  validate = values => {
    const activePage = React.Children.toArray(this.props.children)[
      this.state.page
    ];
    return activePage.props.validate ? activePage.props.validate(values) : {};
  };

  handleSubmit = (values, bag) => {
    const { children, onSubmit } = this.props;
    const { page } = this.state;
    const isLastPage = page === React.Children.count(children) - 1;
    if (isLastPage) {
      return onSubmit(values, bag);
    } else {
      this.next(values);
      bag.setTouched({});
      bag.setSubmitting(false);
    }
  };

  render() {
    const { children } = this.props;
    const { page, values } = this.state;
    const activePage = React.Children.toArray(children)[page];
    const isLastPage = page === React.Children.count(children) - 1;
    return (
      <Formik
        initialValues={values}
        enableReinitialize={false}
        validate={this.validate}
        onSubmit={this.handleSubmit}
        render={({ values, handleSubmit, isSubmitting, handleReset }) => (
          <form onSubmit={handleSubmit}>
            {activePage}

              {page > 0 && (
                <button
                  type="button"
                  className="secondary"
                  onClick={this.previous}
                >
                  « Previous
                </button>
              )}

              {!isLastPage && <button type="submit">Next »</button>}
              {isLastPage && (
                <button type="submit" disabled={isSubmitting}>
                  Submit
                </button>
              )}

            <Debug />
          </form>
        )}
      />
    );
  }
}

const App = () => (

Multistep / Form Wizard

    <Wizard
      initialValues={{
        firstName: '',
        lastName: '',
        email: '',
        favoriteColor: '',
      }}
      onSubmit={(values, actions) => {
        sleep(300).then(() => {
          window.alert(JSON.stringify(values, null, 2));
          actions.setSubmitting(false);
        });
      }}
    >
      <Wizard.Page>

          First Name
          <Field
            name="firstName"
            component="input"
            type="text"
            placeholder="First Name"
            validate={required}
          />
          <ErrorMessage
            name="firstName"
            component="div"
            className="field-error"
          />

          Last Name
          <Field
            name="lastName"
            component="input"
            type="text"
            placeholder="Last Name"
            validate={required}
          />
          <ErrorMessage
            name="lastName"
            component="div"
            className="field-error"
          />

      </Wizard.Page>
      <Wizard.Page
        validate={values => {
          const errors = {};
          if (!values.email) {
            errors.email = 'Required';
          }
          if (!values.favoriteColor) {
            errors.favoriteColor = 'Required';
          }
          return errors;
        }}
      >

          Email
          <Field
            name="email"
            component="input"
            type="email"
            placeholder="Email"
          />
          <ErrorMessage name="email" component="div" className="field-error" />

          Favorite Color
          <Field name="favoriteColor" component="select">
            <option value="">Select a Color</option>
            <option value="#ff0000">❤ Red</option>
            <option value="#00ff00">💚 Green</option>
            <option value="#0000ff">💙 Blue</option>
          </Field>
          <ErrorMessage
            name="favoriteColor"
            component="div"
            className="field-error"
          />

      </Wizard.Page>
    </Wizard>

);

export default App;
<|endoftext|>


<commit_before>define(['app',
	'scbd-angularjs-filters',
	'./view-history-directive.html.js',
    '/app/js/common.js',
    '/app/views/directives/document-metadata-directive.html.js',
	'/app/views/directives/help-directive.html.js',
    '/app/views/directives/internal-record-details.js',
    '/app/views/directives/party-status.js',
    '/app/views/forms/view/view-contact-reference.directive.js'
    ], function (app) {
app.directive('recordLoader', [function () {
	return {
		restrict: 'EAC',
		templateUrl: '/app/views/forms/view/record-loader.directive.html',
		replace: true,
		transclude: false,
		scope: {
			linkTarget: "@",
			document: "=",
			locale  : "=",
			hide: "@",
            showDetails: "="
		},
		link: function($scope) {

            if(!$scope.linkTarget || $scope.linkTarget == '')
				$scope.linkTarget = '_new';
			//debugger;
			$scope.internalDocument     = undefined;
			$scope.internalDocumentInfo = undefined;

			if(!$scope.document)
				$scope.init();
		},
		controller: ['$scope', "$route", 'IStorage', "authentication", "$q", "$location", "commonjs","$timeout",
		"$filter","$http","$http","realm", "$element", '$compile',
			function ($scope, $route, storage, authentication, $q, $location,
				commonjs,$timeout, $filter, $http, $httpAWS, realm, $element, $compile) {
				var schemaMapping = {
					news 				       : '/app/views/forms/view/view-news.directive.html.js',
					absnationalreport 	       : '/app/views/forms/view/view-abs-national-report.directive.js',
					abscheckpoint		       : '/app/views/forms/view/view-abs-checkpoint.directive.js',
				    abscheckpointcommunique    : '/app/views/forms/view/view-abs-checkpoint-communique.directive.js',
				    abspermit			       : '/app/views/forms/view/view-abs-permit.directive.js',
				    authority			       : '/app/views/forms/view/view-authority.directive.js',
				    authorityreference	       : '/app/views/forms/view/view-authority-reference.directive.js',
				    contact				       : '/app/views/forms/view/view-contact.directive.js',
				    contactreference	       : '/app/views/forms/view/view-contact-reference.directive.js',
				    database			       : '/app/views/forms/view/view-database.directive.js',
				    measure				       : '/app/views/forms/view/view-measure.directive.js',
				    organization		       : '/app/views/forms/view/view-organization.directive.js',
				    organizationreference      : '/app/views/forms/view/view-organization-reference.directive.js',
				    resource			       : '/app/views/forms/view/view-resource.directive.js',
				    focalpoint			       : '/app/views/forms/view/view-focalpoint.directive.html.js',
				    meeting				       : '/app/views/forms/view/view-meeting.directive.html.js',
				    statement			       : '/app/views/forms/view/view-statement.directive.html.js',
				    pressrelease		       : '/app/views/forms/view/view-pressrelease.directive.html.js',
				    new					       : '/app/views/forms/view/view-new.directive.html.js',
				    notification		       : '/app/views/forms/view/view-notification.directive.html.js',
					capacitybuildinginitiative : '/app/views/forms/view/view-capacity-building-initiative.directive.js',
					capacitybuildingresource   : '/app/views/forms/view/view-capacity-building-resource.directive.js'
				}

			$scope.$watch("document", function(_new) {
				$scope.error = null;
				$scope.internalDocument = _new;
				if($scope.internalDocument && ($scope.internalDocument.schema || $scope.internalDocument.header)){
					loadViewDirective($scope.internalDocument.schema || $scope.internalDocument.header.schema);
				}
			});

               $scope.getUserCountry = function(id){
                        var term = {};
                        term.identifier = id
                        return $filter('term')(term);
                   }
			//==================================
			//
			//==================================
			$scope.init = function () {

				if ($scope.internalDocument && !$scope.revisionNo)
					return;

				if ($scope.document || $scope.schema)
					return;

				var documentSchema = $route.current.params.documentSchema;
				var documentRevision = $route.current.params.revision;

				var documentID = documentSchema ? commonjs.integerToHex($route.current.params.documentID, documentSchema) : $route.current.params.documentID;

				if($scope.revisionNo)
					documentRevision = $scope.revisionNo;

				if($route.current.params.documentNumber)
					var documentID = $route.current.params.documentNumber;

				if(documentID && documentID.toLowerCase().indexOf('absch')==0){
					var docNum = documentID.split('-');
					if(docNum.length ==5){
						documentID = documentID.toLowerCase();//.replace('absch','ABSCH');
						$scope.documentUID = documentID.toUpperCase();
						var schemaFolder = $filter("mapSchema")(docNum[1]);
						$scope.documentUrl = "https://s3.amazonaws.com/absch.documents." + realm.value.toLowerCase() + "/" + schemaFolder + '/' +  documentID + '.pdf?id=' + new Date();

						$httpAWS.head($scope.documentUrl,{cache:false}).then(function(success){
							$scope.documentSuccess = true;
							window.location.href = $scope.documentUrl;
							closeWindow();
						},
						function(error){
							$scope.documentError = true;
							console.log(error);
						});

						return;
					}
					if(docNum.length <= 4)
						documentID = docNum[docNum.length-1];

				}

				$scope.loadDocument(documentSchema,documentID,documentRevision);
				// else
				// 	$scope.error = "documentID not specified";

			}

            //==================================
			//
			//==================================
			$scope.loadDocument = function(documentSchema,documentID,documentRevision){

				if(documentSchema &&
				_.contains(["FOCALPOINT", "MEETING", "NOTIFICATION", "PRESSRELEASE", "STATEMENT", "NEWS", "NEW", "NFP", "ST", "NT", "MT", "PR", "MTD"],  documentSchema.toUpperCase()))
				{
					commonjs.getReferenceRecordIndex(documentSchema, documentID).then(function(data){
						$scope.internalDocument = data.data;
					});
					loadViewDirective(documentSchema);
				}
				else if (documentID){
					$scope.load(documentID, documentRevision);
				}
			};

			$scope.timeLaspe = 20;
			function closeWindow(){
				if($scope.timeLaspe==0)
					window.close();
				$scope.timeLaspe--;
				$timeout(function(){closeWindow();},1000)
			}
			//==================================
			//
			//==================================
			$scope.getLocale = function () {
				return $scope.$root.locale;
			}

			//==================================
			//
			//==================================
			$scope.load = function (identifier, version) {

				$scope.error = undefined;
				var qDocument;
				var qDocumentInfo;
				if(version=='draft'){
                    qDocument = storage.drafts.get(identifier).then(function(result) { return result.data || result });
                    qDocumentInfo = storage.drafts.get(identifier,{ info: true}).then(function(result) { return result.data || result });
                }
                else if(version==undefined){
					qDocument = storage.documents.get(identifier).then(function(result) { return result.data || result });
                    qDocumentInfo = storage.documents.get(identifier,{ info: true}).then(function(result) { return result.data || result });
				}
				else{
					qDocument = storage.documentVersions.get(identifier,{'version':version}).then(function(result) { return result.data || result });
                    qDocumentInfo = storage.documentVersions.get(identifier,{ info: true}).then(function(result) { return result.data || result });
				}
				$q.all([qDocument, qDocumentInfo]).then(function(results) {

					$scope.internalDocument     = results[0];
					$scope.internalDocumentInfo = results[1];
					$scope.internalDocument.info = results[1];

					$scope.documentVersionCount = $scope.internalDocumentInfo.revision

					if(version && $scope.internalDocumentInfo.revision != version){
						$scope.internalDocumentInfo.revision = version;
					}
					if(version)
						$scope.revisionNo  = version
					else
						$scope.revisionNo  = $scope.documentVersionCount

					loadViewDirective($scope.internalDocument.header.schema);

				}).catch(function(error){
						if(error.status == 404 && version!= 'draft'){
							$scope.load(identifier, 'draft');
						}
					})
				.finally(function(){
						$scope.loading = false;
		        })

			};

			//==================================
			//
			//==================================
			$scope.getUser = function() {

				if(!$scope.user)
				 	$q.when(authentication.getUser(), function(user){ $scope.user = user; });

				return $scope.user
			};

			//==================================
			//
			//==================================
			$scope.edit = function() {
				if (!$scope.canEdit())
					throw "Cannot edit form";

				var schema     = $scope.internalDocumentInfo.type;
				var identifier = $scope.internalDocumentInfo.identifier;
				$timeout(function(){
					$location.path("/register/" + $filter("mapSchema")(schema) + "/" + identifier + '/edit');},1);

			}

			//==================================
			//
			//==================================
			$scope.canEdit = function() {

				if ($scope.getUser() && !$scope.getUser().isAuthenticated)
					return false;

				if(!$scope.internalDocumentInfo && $scope.internalDocument && $scope.internalDocument.info)
				{
					$scope.internalDocumentInfo = $scope.internalDocument.info;
				}

				if (!$scope.internalDocumentInfo)
					return false;
				if ($scope.internalCanEdit === undefined) {

					$scope.internalCanEdit = null; // avoid recall => null !== undefined

					var hasDraft   = !!$scope.internalDocumentInfo.workingDocumentCreatedOn;
					var identifier =   $scope.internalDocumentInfo.identifier;
					var schema     =   $scope.internalDocumentInfo.type;

					var qCanEdit = hasDraft
							     ? storage.drafts.security.canUpdate(identifier, schema)  // has draft
								 : storage.drafts.security.canCreate(identifier, schema); // has no draft

					qCanEdit.then(function(isAllowed) {

						$scope.internalCanEdit = isAllowed || false;

					}).then(null, function(error) {

						$scope.internalCanEdit = false;
					});
				}

				return $scope.internalCanEdit===true;
			};

			$scope.loadRevision = function(val){

				if($scope.revisionNo!=val){
					$scope.revisionNo=val;
					//$scope.internalDocument = null
					$scope.init();
				}
			}

			$scope.$on('loadDocument', function(evt, evtData){

				if(evtData.documentId && evtData.schema && !$scope.document){

					$scope.loadDocument(evtData.schema,evtData.documentId);
				}
				if($scope.document){
					loadViewDirective(evtData.schema)
				}

			});

			function loadViewDirective(schema){

				if(!schema)
					return;

				var lschema = _.clone(schema);

				if(schema.toLowerCase() == 'modelcontractualclause' || schema.toLowerCase() == 'communityprotocol')
					lschema = 'resource';

				if(_.contains(["NEWS", "NEW",], lschema.toUpperCase()))
					lschema = lschema.toLowerCase();
				else if(_.contains(["NFP", "ST", "NT", "MT", "PR", "MTD"], lschema.toUpperCase()))
					lschema = $filter("mapSchema")(lschema);

				var schemaDetails = schemaMapping[lschema.toLowerCase()];

				require([schemaDetails], function() {

					var name = snake_case(lschema);

					var directiveHtml =
						"<DIRECTIVE ng-show='internalDocument' ng-model='internalDocument' document-info='internalDocumentInfo' locale='getLocale()' link-target={{linkTarget}}></DIRECTIVE>"
						.replace(/DIRECTIVE/g, 'view-' + name);

                    $scope.$apply(function() {
						$element.find('#schemaView')
							.empty()
                            .append($compile(directiveHtml)($scope));
                    });
                });

			}
			function snake_case(name, separator) {

			  separator = separator || '-';
			  return name.replace(/[A-Z]/g, function(letter, pos) {
			    return (pos ? separator : '') + letter.toLowerCase();
			  });
			}

		}]
	}
}]);
});
<commit_msg>use new version way to get documents@version<commit_after>define(['app',
	'scbd-angularjs-filters',
	'./view-history-directive.html.js',
    '/app/js/common.js',
    '/app/views/directives/document-metadata-directive.html.js',
	'/app/views/directives/help-directive.html.js',
    '/app/views/directives/internal-record-details.js',
    '/app/views/directives/party-status.js',
    '/app/views/forms/view/view-contact-reference.directive.js'
    ], function (app) {
app.directive('recordLoader', [function () {
	return {
		restrict: 'EAC',
		templateUrl: '/app/views/forms/view/record-loader.directive.html',
		replace: true,
		transclude: false,
		scope: {
			linkTarget: "@",
			document: "=",
			locale  : "=",
			hide: "@",
            showDetails: "="
		},
		link: function($scope) {

            if(!$scope.linkTarget || $scope.linkTarget == '')
				$scope.linkTarget = '_new';
			//debugger;
			$scope.internalDocument     = undefined;
			$scope.internalDocumentInfo = undefined;

			if(!$scope.document)
				$scope.init();
		},
		controller: ['$scope', "$route", 'IStorage', "authentication", "$q", "$location", "commonjs","$timeout",
		"$filter","$http","$http","realm", "$element", '$compile',
			function ($scope, $route, storage, authentication, $q, $location,
				commonjs,$timeout, $filter, $http, $httpAWS, realm, $element, $compile) {
				var schemaMapping = {
					news 				       : '/app/views/forms/view/view-news.directive.html.js',
					absnationalreport 	       : '/app/views/forms/view/view-abs-national-report.directive.js',
					abscheckpoint		       : '/app/views/forms/view/view-abs-checkpoint.directive.js',
				    abscheckpointcommunique    : '/app/views/forms/view/view-abs-checkpoint-communique.directive.js',
				    abspermit			       : '/app/views/forms/view/view-abs-permit.directive.js',
				    authority			       : '/app/views/forms/view/view-authority.directive.js',
				    authorityreference	       : '/app/views/forms/view/view-authority-reference.directive.js',
				    contact				       : '/app/views/forms/view/view-contact.directive.js',
				    contactreference	       : '/app/views/forms/view/view-contact-reference.directive.js',
				    database			       : '/app/views/forms/view/view-database.directive.js',
				    measure				       : '/app/views/forms/view/view-measure.directive.js',
				    organization		       : '/app/views/forms/view/view-organization.directive.js',
				    organizationreference      : '/app/views/forms/view/view-organization-reference.directive.js',
				    resource			       : '/app/views/forms/view/view-resource.directive.js',
				    focalpoint			       : '/app/views/forms/view/view-focalpoint.directive.html.js',
				    meeting				       : '/app/views/forms/view/view-meeting.directive.html.js',
				    statement			       : '/app/views/forms/view/view-statement.directive.html.js',
				    pressrelease		       : '/app/views/forms/view/view-pressrelease.directive.html.js',
				    new					       : '/app/views/forms/view/view-new.directive.html.js',
				    notification		       : '/app/views/forms/view/view-notification.directive.html.js',
					capacitybuildinginitiative : '/app/views/forms/view/view-capacity-building-initiative.directive.js',
					capacitybuildingresource   : '/app/views/forms/view/view-capacity-building-resource.directive.js'
				}

			$scope.$watch("document", function(_new) {
				$scope.error = null;
				$scope.internalDocument = _new;
				if($scope.internalDocument && ($scope.internalDocument.schema || $scope.internalDocument.header)){
					loadViewDirective($scope.internalDocument.schema || $scope.internalDocument.header.schema);
				}
			});

               $scope.getUserCountry = function(id){
                        var term = {};
                        term.identifier = id
                        return $filter('term')(term);
                   }
			//==================================
			//
			//==================================
			$scope.init = function () {

				if ($scope.internalDocument && !$scope.revisionNo)
					return;

				if ($scope.document || $scope.schema)
					return;

				var documentSchema = $route.current.params.documentSchema;
				var documentRevision = $route.current.params.revision;

				var documentID = documentSchema ? commonjs.integerToHex($route.current.params.documentID, documentSchema) : $route.current.params.documentID;

				if($scope.revisionNo)
					documentRevision = $scope.revisionNo;

				if($route.current.params.documentNumber)
					var documentID = $route.current.params.documentNumber;

				if(documentID && documentID.toLowerCase().indexOf('absch')==0){
					var docNum = documentID.split('-');
					if(docNum.length ==5){
						documentID = documentID.toLowerCase();//.replace('absch','ABSCH');
						$scope.documentUID = documentID.toUpperCase();
						var schemaFolder = $filter("mapSchema")(docNum[1]);
						$scope.documentUrl = "https://s3.amazonaws.com/absch.documents." + realm.value.toLowerCase() + "/" + schemaFolder + '/' +  documentID + '.pdf?id=' + new Date();

						$httpAWS.head($scope.documentUrl,{cache:false}).then(function(success){
							$scope.documentSuccess = true;
							window.location.href = $scope.documentUrl;
							closeWindow();
						},
						function(error){
							$scope.documentError = true;
							console.log(error);
						});

						return;
					}
					if(docNum.length <= 4)
						documentID = docNum[docNum.length-1];

				}

				$scope.loadDocument(documentSchema,documentID,documentRevision);
				// else
				// 	$scope.error = "documentID not specified";

			}

            //==================================
			//
			//==================================
			$scope.loadDocument = function(documentSchema,documentID,documentRevision){

				if(documentSchema &&
				_.contains(["FOCALPOINT", "MEETING", "NOTIFICATION", "PRESSRELEASE", "STATEMENT", "NEWS", "NEW", "NFP", "ST", "NT", "MT", "PR", "MTD"],  documentSchema.toUpperCase()))
				{
					commonjs.getReferenceRecordIndex(documentSchema, documentID).then(function(data){
						$scope.internalDocument = data.data;
					});
					loadViewDirective(documentSchema);
				}
				else if (documentID){
					$scope.load(documentID, documentRevision);
				}
			};

			$scope.timeLaspe = 20;
			function closeWindow(){
				if($scope.timeLaspe==0)
					window.close();
				$scope.timeLaspe--;
				$timeout(function(){closeWindow();},1000)
			}
			//==================================
			//
			//==================================
			$scope.getLocale = function () {
				return $scope.$root.locale;
			}

			//==================================
			//
			//==================================
			$scope.load = function (identifier, version) {

				$scope.error = undefined;
				var qDocument;
				var qDocumentInfo;
				if(version=='draft'){
                    qDocument = storage.drafts.get(identifier).then(function(result) { return result.data || result });
                    qDocumentInfo = storage.drafts.get(identifier,{ info: true}).then(function(result) { return result.data || result });
                }
                else if(version==undefined){
					qDocument = storage.documents.get(identifier).then(function(result) { return result.data || result });
                    qDocumentInfo = storage.documents.get(identifier,{ info: true}).then(function(result) { return result.data || result });
				}
				else{
					qDocument = storage.documents.get(identifier + '@' + version).then(function(result) { return result.data || result });
                    qDocumentInfo = storage.documents.get(identifier + '@' + version,{ info: true}).then(function(result) { return result.data || result });
				}
				$q.all([qDocument, qDocumentInfo]).then(function(results) {

					$scope.internalDocument     = results[0];
					$scope.internalDocumentInfo = results[1];
					$scope.internalDocument.info = results[1];

					$scope.documentVersionCount = $scope.internalDocumentInfo.revision

					if(version && $scope.internalDocumentInfo.revision != version){
						$scope.internalDocumentInfo.revision = version;
					}
					if(version)
						$scope.revisionNo  = version
					else
						$scope.revisionNo  = $scope.documentVersionCount

					loadViewDirective($scope.internalDocument.header.schema);

				}).catch(function(error){
						if(error.status == 404 && version!= 'draft'){
							$scope.load(identifier, 'draft');
						}
					})
				.finally(function(){
						$scope.loading = false;
		        })

			};

			//==================================
			//
			//==================================
			$scope.getUser = function() {

				if(!$scope.user)
				 	$q.when(authentication.getUser(), function(user){ $scope.user = user; });

				return $scope.user
			};

			//==================================
			//
			//==================================
			$scope.edit = function() {
				if (!$scope.canEdit())
					throw "Cannot edit form";

				var schema     = $scope.internalDocumentInfo.type;
				var identifier = $scope.internalDocumentInfo.identifier;
				$timeout(function(){
					$location.path("/register/" + $filter("mapSchema")(schema) + "/" + identifier + '/edit');},1);

			}

			//==================================
			//
			//==================================
			$scope.canEdit = function() {

				if ($scope.getUser() && !$scope.getUser().isAuthenticated)
					return false;

				if(!$scope.internalDocumentInfo && $scope.internalDocument && $scope.internalDocument.info)
				{
					$scope.internalDocumentInfo = $scope.internalDocument.info;
				}

				if (!$scope.internalDocumentInfo)
					return false;
				if ($scope.internalCanEdit === undefined) {

					$scope.internalCanEdit = null; // avoid recall => null !== undefined

					var hasDraft   = !!$scope.internalDocumentInfo.workingDocumentCreatedOn;
					var identifier =   $scope.internalDocumentInfo.identifier;
					var schema     =   $scope.internalDocumentInfo.type;

					var qCanEdit = hasDraft
							     ? storage.drafts.security.canUpdate(identifier, schema)  // has draft
								 : storage.drafts.security.canCreate(identifier, schema); // has no draft

					qCanEdit.then(function(isAllowed) {

						$scope.internalCanEdit = isAllowed || false;

					}).then(null, function(error) {

						$scope.internalCanEdit = false;
					});
				}

				return $scope.internalCanEdit===true;
			};

			$scope.loadRevision = function(val){

				if($scope.revisionNo!=val){
					$scope.revisionNo=val;
					//$scope.internalDocument = null
					$scope.init();
				}
			}

			$scope.$on('loadDocument', function(evt, evtData){

				if(evtData.documentId && evtData.schema && !$scope.document){

					$scope.loadDocument(evtData.schema,evtData.documentId);
				}
				if($scope.document){
					loadViewDirective(evtData.schema)
				}

			});

			function loadViewDirective(schema){

				if(!schema)
					return;

				var lschema = _.clone(schema);

				if(schema.toLowerCase() == 'modelcontractualclause' || schema.toLowerCase() == 'communityprotocol')
					lschema = 'resource';

				if(_.contains(["NEWS", "NEW",], lschema.toUpperCase()))
					lschema = lschema.toLowerCase();
				else if(_.contains(["NFP", "ST", "NT", "MT", "PR", "MTD"], lschema.toUpperCase()))
					lschema = $filter("mapSchema")(lschema);

				var schemaDetails = schemaMapping[lschema.toLowerCase()];

				require([schemaDetails], function() {

					var name = snake_case(lschema);

					var directiveHtml =
						"<DIRECTIVE ng-show='internalDocument' ng-model='internalDocument' document-info='internalDocumentInfo' locale='getLocale()' link-target={{linkTarget}}></DIRECTIVE>"
						.replace(/DIRECTIVE/g, 'view-' + name);

                    $scope.$apply(function() {
						$element.find('#schemaView')
							.empty()
                            .append($compile(directiveHtml)($scope));
                    });
                });

			}
			function snake_case(name, separator) {

			  separator = separator || '-';
			  return name.replace(/[A-Z]/g, function(letter, pos) {
			    return (pos ? separator : '') + letter.toLowerCase();
			  });
			}

		}]
	}
}]);
});
<|endoftext|>