<commit_before>import React, { Component } from 'react';
import Gql from 'react-gql';
import classNames from 'classnames';
import listensToClickOutside from 'react-onclickoutside/decorator';
import { wineFragment } from '../fields';

function debounce(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this, args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
}

const config = {
  getState: state => ({
    wines: state.cellar.searchedWines
  }),
  mutations: {
    search: {
      query: `
        query searchWines($q: String!) {
          wines(q: $q) {
            ...wine
          }
        }
        ${wineFragment}
      `,
      action: actions => actions.cellar.getWinesForSearch,
    }
  }
};

class WineSelect extends Component {
  static propTypes = {
    wine: React.PropTypes.object,
    onSelect: React.PropTypes.func,
    onReset: React.PropTypes.func,
    className: React.PropTypes.string,
  };

  constructor(props) {
    super(props);
    this.state = {
      displayOptions: false,
      input: '',
    };

    this.searchWinesDebounced = debounce(() => {
      this.searchWines();
    }, 500);
  }

  searchWines() {
    const { input } = this.state;
    if (!input) return;
    this.props.mutations.search({ q: input });
  }

  handleChange(event) {
    event.preventDefault();
    this.setState({
      ...this.state,
      input: event.target.value,
    });
    this.searchWinesDebounced();
  }

  handleSelect(wine) {
    return (event) =>{
      event.preventDefault();
      this.setState({
        ...this.state,
        input: wine.name,
      });
      this.props.onSelect(wine);
    };
  }

  handleClearSelection() {
    if (this.props.onReset) this.props.onReset();
  }

  handleFocusInput() {
    this.setState({
      ...this.state,
      displayOptions: true,
    });
  }

  handleClickOutside() {
    this.setState({
      ...this.state,
      displayOptions: false,
    });
  }

  renderOptions() {
    const { wines } = this.props;
    if (!this.state.input) return;
    return (

        {wines.map(::this.renderOption)}

    );
  }

  renderOption(wine) {
    return (

        {wine.name} {wine.vintage} ({wine.color})

    );
  }

  renderSelection(wine) {
    return(

          {wine.name} {wine.vintage} ({wine.color})
          <button className="btn btn-secondary" onClick={::this.handleClearSelection}>×</button>

    );
  }

  render() {
    if (this.props.wine) {
      return this.renderSelection(this.props.wine);
    }

    const classDropdown = classNames({
      dropdown: true,
      open: this.state.displayOptions,
    });

    return (

        <input
          type="text"
          name="wine"
          value={this.state.input}
          onChange={::this.handleChange}
          placeholder="Search for a Wine..."
          className={this.props.className}
          onFocus={::this.handleFocusInput}
        />
        {::this.renderOptions()}

    );
  }
}

export default Gql.Root(config)(listensToClickOutside(WineSelect));
<commit_msg>Added: keys navigation<commit_after>import React, { Component } from 'react';
import Gql from 'react-gql';
import classNames from 'classnames';
import listensToClickOutside from 'react-onclickoutside/decorator';
import { wineFragment } from '../fields';

function debounce(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this, args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
}

const config = {
  getState: state => ({
    wines: state.cellar.searchedWines
  }),
  mutations: {
    search: {
      query: `
        query searchWines($q: String!) {
          wines(q: $q) {
            ...wine
          }
        }
        ${wineFragment}
      `,
      action: actions => actions.cellar.getWinesForSearch,
    }
  }
};

class WineSelect extends Component {
  static propTypes = {
    wine: React.PropTypes.object,
    onSelect: React.PropTypes.func,
    onReset: React.PropTypes.func,
    className: React.PropTypes.string,
  };

  constructor(props) {
    super(props);
    this.state = {
      displayOptions: false,
      input: '',
    };

    this.searchWinesDebounced = debounce(() => {
      this.searchWines();
    }, 500);
  }

  searchWines() {
    const { input } = this.state;
    if (!input) return;
    this.props.mutations.search({ q: input });
  }

  handleChange(event) {
    event.preventDefault();
    this.setState({
      ...this.state,
      input: event.target.value,
    });
    this.searchWinesDebounced();
  }

  handleSelect(wine) {
    return (event) =>{
      event.preventDefault();
      this.setState({
        ...this.state,
        input: wine.name,
      });
      this.props.onSelect(wine);
    };
  }

  handleClearSelection() {
    if (this.props.onReset) this.props.onReset();
  }

  handleFocusInput() {
    this.setState({
      ...this.state,
      displayOptions: true,
    });
  }

  handleClickOutside() {
    this.setState({
      ...this.state,
      displayOptions: false,
    });
  }

  handleKeyPress(index) {
    return (event) => {
      let newIndex;
      switch (event.key) {
        case 'ArrowDown':
          newIndex = index + 1;
          break;
        case 'ArrowUp':
          newIndex = index - 1;
          break;
      }

      const ref = this.refs[`option${newIndex}`];
      if (ref) ref.focus();
    };
  }

  renderOptions() {
    const { wines } = this.props;
    if (!this.state.input) return;
    return (

        {wines.map(::this.renderOption)}

    );
  }

  renderOption(wine, index) {
    return (
      <a href
        className="dropdown-item"
        key={wine.id}
        onClick={::this.handleSelect(wine)}
        onKeyDown={::this.handleKeyPress(index)}
        ref={`option${index}`}
      >
        {wine.name} {wine.vintage} ({wine.color})

    );
  }

  renderSelection(wine) {
    return(

          {wine.name} {wine.vintage} ({wine.color})
          <button className="btn btn-secondary" onClick={::this.handleClearSelection}>×</button>

    );
  }

  render() {
    if (this.props.wine) {
      return this.renderSelection(this.props.wine);
    }

    const classDropdown = classNames({
      dropdown: true,
      open: this.state.displayOptions,
    });

    return (

        <input
          type="text"
          name="wine"
          value={this.state.input}
          onChange={::this.handleChange}
          placeholder="Search for a Wine..."
          className={this.props.className}
          onFocus={::this.handleFocusInput}
          onKeyDown={::this.handleKeyPress(-1)}
          ref="option-1"
          autoComplete="off"
        />
        {::this.renderOptions()}

    );
  }
}

export default Gql.Root(config)(listensToClickOutside(WineSelect));
<|endoftext|>


<commit_before>"use strict"

class MSCP{
  async init(){
    this.apiPath = typeof MSCP_API_PATH === "string" ? MSCP_API_PATH : '/api'
    this.def = await this.apireq("")
    this.mscp_request_include_always_parms = {}

    if(this.def.error !== undefined && localStorage.MSCPDefinition !== undefined){
      this.def = JSON.parse(localStorage.MSCPDefinition)
      console.log("Could not fetch MSCP definition, so the one from localStorage is used")
    }

    if(this.def.error === undefined){
      for(let s of this.def.serve){
        this._addDependency(s)
      }
      localStorage.MSCPDefinition = JSON.stringify(this.def);
      return true;
    }

    console.log("Could not get any MSCP definition. Client calls will fail!")
    return false;
  }

  _addDependency(s){
    let obj = this;
    if(s.namespace){
      if(this[s.namespace] === undefined){
        this[s.namespace] = {}
      }
      obj = this[s.namespace];
    }

    obj[s.name] = async function(...args){
      let data = {}
      let i = 0
      for(let i = 0; i < s.args.length && i < args.length; i++){
        let a = s.args[i]
        if(typeof a === "string"){
          data[a] = args[i] !== undefined ? args[i] : null
        } else if (typeof a === "object" && typeof a.name === "string" && a.name != ""){
          data[a.name] = args[i] !== undefined ? args[i] : null
        }
      }

      var response = await this.apireq((s.namespace ? s.namespace + "/" : "") + s.name, data);
      if(response.success === true)
        return response.result;
      else {
        console.log("Error on calling function " + s.name + ": " + response.error)
        throw response.error;
      }
    }
  }

  async apireq(command, data = {}){
    return this.req(`${this.apiPath}/${command}`, data);
  }

  async req(url, data = {}){
    let reqData = jQuery.extend({}, data, this.mscp_request_include_always_parms);
    try{
      let response = await fetch(url, {
        method: 'post',
        body: JSON.stringify(reqData),
        credentials: 'include',
        headers: new Headers({
          'Content-Type': 'application/json'
        })
      });
      if(response.status == 403){
        let accessKey = prompt("You do not have access to this functionality. Enter an access key to continue.")
        if(accessKey){
          data.accessKey = accessKey;
          return await this.req(url, reqData)
        }
      }
      return await response.json();
    } catch(err){
      console.log(err)
      return {success: false, error: "Could not connect to server or received invalid response"};
    }
  }
}

var mscp = new MSCP();
mscp.ready = new Promise((resolve, reject)=>{mscp.readyResolve = resolve})
$(function() {
  (async () => {
    await mscp.init();
    mscp.readyResolve();
  })()
});
<commit_msg>Misc fixes<commit_after>"use strict"

class MSCP{
  async init(){
    this.apiPath = typeof MSCP_API_PATH === "string" ? MSCP_API_PATH : '/api'
    this.def = await this.apireq("")
    this.mscp_request_include_always_parms = {}

    if(this.def.error !== undefined && localStorage.MSCPDefinition !== undefined){
      this.def = JSON.parse(localStorage.MSCPDefinition)
      console.log("Could not fetch MSCP definition, so the one from localStorage is used")
    }

    if(this.def.error === undefined){
      for(let s of this.def.serve){
        this._addDependency(s)
      }
      localStorage.MSCPDefinition = JSON.stringify(this.def);
      return true;
    }

    console.log("Could not get any MSCP definition. Client calls will fail!")
    return false;
  }

  _addDependency(s){
    let obj = this;
    let objKey = s.name;
    if(s.namespace){
      if(this[s.namespace] === undefined){
        this[s.namespace] = {}
      }
      objKey = `${s.namespace}.${s.name}`
      this[s.namespace][s.name] = (...args) => this[objKey].apply(this, args);
    }

    this[objKey] = async function(...args){
      let data = {}
      let i = 0
      for(let i = 0; i < s.args.length && i < args.length; i++){
        let a = s.args[i]
        if(typeof a === "string"){
          data[a] = args[i] !== undefined ? args[i] : null
        } else if (typeof a === "object" && typeof a.name === "string" && a.name != ""){
          data[a.name] = args[i] !== undefined ? args[i] : null
        }
      }

      var response = await this.apireq((s.namespace ? s.namespace + "/" : "") + s.name, data);
      if(response.success === true)
        return response.result;
      else {
        console.log("Error on calling function " + s.name + ": " + response.error)
        throw response.error;
      }
    }
  }

  async apireq(command, data = {}){
    return this.req(`${this.apiPath}/${command}`, data);
  }

  async req(url, data = {}){
    let reqData = jQuery.extend({}, data, this.mscp_request_include_always_parms);
    try{
      let response = await fetch(url, {
        method: 'post',
        body: JSON.stringify(reqData),
        credentials: 'include',
        headers: new Headers({
          'Content-Type': 'application/json'
        })
      });
      if(response.status == 403){
        let accessKey = prompt("You do not have access to this functionality. Enter an access key to continue.")
        if(accessKey){
          data.accessKey = accessKey;
          return await this.req(url, reqData)
        }
      }
      return await response.json();
    } catch(err){
      console.log(err)
      return {success: false, error: "Could not connect to server or received invalid response"};
    }
  }
}

var mscp = new MSCP();
mscp.ready = new Promise((resolve, reject)=>{mscp.readyResolve = resolve})
$(function() {
  (async () => {
    await mscp.init();
    mscp.readyResolve();
  })()
});
<|endoftext|>


<commit_before>/**
 * Created with JetBrains RubyMine.
 * User: teamco
 * Date: 11/17/12
 * Time: 4:10 PM
 * To change this template use File | Settings | File Templates.
 */

define([
    'config/anthill',
    'modules/MVC',
    'api/widget.api',
    'controller/widget.controller',
    'model/widget.model',
    'view/widget.view',
    'event/widget.event.manager',
    'permission/widget.permission',
    'controller/widget/widget.map',
    'controller/widget/widget.wireframe'
], function defineWidget(AntHill, MVC, API, Controller, Model, View, EventManager, Permission, WidgetMap, Wireframe) {

    /**
     * Define Widget
     * @class Widget
     * @param opts {object}
     * @extends AntHill
     * @constructor
     */
    var Widget = function Widget(opts) {

        /**
         * Define dom
         * @property Widget
         * @type {*}
         */
        this.dom = this.base.define(opts.dom, {}, true);

        /**
         * Default config
         * @type {{
         *      preferences: {[overlapping]: boolean},
         *      rules: {},
         *      limit: boolean,
         *      order: number,
         *      html: {header: boolean, footer: boolean, frameLess: boolean, style: string, zIndex: number},
         *      type: string,
         *      maximize: boolean,
         *      attributes: {magnet: string, freeze: boolean, alwaysTop: boolean},
         *      events: {
         *          draggable: {snap: boolean, axis: boolean, scroll: boolean, connectToSortable: boolean, delay: number, scrollSensitivity: number, scrollSpeed: number, cursor: string, appendTo: string, cancel: string},
         *          resizable: {handles: string},
         *          droppable: {activeClass: string, hoverClass: string, greedy: boolean, tolerance: string}
         *      }
         * }}
         */
        var DEFAULTS = {
            preferences: opts.preferences || {},
            rules: opts.rules || {},
            limit: false,
            order: 1,
            html: {
                header: false,
                footer: false,
                frameLess: false,
                style: '',
                zIndex: 0,
                dimensions: {
                    width: 5,
                    height: 5
                }
            },
            type: 'default',
            maximize: false,
            attributes: {
                magnet: 'none',         // {none|+|-}
                freeze: false
            },
            events: {
                draggable: {
                    snap: false,
                    axis: false,
                    scroll: true,
                    connectToSortable: false,
                    delay: 300,
                    distance: 20,
                    scrollSensitivity: 100,
                    scrollSpeed: 100,
                    cursor: 'move',
                    appendTo: 'parent',
                    cancel: '.ui-resizable-handle'
                },
                resizable: {
                    handles: 'all'
                },
                droppable: {
                    activeClass: 'widget-ui-hover',
                    hoverClass: 'widget-ui-active',
                    greedy: true,
                    tolerance: 'pointer'
                }
            }
        };

        /**
         * Define constants
         * @property Widget
         * @type {{magnet: Array}}
         */
        this.CONSTANTS = {
            magnet: ['none', '+', '-']
        };

        /**
         * Transfer content events
         * @property Widget
         * @type {{}}
         */
        this.contentEvents = {};

        /**
         * Transfer content rules
         * @property Widget
         * @type {{}}
         */
        this.contentRules = {};

        /**
         * Define MVC
         * @property Widget
         * @type {MVC}
         */
        this.mvc = new MVC({
            scope: this,
            config: [opts.config, DEFAULTS],
            components: [
                API,
                Controller,
                Model,
                View,
                EventManager,
                Permission
            ],
            render: true
        });

        /**
         * Define map
         * @property Widget
         * @type {WidgetMap}
         */
        this.map = new WidgetMap(this);

        /**
         * Define wireframe
         * @property Widget
         * @type {Wireframe}
         */
        this.wireframe = new Wireframe(this);

        /**
         * Define interactions: Drag/Resize/Drop
         * @property Widget
         * @type {{
         *      draggable: Draggable,
         *      resizable: Resizable,
         *      droppable: undefined
         * }}
         */
        this.interactions = {};

        /**
         * Define draggable interaction
         * @property Widget.interactions
         * @type {Draggable}
         */
        this.interactions.draggable = undefined;

        /**
         * Define resizable interaction
         * @property Widget.interactions
         * @type {Resizable}
         */
        this.interactions.resizable = undefined;

        /**
         * Init content
         * @property Widget
         * @type {WidgetContent}
         */
        this.content = undefined;

        /**
         * Init expanded
         * @property Widget
         * @type {boolean}
         */
        this.expanded = false;

        this.observer.publish(
            this.eventmanager.eventList.successCreated
        );
    };

    return Widget.extend('Widget', {

    }, AntHill.prototype);
});
<commit_msg>add default containment<commit_after>/**
 * Created with JetBrains RubyMine.
 * User: teamco
 * Date: 11/17/12
 * Time: 4:10 PM
 * To change this template use File | Settings | File Templates.
 */

define([
    'config/anthill',
    'modules/MVC',
    'api/widget.api',
    'controller/widget.controller',
    'model/widget.model',
    'view/widget.view',
    'event/widget.event.manager',
    'permission/widget.permission',
    'controller/widget/widget.map',
    'controller/widget/widget.wireframe'
], function defineWidget(AntHill, MVC, API, Controller, Model, View, EventManager, Permission, WidgetMap, Wireframe) {

    /**
     * Define Widget
     * @class Widget
     * @param opts {object}
     * @extends AntHill
     * @constructor
     */
    var Widget = function Widget(opts) {

        /**
         * Define dom
         * @property Widget
         * @type {*}
         */
        this.dom = this.base.define(opts.dom, {}, true);

        /**
         * Default config
         * @type {{
         *      preferences: {[overlapping]: boolean},
         *      rules: {},
         *      limit: boolean,
         *      order: number,
         *      html: {header: boolean, footer: boolean, frameLess: boolean, style: string, zIndex: number},
         *      type: string,
         *      maximize: boolean,
         *      attributes: {magnet: string, freeze: boolean, alwaysTop: boolean},
         *      events: {
         *          draggable: {snap: boolean, axis: boolean, scroll: boolean, connectToSortable: boolean, delay: number, scrollSensitivity: number, scrollSpeed: number, cursor: string, appendTo: string, cancel: string},
         *          resizable: {handles: string},
         *          droppable: {activeClass: string, hoverClass: string, greedy: boolean, tolerance: string}
         *      }
         * }}
         */
        var DEFAULTS = {
            preferences: opts.preferences || {},
            rules: opts.rules || {},
            limit: false,
            order: 1,
            html: {
                header: false,
                footer: false,
                frameLess: false,
                style: '',
                zIndex: 0,
                dimensions: {
                    width: 5,
                    height: 5
                }
            },
            type: 'default',
            maximize: false,
            attributes: {
                magnet: 'none',         // {none|+|-}
                freeze: false
            },
            events: {
                draggable: {
                    snap: false,
                    axis: false,
                    scroll: true,
                    connectToSortable: false,
                    delay: 300,
                    distance: 20,
                    scrollSensitivity: 100,
                    scrollSpeed: 100,
                    cursor: 'move',
                    appendTo: 'parent',
                    cancel: '.ui-resizable-handle',
                    containment: 'parent'
                },
                resizable: {
                    handles: 'all',
                    containment: 'parent'
                },
                droppable: {
                    activeClass: 'widget-ui-hover',
                    hoverClass: 'widget-ui-active',
                    greedy: true,
                    tolerance: 'pointer'
                }
            }
        };

        /**
         * Define constants
         * @property Widget
         * @type {{magnet: Array}}
         */
        this.CONSTANTS = {
            magnet: ['none', '+', '-']
        };

        /**
         * Transfer content events
         * @property Widget
         * @type {{}}
         */
        this.contentEvents = {};

        /**
         * Transfer content rules
         * @property Widget
         * @type {{}}
         */
        this.contentRules = {};

        /**
         * Define MVC
         * @property Widget
         * @type {MVC}
         */
        this.mvc = new MVC({
            scope: this,
            config: [opts.config, DEFAULTS],
            components: [
                API,
                Controller,
                Model,
                View,
                EventManager,
                Permission
            ],
            render: true
        });

        /**
         * Define map
         * @property Widget
         * @type {WidgetMap}
         */
        this.map = new WidgetMap(this);

        /**
         * Define wireframe
         * @property Widget
         * @type {Wireframe}
         */
        this.wireframe = new Wireframe(this);

        /**
         * Define interactions: Drag/Resize/Drop
         * @property Widget
         * @type {{
         *      draggable: Draggable,
         *      resizable: Resizable,
         *      droppable: undefined
         * }}
         */
        this.interactions = {};

        /**
         * Define draggable interaction
         * @property Widget.interactions
         * @type {Draggable}
         */
        this.interactions.draggable = undefined;

        /**
         * Define resizable interaction
         * @property Widget.interactions
         * @type {Resizable}
         */
        this.interactions.resizable = undefined;

        /**
         * Init content
         * @property Widget
         * @type {WidgetContent}
         */
        this.content = undefined;

        /**
         * Init expanded
         * @property Widget
         * @type {boolean}
         */
        this.expanded = false;

        this.observer.publish(
            this.eventmanager.eventList.successCreated
        );
    };

    return Widget.extend('Widget', {

    }, AntHill.prototype);
});
<|endoftext|>


<commit_before>/*
 * This file is part of Search NEU and licensed under AGPL3.
 * See the license file in the root folder for details.
 */

import React from 'react';
import PropTypes from 'prop-types';

import Collapsible from 'react-collapsible';
import macros from '../macros';
import BaseClassPanel from './BaseClassPanel';
import DesktopSectionPanel from './DesktopSectionPanel';
import SignUpForNotifications from '../SignUpForNotifications';

import globe from './globe.svg';

// Class Panel that renders the box with the class title, class description, and class sections
// If mobile, uses MobileSectionPanel to show the sections.
// The code for desktop is inside this file.

// Note, if you do override the constructor,
// Don't do `this.state = {...}`, because the state is already setup in the parent react component
// instead just do this.state.something = 5;

export default class DesktopClassPanel extends BaseClassPanel {
  static propTypes = {
    aClass: PropTypes.object.isRequired,
  };

  componentDidUpdate() {
    macros.debounceTooltipRebuild();
  }

  componentDidMount() {
    macros.debounceTooltipRebuild();
  }

  // Method to decide whether to show the waitlist or not
  // This logic is different than it is on mobile (because of formatting differences)
  // See MobileSectionPanel.js
  shouldShowWaitlist() {
    const aClass = this.props.aClass;

    // If the class does not have a waitlist, don't show the waitlist
    if (!aClass.getHasWaitList()) {
      return false;
    }

    // If all the sections have 0 seats on the waitlist and 0 total seats, don't show the waitlist (because there isn't actually a waitlist).
    let foundSectionWithWaitlistSeats = false;

    for (const section of aClass.sections) {
      if (section.waitRemaining > 0 || section.waitCapacity > 0) {
        foundSectionWithWaitlistSeats = true;
        break;
      }
    }

    if (!foundSectionWithWaitlistSeats) {
      return false;
    }

    // Also show the waitlist if any of the sections have less than 10 seats left.
    // The number 10 is just an arbitrary decision and can be changed in the future.
    for (const section of aClass.sections) {
      if (section.seatsRemaining < 10) {
        return true;
      }
    }

    // If there are plenty of seats left, don't show the waitlist
    return false;
  }

  render() {
    const aClass = this.props.aClass;
    // Render the section table if this class has sections
    let sectionTable = null;
    if (aClass.sections && aClass.sections.length > 0) {
      // Add the Exam column headers if there are any sections in this class that has exam listed
      let examColumnHeaders = null;
      if (aClass.sectionsHaveExam()) {
        examColumnHeaders = [
          Exam time	,
          Exam date	,
          Exam location	,
        ];
      }

      // Add the Online sections head if there are any sections that are online
      const showWaitList = this.shouldShowWaitlist();

      const showHonorsColumn = aClass.getHasHonorsSections();

      sectionTable = (

                    CRN

               Professors
               Weekdays
               Time

               Location
              {examColumnHeaders}
               Seats

                Waitlist seats

                Honors

               Link

            {/* The CSS applied to the table stripes every other row, starting with the second one.
              This tr is hidden so the first visible row is a dark stripe instead of the second one. */}

            {this.state.renderedSections.map((section) => {
              return (
                <DesktopSectionPanel
                  key={ section.crn }
                  showWaitList={ showWaitList }
                  shouldShowExamColumns={ aClass.sectionsHaveExam() }
                  showHonorsColumn={ showHonorsColumn }
                  section={ section }
                />
              );
            })}

      );
    }

    // Render the Show More.. Button
    const showMoreSections = this.getMoreSectionsButton();

    // Figure out the credits string, and course Attributes
    const creditsString = this.getCreditsString();

    const feeString = this.getOptionalFees();

    let feeAmount;

    if (feeString) {
      feeAmount = feeString.split(' ');
      feeAmount = feeAmount[feeAmount.length - 1];
      feeAmount = 'You must pay ' + feeAmount + ' extra to take this class';
    }
    const courseAttrString = this.getClassAttributesString();

    let courseAttr;
    if (courseAttrString) {
      courseAttr = courseAttrString.map((i, k) => {
        return
{i}
;
      });
    }

    return (

            {aClass.subject} {aClass.classId}: {aClass.name}

            <a
              target='_blank'
              rel='noopener noreferrer'
              className='classGlobeLink'
              data-tip={ `View on ${aClass.host}` }
              href={ aClass.prettyUrl || aClass.url }
            >

          {aClass.desc}

              Prerequisites: {this.optionalDisplay(macros.prereqTypes.PREREQ)} {this.showMore(macros.prereqTypes.PREREQ)}

              Corequisites: {this.optionalDisplay(macros.prereqTypes.COREQ)} {this.showMore(macros.prereqTypes.COREQ)}

              Prerequisite for: {this.optionalDisplay(macros.prereqTypes.PREREQ_FOR)} {this.showMore(macros.prereqTypes.PREREQ_FOR)}

        Optional Prerequisite for: {this.optionalDisplay(macros.prereqTypes.OPT_PREREQ_FOR)} {this.showMore(macros.prereqTypes.OPT_PREREQ_FOR)}

            <Collapsible trigger='Show Course Attributes'>

	        {courseAttr}

        </Collapsible>

{feeString}

 Updated {aClass.getLastUpdateString()}

            {creditsString}

              <SignUpForNotifications aClass={ aClass } />

        {sectionTable}
        {showMoreSections}

    );
  }
}

// Number of sections to show by default. This is different on mobile.
DesktopClassPanel.sectionsShownByDefault = 3;
<commit_msg>fixed linting thigs<commit_after>/*
 * This file is part of Search NEU and licensed under AGPL3.
 * See the license file in the root folder for details.
 */

import React from 'react';
import PropTypes from 'prop-types';

import Collapsible from 'react-collapsible';
import macros from '../macros';
import BaseClassPanel from './BaseClassPanel';
import DesktopSectionPanel from './DesktopSectionPanel';
import SignUpForNotifications from '../SignUpForNotifications';

import globe from './globe.svg';

// Class Panel that renders the box with the class title, class description, and class sections
// If mobile, uses MobileSectionPanel to show the sections.
// The code for desktop is inside this file.

// Note, if you do override the constructor,
// Don't do `this.state = {...}`, because the state is already setup in the parent react component
// instead just do this.state.something = 5;

export default class DesktopClassPanel extends BaseClassPanel {
  static propTypes = {
    aClass: PropTypes.object.isRequired,
  };

  componentDidUpdate() {
    macros.debounceTooltipRebuild();
  }

  componentDidMount() {
    macros.debounceTooltipRebuild();
  }

  // Method to decide whether to show the waitlist or not
  // This logic is different than it is on mobile (because of formatting differences)
  // See MobileSectionPanel.js
  shouldShowWaitlist() {
    const aClass = this.props.aClass;

    // If the class does not have a waitlist, don't show the waitlist
    if (!aClass.getHasWaitList()) {
      return false;
    }

    // If all the sections have 0 seats on the waitlist and 0 total seats, don't show the waitlist (because there isn't actually a waitlist).
    let foundSectionWithWaitlistSeats = false;

    for (const section of aClass.sections) {
      if (section.waitRemaining > 0 || section.waitCapacity > 0) {
        foundSectionWithWaitlistSeats = true;
        break;
      }
    }

    if (!foundSectionWithWaitlistSeats) {
      return false;
    }

    // Also show the waitlist if any of the sections have less than 10 seats left.
    // The number 10 is just an arbitrary decision and can be changed in the future.
    for (const section of aClass.sections) {
      if (section.seatsRemaining < 10) {
        return true;
      }
    }

    // If there are plenty of seats left, don't show the waitlist
    return false;
  }

  render() {
    const aClass = this.props.aClass;
    // Render the section table if this class has sections
    let sectionTable = null;
    if (aClass.sections && aClass.sections.length > 0) {
      // Add the Exam column headers if there are any sections in this class that has exam listed
      let examColumnHeaders = null;
      if (aClass.sectionsHaveExam()) {
        examColumnHeaders = [
          Exam time	,
          Exam date	,
          Exam location	,
        ];
      }

      // Add the Online sections head if there are any sections that are online
      const showWaitList = this.shouldShowWaitlist();

      const showHonorsColumn = aClass.getHasHonorsSections();

      sectionTable = (

                    CRN

               Professors
               Weekdays
               Time

               Location
              {examColumnHeaders}
               Seats

                Waitlist seats

                Honors

               Link

            {/* The CSS applied to the table stripes every other row, starting with the second one.
              This tr is hidden so the first visible row is a dark stripe instead of the second one. */}

            {this.state.renderedSections.map((section) => {
              return (
                <DesktopSectionPanel
                  key={ section.crn }
                  showWaitList={ showWaitList }
                  shouldShowExamColumns={ aClass.sectionsHaveExam() }
                  showHonorsColumn={ showHonorsColumn }
                  section={ section }
                />
              );
            })}

      );
    }

    // Render the Show More.. Button
    const showMoreSections = this.getMoreSectionsButton();

    // Figure out the credits string, and course Attributes
    const creditsString = this.getCreditsString();

    const feeString = this.getOptionalFees();

    let feeAmount;

    if (feeString) {
      feeAmount = feeString.split(' ');
      feeAmount = feeAmount[feeAmount.length - 1];
      feeAmount = `You must pay ${feeAmount} extra to take this class`;
    }
    const courseAttrString = this.getClassAttributesString();

    let courseAttr;
    if (courseAttrString) {
      courseAttr = courseAttrString.map((i, k) => {
        return
{i}
;
      });
    }

    return (

            {aClass.subject} {aClass.classId}: {aClass.name}

            <a
              target='_blank'
              rel='noopener noreferrer'
              className='classGlobeLink'
              data-tip={ `View on ${aClass.host}` }
              href={ aClass.prettyUrl || aClass.url }
            >

          {aClass.desc}

              Prerequisites: {this.optionalDisplay(macros.prereqTypes.PREREQ)} {this.showMore(macros.prereqTypes.PREREQ)}

              Corequisites: {this.optionalDisplay(macros.prereqTypes.COREQ)} {this.showMore(macros.prereqTypes.COREQ)}

              Prerequisite for: {this.optionalDisplay(macros.prereqTypes.PREREQ_FOR)} {this.showMore(macros.prereqTypes.PREREQ_FOR)}

              Optional Prerequisite for: {this.optionalDisplay(macros.prereqTypes.OPT_PREREQ_FOR)} {this.showMore(macros.prereqTypes.OPT_PREREQ_FOR)}

            <Collapsible trigger='Show Course Attributes'>

                {courseAttr}

            </Collapsible>

{feeString}

 Updated {aClass.getLastUpdateString()}

            {creditsString}

              <SignUpForNotifications aClass={ aClass } />

        {sectionTable}
        {showMoreSections}

    );
  }
}

// Number of sections to show by default. This is different on mobile.
DesktopClassPanel.sectionsShownByDefault = 3;
<|endoftext|>


<commit_before>
angular.module('mopidy-mobile.library', [
  'ionic',
  'mopidy-mobile.actions',
  'mopidy-mobile.connection',
  'mopidy-mobile.coverart',
  'mopidy-mobile.ui'
])

.config(function($stateProvider) {
  $stateProvider
    .state('main.library', {
      abstract: true,
      url: '/library',
      views: {
        'library': {
          template: '<ion-nav-view></ion-nav-view>',
        }
      }
    })
    .state('main.library.root', {
      url: '',
      templateUrl: 'templates/browse.html',
      controller: 'BrowseCtrl',
      resolve: {
        ref: function() {
          return null;
        },
        refs: function(connection) {
          return connection(function(mopidy) {
            return mopidy.library.browse({uri: null});
          }, true);
        }
      }
    })
    .state('main.library.browse', {
      url: '/browse?type&name&uri',
      controller: 'BrowseCtrl',
      templateUrl: 'templates/browse.html',
      resolve: {
        ref: function($stateParams) {
          return {
            type: $stateParams.type,
            name: $stateParams.name,
            uri: $stateParams.uri,
          };
        },
        refs: function($stateParams, connection) {
          return connection(function(mopidy) {
            return mopidy.library.browse({uri: $stateParams.uri});
          }, true);
        }
      }
    })
    .state('main.library.search', {
      url: '/search?q&uri',
      controller: 'SearchCtrl',
      templateUrl: 'templates/search.html',
      resolve: {
        q: function($stateParams) {
          return $stateParams.q;
        },
        results: function($stateParams, connection) {
          return connection(function(mopidy) {
            return mopidy.library.search({
              query: {any: $stateParams.q},
              uris: $stateParams.uri ? [$stateParams.uri] : null
            });
          }, true);
        }
      }
    })
    .state('main.library.lookup', {
      url: '/lookup?name&uri',
      controller: 'LookupCtrl',
      templateUrl: 'templates/lookup.html',
      resolve: {
        name: function($stateParams) {
          return $stateParams.name;
        },
        uri: function($stateParams) {
          return $stateParams.uri;
        },
        tracks: function($stateParams, connection) {
          return connection(function(mopidy) {
            return mopidy.library.lookup({uri: $stateParams.uri});
          }, true);
        }
      }
    })
  ;
})

.controller('BrowseCtrl', function($scope, $state, connection, actions, ref, refs) {
  angular.extend($scope, {
    ref: ref,
    refs: refs,
    tracks: refs.filter(function(ref) { return ref.type === 'track'; }),
    click: actions.default,
    refresh: function() {
      connection(function(mopidy) {
        return mopidy.library.refresh({uri: $scope.ref ? $scope.ref.uri : null});
      }, true).then(function() {
        $scope.$broadcast('scroll.refreshComplete');
      });
    },
    search: function(q) {
      $state.go('^.search', {q: q, uri: $scope.ref ? $scope.ref.uri : null});
    }
  });
})

.controller('SearchCtrl', function($scope, connection, actions, coverart, q, results) {
  function compare(a, b) {
    if ((a.name || '') > (b.name || '')) {
      return 1;
    } else if ((a.name || '') < (b.name || '')) {
      return -1;
    } else {
      return 0;
    }
  }

  switch (results.length) {
  case 0:
    $scope.artists = $scope.albums = $scope.tracks = [];
    break;
  case 1:
    // single result - keep order
    $scope.artists = results[0].artists || [];
    $scope.albums = results[0].albums || [];
    $scope.tracks = results[0].tracks || [];
    break;
  default:
    // multiple results - merge and sort by name
    $scope.artists = Array.prototype.concat.apply([], results.map(function(result) {
      return result.artists || [];
    })).sort(compare);
    $scope.albums = Array.prototype.concat.apply([], results.map(function(result) {
      return result.albums || [];
    })).sort(compare);
    $scope.tracks = Array.prototype.concat.apply([], results.map(function(result) {
      return result.tracks || [];
    })).sort(compare);
  }

  angular.extend($scope, {
    q: q,
    click: actions.default,
    images: {}
  });

  coverart.getImages([].concat($scope.artists, $scope.albums, $scope.tracks), {
    width: $scope.thumbnailWidth,
    height: $scope.thumbnailHeight
  }).then(function(result) {
    angular.extend($scope.images, result);
  });
})

.controller('LookupCtrl', function($scope, connection, actions, coverart, name, tracks, uri) {
  angular.extend($scope, {
    name: name,
    tracks: tracks,
    uri: uri,
    click: actions.default
  });

  coverart.getImages(tracks, {
    width: $scope.thumbnailWidth,
    height: $scope.thumbnailHeight
  }).then(function(images) {
    $scope.images = images;
  });
})

.controller('LibraryMenuCtrl', function($scope, $rootScope, popoverMenu, actions) {
  function createPopoverMenu() {
    return popoverMenu([{
      text: 'Play Now',
      click: 'popover.hide() && actions.play(tracks)',
      disabled: '!tracks.length'
    }, {
      text: 'Play Next',
      click: 'popover.hide() && actions.next(tracks)',
      disabled: '!tracks.length'
    }, {
      text: 'Add to Tracklist',
      click: 'popover.hide() && actions.add(tracks)',
      disabled: '!tracks.length'
    }, {
      text: 'Replace Tracklist',
      click: 'popover.hide() && actions.replace(tracks)',
      disabled: '!tracks.length'
    }], {
      scope: $scope
    });
  }

  angular.extend($scope, {
    popover: createPopoverMenu(),
    actions: actions
  });

  $scope.$on('$destroy', function() {
    $scope.popover.remove();
  });

  $rootScope.$on('$translateChangeSuccess', function() {
    $scope.popover.remove();
    $scope.popover = createPopoverMenu();
  });
});
<commit_msg>Fix #29: Correct search query.<commit_after>
angular.module('mopidy-mobile.library', [
  'ionic',
  'mopidy-mobile.actions',
  'mopidy-mobile.connection',
  'mopidy-mobile.coverart',
  'mopidy-mobile.ui'
])

.config(function($stateProvider) {
  $stateProvider
    .state('main.library', {
      abstract: true,
      url: '/library',
      views: {
        'library': {
          template: '<ion-nav-view></ion-nav-view>',
        }
      }
    })
    .state('main.library.root', {
      url: '',
      templateUrl: 'templates/browse.html',
      controller: 'BrowseCtrl',
      resolve: {
        ref: function() {
          return null;
        },
        refs: function(connection) {
          return connection(function(mopidy) {
            return mopidy.library.browse({uri: null});
          }, true);
        }
      }
    })
    .state('main.library.browse', {
      url: '/browse?type&name&uri',
      controller: 'BrowseCtrl',
      templateUrl: 'templates/browse.html',
      resolve: {
        ref: function($stateParams) {
          return {
            type: $stateParams.type,
            name: $stateParams.name,
            uri: $stateParams.uri,
          };
        },
        refs: function($stateParams, connection) {
          return connection(function(mopidy) {
            return mopidy.library.browse({uri: $stateParams.uri});
          }, true);
        }
      }
    })
    .state('main.library.search', {
      url: '/search?q&uri',
      controller: 'SearchCtrl',
      templateUrl: 'templates/search.html',
      resolve: {
        q: function($stateParams) {
          return $stateParams.q;
        },
        results: function($stateParams, connection) {
          return connection(function(mopidy) {
            return mopidy.library.search({
              query: {any: [$stateParams.q]},
              uris: $stateParams.uri ? [$stateParams.uri] : null
            });
          }, true);
        }
      }
    })
    .state('main.library.lookup', {
      url: '/lookup?name&uri',
      controller: 'LookupCtrl',
      templateUrl: 'templates/lookup.html',
      resolve: {
        name: function($stateParams) {
          return $stateParams.name;
        },
        uri: function($stateParams) {
          return $stateParams.uri;
        },
        tracks: function($stateParams, connection) {
          return connection(function(mopidy) {
            return mopidy.library.lookup({uri: $stateParams.uri});
          }, true);
        }
      }
    })
  ;
})

.controller('BrowseCtrl', function($scope, $state, connection, actions, ref, refs) {
  angular.extend($scope, {
    ref: ref,
    refs: refs,
    tracks: refs.filter(function(ref) { return ref.type === 'track'; }),
    click: actions.default,
    refresh: function() {
      connection(function(mopidy) {
        return mopidy.library.refresh({uri: $scope.ref ? $scope.ref.uri : null});
      }, true).then(function() {
        $scope.$broadcast('scroll.refreshComplete');
      });
    },
    search: function(q) {
      $state.go('^.search', {q: q, uri: $scope.ref ? $scope.ref.uri : null});
    }
  });
})

.controller('SearchCtrl', function($scope, connection, actions, coverart, q, results) {
  function compare(a, b) {
    if ((a.name || '') > (b.name || '')) {
      return 1;
    } else if ((a.name || '') < (b.name || '')) {
      return -1;
    } else {
      return 0;
    }
  }

  switch (results.length) {
  case 0:
    $scope.artists = $scope.albums = $scope.tracks = [];
    break;
  case 1:
    // single result - keep order
    $scope.artists = results[0].artists || [];
    $scope.albums = results[0].albums || [];
    $scope.tracks = results[0].tracks || [];
    break;
  default:
    // multiple results - merge and sort by name
    $scope.artists = Array.prototype.concat.apply([], results.map(function(result) {
      return result.artists || [];
    })).sort(compare);
    $scope.albums = Array.prototype.concat.apply([], results.map(function(result) {
      return result.albums || [];
    })).sort(compare);
    $scope.tracks = Array.prototype.concat.apply([], results.map(function(result) {
      return result.tracks || [];
    })).sort(compare);
  }

  angular.extend($scope, {
    q: q,
    click: actions.default,
    images: {}
  });

  coverart.getImages([].concat($scope.artists, $scope.albums, $scope.tracks), {
    width: $scope.thumbnailWidth,
    height: $scope.thumbnailHeight
  }).then(function(result) {
    angular.extend($scope.images, result);
  });
})

.controller('LookupCtrl', function($scope, connection, actions, coverart, name, tracks, uri) {
  angular.extend($scope, {
    name: name,
    tracks: tracks,
    uri: uri,
    click: actions.default
  });

  coverart.getImages(tracks, {
    width: $scope.thumbnailWidth,
    height: $scope.thumbnailHeight
  }).then(function(images) {
    $scope.images = images;
  });
})

.controller('LibraryMenuCtrl', function($scope, $rootScope, popoverMenu, actions) {
  function createPopoverMenu() {
    return popoverMenu([{
      text: 'Play Now',
      click: 'popover.hide() && actions.play(tracks)',
      disabled: '!tracks.length'
    }, {
      text: 'Play Next',
      click: 'popover.hide() && actions.next(tracks)',
      disabled: '!tracks.length'
    }, {
      text: 'Add to Tracklist',
      click: 'popover.hide() && actions.add(tracks)',
      disabled: '!tracks.length'
    }, {
      text: 'Replace Tracklist',
      click: 'popover.hide() && actions.replace(tracks)',
      disabled: '!tracks.length'
    }], {
      scope: $scope
    });
  }

  angular.extend($scope, {
    popover: createPopoverMenu(),
    actions: actions
  });

  $scope.$on('$destroy', function() {
    $scope.popover.remove();
  });

  $rootScope.$on('$translateChangeSuccess', function() {
    $scope.popover.remove();
    $scope.popover = createPopoverMenu();
  });
});
<|endoftext|>


<commit_before>Settings = {
  'token_url': "get_token.php",
  'token_name': "csrf_token",
  'token_value': "default_value",
  'ajax_header_name': 'X-CSRF-Token',
  'check_origin': false
};

function injectFormTokens() {
  var host = location.href.replace(/^(http?.:\/\/)/gi,"").split("/")[0];
  var forms = document.getElementsByTagName('form');
  for(var i=0;i<forms.length;i++) {
    var csrf_tag = document.createElement('input');
    csrf_tag.setAttribute('type', 'hidden');
    csrf_tag.setAttribute('id', Settings.token_name);
    csrf_tag.setAttribute('name', Settings.token_name);
    csrf_tag.setAttribute('value', Settings.token_value);
    if (Settings.check_origin === false) {
        forms[i].appendChild(csrf_tag);
    } else {
      var form_action = forms[i].action.replace(/^(http?.:\/\/)/gi,"").split("/")[0];
      if (form_action === host) {
        forms[i].appendChild(csrf_tag);
      }
    }}
};

function getToken() {
  var http = new XMLHttpRequest();
  http.onreadystatechange = function () {
  	if (http.readyState==4 && http.status==200) {
      var resp = JSON.parse(http.responseText);
      Settings.token_name = resp.token_name;
      Settings.token_value = resp.token_value;
  	}
  };
  http.open('GET', Settings.token_url, false);
  http.send();
};

function csrf_init() {
  getToken();
  overloadXHR();
};

function overloadXHR() {
  var overloadedXHROpen = XMLHttpRequest.prototype.open;
  XMLHttpRequest.prototype.open = function(a,b,c,d,e) {
    overloadedXHROpen.call(this,a,b,c,d);
    this.setRequestHeader(Settings.ajax_header_name, Settings.token_value);
    return;
}};

document.addEventListener("DOMContentLoaded", function(event) {
  injectFormTokens();
});

csrf_init();
<commit_msg>added configurations<commit_after>Settings = {
  'token_url': "get_token.php",
  'token_name': "csrf_token",
  'token_value': "default_value",
  'ajax_header_name': 'X-CSRF-Token',
  'post_only': true,
  'match_origin': true
};

function prepareToken() {
  var csrf_tag = document.createElement('input');
  csrf_tag.setAttribute('type', 'hidden');
  csrf_tag.setAttribute('id', Settings.token_name);
  csrf_tag.setAttribute('name', Settings.token_name);
  csrf_tag.setAttribute('value', Settings.token_value);
  return csrf_tag;
}

function injectFormTokens() {
  var host = location.href.replace(/^(http?.:\/\/)/gi,"").split("/")[0];
  var forms = document.getElementsByTagName('form');
  for(var i=0;i<forms.length;i++) {
    var token = prepareToken();
    if (Settings.post_only === true) {
      if (forms[i].method.toUpperCase() === 'POST') {
        forms[i].appendChild(token);
      } else {
        forms[i].removeChild(token);
      }
    } else { forms[i].appendChild(token); }

    if (Settings.match_origin === true) {
        var form_action = forms[i].action.replace(/^(http?.:\/\/)/gi,"").split("/")[0];
        if (form_action === host) {
          forms[i].appendChild(token);
        } else { forms[i].removeChild(token); }
    }
    else {
      forms[i].appendChild(token);
    }
  };
};

function getToken() {
  var http = new XMLHttpRequest();
  http.onreadystatechange = function () {
  	if (http.readyState==4 && http.status==200) {
      var resp = JSON.parse(http.responseText);
      Settings.token_name = resp.token_name;
      Settings.token_value = resp.token_value;
  	}
  };
  http.open('GET', Settings.token_url, false);
  http.send();
};

function csrf_init() {
  getToken();
  overloadXHR();
};

function overloadXHR() {
  var overloadedXHROpen = XMLHttpRequest.prototype.open;
  XMLHttpRequest.prototype.open = function(a,b,c,d,e) {
    overloadedXHROpen.call(this,a,b,c,d);
    this.setRequestHeader(Settings.ajax_header_name, Settings.token_value);
    return;
}};

document.addEventListener("DOMContentLoaded", function(event) {
  injectFormTokens();
});

csrf_init();
<|endoftext|>


<commit_before>/*
* Cepat Sembuh v1.0
* Copyright 2016 Cepat Sembuh
*/

// Firebase go online whenever the application is open
document.addEventListener("deviceready", function () {
    Firebase.goOnline();
});

// Not available faskes
$('#not-available').on('click', function() {
	alert("Faskes is not available")
})

// Get no antrian function
function getNoAntri(tipe, username, name) {
  // Define firebase URL
  var faskesRef = new Firebase("https://cepatsembuh.firebaseio.com/" + tipe + "/faskes/" + username);

  // Log firebase URL
  console.log('Url :' + "https://cepatsembuh.firebaseio.com/" + tipe + "/faskes/" + username);

  // Warn user that this fiture need internet
	alert('Fitur ini membutuhkan internet untuk mengambil data');

  // Confirmation
  alert("Mohon konfirmasi ulang");
  var nama = prompt("Masukan nama"),
      nik = prompt("Masukan NIK:");

  if (nama != "" || nik.length == 16) {
      // Firebase
      var pasien = new Firebase("https://cepatsembuh.firebaseio.com/" + tipe + "/faskes/" + username + '/pasien/');

      // Get data
      faskesRef.on("value", function(snapshot) {
        // Declare data variables
        data = snapshot.val().antrian;

        // Print data
        alert('No antrian: ' + data);

        // Push data to firebase
        /* pasien.push().set({
          nama: nama,
          nik: nik,
          nomor_antrian: snapshot.val().antrian
        }) */
      });
  } else {
    // Error message
    alert("Input anda tidak valid. " + "\n" +"Anda tidak bisa mendapatkan nomor antrian");
  }
}

function tempatTidur(tipe, username) {
  // Firebase
  brea = new Firebase("https://cepatsembuh.firebaseio.com/" + tipe + '/faskes/' + username + '/tempat_tidur');

  // Log
  wait = 'Getting data..';
  console.log(wait);
  alert(wait);

  // Get data
  brea.on("value", function(snapshot) {
    // Data's
    satu = snapshot.val().satu;
    dua = snapshot.val().dua;
    tiga = snapshot.val().tiga;

    // Show user the data's
    alert("Kelas I: " + satu + "\n" + "Kelas II: " + dua + "\n" + "Kelas III: " + tiga);

    /* swal({
        title: "Jumlah Tempat Tidur",
        text: text,
        type: "success",
        html: true
      }) */
  })
}

function doctorProfile(nama, gambar, lulusan, tahun) {
  // Text
  giant = "Lulusan: " + lulusan + "\n" + "Tahun: " + tahun;
  name = "dr. " + nama;
  image = "../../img/" + gambar;

  // Pop-up
  alert(name + "\n" + giant);
  /* swal({
    title: name,
    imageUrl: image,
    text: giant,
    html: true
  }) */
}
<commit_msg>Push data to firebase again<commit_after>/*
* Cepat Sembuh v1.0
* Copyright 2016 Cepat Sembuh
*/

// Firebase go online whenever the application is open
document.addEventListener("deviceready", function () {
    Firebase.goOnline();
});

// Not available faskes
$('#not-available').on('click', function() {
	alert("Faskes is not available")
})

// Get no antrian function
function getNoAntri(tipe, username, name) {
  // Define firebase URL
  var faskesRef = new Firebase("https://cepatsembuh.firebaseio.com/" + tipe + "/faskes/" + username);

  // Log firebase URL
  console.log('Url :' + "https://cepatsembuh.firebaseio.com/" + tipe + "/faskes/" + username);

  // Warn user that this fiture need internet
	alert('Fitur ini membutuhkan internet untuk mengambil data');

  // Confirmation
  alert("Mohon konfirmasi ulang");
  var nama = prompt("Masukan nama"),
      nik = prompt("Masukan NIK:");

  if (nama != "" || nik.length == 16) {
      // Firebase
      var pasien = new Firebase("https://cepatsembuh.firebaseio.com/" + tipe + "/faskes/" + username + '/pasien/');

      // Get data
      faskesRef.on("value", function(snapshot) {
        // Declare data variables
        data = snapshot.val().antrian;

        // Print data
        alert('No antrian: ' + data);

        // Push data to firebase
        pasien.push().set({
          nama: nama,
          nik: nik,
          nomor_antrian: data
        })
      });
  } else {
    // Error message
    alert("Input anda tidak valid. " + "\n" +"Anda tidak bisa mendapatkan nomor antrian");
  }
}

function tempatTidur(tipe, username) {
  // Firebase
  brea = new Firebase("https://cepatsembuh.firebaseio.com/" + tipe + '/faskes/' + username + '/tempat_tidur');

  // Log
  wait = 'Getting data..';
  console.log(wait);
  alert(wait);

  // Get data
  brea.on("value", function(snapshot) {
    // Data's
    satu = snapshot.val().satu;
    dua = snapshot.val().dua;
    tiga = snapshot.val().tiga;

    // Show user the data's
    alert("Kelas I: " + satu + "\n" + "Kelas II: " + dua + "\n" + "Kelas III: " + tiga);

    /* swal({
        title: "Jumlah Tempat Tidur",
        text: text,
        type: "success",
        html: true
      }) */
  })
}

function doctorProfile(nama, gambar, lulusan, tahun) {
  // Text
  giant = "Lulusan: " + lulusan + "\n" + "Tahun: " + tahun;
  name = "dr. " + nama;
  image = "../../img/" + gambar;

  // Pop-up
  alert(name + "\n" + giant);
  /* swal({
    title: name,
    imageUrl: image,
    text: giant,
    html: true
  }) */
}
<|endoftext|>


<commit_before>;

function initFormPostEdit($form) {
    if (!$form.length) {
        return;
    }

    var $textarea = $form.find('textarea'),
        textareaSize = $textarea.outerHeight(),
        $textCounter = $form.find('.input-counter');

    $textarea.on('focus', function() {
        $form.find('.hidden.show-on-focus').hide().removeClass('hidden').slideDown();
    });

    $textarea.on('keyup', function() {
        $textCounter.val($textarea.attr('maxlength') - $textarea.val().length);
    });

    showPoll();

    $form.ajaxForm({
        async: false,
        success: function(response) {
            if (/^ERROR:/.test(response)) {
                return mDialog.notify(response, 5);
            }

            var id = parseInt($form.find('input[name="post_id"]').val()),
                $container;

            if (id > 0) {
                $container = $('#pcontainer-' + id);
            } else {
                $('.comments-list:first').prepend($container = $('
'));
            }

            $textarea.animate({ height: textareaSize });

            $container.html(response).trigger('DOMChanged', $container);

            $form.find('.show-on-focus').slideUp().addClass('hidden');
            $form.find('textarea, input[type="text"], input[name="post_id"]').val('');
            $form.find('input[name="key"]').val(Math.floor(Math.random() * (100000000 - 1000000)) + 1000000);

            initPollVote($container.find('.poll-vote form').first());
        }
    });

    $form.droparea({
        maxsize: $form.find('input[name="MAX_FILE_SIZE"]').val()
    });

    $form.find('.uploadFile').nicefileinput();

    $textarea.autosize();
}

function initPollVote($form) {
    if (!$form || !$form.length) {
        return;
    }

    $form.ajaxForm({
        async: false,
        success: function(response) {
            if (/^ERROR:/.test(response)) {
                return mDialog.notify(response, 5);
            }

            $form.closest('.poll-vote').replaceWith(response);
        }
    });
}

function showPoll() {
    $('[data-show-poll="true"]').off('click').on('click', function(e) {
        e.preventDefault();

        var $element = $(this).closest('form').find('.poll-edit');

        if ($element.is(':visible')) {
            $element.slideUp();
        } else {
            $element.hide().removeClass('hidden').slideDown();
        }
    });
}

;(function($) {
    var INIT = {};

    INIT.formRegister = function() {
        var $form = $('#form-register');

        if (!$form.length) {
            return;
        }

        var $password = $form.find('#password'),
            $name = $form.find('#name'),
            $email = $form.find('#email');

        function setStatus($input, response, hideError) {
            var $parent = $input.parent(),
                $status = $parent.find('.input-status');

            $parent.removeClass('input-error input-success');
            $status.removeClass('fa-check fa-times');

            $parent.find('.input-error-message').remove();

            if (response === 'OK') {
                $parent.addClass('input-success');
                $status.addClass('fa-check');

                return;
            }

            if (hideError !== true) {
                $parent.addClass('input-error');
                $status.addClass('fa-times');
            }

            if (response !== 'KO') {
                $parent.append('' + response + '');
            }
        }

        function checkAjaxField($input, callback) {
            var value = $input.val();

            if ($input.data('previous') === value) {
                return;
            }

            if (typeof callback !== 'function') {
                callback = setStatus;
            }

            $.get(base_url + 'backend/checkfield', {type: $input.attr('name'), name: value}, function(response) {
                callback($input, response);
            });

            $input.data('previous', value);
        }

        function securePasswordCheck(value) {
            return (value.length >= 8) && value.match('^(?=.{8,})(?=(.*[a-z].*))(?=(.*[A-Z].*))(?=(.*[0-9].*)).*$', 'g');
        }

        $name.on('change', function() {
            checkAjaxField($name);
        });

        $email.on('change', function() {
            checkAjaxField($email);
        });

        $password.on('keyup', function() {
            setStatus($password, securePasswordCheck($password.val()) ? 'OK' : 'KO', true);
        });

        $password.on('change', function() {
            setStatus($password, securePasswordCheck($password.val()) ? 'OK' : 'KO');
        });

        $('.input-password-show').on('click', function(e) {
            e.preventDefault();

            var $icon = $(this).find('.fa');

            if ($password.attr('type') === 'text') {
                $password.attr('type', 'password');
                $icon.removeClass('fa-eye-slash').addClass('fa-eye');
            } else {
                $password.attr('type', 'text');
                $icon.removeClass('fa-eye').addClass('fa-eye-slash');
            }
        });

        $form.on('submit', function(e) {
            $name.trigger('change');
            $email.trigger('change');
            $password.trigger('change');

            if ($form.find('.input-validate').length !== $form.find('.input-validate.input-success').length) {
                e.preventDefault();
                return;
            }

            $form.append('<input type="hidden" name="base_key" value="' + base_key + '" />');
        });

        if ($name.val()) {
            $name.trigger('change');
        }

        if ($email.val()) {
            $email.trigger('change');
        }
    };

    INIT.showSubDescription = function() {
        $('.show-sub-description').on('click', function(e) {
            e.preventDefault();

            var $description = $('.sub-description');

            if ($description.hasClass('hidden')) {
                $description.hide().removeClass('hidden');
            }

            $description.slideToggle();
        });
    };

    INIT.formSubsSearch = function() {
        var $form = $('#form-subs-search');

        if (!$form.length) {
            return;
        }

        var $inputSearch = $form.find('.input-search');

        $.ajax({
            url: base_url + 'backend/get_subs.php',
            cache: false,
            dataType: 'json',
            success: function(data) {
                $inputSearch.typeahead({
                    source: data,
                    fitToElement: true,
                    displayText: function(item) {
                        return '
' + item.name + '

' + item.name_long + '
';
                    },
                    highlighter: function(item) {
                        return item;
                    },
                    afterSelect: function(item) {
                        $inputSearch.val(item.name);

                        window.location = base_url + 'm/' + item.name;
                    }
                });
            }
        });

        $form.find('.input-filter').on('change', function(e) {
            window.location = base_url + 'subs?' + $(this).val();
        });
    };

    INIT.formPostEdit = function() {
        $('.post-edit form').each(function() {
            var $form = $(this);

            addPostCode(function() {
                initFormPostEdit($form);
            });
        });
    };

    INIT.commentExpand = function() {
        function hide($button, $parent, $childs, id) {
            $childs.hide();
            $parent.addClass('comment-collapsed');
            $button.text('[+]');
        }

        function show($button, $parent, $childs, id) {
            $childs.show();
            $parent.removeClass('comment-collapsed');
            $button.text('[–]');
        }

        $('.comment-header .comment-expand').on('click', function(e) {
            e.preventDefault();

            var $this = $(this),
                $parent = $this.closest('.threader'),
                $childs = $parent.find('> .threader'),
                id = $this.data('id');

            if ($parent.hasClass('comment-collapsed')) {
                show($this, $parent, $childs, id);
            } else {
                hide($this, $parent, $childs, id);
            }
        });
    };

    INIT.formPollVote = function() {
        $('.poll-vote form').each(function() {
            var $form = $(this);

            addPostCode(function() {
                initPollVote($form);
            });
        });
    };

    INIT.showPoll = function() {
        showPoll();
    };

    INIT.formRegister();
    INIT.showSubDescription();
    INIT.formSubsSearch();
    INIT.formPostEdit();
    INIT.showPoll();
    INIT.formPollVote();
    INIT.commentExpand();
})(jQuery);
<commit_msg>Added cookie store to collapsed comments<commit_after>;

/*!
 * JavaScript Cookie v2.1.3
 * https://github.com/js-cookie/js-cookie
 *
 * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
 * Released under the MIT license
 */
;(function (factory) {
    var registeredInModuleLoader = false;

    if (typeof define === 'function' && define.amd) {
        define(factory);
        registeredInModuleLoader = true;
    }

    if (typeof exports === 'object') {
        module.exports = factory();
        registeredInModuleLoader = true;
    }

    if (!registeredInModuleLoader) {
        var OldCookies = window.Cookies;
        var api = window.Cookies = factory();
        api.noConflict = function () {
            window.Cookies = OldCookies;
            return api;
        };
    }
}(function () {
    function extend () {
        var i = 0;
        var result = {};

        for (; i < arguments.length; i++) {
            var attributes = arguments[i];

            for (var key in attributes) {
                result[key] = attributes[key];
            }
        }

        return result;
    }

    function init (converter) {
        function api (key, value, attributes) {
            var result;

            if (typeof document === 'undefined') {
                return;
            }

            if (arguments.length > 1) {
                attributes = extend({
                    path: '/'
                }, api.defaults, attributes);

                if (typeof attributes.expires === 'number') {
                    var expires = new Date();
                    expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
                    attributes.expires = expires;
                }

                attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';

                try {
                    result = JSON.stringify(value);

                    if (/^[\{\[]/.test(result)) {
                        value = result;
                    }
                } catch (e) {}

                if (!converter.write) {
                    value = encodeURIComponent(String(value))
                        .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
                } else {
                    value = converter.write(value, key);
                }

                key = encodeURIComponent(String(key));
                key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
                key = key.replace(/[\(\)]/g, escape);

                var stringifiedAttributes = '';

                for (var attributeName in attributes) {
                    if (!attributes[attributeName]) {
                        continue;
                    }

                    stringifiedAttributes += '; ' + attributeName;

                    if (attributes[attributeName] === true) {
                        continue;
                    }

                    stringifiedAttributes += '=' + attributes[attributeName];
                }

                return (document.cookie = key + '=' + value + stringifiedAttributes);
            }

            if (!key) {
                result = {};
            }

            var cookies = document.cookie ? document.cookie.split('; ') : [];
            var rdecode = /(%[0-9A-Z]{2})+/g;
            var i = 0;

            for (; i < cookies.length; i++) {
                var parts = cookies[i].split('=');
                var cookie = parts.slice(1).join('=');

                if (cookie.charAt(0) === '"') {
                    cookie = cookie.slice(1, -1);
                }

                try {
                    var name = parts[0].replace(rdecode, decodeURIComponent);
                    cookie = converter.read ?
                        converter.read(cookie, name) : converter(cookie, name) ||
                        cookie.replace(rdecode, decodeURIComponent);

                    if (this.json) {
                        try {
                            cookie = JSON.parse(cookie);
                        } catch (e) {}
                    }

                    if (key === name) {
                        result = cookie;
                        break;
                    }

                    if (!key) {
                        result[name] = cookie;
                    }
                } catch (e) {}
            }

            return result;
        }

        api.set = api;

        api.get = function (key) {
            return api.call(api, key);
        };

        api.getJSON = function () {
            return api.apply({
                json: true
            }, [].slice.call(arguments));
        };

        api.defaults = {};

        api.remove = function (key, attributes) {
            api(key, '', extend(attributes, {
                expires: -1
            }));
        };

        api.withConverter = init;

        return api;
    }

    return init(function () {});
}));

function initFormPostEdit($form) {
    if (!$form.length) {
        return;
    }

    var $textarea = $form.find('textarea'),
        textareaSize = $textarea.outerHeight(),
        $textCounter = $form.find('.input-counter');

    $textarea.on('focus', function() {
        $form.find('.hidden.show-on-focus').hide().removeClass('hidden').slideDown();
    });

    $textarea.on('keyup', function() {
        $textCounter.val($textarea.attr('maxlength') - $textarea.val().length);
    });

    showPoll();

    $form.ajaxForm({
        async: false,
        success: function(response) {
            if (/^ERROR:/.test(response)) {
                return mDialog.notify(response, 5);
            }

            var id = parseInt($form.find('input[name="post_id"]').val()),
                $container;

            if (id > 0) {
                $container = $('#pcontainer-' + id);
            } else {
                $('.comments-list:first').prepend($container = $('
'));
            }

            $textarea.animate({ height: textareaSize });

            $container.html(response).trigger('DOMChanged', $container);

            $form.find('.show-on-focus').slideUp().addClass('hidden');
            $form.find('textarea, input[type="text"], input[name="post_id"]').val('');
            $form.find('input[name="key"]').val(Math.floor(Math.random() * (100000000 - 1000000)) + 1000000);

            initPollVote($container.find('.poll-vote form').first());
        }
    });

    $form.droparea({
        maxsize: $form.find('input[name="MAX_FILE_SIZE"]').val()
    });

    $form.find('.uploadFile').nicefileinput();

    $textarea.autosize();
}

function initPollVote($form) {
    if (!$form || !$form.length) {
        return;
    }

    $form.ajaxForm({
        async: false,
        success: function(response) {
            if (/^ERROR:/.test(response)) {
                return mDialog.notify(response, 5);
            }

            $form.closest('.poll-vote').replaceWith(response);
        }
    });
}

function showPoll() {
    $('[data-show-poll="true"]').off('click').on('click', function(e) {
        e.preventDefault();

        var $element = $(this).closest('form').find('.poll-edit');

        if ($element.is(':visible')) {
            $element.slideUp();
        } else {
            $element.hide().removeClass('hidden').slideDown();
        }
    });
}

;(function($) {
    var INIT = {};

    INIT.formRegister = function() {
        var $form = $('#form-register');

        if (!$form.length) {
            return;
        }

        var $password = $form.find('#password'),
            $name = $form.find('#name'),
            $email = $form.find('#email');

        function setStatus($input, response, hideError) {
            var $parent = $input.parent(),
                $status = $parent.find('.input-status');

            $parent.removeClass('input-error input-success');
            $status.removeClass('fa-check fa-times');

            $parent.find('.input-error-message').remove();

            if (response === 'OK') {
                $parent.addClass('input-success');
                $status.addClass('fa-check');

                return;
            }

            if (hideError !== true) {
                $parent.addClass('input-error');
                $status.addClass('fa-times');
            }

            if (response !== 'KO') {
                $parent.append('' + response + '');
            }
        }

        function checkAjaxField($input, callback) {
            var value = $input.val();

            if ($input.data('previous') === value) {
                return;
            }

            if (typeof callback !== 'function') {
                callback = setStatus;
            }

            $.get(base_url + 'backend/checkfield', {type: $input.attr('name'), name: value}, function(response) {
                callback($input, response);
            });

            $input.data('previous', value);
        }

        function securePasswordCheck(value) {
            return (value.length >= 8) && value.match('^(?=.{8,})(?=(.*[a-z].*))(?=(.*[A-Z].*))(?=(.*[0-9].*)).*$', 'g');
        }

        $name.on('change', function() {
            checkAjaxField($name);
        });

        $email.on('change', function() {
            checkAjaxField($email);
        });

        $password.on('keyup', function() {
            setStatus($password, securePasswordCheck($password.val()) ? 'OK' : 'KO', true);
        });

        $password.on('change', function() {
            setStatus($password, securePasswordCheck($password.val()) ? 'OK' : 'KO');
        });

        $('.input-password-show').on('click', function(e) {
            e.preventDefault();

            var $icon = $(this).find('.fa');

            if ($password.attr('type') === 'text') {
                $password.attr('type', 'password');
                $icon.removeClass('fa-eye-slash').addClass('fa-eye');
            } else {
                $password.attr('type', 'text');
                $icon.removeClass('fa-eye').addClass('fa-eye-slash');
            }
        });

        $form.on('submit', function(e) {
            $name.trigger('change');
            $email.trigger('change');
            $password.trigger('change');

            if ($form.find('.input-validate').length !== $form.find('.input-validate.input-success').length) {
                e.preventDefault();
                return;
            }

            $form.append('<input type="hidden" name="base_key" value="' + base_key + '" />');
        });

        if ($name.val()) {
            $name.trigger('change');
        }

        if ($email.val()) {
            $email.trigger('change');
        }
    };

    INIT.showSubDescription = function() {
        $('.show-sub-description').on('click', function(e) {
            e.preventDefault();

            var $description = $('.sub-description');

            if ($description.hasClass('hidden')) {
                $description.hide().removeClass('hidden');
            }

            $description.slideToggle();
        });
    };

    INIT.formSubsSearch = function() {
        var $form = $('#form-subs-search');

        if (!$form.length) {
            return;
        }

        var $inputSearch = $form.find('.input-search');

        $.ajax({
            url: base_url + 'backend/get_subs.php',
            cache: false,
            dataType: 'json',
            success: function(data) {
                $inputSearch.typeahead({
                    source: data,
                    fitToElement: true,
                    displayText: function(item) {
                        return '
' + item.name + '

' + item.name_long + '
';
                    },
                    highlighter: function(item) {
                        return item;
                    },
                    afterSelect: function(item) {
                        $inputSearch.val(item.name);

                        window.location = base_url + 'm/' + item.name;
                    }
                });
            }
        });

        $form.find('.input-filter').on('change', function(e) {
            window.location = base_url + 'subs?' + $(this).val();
        });
    };

    INIT.formPostEdit = function() {
        $('.post-edit form').each(function() {
            var $form = $(this);

            addPostCode(function() {
                initFormPostEdit($form);
            });
        });
    };

    INIT.commentExpand = function() {
        var cookieName = 'comments-collapsed';

        function getUnique(values) {
            return values.filter(function (value, index, values) {
                return values.indexOf(value) === index;
            });
        }

        function cookieGet() {
            return Cookies.getJSON(cookieName) || [];
        }

        function cookieSet(values) {
            Cookies.set(cookieName, getUnique(values));
        }

        function addCookie(id) {
            var current = cookieGet();

            current.push(id);

            cookieSet(current);
        }

        function removeCookie(id) {
            var current = cookieGet();

            while ((index = current.indexOf(id)) !== -1) {
                current.splice(index, 1);
            }

            cookieSet(current);
        }

        function hide($button, $parent, $childs, id) {
            $childs.hide();
            $parent.addClass('comment-collapsed');
            $button.text('[+]');
        }

        function show($button, $parent, $childs, id) {
            $childs.show();
            $parent.removeClass('comment-collapsed');
            $button.text('[–]');
        }

        $.each(cookieGet(), function(key, id) {
            var $this = $('.comment-expand[data-id="' + id + '"]');

            if (!$this.length) {
                return;
            }

            var $parent = $this.closest('.threader');

            hide($this, $parent, $parent.find('> .threader'), $this.data('id'));
        });

        $('.comment-header .comment-expand').on('click', function(e) {
            e.preventDefault();

            var $this = $(this),
                $parent = $this.closest('.threader'),
                $childs = $parent.find('> .threader'),
                id = $this.data('id');

            if ($parent.hasClass('comment-collapsed')) {
                show($this, $parent, $childs, id);
                removeCookie(id);
            } else {
                hide($this, $parent, $childs, id);
                addCookie(id);
            }
        });
    };

    INIT.formPollVote = function() {
        $('.poll-vote form').each(function() {
            var $form = $(this);

            addPostCode(function() {
                initPollVote($form);
            });
        });
    };

    INIT.showPoll = function() {
        showPoll();
    };

    INIT.formRegister();
    INIT.showSubDescription();
    INIT.formSubsSearch();
    INIT.formPostEdit();
    INIT.showPoll();
    INIT.formPollVote();
    INIT.commentExpand();
})(jQuery);
<|endoftext|>


<commit_before>define(['Ti/_/declare', 'Ti/_/Evented'], function(declare, Evented) {
	var obj = declare(null, {

		constructor: function(args, nativeObj) {
			// nativeObj is a native Tizen object; simply wrap it (take ownership of it)
			this._obj = nativeObj;
		},

		constants: {
			id: {
				get: function() {
					return this._obj.id;
				}
			},
			name: {
				get: function() {
					return this._obj.name;
				}
			},
			iconPath: {
				get: function() {
					return this._obj.iconPath;
				}
			},
			version: {
				get: function() {
					return this._obj.version;
				}
			},
			totalSize: {
				get: function() {
					return this._obj.totalSize;
				}
			},
			dataSize: {
				get: function() {
					return this._obj.dataSize;
				}
			},
			lastModified: {
				get: function() {
					return this._obj.lastModified;
				}
			},
			author: {
				get: function() {
					return this._obj.author;
				}
			},
			description: {
				get: function() {
					return this._obj.description;
				}
			},
			appIds: {
				get: function() {
					return this._obj.appIds;
				}
			},
		},

	});

	// Initialize declaredClass, so that toString() works properly on such objects.
	// Correct operation of toString() is required for proper wrapping and automated testing.
	obj.prototype.declaredClass = 'Tizen.Package.PackageInformation';
	return obj;
});<commit_msg>define section changed<commit_after>define(['Ti/_/declare', 'Ti/_/Evented'], function(declare, Evented) {
	var obj = declare(Evented, {

		constructor: function(args, nativeObj) {
			// nativeObj is a native Tizen object; simply wrap it (take ownership of it)
			this._obj = nativeObj;
		},

		constants: {
			id: {
				get: function() {
					return this._obj.id;
				}
			},
			name: {
				get: function() {
					return this._obj.name;
				}
			},
			iconPath: {
				get: function() {
					return this._obj.iconPath;
				}
			},
			version: {
				get: function() {
					return this._obj.version;
				}
			},
			totalSize: {
				get: function() {
					return this._obj.totalSize;
				}
			},
			dataSize: {
				get: function() {
					return this._obj.dataSize;
				}
			},
			lastModified: {
				get: function() {
					return this._obj.lastModified;
				}
			},
			author: {
				get: function() {
					return this._obj.author;
				}
			},
			description: {
				get: function() {
					return this._obj.description;
				}
			},
			appIds: {
				get: function() {
					return this._obj.appIds;
				}
			},
		},

	});

	// Initialize declaredClass, so that toString() works properly on such objects.
	// Correct operation of toString() is required for proper wrapping and automated testing.
	obj.prototype.declaredClass = 'Tizen.Package.PackageInformation';
	return obj;
});<|endoftext|>