<commit_before>piggydb.namespace("piggydb.widget", {

});

/**
 *  The base class for HTML widgets
 */
piggydb.widget.Widget = function(jQueryElement) {
	this.element = jQueryElement;
};
piggydb.widget.Widget.prototype = {

  saveState: function(name, value) {
  	piggydb.server.putSessionValue(name, value);
  }
};

/**
 *  Facebox based on facebox (http://famspam.com/facebox)
 */
piggydb.widget.Facebox = function(id) {
	piggydb.widget.Widget.call(this, jQuery('\

 \

 \

 \

 \

 \
           \

 \

 \
           \
           \

 \
              \
              \

 \

 \
          	 \
           \

 \

 \
           \

 \

 \

 \

 \

'));

  this.id = id;
  this.body = this.element.find('.body');
  this.content = this.element.find('.content');
};
piggydb.widget.Facebox.prototype = jQuery.extend({

  show: function(url) {
    this.init();
    this.loading();

    var outer = this;
    jQuery.get(url, function(data) {
    	outer.reveal(data);
	  });
  },

  showImage: function(url) {
    this.init();
    this.loading();

    var maxWidth = jQuery(window).width() - 80;
    var maxHeight = jQuery(window).height() - 120;
    var image = new Image();
    var outer = this;
    image.onload = function() {
    	outer.reveal('

');
      var width = image.width < maxWidth ? image.width : maxWidth;
      var height = image.height < maxHeight ? image.height : maxHeight;
      if (width < maxWidth && height == maxHeight) width = Math.min(width + 15, maxWidth);
      if (height < maxHeight && width == maxWidth) height = Math.min(height + 15, maxHeight);
      outer.content.css({
	      'width':  width,
	      'height': height
	    });
    };
    image.src = url;
  },

  init: function() {
    jQuery('#' + this.id).remove();
    this.content.empty();
    this.element.find(".close").click(this.onCloseClick);
    this.element.appendTo(jQuery('body'));
  },

  loading: function () {
	  if (this.element.find('.loading').length == 1) return true;

	  this.body.children().hide().end().
	  	append('

');
	  this.element.show();
	},

	reveal: function (data) {
    this.content.append(data);
    this.element.find('.loading').remove();
    this.body.children().fadeIn('normal');
	},

  onCloseClick: function () {
    var element = jQuery(this).closest(".facebox");
    element.fadeOut(function() {
    	element.find('.loading').remove();
	  });
	  return false;
	}
}, piggydb.widget.Widget.prototype);

/**
 *  ShowHideToggle
 */
piggydb.widget.ShowHideToggle = function(id, target) {
  this.id = id;
  this.target = target;
  this.onShow = null;

  this.widget = jQuery('#' + id);
  this.icon = this.widget.children("img");

  var outer = this;
  this.widget.click(function() {
    outer.onToggleClick();
    return false;
  });
};
piggydb.widget.ShowHideToggle.prototype = jQuery.extend({

  SHOW: "down",
  HIDE: "up",

  onToggleClick: function() {
    var iconSrc = this.icon.attr("src");
    var stateKey = "state." + this.id;
    if (iconSrc.indexOf(this.SHOW) != -1) {
      this.icon.attr("src", iconSrc.replace(this.SHOW, this.HIDE));
      this.target.slideDown("fast");
      this.saveState(stateKey, "shown");
      if (this.onShow) this.onShow();
    }
    else if (iconSrc.indexOf(this.HIDE) != -1) {
      this.target.slideUp("fast");
      this.icon.attr("src", iconSrc.replace(this.HIDE, this.SHOW));
      this.saveState(stateKey, "hidden");
    }
  }
}, piggydb.widget.Widget.prototype);

<commit_msg>#refactoring #javascript: updated ShowHideToggle to follow the Widget rule<commit_after>piggydb.namespace("piggydb.widget", {

});

/**
 *  The base class for HTML widgets
 */
piggydb.widget.Widget = function(jQueryElement) {
	this.element = jQueryElement;
};
piggydb.widget.Widget.prototype = {

  saveState: function(name, value) {
  	piggydb.server.putSessionValue(name, value);
  }
};

/**
 *  Facebox based on facebox (http://famspam.com/facebox)
 */
piggydb.widget.Facebox = function(id) {
	piggydb.widget.Widget.call(this, jQuery('\

 \

 \

 \

 \

 \
           \

 \

 \
           \
           \

 \
              \
              \

 \

 \
          	 \
           \

 \

 \
           \

 \

 \

 \

 \

'));

  this.id = id;
  this.body = this.element.find('.body');
  this.content = this.element.find('.content');
};
piggydb.widget.Facebox.prototype = jQuery.extend({

  show: function(url) {
    this.init();
    this.loading();

    var outer = this;
    jQuery.get(url, function(data) {
    	outer.reveal(data);
	  });
  },

  showImage: function(url) {
    this.init();
    this.loading();

    var maxWidth = jQuery(window).width() - 80;
    var maxHeight = jQuery(window).height() - 120;
    var image = new Image();
    var outer = this;
    image.onload = function() {
    	outer.reveal('

');
      var width = image.width < maxWidth ? image.width : maxWidth;
      var height = image.height < maxHeight ? image.height : maxHeight;
      if (width < maxWidth && height == maxHeight) width = Math.min(width + 15, maxWidth);
      if (height < maxHeight && width == maxWidth) height = Math.min(height + 15, maxHeight);
      outer.content.css({
	      'width':  width,
	      'height': height
	    });
    };
    image.src = url;
  },

  init: function() {
    jQuery('#' + this.id).remove();
    this.content.empty();
    this.element.find(".close").click(this.onCloseClick);
    this.element.appendTo(jQuery('body'));
  },

  loading: function () {
	  if (this.element.find('.loading').length == 1) return true;

	  this.body.children().hide().end().
	  	append('

');
	  this.element.show();
	},

	reveal: function (data) {
    this.content.append(data);
    this.element.find('.loading').remove();
    this.body.children().fadeIn('normal');
	},

  onCloseClick: function () {
    var element = jQuery(this).closest(".facebox");
    element.fadeOut(function() {
    	element.find('.loading').remove();
	  });
	  return false;
	}
}, piggydb.widget.Widget.prototype);

/**
 *  ShowHideToggle
 */
piggydb.widget.ShowHideToggle = function(id, target) {
	piggydb.widget.Widget.call(this, jQuery('#' + id));

  this.id = id;
  this.target = target;
  this.onShow = null;
  this.icon = this.element.children("img");

  var outer = this;
  this.element.click(function() {
    outer.onToggleClick();
    return false;
  });
};
piggydb.widget.ShowHideToggle.prototype = jQuery.extend({

  SHOW: "down",
  HIDE: "up",

  onToggleClick: function() {
    var iconSrc = this.icon.attr("src");
    var stateKey = "state." + this.id;
    if (iconSrc.indexOf(this.SHOW) != -1) {
      this.icon.attr("src", iconSrc.replace(this.SHOW, this.HIDE));
      this.target.slideDown("fast");
      this.saveState(stateKey, "shown");
      if (this.onShow) this.onShow();
    }
    else if (iconSrc.indexOf(this.HIDE) != -1) {
      this.target.slideUp("fast");
      this.icon.attr("src", iconSrc.replace(this.HIDE, this.SHOW));
      this.saveState(stateKey, "hidden");
    }
  }
}, piggydb.widget.Widget.prototype);

<|endoftext|>


<commit_before>/*jslint indent: 2 */
/*global document: false, chrome: false, $: false, createLink: false, createProjectSelect: false*/

(function () {
  "use strict";
  var iframeRegex = /oauth2relay/, userData = null,
    selectedProjectId = null, selectedProjectBillable = false;

  function createTimerLink(taskName) {
    var link = createLink('toggl-button teambox');
    link.addEventListener("click", function (e) {
      chrome.extension.sendMessage({
        type: 'timeEntry',
        description: taskName,
        projectId: selectedProjectId,
        billable: selectedProjectBillable
      });
      link.innerHTML = "Started...";
      return false;
    });
    return link;
  }

  function addButton(e) {
    if (e.target.className === "comments" || iframeRegex.test(e.target.name)) {
      var task = e.target.parentNode.parentNode.parentNode,
          nameHolder = task.querySelector('.name_holder .name'),
          title = nameHolder.innerHTML;

      var projectSelect = createProjectSelect(userData, "toggl-select teambox");

      //make sure we init the values when switching between tasks
      selectedProjectId = null;
      selectedProjectBillable = false;

      projectSelect.onchange = function (event) {
        selectedProjectId = event.target.options[event.target.selectedIndex].value;
        if (selectedProjectId !== "default") {
          selectedProjectBillable = userData.projects.filter(function (elem, index, array) {
            return (elem.id === selectedProjectId);
          })[0].billable;
        } else {
          selectedProjectId = null;
          selectedProjectBillable = false;
        }
      };

      nameHolder.parentNode.insertBefore(createTimerLink(title), nameHolder.nextSibling);
      nameHolder.parentNode.insertBefore(projectSelect, nameHolder.nextSibling);
    }
  }

  chrome.extension.sendMessage({type: 'activate'}, function (response) {
    if (response.success) {
      userData = response.user;
      document.addEventListener("DOMNodeInserted", addButton);
    }
  });

}());
<commit_msg>added pre-selection of project in teambox.js too<commit_after>/*jslint indent: 2 */
/*global document: false, chrome: false, $: false, createLink: false, createProjectSelect: false*/

(function () {
  "use strict";
  var iframeRegex = /oauth2relay/, userData = null,
      selectedProjectId = null, selectedProjectBillable = false;

  function createTimerLink(taskName) {
    var link = createLink('toggl-button teambox');
    link.addEventListener("click", function (e) {
      chrome.extension.sendMessage({
        type: 'timeEntry',
        description: taskName,
        projectId: selectedProjectId,
        billable: selectedProjectBillable
      });
      link.innerHTML = "Started...";
      return false;
    });
    return link;
  }

  // finds the project's name either directly on the task's details
  // or in navigation bar on top
  function findProjectName(task) {
    // is the project's name in task header?
    var projectNameHolder = task.querySelector('.taskHeader .project a');
    if (projectNameHolder) {
      return projectNameHolder.innerText.toLowerCase();
    } else {
      return '';
    }
  }

  function addButton(e) {
    if (e.target.className === "comments" || iframeRegex.test(e.target.name)) {
      var task = e.target.parentNode.parentNode.parentNode,
          nameHolder = task.querySelector('.name_holder .name'),
          title = nameHolder.innerHTML,
          projectName = findProjectName(task);

      var projectSelect = createProjectSelect(userData, "toggl-select teambox");

      if (projectName) {
        var options = projectSelect.options;

        for (var i = 0; i < options.length; i++) {
          if (options[i].getAttribute('data-project-name') && options[i].getAttribute('data-project-name').toLowerCase() === projectName) {
            options[i].selected = true;
          }
        }
      }

      //make sure we init the values when switching between tasks
      selectedProjectId = null;
      selectedProjectBillable = false;

      projectSelect.onchange = function (event) {
        selectedProjectId = event.target.options[event.target.selectedIndex].value;
        if (selectedProjectId !== "default") {
          selectedProjectBillable = userData.projects.filter(function (elem, index, array) {
            return (elem.id === selectedProjectId);
          })[0].billable;
        } else {
          selectedProjectId = null;
          selectedProjectBillable = false;
        }
      };

      nameHolder.parentNode.insertBefore(createTimerLink(title), nameHolder.nextSibling);
      nameHolder.parentNode.insertBefore(projectSelect, nameHolder.nextSibling);
    }
  }

  chrome.extension.sendMessage({type: 'activate'}, function (response) {
    if (response.success) {
      userData = response.user;
      document.addEventListener("DOMNodeInserted", addButton);
    }
  });

}());
<|endoftext|>


<commit_before>// http://courses.csail.mit.edu/iap/interview/Hacking_a_Google_Interview_Handout_2.pdf
// Merge Sort:

var merge_sort_inplace = function(ar, s, e) {
    var left, right, left_tail;
    if (s===e) { return; }
    left_tail = s+Math.floor((e-s)/2);
    merge_sort_inplace(ar, s, left_tail);
    merge_sort_inplace(ar, left_tail+1, e);
    merge(ar, s, left_tail, e);
};

var merge = function(ar, l_h, l_t, r_t) {
    var i = l_h,
        l_i=0, r_i=0, val,
        left = ar.slice(l_h, l_t+1),
        l_len = left.length,
        right = ar.slice(l_t+1, r_t+1),
        r_len = right.length;

    for (;i<=r_t;i+=1) {
        if (l_i==l_len || right[r_i]<left[l_i]) {
            val = right[r_i]; r_i+=1;
        } else {
            val = left[l_i];  l_i+=1;
        }
        ar[i] = val;
    }
};

var ar = [8,2,6,3,4,3,9,1];
merge_sort_inplace(ar, 0, ar.length-1);
console.log(ar);

var merge_sort_immutable = function(ar) {
    var left, right, len = ar.length;
    if (len===1) { return ar; }
    left = merge_sort_immutable(ar.slice(0,Math.ceil(len/2)));
    right = merge_sort_immutable(ar.slice(Math.ceil(len/2)));
    return _merge_immutable(left,right);
};

var _merge_immutable = function(l, r) {
    var l_val, r_val, val, result = [];
    if (l==null) { l = []; }
    if (r==null) { r = []; }
    while (l.length>0||r.length>0) {
        l_val = l[0] || Number.MAX_VALUE;
        r_val = r[0] || Number.MAX_VALUE;
        if (l_val<r_val) {
            result.push(l.shift());
        } else {
            result.push(r.shift());
        }
    }
    return result;
};

ar = [8,2,6,3,4,3,9,1];
console.log(merge_sort_immutable(ar));

// http://courses.csail.mit.edu/iap/interview/Hacking_a_Google_Interview_Handout_2.pdf
// Quicksort:

var quick_sort_immutable = function(ar) {
    var i=0, left=[], right=[], pivot;
    if (ar.length<2) { return ar; }
    pivot = ar.shift();
    for (;i<ar.length; i+=1) {
        if (ar[i]<pivot) {
            left.push(ar[i]);
        } else {
            right.push(ar[i]);
        }
    }
    return quick_sort_immutable(left).concat([pivot]).concat(quick_sort_immutable(right));
};

// 0 2 2 2 [ 1, 2, 3, 3, 4, 6, 9, 8 ]
// 1 3 2 1 [ 1, 2, 3, 3, 4, 6, 9, 8 ]
var quick_sort_inplace_headpivot = function(ar, s, e) {
    var temp, i=s+1,j=e-1, pivot = ar[s];
    if (e-s<2) { return; }
    while (i<j) {
        while (ar[i]<=pivot) { i+=1; }
        while (ar[j]>pivot) { j-=1; }
        if (i<j) {
            temp  = ar[j];
            ar[j] = ar[i];
            ar[i] = temp;
            i+=1;
            j-=1;
        }
    }
    ar[s] = ar[j];
    ar[j] = pivot;
    quick_sort_inplace_headpivot(ar, s, j);
    quick_sort_inplace_headpivot(ar, j+1, e);
};

var quick_sort_inplace_tailpivot = function(ar, s, e) {
    var pivot = ar[e-1], temp, i=s, j=i;
    if (e-s<2) { return; }
    for (; i<e-1; i+=1) {
        if (ar[i]<=pivot) {
            if (i!=j) {
              	temp = ar[i];
              	ar[i] = ar[j];
              	ar[j] = temp;
            }
            j+=1;
        }
    }
    ar[e-1] = ar[j];
    ar[j] = pivot;
    quick_sort_inplace_tailpivot(ar, s, j);
    quick_sort_inplace_tailpivot(ar, j+1, e);
};

ar = [8,2,6,3,4,3,9,1];
console.log(quick_sort_immutable(ar));
ar = [8,2,6,3,4,3,9,1];
quick_sort_inplace_tailpivot(ar, 0, ar.length);
console.log(ar);

// http://courses.csail.mit.edu/iap/interview/Hacking_a_Google_Interview_Handout_2.pdf
// Order Statistics:

var kth = function(ar, s, e, k) {
    var pivot = ar[e], i=s, j=i, temp;
    // base case
    if (e==s && k==s) { return ar[k]; }
    if (e==s+1 && (s==k||e==k)) { return ar[k]; }

    for (i; i<e; i+=1) {
        if (ar[i] <= pivot) {
            if (i!==j) {
              	temp = ar[i];
              	ar[i] = ar[j];
              	ar[j] = temp;
            }
            j+=1;
        }
    }
    ar[e] = ar[j];
    ar[j] = pivot;
    if (j==k) { return ar[k]; }
    if (j>k) {
        return kth(ar, s, j-1, k);
    } else {
        return kth(ar, j+1, e, k);
    }
};

ar = [8,2,6,3,4,3,9,1];
console.log(kth(ar, 0, ar.length-1, 5));

// http://courses.csail.mit.edu/iap/interview/Hacking_a_Google_Interview_Handout_2.pdf
// Question: Nearest Neighbor

var neighbor = function(ar, k) {
    var i=0, len=ar.length, neighbors=[], nbr, l_i, u_i, j;
    ar.sort(function(a,b) {return +a-(+b);});
    console.log(ar);
    for (;i<len; i+=1) {
        nbr = [];
        l_i = i-1;
        u_i = i+1;
        while(nbr.length<k) {
            if (ar[l_i] && Math.abs(ar[i]-ar[l_i])<=Math.abs(ar[i]-ar[u_i])||!ar[u_i]) { nbr.push(ar[l_i]); l_i-=1; }
            if (nbr.length>=k) break;
            if (ar[u_i] && Math.abs(ar[i]-ar[u_i])<=Math.abs(ar[i]-ar[l_i])||!ar[l_i]) { nbr.push(ar[u_i]); u_i+=1; }
        }
        neighbors.push(nbr);
    }
    return neighbors;
};

ar = [8,2,6,3,4,3,9,1];
console.log(neighbor(ar, 2));

// Counting sort: Applicable if value's distribution is limited up to k (bucket size)

var counting_sort = function(ar) {
    var i=0, j=0,
        k=-Infinity,
        bucket = ar.reduce(function(bucket, val) {
            bucket[val] = bucket[val] || 0;
            bucket[val] += 1;
            if (val>k) { k=val; }
            return bucket;
        }, []);

    for (; i<=k; i+=1) {
        if (bucket[i] != null) {
            while (bucket[i]>0) {
                ar[j] = i;
                bucket[i] -= 1;
                j += 1;
            }
        }
    }
    return ar;
};

console.log(counting_sort([3,0,2,0,0,2,2]));

<commit_msg>Implemented bucket sort<commit_after>// http://courses.csail.mit.edu/iap/interview/Hacking_a_Google_Interview_Handout_2.pdf
// Merge Sort:

var merge_sort_inplace = function(ar, s, e) {
    var left, right, left_tail;
    if (s===e) { return; }
    left_tail = s+Math.floor((e-s)/2);
    merge_sort_inplace(ar, s, left_tail);
    merge_sort_inplace(ar, left_tail+1, e);
    merge(ar, s, left_tail, e);
};

var merge = function(ar, l_h, l_t, r_t) {
    var i = l_h,
        l_i=0, r_i=0, val,
        left = ar.slice(l_h, l_t+1),
        l_len = left.length,
        right = ar.slice(l_t+1, r_t+1),
        r_len = right.length;

    for (;i<=r_t;i+=1) {
        if (l_i==l_len || right[r_i]<left[l_i]) {
            val = right[r_i]; r_i+=1;
        } else {
            val = left[l_i];  l_i+=1;
        }
        ar[i] = val;
    }
};

var ar = [8,2,6,3,4,3,9,1];
merge_sort_inplace(ar, 0, ar.length-1);
console.log(ar);

var merge_sort_immutable = function(ar) {
    var left, right, len = ar.length;
    if (len===1) { return ar; }
    left = merge_sort_immutable(ar.slice(0,Math.ceil(len/2)));
    right = merge_sort_immutable(ar.slice(Math.ceil(len/2)));
    return _merge_immutable(left,right);
};

var _merge_immutable = function(l, r) {
    var l_val, r_val, val, result = [];
    if (l==null) { l = []; }
    if (r==null) { r = []; }
    while (l.length>0||r.length>0) {
        l_val = l[0] || Number.MAX_VALUE;
        r_val = r[0] || Number.MAX_VALUE;
        if (l_val<r_val) {
            result.push(l.shift());
        } else {
            result.push(r.shift());
        }
    }
    return result;
};

ar = [8,2,6,3,4,3,9,1];
console.log(merge_sort_immutable(ar));

// http://courses.csail.mit.edu/iap/interview/Hacking_a_Google_Interview_Handout_2.pdf
// Quicksort:

var quick_sort_immutable = function(ar) {
    var i=0, left=[], right=[], pivot;
    if (ar.length<2) { return ar; }
    pivot = ar.shift();
    for (;i<ar.length; i+=1) {
        if (ar[i]<pivot) {
            left.push(ar[i]);
        } else {
            right.push(ar[i]);
        }
    }
    return quick_sort_immutable(left).concat([pivot]).concat(quick_sort_immutable(right));
};

// 0 2 2 2 [ 1, 2, 3, 3, 4, 6, 9, 8 ]
// 1 3 2 1 [ 1, 2, 3, 3, 4, 6, 9, 8 ]
var quick_sort_inplace_headpivot = function(ar, s, e) {
    var temp, i=s+1,j=e-1, pivot = ar[s];
    if (e-s<2) { return; }
    while (i<j) {
        while (ar[i]<=pivot) { i+=1; }
        while (ar[j]>pivot) { j-=1; }
        if (i<j) {
            temp  = ar[j];
            ar[j] = ar[i];
            ar[i] = temp;
            i+=1;
            j-=1;
        }
    }
    ar[s] = ar[j];
    ar[j] = pivot;
    quick_sort_inplace_headpivot(ar, s, j);
    quick_sort_inplace_headpivot(ar, j+1, e);
};

var quick_sort_inplace_tailpivot = function(ar, s, e) {
    var pivot = ar[e-1], temp, i=s, j=i;
    if (e-s<2) { return; }
    for (; i<e-1; i+=1) {
        if (ar[i]<=pivot) {
            if (i!=j) {
              	temp = ar[i];
              	ar[i] = ar[j];
              	ar[j] = temp;
            }
            j+=1;
        }
    }
    ar[e-1] = ar[j];
    ar[j] = pivot;
    quick_sort_inplace_tailpivot(ar, s, j);
    quick_sort_inplace_tailpivot(ar, j+1, e);
};

ar = [8,2,6,3,4,3,9,1];
console.log(quick_sort_immutable(ar));
ar = [8,2,6,3,4,3,9,1];
quick_sort_inplace_tailpivot(ar, 0, ar.length);
console.log(ar);

// http://courses.csail.mit.edu/iap/interview/Hacking_a_Google_Interview_Handout_2.pdf
// Order Statistics:

var kth = function(ar, s, e, k) {
    var pivot = ar[e], i=s, j=i, temp;
    // base case
    if (e==s && k==s) { return ar[k]; }
    if (e==s+1 && (s==k||e==k)) { return ar[k]; }

    for (i; i<e; i+=1) {
        if (ar[i] <= pivot) {
            if (i!==j) {
              	temp = ar[i];
              	ar[i] = ar[j];
              	ar[j] = temp;
            }
            j+=1;
        }
    }
    ar[e] = ar[j];
    ar[j] = pivot;
    if (j==k) { return ar[k]; }
    if (j>k) {
        return kth(ar, s, j-1, k);
    } else {
        return kth(ar, j+1, e, k);
    }
};

ar = [8,2,6,3,4,3,9,1];
console.log(kth(ar, 0, ar.length-1, 5));

// http://courses.csail.mit.edu/iap/interview/Hacking_a_Google_Interview_Handout_2.pdf
// Question: Nearest Neighbor

var neighbor = function(ar, k) {
    var i=0, len=ar.length, neighbors=[], nbr, l_i, u_i, j;
    ar.sort(function(a,b) {return +a-(+b);});
    console.log(ar);
    for (;i<len; i+=1) {
        nbr = [];
        l_i = i-1;
        u_i = i+1;
        while(nbr.length<k) {
            if (ar[l_i] && Math.abs(ar[i]-ar[l_i])<=Math.abs(ar[i]-ar[u_i])||!ar[u_i]) { nbr.push(ar[l_i]); l_i-=1; }
            if (nbr.length>=k) break;
            if (ar[u_i] && Math.abs(ar[i]-ar[u_i])<=Math.abs(ar[i]-ar[l_i])||!ar[l_i]) { nbr.push(ar[u_i]); u_i+=1; }
        }
        neighbors.push(nbr);
    }
    return neighbors;
};

ar = [8,2,6,3,4,3,9,1];
console.log(neighbor(ar, 2));

// Counting sort: Applicable if value's distribution is limited up to k (bucket size)

var counting_sort = function(ar) {
    var i=0, j=0,
        k=-Infinity,
        bucket = ar.reduce(function(bucket, val) {
            bucket[val] = bucket[val] || 0;
            bucket[val] += 1;
            if (val>k) { k=val; }
            return bucket;
        }, []);

    for (; i<=k; i+=1) {
        if (bucket[i] != null) {
            while (bucket[i]>0) {
                ar[j] = i;
                bucket[i] -= 1;
                j += 1;
            }
        }
    }
    return ar;
};

console.log(counting_sort([3,0,2,0,0,2,2]));

// Implement to use in bucket sort
var insertion_sort = function(ar) {
    var i=1, j, temp, len=ar.length;
    if (len<2) { return ar; }
    for (; i<len; i+=1) {
        for (j=0; j<=i; j+=1) {
            if (ar[j] <= ar[i]) { continue; }
            temp = ar[i];
            ar[i] = ar[j];
            ar[j] = temp;
        }
    }
    return ar;
};

console.log(insertion_sort([15,9,8,1,4,11,7,12,13]));

var bucket_sort = function(ar) {
    var min=Infinity, max=-Infinity, bucket, hash, bucket_count, i=0;
    if (ar.length<1) { return ar; }
    ar.forEach(function(val) {
        if (val < min) { min = val; }
        if (val > max) { max = val; }
    });
    bucket_count = Math.ceil((max-min)/3);
    hash = function(i) { return Math.floor((i-min)/3); };

    // make bucket
    bucket = ar.reduce(function(bucket, val) {
        var _hash = hash(val);
        bucket[_hash] = bucket[_hash] || [];
        bucket[_hash].push(val);
        return bucket;
    }, []);

    // bucket -> array
    bucket.forEach(function(slot) {
        insertion_sort(slot);
        slot.forEach(function(val,j) {
            ar[i] = val;
            i+=1;
        });
    });
    return ar;
};

console.log(bucket_sort([7,5,13,2,14,1,6]));

<|endoftext|>


<commit_before>/*##################################################|*/
/* #CMS# */

// ensuring django namespace is set correctly
var django = window.django || undefined;

// ensuring jQuery namespace is set correctly
var jQuery = (django) ? django.jQuery : window.jQuery || undefined;

// ensuring Class namespace is set correctly
var Class = window.Class || undefined;

// ensuring CMS namespace is set correctly
var CMS = {
	'$': (jQuery) ? jQuery.noConflict() : undefined,
	'Class': (Class) ? Class.noConflict() : undefined,
	'API': {}
};

/*##################################################|*/
/* #CMS.API# */
(function($) {
// CMS.$ will be passed for $
$(document).ready(function () {
	/*!
	 * CNS.API.Helpers
	 * Multiple helpers used accross all CMS features
	 */
	CMS.API.Helpers = {

		// redirects to a specific url or reloads browser
		reloadBrowser: function (url, timeout) {
			// is there a parent window?
			var parent = (window.parent) ? window.parent : window;
			// add timeout if provided
			parent.setTimeout(function () {
				(url) ? parent.location.href = url : parent.location.reload();
			}, timeout || 0);
		},

		// disable multiple form submissions
		preventSubmit: function () {
			var forms = $('#cms_toolbar').find('form');
			forms.submit(function (e) {
				// show loader
				CMS.API.Toolbar._loader(true);
				// we cannot use disabled as the name action will be ignored
				$('input[type="submit"]').bind('click', function (e) {
					e.preventDefault();
				}).css('opacity', 0.5);
			});
		},

		// fixes csrf behaviour
		csrf: function (csrf_token) {
			$.ajaxSetup({
				beforeSend: function (xhr) {
					// set csrf_token
					xhr.setRequestHeader("X-CSRFToken", csrf_token);
				}
			});
		},

		// handles the tooltip for the plugins
		showTooltip: function (name, id) {
			var tooltip = $('.cms_tooltip');

			// change css and attributes
			tooltip.css('visibility', 'visible')
				.data('plugin_id', id || null)
				.show()
				.find('span').html(name);

			// attaches move event
			// this sets the correct position for the edit tooltip
			$('body').bind('mousemove.cms', function (e) {
				// so lets figure out where we are
				var offset = 20;
				var bound = $(document).width();
				var pos = e.pageX + tooltip.outerWidth(true) + offset;

				tooltip.css({
					'left': (pos >= bound) ? e.pageX - tooltip.outerWidth(true) - offset : e.pageX + offset,
					'top': e.pageY - 12
				});
			});

			// attach tooltip event for touch devices
			tooltip.bind('touchstart.cms', function () {
				$('#cms_plugin-' + $(this).data('plugin_id')).trigger('dblclick');
			});
		},

		hideTooltip: function () {
			var tooltip = $('.cms_tooltip');

			// change css
			tooltip.css('visibility', 'hidden').hide();

			// unbind events
			$('body').unbind('mousemove.cms');
			tooltip.unbind('touchstart.cms');
		},

		// sends or retrieves a JSON from localStorage or the session if local storage is not available
		setSettings: function (settings) {
			var that = this;
			// merge settings
			settings = JSON.stringify($.extend({}, CMS.config.settings, settings));
			// set loader
			if(CMS.API.Toolbar) CMS.API.Toolbar._loader(true);

			// use local storage or session
			if(window.localStorage) {
				// save within local storage
				localStorage.setItem('cms_cookie', settings);
			} else {
				// save within session
				$.ajax({
					'async': false,
					'type': 'POST',
					'url': CMS.config.urls.settings,
					'data': {
						'csrfmiddlewaretoken': this.config.csrf,
						'settings': settings
					},
					'success': function (data) {
						// determine if logged in or not
						settings = (data) ? JSON.parse(data) : CMS.config.settings;
						if(CMS.API.Toolbar) CMS.API.Toolbar._loader(false);
					},
					'error': function (jqXHR) {
						that.showError(jqXHR.response + ' | ' + jqXHR.status + ' ' + jqXHR.statusText);
					}
				});
			}

			// save settings
			CMS.settings = settings;

			// ensure new settings are returned
			return settings;
		},

		getSettings: function () {
			var that = this;
			var settings;
			// set loader
			if(CMS.API.Toolbar) CMS.API.Toolbar._loader(true);

			// use local storage or session
			if(window.localStorage) {
				// get from local storage
				settings = JSON.parse(localStorage.getItem('cms_cookie'));
			} else {
				// get from session
				$.ajax({
					'async': false,
					'type': 'GET',
					'url': CMS.config.urls.settings,
					'success': function (data) {
						// determine if logged in or not
						settings = (data) ? JSON.parse(data) : CMS.config.settings;
						if(CMS.API.Toolbar) CMS.API.Toolbar._loader(false);
					},
					'error': function (jqXHR) {
						that.showError(jqXHR.response + ' | ' + jqXHR.status + ' ' + jqXHR.statusText);
					}
				});
			}

			if(settings === null) settings = this.setSettings(CMS.config.settings);

			// save settings
			CMS.settings = settings;

			// ensure new settings are returned
			return settings;
		},

		// prevents scrolling when another scrollbar is used (for better ux)
		preventScroll: function (disable) {
			// disable
			return false;

			// cancel if scrollbar is not visible
			if($(document).height() <= $(window).height()) return false;

			var scrollTop = $(window).scrollTop();
			var html = $('html');

			if(disable) {
				html.addClass('cms_toolbar-noscroll').css('top',-scrollTop).data('scroll', scrollTop);
			} else {
				html.removeClass('cms_toolbar-noscroll');
				$(window).scrollTop(html.data('scroll'));
			}
		}

	};

	// autoinits
	CMS.API.Helpers.preventSubmit();

});
})(CMS.$);

// this will be fixed in jQuery 1.6+
(function ( $ ) {
    var filters = $.expr[":"];
    if ( !filters.focus ) {
        filters.focus = function( elem ) {
           return elem === document.activeElement && ( elem.type || elem.href );
        };
    }
})( CMS.$ );
<commit_msg>added missing loader reset<commit_after>/*##################################################|*/
/* #CMS# */

// ensuring django namespace is set correctly
var django = window.django || undefined;

// ensuring jQuery namespace is set correctly
var jQuery = (django) ? django.jQuery : window.jQuery || undefined;

// ensuring Class namespace is set correctly
var Class = window.Class || undefined;

// ensuring CMS namespace is set correctly
var CMS = {
	'$': (jQuery) ? jQuery.noConflict() : undefined,
	'Class': (Class) ? Class.noConflict() : undefined,
	'API': {}
};

/*##################################################|*/
/* #CMS.API# */
(function($) {
// CMS.$ will be passed for $
$(document).ready(function () {
	/*!
	 * CNS.API.Helpers
	 * Multiple helpers used accross all CMS features
	 */
	CMS.API.Helpers = {

		// redirects to a specific url or reloads browser
		reloadBrowser: function (url, timeout) {
			// is there a parent window?
			var parent = (window.parent) ? window.parent : window;
			// add timeout if provided
			parent.setTimeout(function () {
				(url) ? parent.location.href = url : parent.location.reload();
			}, timeout || 0);
		},

		// disable multiple form submissions
		preventSubmit: function () {
			var forms = $('#cms_toolbar').find('form');
			forms.submit(function (e) {
				// show loader
				CMS.API.Toolbar._loader(true);
				// we cannot use disabled as the name action will be ignored
				$('input[type="submit"]').bind('click', function (e) {
					e.preventDefault();
				}).css('opacity', 0.5);
			});
		},

		// fixes csrf behaviour
		csrf: function (csrf_token) {
			$.ajaxSetup({
				beforeSend: function (xhr) {
					// set csrf_token
					xhr.setRequestHeader("X-CSRFToken", csrf_token);
				}
			});
		},

		// handles the tooltip for the plugins
		showTooltip: function (name, id) {
			var tooltip = $('.cms_tooltip');

			// change css and attributes
			tooltip.css('visibility', 'visible')
				.data('plugin_id', id || null)
				.show()
				.find('span').html(name);

			// attaches move event
			// this sets the correct position for the edit tooltip
			$('body').bind('mousemove.cms', function (e) {
				// so lets figure out where we are
				var offset = 20;
				var bound = $(document).width();
				var pos = e.pageX + tooltip.outerWidth(true) + offset;

				tooltip.css({
					'left': (pos >= bound) ? e.pageX - tooltip.outerWidth(true) - offset : e.pageX + offset,
					'top': e.pageY - 12
				});
			});

			// attach tooltip event for touch devices
			tooltip.bind('touchstart.cms', function () {
				$('#cms_plugin-' + $(this).data('plugin_id')).trigger('dblclick');
			});
		},

		hideTooltip: function () {
			var tooltip = $('.cms_tooltip');

			// change css
			tooltip.css('visibility', 'hidden').hide();

			// unbind events
			$('body').unbind('mousemove.cms');
			tooltip.unbind('touchstart.cms');
		},

		// sends or retrieves a JSON from localStorage or the session if local storage is not available
		setSettings: function (settings) {
			var that = this;
			// merge settings
			settings = JSON.stringify($.extend({}, CMS.config.settings, settings));
			// set loader
			if(CMS.API.Toolbar) CMS.API.Toolbar._loader(true);

			// use local storage or session
			if(window.localStorage) {
				// save within local storage
				localStorage.setItem('cms_cookie', settings);
				if(CMS.API.Toolbar) CMS.API.Toolbar._loader(false);
			} else {
				// save within session
				$.ajax({
					'async': false,
					'type': 'POST',
					'url': CMS.config.urls.settings,
					'data': {
						'csrfmiddlewaretoken': this.config.csrf,
						'settings': settings
					},
					'success': function (data) {
						// determine if logged in or not
						settings = (data) ? JSON.parse(data) : CMS.config.settings;
						if(CMS.API.Toolbar) CMS.API.Toolbar._loader(false);
					},
					'error': function (jqXHR) {
						that.showError(jqXHR.response + ' | ' + jqXHR.status + ' ' + jqXHR.statusText);
					}
				});
			}

			// save settings
			CMS.settings = settings;

			// ensure new settings are returned
			return settings;
		},

		getSettings: function () {
			var that = this;
			var settings;
			// set loader
			if(CMS.API.Toolbar) CMS.API.Toolbar._loader(true);

			// use local storage or session
			if(window.localStorage) {
				// get from local storage
				settings = JSON.parse(localStorage.getItem('cms_cookie'));
				if(CMS.API.Toolbar) CMS.API.Toolbar._loader(false);
			} else {
				// get from session
				$.ajax({
					'async': false,
					'type': 'GET',
					'url': CMS.config.urls.settings,
					'success': function (data) {
						// determine if logged in or not
						settings = (data) ? JSON.parse(data) : CMS.config.settings;
						if(CMS.API.Toolbar) CMS.API.Toolbar._loader(false);
					},
					'error': function (jqXHR) {
						that.showError(jqXHR.response + ' | ' + jqXHR.status + ' ' + jqXHR.statusText);
					}
				});
			}

			if(settings === null) settings = this.setSettings(CMS.config.settings);

			// save settings
			CMS.settings = settings;

			// ensure new settings are returned
			return settings;
		},

		// prevents scrolling when another scrollbar is used (for better ux)
		preventScroll: function (disable) {
			// disable
			return false;

			// cancel if scrollbar is not visible
			if($(document).height() <= $(window).height()) return false;

			var scrollTop = $(window).scrollTop();
			var html = $('html');

			if(disable) {
				html.addClass('cms_toolbar-noscroll').css('top',-scrollTop).data('scroll', scrollTop);
			} else {
				html.removeClass('cms_toolbar-noscroll');
				$(window).scrollTop(html.data('scroll'));
			}
		}

	};

	// autoinits
	CMS.API.Helpers.preventSubmit();

});
})(CMS.$);

// this will be fixed in jQuery 1.6+
(function ( $ ) {
    var filters = $.expr[":"];
    if ( !filters.focus ) {
        filters.focus = function( elem ) {
           return elem === document.activeElement && ( elem.type || elem.href );
        };
    }
})( CMS.$ );
<|endoftext|>


<commit_before><commit_msg>Make 'makerlab' standalone app identifier propagate during remixes, new project button, etc.<commit_after><|endoftext|>


<commit_before>import {compose, withProps, withPropsOnChange, withState} from 'recompose';
import classNames from 'classnames';
import {withDefaultProps} from './';
import {withImmutableProps} from '../utils';
import isBefore from 'date-fns/is_before';
import enhanceHeader from '../Header/withRange';
import format from 'date-fns/format';
import parse from 'date-fns/parse';
import styles from '../Day/Day.scss';

let isTouchDevice = false;

export const EVENT_TYPE = {
  END: 3,
  HOVER: 2,
  START: 1,
};

// Enhance Day component to display selected state based on an array of selected dates
export const enhanceDay = withPropsOnChange(['selected'], ({date, selected, theme}) => {
  const isSelected = date >= selected.start && date <= selected.end;
  const isStart = date === selected.start;
  const isEnd = date === selected.end;
  const isRange = !(isStart && isEnd);
  const style = isRange && (
    isStart && {backgroundColor: theme.accentColor} ||
    isEnd && {borderColor: theme.accentColor}
  );

  return {
    className: isSelected && isRange && classNames(styles.range, {
      [styles.start]: isStart,
      [styles.betweenRange]: !isStart && !isEnd,
      [styles.end]: isEnd,
    }),
    isSelected,
    selectionStyle: style,
  };
});

// Enhancer to handle selecting and displaying multiple dates
export const withRange = compose(
  withDefaultProps,
  withState('scrollDate', 'setScrollDate', getInitialDate),
  withState('displayKey', 'setDisplayKey', getInitialDate),
  withState('selectionStart', 'setSelectionStart', null),
  withImmutableProps(({
    DayComponent,
    HeaderComponent,
    YearsComponent,
  }) => ({
    DayComponent: enhanceDay(DayComponent),
    HeaderComponent: enhanceHeader(HeaderComponent),
  })),
  withProps(({displayKey, passThrough, selected, setDisplayKey, ...props}) => ({
    /* eslint-disable sort-keys */
    passThrough: {
      ...passThrough,
      Day: {
        onClick: (date) => handleSelect(date, {selected, ...props}),
        handlers: {
          onMouseOver: !isTouchDevice && props.selectionStart
            ? (e) => handleMouseOver(e, {selected, ...props})
            : null,
        },
      },
      Years: {
        selected: selected[displayKey],
        onSelect: (date) => handleYearSelect(date, {displayKey, selected, ...props}),
      },
      Header: {
        onYearClick: (date, e, key) => setDisplayKey(key || 'start'),
      },
    },
    selected: {
      start: format(selected.start, 'YYYY-MM-DD'),
      end: format(selected.end, 'YYYY-MM-DD'),
    },
  })),
);

function getSortedSelection({start, end}) {
  return isBefore(start, end)
    ? {start, end}
    : {start: end, end: start};
}

function handleSelect(date, {onSelect, selected, selectionStart, setSelectionStart}) {
  if (selectionStart) {
    onSelect({
      eventType: EVENT_TYPE.END,
      ...getSortedSelection({
        start: selectionStart,
        end: date,
      }),
    });
    setSelectionStart(null);
  } else {
    onSelect({eventType:EVENT_TYPE.START, start: date, end: date});
    setSelectionStart(date);
  }
}

function handleMouseOver(e, {onSelect, selectionStart}) {
  const dateStr = e.target.getAttribute('data-date');
  const date = dateStr && parse(dateStr);

  if (!date) { return; }

  onSelect({
    eventType: EVENT_TYPE.HOVER,
    ...getSortedSelection({
      start: selectionStart,
      end: date,
    }),
  });
}

function handleYearSelect(date, {displayKey, onSelect, selected, setScrollDate}) {

  setScrollDate(date);
  onSelect(getSortedSelection(
    Object.assign({}, selected, {[displayKey]: parse(date)}))
  );
}

function getInitialDate({selected}) {
  return selected.start || new Date();
}

if (typeof window !== 'undefined') {
  window.addEventListener('touchstart', function onTouch() {
    isTouchDevice = true;

    window.removeEventListener('touchstart', onTouch, false);
  });
}
<commit_msg>fix: withRange should support passing a blank selected state (#108)<commit_after>import {compose, withProps, withPropsOnChange, withState} from 'recompose';
import classNames from 'classnames';
import {withDefaultProps} from './';
import {withImmutableProps} from '../utils';
import isBefore from 'date-fns/is_before';
import enhanceHeader from '../Header/withRange';
import format from 'date-fns/format';
import parse from 'date-fns/parse';
import styles from '../Day/Day.scss';

let isTouchDevice = false;

export const EVENT_TYPE = {
  END: 3,
  HOVER: 2,
  START: 1,
};

// Enhance Day component to display selected state based on an array of selected dates
export const enhanceDay = withPropsOnChange(['selected'], ({date, selected, theme}) => {
  const isSelected = date >= selected.start && date <= selected.end;
  const isStart = date === selected.start;
  const isEnd = date === selected.end;
  const isRange = !(isStart && isEnd);
  const style = isRange && (
    isStart && {backgroundColor: theme.accentColor} ||
    isEnd && {borderColor: theme.accentColor}
  );

  return {
    className: isSelected && isRange && classNames(styles.range, {
      [styles.start]: isStart,
      [styles.betweenRange]: !isStart && !isEnd,
      [styles.end]: isEnd,
    }),
    isSelected,
    selectionStyle: style,
  };
});

// Enhancer to handle selecting and displaying multiple dates
export const withRange = compose(
  withDefaultProps,
  withState('scrollDate', 'setScrollDate', getInitialDate),
  withState('displayKey', 'setDisplayKey', getInitialDate),
  withState('selectionStart', 'setSelectionStart', null),
  withImmutableProps(({
    DayComponent,
    HeaderComponent,
    YearsComponent,
  }) => ({
    DayComponent: enhanceDay(DayComponent),
    HeaderComponent: enhanceHeader(HeaderComponent),
  })),
  withProps(({displayKey, passThrough, selected, setDisplayKey, ...props}) => ({
    /* eslint-disable sort-keys */
    passThrough: {
      ...passThrough,
      Day: {
        onClick: (date) => handleSelect(date, {selected, ...props}),
        handlers: {
          onMouseOver: !isTouchDevice && props.selectionStart
            ? (e) => handleMouseOver(e, {selected, ...props})
            : null,
        },
      },
      Years: {
        selected: selected && selected[displayKey],
        onSelect: (date) => handleYearSelect(date, {displayKey, selected, ...props}),
      },
      Header: {
        onYearClick: (date, e, key) => setDisplayKey(key || 'start'),
      },
    },
    selected: {
      start: selected && format(selected.start, 'YYYY-MM-DD'),
      end: selected && format(selected.end, 'YYYY-MM-DD'),
    },
  })),
);

function getSortedSelection({start, end}) {
  return isBefore(start, end)
    ? {start, end}
    : {start: end, end: start};
}

function handleSelect(date, {onSelect, selected, selectionStart, setSelectionStart}) {
  if (selectionStart) {
    onSelect({
      eventType: EVENT_TYPE.END,
      ...getSortedSelection({
        start: selectionStart,
        end: date,
      }),
    });
    setSelectionStart(null);
  } else {
    onSelect({eventType:EVENT_TYPE.START, start: date, end: date});
    setSelectionStart(date);
  }
}

function handleMouseOver(e, {onSelect, selectionStart}) {
  const dateStr = e.target.getAttribute('data-date');
  const date = dateStr && parse(dateStr);

  if (!date) { return; }

  onSelect({
    eventType: EVENT_TYPE.HOVER,
    ...getSortedSelection({
      start: selectionStart,
      end: date,
    }),
  });
}

function handleYearSelect(date, {displayKey, onSelect, selected, setScrollDate}) {

  setScrollDate(date);
  onSelect(getSortedSelection(
    Object.assign({}, selected, {[displayKey]: parse(date)}))
  );
}

function getInitialDate({selected}) {
  return selected && selected.start || new Date();
}

if (typeof window !== 'undefined') {
  window.addEventListener('touchstart', function onTouch() {
    isTouchDevice = true;

    window.removeEventListener('touchstart', onTouch, false);
  });
}
<|endoftext|>


<commit_before>var HIDDEN="hidden";
var LEVEL = "level";
var PLUS_SRC="dom-images/butplus.gif";
var MIN_SRC="dom-images/butmin.gif";
var newRoot;
var maxColumns=1;

function loadDomViewer() {
    // See if the rootDocument variable has been set on this window.
    var rootDocument = window.rootDocument;

    // If not look to the opener for an explicity rootDocument variable, otherwise, use the opener document
    if (!rootDocument && window.opener) {
        rootDocument = window.opener.rootDocument || window.opener.document;
    }

    if (rootDocument) {
        document.body.innerHTML = displayDOM(rootDocument);
    }
    else {
        document.body.innerHTML = "Must specify rootDocument for window. This can be done by setting the rootDocument variable on this window, or on the opener window for a popup window.";
    }
}

function displayDOM(root){
	var str = "";
	str+="
";
	str += treeTraversal(root,0);
	// to make table columns work well.
	str += "
";
	for (var i=0; i < maxColumns; i++) {
	    str+= "    	";
	}
	str += "
";
	str += "
";
	return str;
}

function checkForChildren(element){
	if(!element.hasChildNodes())
		return false;

	var nodes = element.childNodes;
	var size = nodes.length;
	var count=0;

	for(var i=0; i< size; i++){
		var node = nodes.item(i);
		//if(node.toString()=="[object Text]"){
		//this is equalent to the above
		//but will work with more browsers
		if(node.nodeType!=1){
			count++;
		}
	}

	if(count == size)
		return false;
	else
		return true;
}

function treeTraversal(root, level){
	var str = "";
	var nodes= null;
	var size = null;
	//it is supposed to show the last node,
	//but the last node is always nodeText type
	//and we don't show it
	if(!root.hasChildNodes())
		return "";//displayNode(root,level,false);

	nodes = root.childNodes;
	size = nodes.length;

	for(var i=0; i< size; i++){
		var element = nodes.item(i);
		//if the node is textNode, don't display
		if(element.nodeType==1){
			str+= displayNode(element,level,checkForChildren(element));
			str+=treeTraversal(element, level+1);
		}
	}
	return str;
}

function displayNode(element, level, isLink){
        nodeContent = getNodeContent(element);
        columns = Math.round((nodeContent.length / 12) + 0.5);
        if (columns + level > maxColumns) {
            maxColumns = columns + level;
        }
		var str ="
";
		for (var i=0; i < level; i++)
			str+= " 	";
		str+="";
		if(isLink){
			str+='';
			str+='';
		}
        str += nodeContent;
		if(isLink)
			str+="
";
		return str;
}

function getNodeContent(element) {
        str = "";
		id ="";
		if (element.id != null && element.id != "") {
		    id = " ID(" + element.id +")";
		}
		name ="";
		if (element.name != null && element.name != "") {
		    name = " NAME(" + element.name + ")";
		}
		value ="";
		if (element.value != null && element.value != "") {
		    value = " VALUE(" + element.value + ")";
		}
		href ="";
		if (element.href != null && element.href != "") {
		    href = " HREF(" + element.href + ")";
		}
		text ="";
		if (element.text != null && element.text != "" && element.text != "undefined") {
		    text = " #TEXT(" + trim(element.text) +")";
		}
		str+=" "+ element.nodeName + id + name + value + href + text + "";
		return str;

}

function trim(val) {
        val2 = val.substring(0,20) + "                   ";
        var spaceChr = String.fromCharCode(32);
        var length = val2.length;
        var retVal = "";
        var ix = length -1;

        while(ix > -1){
            if(val2.charAt(ix) == spaceChr) {
            } else {
                retVal = val2.substring(0, ix +1);
                break;
            }
            ix = ix-1;
        }
        if (val.length > 20) {
            retVal += "...";
        }
        return retVal;
}

function hide(hlink){
	var isHidden = false;
	var image = hlink.firstChild;
	if(image.src.toString().indexOf(MIN_SRC)!=-1){
		image.src=PLUS_SRC;
		isHidden=true;
	}else{
		image.src=MIN_SRC;
	}
	var rowObj= hlink.parentNode.parentNode;
	var rowLevel = parseInt(rowObj.className.substring(LEVEL.length));

	var sibling = rowObj.nextSibling;
	var siblingLevel = sibling.className.substring(LEVEL.length);
	if(siblingLevel.indexOf(HIDDEN)!=-1){
		siblingLevel = siblingLevel.substring(0,siblingLevel.length - HIDDEN.length-1);
	}
	siblingLevel=parseInt(siblingLevel);
	while(sibling!=null && rowLevel<siblingLevel){
		if(isHidden){
			sibling.className += " "+ HIDDEN;
		}else if(!isHidden && sibling.className.indexOf(HIDDEN)!=-1){
			var str = sibling.className;
			sibling.className=str.substring(0, str.length - HIDDEN.length-1);
		}
		sibling = sibling.nextSibling;
		siblingLevel = parseInt(sibling.className.substring(LEVEL.length));
	}
}

function LOG(message) {
    window.opener.LOG.warn(message);
}<commit_msg>remove tabs<commit_after>var HIDDEN="hidden";
var LEVEL = "level";
var PLUS_SRC="dom-images/butplus.gif";
var MIN_SRC="dom-images/butmin.gif";
var newRoot;
var maxColumns=1;

function loadDomViewer() {
    // See if the rootDocument variable has been set on this window.
    var rootDocument = window.rootDocument;

    // If not look to the opener for an explicity rootDocument variable, otherwise, use the opener document
    if (!rootDocument && window.opener) {
        rootDocument = window.opener.rootDocument || window.opener.document;
    }

    if (rootDocument) {
        document.body.innerHTML = displayDOM(rootDocument);
    }
    else {
        document.body.innerHTML = "Must specify rootDocument for window. This can be done by setting the rootDocument variable on this window, or on the opener window for a popup window.";
    }
}

function displayDOM(root){
    var str = "";
    str+="
";
    str += treeTraversal(root,0);
    // to make table columns work well.
    str += "
";
    for (var i=0; i < maxColumns; i++) {
        str+= "    	";
    }
    str += "
";
    str += "
";
    return str;
}

function checkForChildren(element){
    if(!element.hasChildNodes())
        return false;

    var nodes = element.childNodes;
    var size = nodes.length;
    var count=0;

    for(var i=0; i< size; i++){
        var node = nodes.item(i);
        //if(node.toString()=="[object Text]"){
        //this is equalent to the above
        //but will work with more browsers
        if(node.nodeType!=1){
            count++;
        }
    }

    if(count == size)
        return false;
    else
        return true;
}

function treeTraversal(root, level){
    var str = "";
    var nodes= null;
    var size = null;
    //it is supposed to show the last node,
    //but the last node is always nodeText type
    //and we don't show it
    if(!root.hasChildNodes())
        return "";//displayNode(root,level,false);

    nodes = root.childNodes;
    size = nodes.length;

    for(var i=0; i< size; i++){
        var element = nodes.item(i);
        //if the node is textNode, don't display
        if(element.nodeType==1){
            str+= displayNode(element,level,checkForChildren(element));
            str+=treeTraversal(element, level+1);
        }
    }
    return str;
}

function displayNode(element, level, isLink){
    nodeContent = getNodeContent(element);
    columns = Math.round((nodeContent.length / 12) + 0.5);
    if (columns + level > maxColumns) {
        maxColumns = columns + level;
    }
    var str ="
";
    for (var i=0; i < level; i++)
        str+= " 	";
    str+="";
    if(isLink){
        str+='';
        str+='';
    }
    str += nodeContent;
    if(isLink)
        str+="
";
    return str;
}

function getNodeContent(element) {
    str = "";
    id ="";
    if (element.id != null && element.id != "") {
        id = " ID(" + element.id +")";
    }
    name ="";
    if (element.name != null && element.name != "") {
        name = " NAME(" + element.name + ")";
    }
    value ="";
    if (element.value != null && element.value != "") {
        value = " VALUE(" + element.value + ")";
    }
    href ="";
    if (element.href != null && element.href != "") {
        href = " HREF(" + element.href + ")";
    }
    text ="";
    if (element.text != null && element.text != "" && element.text != "undefined") {
        text = " #TEXT(" + trim(element.text) +")";
    }
    str+=" "+ element.nodeName + id + name + value + href + text + "";
    return str;

}

function trim(val) {
    val2 = val.substring(0,20) + "                   ";
    var spaceChr = String.fromCharCode(32);
    var length = val2.length;
    var retVal = "";
    var ix = length -1;

    while(ix > -1){
        if(val2.charAt(ix) == spaceChr) {
        } else {
            retVal = val2.substring(0, ix +1);
            break;
        }
        ix = ix-1;
    }
    if (val.length > 20) {
        retVal += "...";
    }
    return retVal;
}

function hide(hlink){
    var isHidden = false;
    var image = hlink.firstChild;
    if(image.src.toString().indexOf(MIN_SRC)!=-1){
        image.src=PLUS_SRC;
        isHidden=true;
    }else{
        image.src=MIN_SRC;
    }
    var rowObj= hlink.parentNode.parentNode;
    var rowLevel = parseInt(rowObj.className.substring(LEVEL.length));

    var sibling = rowObj.nextSibling;
    var siblingLevel = sibling.className.substring(LEVEL.length);
    if(siblingLevel.indexOf(HIDDEN)!=-1){
        siblingLevel = siblingLevel.substring(0,siblingLevel.length - HIDDEN.length-1);
    }
    siblingLevel=parseInt(siblingLevel);
    while(sibling!=null && rowLevel<siblingLevel){
        if(isHidden){
            sibling.className += " "+ HIDDEN;
        }else if(!isHidden && sibling.className.indexOf(HIDDEN)!=-1){
            var str = sibling.className;
            sibling.className=str.substring(0, str.length - HIDDEN.length-1);
        }
        sibling = sibling.nextSibling;
        siblingLevel = parseInt(sibling.className.substring(LEVEL.length));
    }
}

function LOG(message) {
    window.opener.LOG.warn(message);
}
<|endoftext|>


<commit_before>var path = require('path')
  , http = require('http')
  , fs = require('fs')
  , filed = require('filed')
  , follow = require('follow')
  , request = require('request').defaults({json:true})
  , handlebars = require('./handlebars')
  , build = path.join(__dirname, 'build')
  , registry = 'http://isaacs.iriscouch.com:5984/registry'
  , template = fs.readFileSync(path.join(__dirname, 'package.html')).toString()
  , port = process.env.NPMJSPORT || 8000
  ;

try {
  fs.mkdirSync(build, 0755)
} catch(e) {
  // already there most likely
}

http.createServer(function (req, resp) {
  var f = filed(path.join(build, req.url.slice(1)))
  req.pipe(f)
  f.pipe(resp)
})
.listen(port)

var follower = follow(registry, function(error, change) {
  request(registry + '/' + encodeURIComponent(change.id), function (e, resp, doc) {
    if (resp.statusCode !== 200) return // most likely deleted
    var f = filed(path.join(build, change.id+'.html'))
    f.write(handlebars.compile(template)(doc))
    f.end()
    console.log(doc)
  })
})

// while debugging only generate a few docs
follower.limit = 2
follower.since = 4000<commit_msg>No need for Mikeal's old script<commit_after><|endoftext|>


<commit_before>"use strict";

var $ = require('jquery'),
    L = require('leaflet'),
    Marionette = require('../../shim/backbone.marionette'),
    moment = require('moment'),
    App = require('../app'),
    settings = require('../core/settings'),
    utils = require('./utils'),
    errorTmpl = require('./templates/error.html'),
    formTmpl = require('./templates/form.html'),
    pagerTmpl = require('./templates/pager.html'),
    searchResultTmpl = require('./templates/searchResult.html'),
    cuahsiSearchResultTmpl = require('./templates/cuahsiSearchResult.html'),
    tabContentTmpl = require('./templates/tabContent.html'),
    tabPanelTmpl = require('./templates/tabPanel.html'),
    windowTmpl = require('./templates/window.html');

var ENTER_KEYCODE = 13,
    PAGE_SIZE = settings.get('data_catalog_page_size'),
    CATALOG_RESULT_TEMPLATE = {
        cinergi: searchResultTmpl,
        hydroshare: searchResultTmpl,
        cuahsi: cuahsiSearchResultTmpl,
    };

var DataCatalogWindow = Marionette.LayoutView.extend({
    template: windowTmpl,
    className: 'data-catalog-window',

    ui: {
        introText: '.intro-text',
        tabs: '.output-tabs-wrapper'
    },

    regions: {
        formRegion: '.form-region',
        panelsRegion: '.tab-panels-region',
        contentsRegion: '.tab-contents-region'
    },

    childEvents: {
        'search': 'doSearch',
        'selectCatalog': 'onSelectCatalog'
    },

    collectionEvents: {
        'change:active change:loading': 'updateMap'
    },

    onShow: function() {
        this.formRegion.show(new FormView({
            model: this.model
        }));
        this.panelsRegion.show(new TabPanelsView({
            collection: this.collection
        }));
        this.contentsRegion.show(new TabContentsView({
            collection: this.collection
        }));
    },

    getActiveCatalog: function() {
        return this.collection.findWhere({ active: true });
    },

    onSelectCatalog: function(childView, catalogId) {
        // Deactiveate previous catalog
        var prevCatalog = this.getActiveCatalog();
        if (prevCatalog && prevCatalog.id !== catalogId) {
            prevCatalog.set('active', false);
        }

        // Activate selected catalog
        var nextCatalog = this.collection.get(catalogId);
        nextCatalog.set('active', true);

        this.doSearch();
    },

    doSearch: function() {
        var catalog = this.getActiveCatalog(),
            query = this.model.get('query'),
            fromDate = this.model.get('fromDate'),
            toDate = this.model.get('toDate'),
            aoiGeoJson = L.geoJson(App.map.get('areaOfInterest')),
            bounds = utils.formatBounds(aoiGeoJson.getBounds());

        // Disable intro text after first search request
        this.ui.introText.addClass('hide');
        this.ui.tabs.removeClass('hide');

        catalog.searchIfNeeded(query, fromDate, toDate, bounds);
    },

    updateMap: function() {
        var catalog = this.getActiveCatalog(),
            geoms = catalog && catalog.get('results').pluck('geom');
        App.map.set('dataCatalogResults', geoms);
    }
});

var FormView = Marionette.ItemView.extend({
    template: formTmpl,
    className: 'data-catalog-form',

    ui: {
        dateInput: '.data-catalog-date-input',
        filterToggle: '.date-filter-toggle',
        searchInput: '.data-catalog-search-input',
        clearable: '.data-catalog-clearable-input a',
    },

    modelEvents: {
        'change:showingFilters change:isValid change:toDate change:fromDate': 'render'
    },

    events: {
        'keyup @ui.searchInput': 'onSearchInputChanged',
        'click @ui.filterToggle': 'onFilterToggle',
        'change @ui.dateInput': 'onDateInputChanged',
        'keyup @ui.dateInput': 'onDateInputKeyup',
        'click @ui.clearable': 'onClearInput',
    },

    onRender: function() {
        $('.data-catalog-date-input').datepicker();
    },

    onClearInput: function(e) {
        var $el = $(e.currentTarget).siblings('input').val('');
        this.updateDateInput($el);
    },

    onSearchInputChanged: function(e) {
        var query = this.ui.searchInput.val().trim();
        if (e.keyCode === ENTER_KEYCODE) {
            this.triggerSearch();
        } else {
            this.model.set('query', query);
        }
    },

    onDateInputKeyup: function(e) {
        if (e.keyCode === ENTER_KEYCODE) {
            this.triggerSearch();
        }
    },

    onDateInputChanged: function(e) {
        this.updateDateInput($(e.currentTarget));
    },

    onFilterToggle: function() {
        var newVal = !this.model.get('showingFilters');
        this.model.set('showingFilters', newVal);
    },

    updateDateInput: function($dateEl) {
        var isFromDate = $dateEl.hasClass('from-date'),
            attr = isFromDate ? 'fromDate' : 'toDate';

        this.model.set(attr, $dateEl.val());
    },

    triggerSearch: function() {
        if (this.validate()) {
            this.triggerMethod('search');
        }
    },

    validate: function() {
        // Only need to validate if there are two dates.  Ensure that
        // before is earlier than after
        var dateFormat = "MM/DD/YYYY",
            toDate = this.model.get('toDate'),
            fromDate = this.model.get('fromDate'),
            isValid = false;

        if (!toDate || !fromDate) {
            isValid = true;
        } else {
            isValid = moment(fromDate, dateFormat)
                        .isBefore(moment(toDate, dateFormat));
        }

        this.model.set('isValid', isValid);
        return isValid;
    },

    templateHelpers: function() {
        var showingFilters = this.model.get('showingFilters');

        return {
            filterText: showingFilters ? 'Hide Filters' : 'Show Filters',
        };
    }
});

var TabPanelView = Marionette.ItemView.extend({
    tagName: 'li',
    template: tabPanelTmpl,
    attributes: {
        role: 'presentation'
    },

    events: {
        'click a': 'onTabClicked'
    },

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

    onTabClicked: function() {
        this.triggerMethod('selectCatalog', this.model.id);
    },

    onRender: function() {
        this.$el.toggleClass('active', this.model.get('active'));
    }
});

var TabPanelsView = Marionette.CollectionView.extend({
    tagName: 'ul',
    className: 'nav nav-tabs',
    attributes: {
        role: 'tablist'
    },
    childView: TabPanelView
});

var ErrorView = Marionette.ItemView.extend({
    template: errorTmpl,
    modelEvents: {
        'change:error': 'render',
    },
});

var TabContentView = Marionette.LayoutView.extend({
    className: 'tab-pane',
    id: function() {
        return this.model.id;
    },
    template: tabContentTmpl,
    attributes: {
        role: 'tabpanel'
    },

    ui: {
        noResults: '.no-results-panel'
    },

    regions: {
        pagerRegion: '.pager-region',
        resultRegion: '.result-region',
        errorRegion: '.error-region',
    },

    modelEvents: {
        'change': 'update',
        'change:active': 'toggleActiveClass',
    },

    onShow: function() {
        this.toggleActiveClass();

        this.resultRegion.show(new ResultsView({
            collection: this.model.get('results'),
            catalog: this.model.id,
        }));

        this.errorRegion.show(new ErrorView({
            model: this.model,
        }));

        if (this.model.get('is_pageable')) {
            this.pagerRegion.show(new PagerView({
                model: this.model,
            }));
        }
    },

    toggleActiveClass: function() {
        this.$el.toggleClass('active', this.model.get('active'));
    },

    update: function() {
        this.ui.noResults.addClass('hide');
        this.errorRegion.$el.addClass('hide');
        this.resultRegion.$el.addClass('hide');
        this.pagerRegion.$el.addClass('hide');

        var error = this.model.get('error'),
            // Don't show "no results" while search request is in progress
            showNoResults = !this.model.get('loading') &&
                            this.model.get('resultCount') === 0 && !error;

        if (showNoResults) {
            this.ui.noResults.removeClass('hide');
        } else if (error) {
            this.errorRegion.$el.removeClass('hide');
        } else {
            this.resultRegion.$el.removeClass('hide');
            this.pagerRegion.$el.removeClass('hide');
        }
    }
});

var TabContentsView = Marionette.CollectionView.extend({
    className: 'tab-content',
    childView: TabContentView
});

var ResultView = Marionette.ItemView.extend({
    getTemplate: function() {
        return CATALOG_RESULT_TEMPLATE[this.options.catalog];
    },

    className: 'resource',

    events: {
        'mouseover': 'highlightResult',
        'mouseout': 'unHighlightResult',
    },

    highlightResult: function() {
        App.map.set('dataCatalogActiveResult', this.model.get('geom'));
    },

    unHighlightResult: function() {
        App.map.set({ dataCatalogActiveResult: null });
    }
});

var ResultsView = Marionette.CollectionView.extend({
    childView: ResultView,

    childViewOptions: function() {
        return {
            catalog: this.options.catalog,
        };
    },

    modelEvents: {
        'sync error': 'render'
    }
});

var PagerView = Marionette.ItemView.extend({
    template: pagerTmpl,

    ui: {
        previous: '#pager-previous',
        next: '#pager-next',
    },

    events: {
        'click @ui.previous': 'previousPage',
        'click @ui.next': 'nextPage',
    },

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

    templateHelpers: function() {
         var resultCount = this.model.get('resultCount'),
             page = this.model.get('page'),
             lastPage = Math.ceil(resultCount / PAGE_SIZE);

         return {
             has_results: resultCount > 0,
             has_previous: page > 1,
             has_next: page < lastPage,
         };
    },

    previousPage: function() {
        return this.model.previousPage();
    },

    nextPage: function() {
        return this.model.nextPage();
    }
});

module.exports = {
    DataCatalogWindow: DataCatalogWindow
};
<commit_msg>Whitespace<commit_after>"use strict";

var $ = require('jquery'),
    L = require('leaflet'),
    Marionette = require('../../shim/backbone.marionette'),
    moment = require('moment'),
    App = require('../app'),
    settings = require('../core/settings'),
    utils = require('./utils'),
    errorTmpl = require('./templates/error.html'),
    formTmpl = require('./templates/form.html'),
    pagerTmpl = require('./templates/pager.html'),
    searchResultTmpl = require('./templates/searchResult.html'),
    cuahsiSearchResultTmpl = require('./templates/cuahsiSearchResult.html'),
    tabContentTmpl = require('./templates/tabContent.html'),
    tabPanelTmpl = require('./templates/tabPanel.html'),
    windowTmpl = require('./templates/window.html');

var ENTER_KEYCODE = 13,
    PAGE_SIZE = settings.get('data_catalog_page_size'),
    CATALOG_RESULT_TEMPLATE = {
        cinergi: searchResultTmpl,
        hydroshare: searchResultTmpl,
        cuahsi: cuahsiSearchResultTmpl,
    };

var DataCatalogWindow = Marionette.LayoutView.extend({
    template: windowTmpl,
    className: 'data-catalog-window',

    ui: {
        introText: '.intro-text',
        tabs: '.output-tabs-wrapper'
    },

    regions: {
        formRegion: '.form-region',
        panelsRegion: '.tab-panels-region',
        contentsRegion: '.tab-contents-region'
    },

    childEvents: {
        'search': 'doSearch',
        'selectCatalog': 'onSelectCatalog'
    },

    collectionEvents: {
        'change:active change:loading': 'updateMap'
    },

    onShow: function() {
        this.formRegion.show(new FormView({
            model: this.model
        }));
        this.panelsRegion.show(new TabPanelsView({
            collection: this.collection
        }));
        this.contentsRegion.show(new TabContentsView({
            collection: this.collection
        }));
    },

    getActiveCatalog: function() {
        return this.collection.findWhere({ active: true });
    },

    onSelectCatalog: function(childView, catalogId) {
        // Deactiveate previous catalog
        var prevCatalog = this.getActiveCatalog();
        if (prevCatalog && prevCatalog.id !== catalogId) {
            prevCatalog.set('active', false);
        }

        // Activate selected catalog
        var nextCatalog = this.collection.get(catalogId);
        nextCatalog.set('active', true);

        this.doSearch();
    },

    doSearch: function() {
        var catalog = this.getActiveCatalog(),
            query = this.model.get('query'),
            fromDate = this.model.get('fromDate'),
            toDate = this.model.get('toDate'),
            aoiGeoJson = L.geoJson(App.map.get('areaOfInterest')),
            bounds = utils.formatBounds(aoiGeoJson.getBounds());

        // Disable intro text after first search request
        this.ui.introText.addClass('hide');
        this.ui.tabs.removeClass('hide');

        catalog.searchIfNeeded(query, fromDate, toDate, bounds);
    },

    updateMap: function() {
        var catalog = this.getActiveCatalog(),
            geoms = catalog && catalog.get('results').pluck('geom');
        App.map.set('dataCatalogResults', geoms);
    }
});

var FormView = Marionette.ItemView.extend({
    template: formTmpl,
    className: 'data-catalog-form',

    ui: {
        dateInput: '.data-catalog-date-input',
        filterToggle: '.date-filter-toggle',
        searchInput: '.data-catalog-search-input',
        clearable: '.data-catalog-clearable-input a',
    },

    modelEvents: {
        'change:showingFilters change:isValid change:toDate change:fromDate': 'render'
    },

    events: {
        'keyup @ui.searchInput': 'onSearchInputChanged',
        'click @ui.filterToggle': 'onFilterToggle',
        'change @ui.dateInput': 'onDateInputChanged',
        'keyup @ui.dateInput': 'onDateInputKeyup',
        'click @ui.clearable': 'onClearInput',
    },

    onRender: function() {
        $('.data-catalog-date-input').datepicker();
    },

    onClearInput: function(e) {
        var $el = $(e.currentTarget).siblings('input').val('');
        this.updateDateInput($el);
    },

    onSearchInputChanged: function(e) {
        var query = this.ui.searchInput.val().trim();
        if (e.keyCode === ENTER_KEYCODE) {
            this.triggerSearch();
        } else {
            this.model.set('query', query);
        }
    },

    onDateInputKeyup: function(e) {
        if (e.keyCode === ENTER_KEYCODE) {
            this.triggerSearch();
        }
    },

    onDateInputChanged: function(e) {
        this.updateDateInput($(e.currentTarget));
    },

    onFilterToggle: function() {
        var newVal = !this.model.get('showingFilters');
        this.model.set('showingFilters', newVal);
    },

    updateDateInput: function($dateEl) {
        var isFromDate = $dateEl.hasClass('from-date'),
            attr = isFromDate ? 'fromDate' : 'toDate';

        this.model.set(attr, $dateEl.val());
    },

    triggerSearch: function() {
        if (this.validate()) {
            this.triggerMethod('search');
        }
    },

    validate: function() {
        // Only need to validate if there are two dates.  Ensure that
        // before is earlier than after
        var dateFormat = "MM/DD/YYYY",
            toDate = this.model.get('toDate'),
            fromDate = this.model.get('fromDate'),
            isValid = false;

        if (!toDate || !fromDate) {
            isValid = true;
        } else {
            isValid = moment(fromDate, dateFormat)
                        .isBefore(moment(toDate, dateFormat));
        }

        this.model.set('isValid', isValid);
        return isValid;
    },

    templateHelpers: function() {
        var showingFilters = this.model.get('showingFilters');

        return {
            filterText: showingFilters ? 'Hide Filters' : 'Show Filters',
        };
    }
});

var TabPanelView = Marionette.ItemView.extend({
    tagName: 'li',
    template: tabPanelTmpl,
    attributes: {
        role: 'presentation'
    },

    events: {
        'click a': 'onTabClicked'
    },

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

    onTabClicked: function() {
        this.triggerMethod('selectCatalog', this.model.id);
    },

    onRender: function() {
        this.$el.toggleClass('active', this.model.get('active'));
    }
});

var TabPanelsView = Marionette.CollectionView.extend({
    tagName: 'ul',
    className: 'nav nav-tabs',
    attributes: {
        role: 'tablist'
    },
    childView: TabPanelView
});

var ErrorView = Marionette.ItemView.extend({
    template: errorTmpl,
    modelEvents: {
        'change:error': 'render',
    },
});

var TabContentView = Marionette.LayoutView.extend({
    className: 'tab-pane',
    id: function() {
        return this.model.id;
    },
    template: tabContentTmpl,
    attributes: {
        role: 'tabpanel'
    },

    ui: {
        noResults: '.no-results-panel'
    },

    regions: {
        pagerRegion: '.pager-region',
        resultRegion: '.result-region',
        errorRegion: '.error-region',
    },

    modelEvents: {
        'change': 'update',
        'change:active': 'toggleActiveClass',
    },

    onShow: function() {
        this.toggleActiveClass();

        this.resultRegion.show(new ResultsView({
            collection: this.model.get('results'),
            catalog: this.model.id,
        }));

        this.errorRegion.show(new ErrorView({
            model: this.model,
        }));

        if (this.model.get('is_pageable')) {
            this.pagerRegion.show(new PagerView({
                model: this.model,
            }));
        }
    },

    toggleActiveClass: function() {
        this.$el.toggleClass('active', this.model.get('active'));
    },

    update: function() {
        this.ui.noResults.addClass('hide');
        this.errorRegion.$el.addClass('hide');
        this.resultRegion.$el.addClass('hide');
        this.pagerRegion.$el.addClass('hide');

        var error = this.model.get('error'),
            // Don't show "no results" while search request is in progress
            showNoResults = !this.model.get('loading') &&
                            this.model.get('resultCount') === 0 && !error;

        if (showNoResults) {
            this.ui.noResults.removeClass('hide');
        } else if (error) {
            this.errorRegion.$el.removeClass('hide');
        } else {
            this.resultRegion.$el.removeClass('hide');
            this.pagerRegion.$el.removeClass('hide');
        }
    }
});

var TabContentsView = Marionette.CollectionView.extend({
    className: 'tab-content',
    childView: TabContentView
});

var ResultView = Marionette.ItemView.extend({
    getTemplate: function() {
        return CATALOG_RESULT_TEMPLATE[this.options.catalog];
    },

    className: 'resource',

    events: {
        'mouseover': 'highlightResult',
        'mouseout': 'unHighlightResult',
    },

    highlightResult: function() {
        App.map.set('dataCatalogActiveResult', this.model.get('geom'));
    },

    unHighlightResult: function() {
        App.map.set({ dataCatalogActiveResult: null });
    }
});

var ResultsView = Marionette.CollectionView.extend({
    childView: ResultView,

    childViewOptions: function() {
        return {
            catalog: this.options.catalog,
        };
    },

    modelEvents: {
        'sync error': 'render'
    }
});

var PagerView = Marionette.ItemView.extend({
    template: pagerTmpl,

    ui: {
        previous: '#pager-previous',
        next: '#pager-next',
    },

    events: {
        'click @ui.previous': 'previousPage',
        'click @ui.next': 'nextPage',
    },

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

    templateHelpers: function() {
        var resultCount = this.model.get('resultCount'),
            page = this.model.get('page'),
            lastPage = Math.ceil(resultCount / PAGE_SIZE);

        return {
            has_results: resultCount > 0,
            has_previous: page > 1,
            has_next: page < lastPage,
        };
    },

    previousPage: function() {
        return this.model.previousPage();
    },

    nextPage: function() {
        return this.model.nextPage();
    }
});

module.exports = {
    DataCatalogWindow: DataCatalogWindow
};
<|endoftext|>


<commit_before>#!  /usr/bin/node

var rep = require("./representation.js");
var tools = require("./tools.js");
var operators = Object.keys(rep.OPInfo);

var matchop = tools.opMatch(operators);

function isDigit(a) {
  if (!a)
    return false;
  var code = a.charCodeAt();
  return (46 < code && code < 58 || code < 58 && code > 46);
}

function isWhitespace(a) {
  if (!a)
    return true;

  var code = a.charCodeAt();
  return (code === 9 || code === 32 || code === 10 || code === 13 || code === 11);
}

function isIdentifier(a) {
  var code = a.charCodeAt();
  return code !== 41 && code !== 40 && code && 125 && code && 123 && code !== 93 && code !== 91 && code !== 44;
}

function tokenizeNum(tokstream, charnum, linenum) {
  var number = [];
  var code = tokstream[0].charCodeAt();
  var isFloat = false;
  var n = 0;
  // + -
  if (code === 43 || code === 45) { // + or -
    number.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    n++;
  }
  else if (code === 46) { // .
    tokstream = tokstream.substr(1);
    n++;
    charnum++;
    number.push('0');
    number.push('.');
    isFloat = true;
  }

  while (isDigit(tokstream[0]) && tokstream.length !== 0) {
    number.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    charnum++;
    n++;
  }
  if (tokstream[0] === '.' && isDigit(tokstream[1])) {
    number.push('.');
    number.push(tokstream[1]);
    tokstream = tokstream.substr(2);
    charnum++; charnum++;
    n++; n++;
    while (isDigit(tokstream[0]) && tokstream.length !== 0) {
      number.push(tokstream[0]);
      tokstream = tokstream.substr(1);
      n++;
      charnum++;
    }
    return [n, ["float", parseFloat(number.join(''), 10), charnum, linenum]];
  }
  if (!isFloat)
    return [n, ["integer", parseInt(number.join(''), 10), charnum, linenum]];
  else
    return [n, ["float", parseFloat(number.join(''), 10), charnum, linenum]];
}

/* Split up the tokenized identifier if an operator appears in it
 * prefer longer identifiers that start with the same character(s) as shorter ones
 * e.g. ++ over +
 * Everything after the operator goes back on to the token stream
 */

function tokenizeIdent(tokstream, charnum, linenum) {
  var identifier = [];
  var n = 0;
  while ((!isWhitespace(tokstream[0])) && isIdentifier(tokstream[0]) && !matchop(tokstream)) {
    identifier.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    n++;
    charnum++;
  }
  identifier = identifier.join('');

  return [[n, ["identifier", identifier, charnum, linenum]]];
}

function tokenizeStr(tokstream, charnum, linenum) {
  var stringlit = [];
  var n = 1;
  tokstream = tokstream.substr(1);
  while (tokstream[0].charCodeAt() !== 34) {
    stringlit.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    n++;
    charnum++;
    if (tokstream.length < 1) {
      throw "Error: missing quotation mark";
    }
  }
  n++;
  return [n, ["stringlit", stringlit.join(''), charnum, linenum]];

}

function tokenizeT(tokstreami, charnum, linenum) {
  if (tokstream.length < 4)
    return false;
  var next4 = tokstream.substr(0,4);
  if (next4 === "then")
    return ["thenexp", "then"];
  else if (next4 === "true")
    return ["truelit", "true"];
  return false;
}

function peek(tokstream, toktype, word, charnum, linenum) {
  var n = word.length;
  if (tokstream.length < n)
    return false;
  var nextN = tokstream.substr(0, n);
  if (nextN == word) {
    return [toktype, word];
  }
  return false;
}

function tokenize(tokstream) {
  var tokens = [];
  var charnum = 1;
  var linenum = 1;

  while (tokstream) {
    switch (tokstream[0].charCodeAt()) {
      case 9: // '\t'
        charnum++;
        tokens.push(["whitespace", '\t', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 32: // ' '
        charnum++;
        tokens.push(["whitespace", ' ', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 10: // '\n'
        linenum++;
        charnum = 1;
        tokens.push(["whitespace", '\n', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 44: // ','
        charnum++;
        tokens.push(["comma", ",", charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 40: // '('
        charnum++;
        tokens.push(["left_paren", '(', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 41: // ')'
        charnum++;
        tokens.push(["right_paren", ')', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 123: // '{'
        charnum++;
        tokens.push(["left_brace", '{', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 125: // '}'
        charnum++;
        tokens.push(["right_brace", '}', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 91: // '['
        charnum++;
        tokens.push(["left_square", '[', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 93: // ']'
        charnum++;
        tokens.push(["right_square", ']', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 34: // '"'
        var result = tokenizeStr(tokstream, charnum, linenum);
        var str = result[1];
        var i = result[0];
        tokens.push(str);
        tokstream = tokstream.substr(i);
        break;

      case 45: // '-'
        var lambda = peek(tokstream, "arrow", "->");
        if (lambda) {
          tokens.push(lambda);
          tokstream = tokstream.substr(2);
          break;
        }
        else {
          tokens.push(["identifier", "-", charnum, linenum]);
          charnum++;
          tokstream = tokstream.substr(1);
          break;
        }

      case 46: // '.'
        if (isDigit(tokstream[1])) {
          var result = tokenizeNum(tokstream, charnum, linenum);
          var num = result[1];
          var i = result[0];
          if (num[1] !== NaN)
            tokens.push(num);
          tokstream = tokstream.substr(i);
          break;
        }
      case 116: // 't'
        var result = tokenizeT(tokstream);
        if (result) {
          tokens.push(result);
          tokstream = tokstream.substr(4); // 4 = length of either token
          break;
        }

      case 105: // 'i'
        var ifexp = peek(tokstream, "ifexp", "if");
        if (ifexp) {
          tokens.push(ifexp);
          tokstream = tokstream.substr(2);
          break;
        }
        var inkeyword = peek(tokstream, "in", "in");
        if (inkeyword) {
          tokens.push(inkeyword);
          tokstream = tokstream.substr(2);
          break;
        }

      case 100: // 'd'
        var result = peek(tokstream, "def", "def");
        if (result) {
          tokens.push(result);
          tokstream = tokstream.substr(3);
          break;
        }
      case 101: // e
        var result = peek(tokstream, "elsexp", "else");
        if (result) {
          tokens.push(result);
          tokstream = tokstream.substr(4);
          break;
        }
      case 102: // f
        var result = peek(tokstream, "falselit", "false");
        if (result) {
          tokens.push(result);
          tokstream = tokstream.substr(5);
          break;
        }
      case 108: // l
        var lambda = peek(tokstream, "lambda", "lambda");
        if (lambda) {
          tokens.push(lambda);
          tokstream = tokstream.substr(6);
          break;
        }
        var letexp = peek(tokstream, "let", "let");
        if (letexp) {
          tokens.push(letexp);
          tokstream = tokstream.substr(3);
          break;
        }

      default:
        if (isDigit(tokstream[0])) {
          var result = tokenizeNum(tokstream, charnum, linenum);
          var num = result[1];
          var i = result[0];
          if (num[1] !== NaN)
            tokens.push(num);
          tokstream = tokstream.substr(i);
          break;
        }
        var op = matchop(tokstream);
        if (op) {
          var l = op.length;
          charnum = charnum + l;
          tokstream = tokstream.substr(l);
          tokens.push(["identifier", op, charnum, linenum]);
        }
        else {
          var result = tokenizeIdent(tokstream, charnum, linenum);
          result.map(function(x) {
            charnum++;
            tokens.push(x[1]);
            tokstream = tokstream.substr(x[0]);
          });
        }
    }
  }
  return tokens;
}

function tokenizeFull(input) {
  try {
    return tokenize(input).reverse().filter(function(x) {
      return x[0] !== "whitespace";
    });
  } catch (e) {
    console.log("An error occured during tokenization");
    console.log(e);
    process.exit(1);
  }
}

module.exports = {tokenize : tokenizeFull};
<commit_msg>reverted bug<commit_after>#!  /usr/bin/node

var rep = require("./representation.js");
var tools = require("./tools.js");
var operators = Object.keys(rep.OPInfo);

var matchop = tools.opMatch(operators);

function isDigit(a) {
  if (!a)
    return false;
  var code = a.charCodeAt();
  return (46 < code && code < 58 || code < 58 && code > 46);
}

function isWhitespace(a) {
  if (!a)
    return true;

  var code = a.charCodeAt();
  return (code === 9 || code === 32 || code === 10 || code === 13 || code === 11);
}

function isIdentifier(a) {
  var code = a.charCodeAt();
  return code !== 41 && code !== 40 && code && 125 && code && 123 && code !== 93 && code !== 91 && code !== 44;
}

function tokenizeNum(tokstream, charnum, linenum) {
  var number = [];
  var code = tokstream[0].charCodeAt();
  var isFloat = false;
  var n = 0;
  // + -
  // might want to remove this since it probably won't ever get run?
  if (code === 43 || code === 45) { // + or -
    number.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    n++;
  }
  else if (code === 46) { // .
    tokstream = tokstream.substr(1);
    n++;
    charnum++;
    number.push('0');
    number.push('.');
    isFloat = true;
  }

  while (isDigit(tokstream[0]) && tokstream.length !== 0) {
    number.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    charnum++;
    n++;
  }
  if (tokstream[0] === '.' && isDigit(tokstream[1])) {
    number.push('.');
    number.push(tokstream[1]);
    tokstream = tokstream.substr(2);
    charnum++; charnum++;
    n++; n++;
    while (isDigit(tokstream[0]) && tokstream.length !== 0) {
      number.push(tokstream[0]);
      tokstream = tokstream.substr(1);
      n++;
      charnum++;
    }
    return [n, ["float", parseFloat(number.join(''), 10), charnum, linenum]];
  }
  if (!isFloat)
    return [n, ["integer", parseInt(number.join(''), 10), charnum, linenum]];
  else
    return [n, ["float", parseFloat(number.join(''), 10), charnum, linenum]];
}

/* Split up the tokenized identifier if an operator appears in it
 * prefer longer identifiers that start with the same character(s) as shorter ones
 * e.g. ++ over +
 * Everything after the operator goes back on to the token stream
 */

function tokenizeIdent(tokstream, charnum, linenum) {
  var identifier = [];
  var n = 0;
  while ((!isWhitespace(tokstream[0])) && isIdentifier(tokstream[0]) && !matchop(tokstream)) {
    identifier.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    n++;
    charnum++;
  }
  identifier = identifier.join('');

  return [[n, ["identifier", identifier, charnum, linenum]]];
}

function tokenizeStr(tokstream, charnum, linenum) {
  var stringlit = [];
  var n = 1;
  tokstream = tokstream.substr(1);
  while (tokstream[0].charCodeAt() !== 34) {
    stringlit.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    n++;
    charnum++;
    if (tokstream.length < 1) {
      throw "Error: missing quotation mark";
    }
  }
  n++;
  return [n, ["stringlit", stringlit.join(''), charnum, linenum]];

}

function tokenizeT(tokstreami, charnum, linenum) {
  if (tokstream.length < 4)
    return false;
  var next4 = tokstream.substr(0,4);
  if (next4 === "then")
    return ["thenexp", "then"];
  else if (next4 === "true")
    return ["truelit", "true"];
  return false;
}

function peek(tokstream, toktype, word, charnum, linenum) {
  var n = word.length;
  if (tokstream.length < n)
    return false;
  var nextN = tokstream.substr(0, n);
  if (nextN == word) {
    return [toktype, word];
  }
  return false;
}

function tokenize(tokstream) {
  var tokens = [];
  var charnum = 1;
  var linenum = 1;

  while (tokstream) {
    switch (tokstream[0].charCodeAt()) {
      case 9: // '\t'
        charnum++;
        tokens.push(["whitespace", '\t', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 32: // ' '
        charnum++;
        tokens.push(["whitespace", ' ', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 10: // '\n'
        linenum++;
        charnum = 1;
        tokens.push(["whitespace", '\n', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 44: // ','
        charnum++;
        tokens.push(["comma", ",", charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 40: // '('
        charnum++;
        tokens.push(["left_paren", '(', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 41: // ')'
        charnum++;
        tokens.push(["right_paren", ')', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 123: // '{'
        charnum++;
        tokens.push(["left_brace", '{', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 125: // '}'
        charnum++;
        tokens.push(["right_brace", '}', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 91: // '['
        charnum++;
        tokens.push(["left_square", '[', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 93: // ']'
        charnum++;
        tokens.push(["right_square", ']', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 34: // '"'
        var result = tokenizeStr(tokstream, charnum, linenum);
        var str = result[1];
        var i = result[0];
        tokens.push(str);
        tokstream = tokstream.substr(i);
        break;

      case 45: // '-'
        var lambda = peek(tokstream, "arrow", "->");
        if (lambda) {
          tokens.push(lambda);
          tokstream = tokstream.substr(2);
          break;
        }
        else {
          tokens.push(["identifier", "-", charnum, linenum]);
          charnum++;
          tokstream = tokstream.substr(1);
          break;
        }

      case 46: // '.'
        if (isDigit(tokstream[1])) {
          var result = tokenizeNum(tokstream, charnum, linenum);
          var num = result[1];
          var i = result[0];
          if (num[1] !== NaN)
            tokens.push(num);
          tokstream = tokstream.substr(i);
          break;
        }
      case 116: // 't'
        var result = tokenizeT(tokstream);
        if (result) {
          tokens.push(result);
          tokstream = tokstream.substr(4); // 4 = length of either token
          break;
        }

      case 105: // 'i'
        var ifexp = peek(tokstream, "ifexp", "if");
        if (ifexp) {
          tokens.push(ifexp);
          tokstream = tokstream.substr(2);
          break;
        }
        var inkeyword = peek(tokstream, "in", "in");
        if (inkeyword) {
          tokens.push(inkeyword);
          tokstream = tokstream.substr(2);
          break;
        }

      case 100: // 'd'
        var result = peek(tokstream, "def", "def");
        if (result) {
          tokens.push(result);
          tokstream = tokstream.substr(3);
          break;
        }
      case 101: // e
        var result = peek(tokstream, "elsexp", "else");
        if (result) {
          tokens.push(result);
          tokstream = tokstream.substr(4);
          break;
        }
      case 102: // f
        var result = peek(tokstream, "falselit", "false");
        if (result) {
          tokens.push(result);
          tokstream = tokstream.substr(5);
          break;
        }
      case 108: // l
        var lambda = peek(tokstream, "lambda", "lambda");
        if (lambda) {
          tokens.push(lambda);
          tokstream = tokstream.substr(6);
          break;
        }
        var letexp = peek(tokstream, "let", "let");
        if (letexp) {
          tokens.push(letexp);
          tokstream = tokstream.substr(3);
          break;
        }

      default:
        if (isDigit(tokstream[0])) {
          var result = tokenizeNum(tokstream, charnum, linenum);
          var num = result[1];
          var i = result[0];
          if (num[1] !== NaN)
            tokens.push(num);
          tokstream = tokstream.substr(i);
          break;
        }
        var op = matchop(tokstream);
        if (op) {
          var l = op.length;
          charnum = charnum + l;
          tokstream = tokstream.substr(l);
          tokens.push(["identifier", op, charnum, linenum]);
        }
        else {
          var result = tokenizeIdent(tokstream, charnum, linenum);
          result.map(function(x) {
            charnum++;
            tokens.push(x[1]);
            tokstream = tokstream.substr(x[0]);
          });
        }
    }
  }
  return tokens;
}

function tokenizeFull(input) {
  try {
    return tokenize(input).reverse().filter(function(x) {
      return x[0] !== "whitespace";
    });
  } catch (e) {
    console.log("An error occured during tokenization");
    console.log(e);
    process.exit(1);
  }
}

module.exports = {tokenize : tokenizeFull};
<|endoftext|>


<commit_before>var validators = require('./validators'),
    widgets = require('./widgets');

var Field = exports.Field = function (options) {
    options = options || {};

    this.omit_empty = options.omit_empty;
    this.default_value = options.default_value;
    this.label = options.label;
    this.widget = options.widget || widgets.text();
    this.required = ('required' in options) ? options.required: true;
    this.validators = ('validators' in options) ? options.validators: [];
    this.parse = options.parse || function (raw) {
        return raw;
    };
};

Field.prototype.errorHTML = function (errors) {
    if (errors && errors.length) {
        var html = '
';
        for (var i = 0; i < errors.length; i++) {
            html += '
' + errors[i] + '
';
        }
        html += '
';
        return html;
    }
    return '';
};

Field.prototype.labelText = function (name) {
    if (this.label) {
        return this.label;
    }
    return name[0].toUpperCase() + name.substr(1).replace('_', ' ');
};

Field.prototype.labelHTML = function (name, id) {
    return '' +
        this.labelText(name, id) +
    '';
};

Field.prototype.classes = function (errors) {
    var r = ['field'];
    if (errors && errors.length) {
        r.push('error');
    }
    if (this.required) {
        r.push('required');
    }
    return r;
};

Field.prototype.validate = function (doc, value) {
    if (value === '' || value === null || value === undefined) {
        // don't validate empty fields, but check if required
        if (this.required) {
            throw new Error('required field');
        }
    }
    else {
        for (var i = 0; i < this.validators.length; i++) {
            this.validators[i](doc, value);
        }
    }
};

exports.string = function (options) {
    options = options || {};

    options.parse = function (raw) {
        return '' + raw;
    };
    return new Field(options);
};

exports.number = function (options) {
    options = options || {};

    options.parse = function (raw) {
        if (raw === null || raw === '') {
            return NaN;
        }
        return Number(raw);
    };
    if (!options.validators) {
        options.validators = [];
    }
    options.validators.unshift(function (doc, value) {
        if (isNaN(value)) {
            throw new Error('Not a number');
        }
    });
    return new Field(options);
};

exports.boolean = function (options) {
    options = options || {};

    options.parse = function (raw) {
        return Boolean(raw);
    };
    return new Field(options);
};

exports.url = function (options) {
    options = options || {};

    if (!options.validators) {
        options.validators = [];
    }
    options.validators.unshift(validators.url());
    return exports.string(options);
};

exports.email = function (options) {
    options = options || {};

    if (!options.validators) {
        options.validators = [];
    }
    options.validators.unshift(validators.email());
    return exports.string(options);
};
<commit_msg>don't return NaN from empty number field<commit_after>var validators = require('./validators'),
    widgets = require('./widgets');

var Field = exports.Field = function (options) {
    options = options || {};

    this.omit_empty = options.omit_empty;
    this.default_value = options.default_value;
    this.label = options.label;
    this.widget = options.widget || widgets.text();
    this.required = ('required' in options) ? options.required: true;
    this.validators = ('validators' in options) ? options.validators: [];
    this.parse = options.parse || function (raw) {
        return raw;
    };
};

Field.prototype.errorHTML = function (errors) {
    if (errors && errors.length) {
        var html = '
';
        for (var i = 0; i < errors.length; i++) {
            html += '
' + errors[i] + '
';
        }
        html += '
';
        return html;
    }
    return '';
};

Field.prototype.labelText = function (name) {
    if (this.label) {
        return this.label;
    }
    return name[0].toUpperCase() + name.substr(1).replace('_', ' ');
};

Field.prototype.labelHTML = function (name, id) {
    return '' +
        this.labelText(name, id) +
    '';
};

Field.prototype.classes = function (errors) {
    var r = ['field'];
    if (errors && errors.length) {
        r.push('error');
    }
    if (this.required) {
        r.push('required');
    }
    return r;
};

Field.prototype.validate = function (doc, value) {
    if (value === '' || value === null || value === undefined) {
        // don't validate empty fields, but check if required
        if (this.required) {
            throw new Error('required field');
        }
    }
    else {
        for (var i = 0; i < this.validators.length; i++) {
            this.validators[i](doc, value);
        }
    }
};

exports.string = function (options) {
    options = options || {};

    options.parse = function (raw) {
        return '' + raw;
    };
    return new Field(options);
};

exports.number = function (options) {
    options = options || {};

    options.parse = function (raw) {
        if (raw === null || raw === '') {
            return '';
        }
        return Number(raw);
    };
    if (!options.validators) {
        options.validators = [];
    }
    options.validators.unshift(function (doc, value) {
        if (isNaN(value)) {
            throw new Error('Not a number');
        }
    });
    return new Field(options);
};

exports.boolean = function (options) {
    options = options || {};

    options.parse = function (raw) {
        return Boolean(raw);
    };
    return new Field(options);
};

exports.url = function (options) {
    options = options || {};

    if (!options.validators) {
        options.validators = [];
    }
    options.validators.unshift(validators.url());
    return exports.string(options);
};

exports.email = function (options) {
    options = options || {};

    if (!options.validators) {
        options.validators = [];
    }
    options.validators.unshift(validators.email());
    return exports.string(options);
};
<|endoftext|>