<commit_before>// Делает контейнер калейдоскопа на всю страницу
$(window).on("load", function() {
    Typekit.load();

    setTimeout(function() {
        $("#melinda-logo").addClass("fadein");

        setTimeout(function() {
            $("#melinda-logo").addClass("fadeout");
            $("#bar-layer").addClass("shown");
        }, 2000);
    }, 500);

    $("#howto-button").click(function() {
        $("#howto-layer").show(0);
        $("#kaleidoscope-layer").css({
            "-webkit-filter" : "blur(5px)"
        });
    });

    $("#howto-layer").click(function() {
        $("#howto-layer").hide();
           $("#kaleidoscope-layer").css({
            "-webkit-filter" : ""
        });
    });

    function updateURL() {
        var url = window.location.host;

        if(window.location.pathname !== "/") {
            url += window.location.pathname;
        }

        $("#scope-address").val(url);

        $("#facebook-button").attr({
            "href" : "http://www.facebook.com/sharer/sharer.php?s=100&p[url]=" + location.href + "&p[title]=Check this out!"
        });

        $("#twitter-button").attr({
            "href" : "http://twitter.com/share?url=" + location.href + "&text=Check this out!"
        });

        $("#vk-button").attr({
            "href" : "http://vk.com/share.php?url=" + location.href + "&title=Check this out!"
        });

    }

    var kaleidoscopeLayer = $('#kaleidoscope-layer');
    var dragdropLayer = $("#dragdrop-layer");

    window.scope = new Graphemescope( kaleidoscopeLayer[0] );
    window.model = {};

    var createNewScope = function(callback) {
        $.ajax({
            type : "PUT",
            data : window.model,
            url  : "/scopes"
        })
        .done(function(data) {
            model = data;
            page.show("/" + model._id, {}, false);
            updateURL();
            callback();
        })
        .fail(function(err) {
            callback(err);
        });
    };

    dragdropLayer.click(function() {

        if( scope.analyser.isPaused() ) {
            $("#play-image").show(0);
            $("#play-image").addClass("fadeout");

            scope.analyser.play();
        } else {
            $("#pause-image").show(0);
            $("#pause-image").addClass("fadeout");

            scope.analyser.pause();
        }
    });

    dragdropLayer.mousemove(function() {
        var factorx = event.pageX / $(window).width();
        var factory = event.pageY / $(window).height();

        if(scope.analyser.isPaused() ) {
            scope.kaleidoscope.angleTarget = factorx;
            scope.kaleidoscope.zoomTarget  = 1.0 + 0.5 * factory;
        }
    });

    new DragDrop(dragdropLayer[0], function(files) {
        if(files.length <= 0) return;

        var formData = new FormData();
        formData.append('file', files[0]);

        createNewScope(function(err) {
            jQuery.ajax('/files', {
                type : "POST",
                processData: false,
                contentType: false,
                data: formData
            })
            .done(function(data) {
                var imageSrc = "files/" + data._id;

                var type = files[0].type.substring(0, 5);

                if(type === "audio") {
                    console.log("Set audio");

                    $.post('scopes/' + model._id, {
                       'audio' : data._id
                    }).done(function() {

                        model.audio = data._id;
                        scope.setAudio("files/" + data._id);
                    });
                }

                if(type === "image") {
                    console.log("Set image");

                    $.post('scopes/' + model._id, {
                       'image' : data._id
                    }).done(function() {

                        model.image = data._id;
                        scope.setImage("files/" + data._id);
                    });
                }
            });
        });
    });

    page("/*", function(req, next) {
        updateURL();
        next();
    });

    page('/:id?', function(req) {
        var id = req.params['id'] || "default";

        $.get("/scopes/" + id)
        .done(function(data) {
            window.model = data;

            scope.setImage("files/" + model.image);
            scope.setAudio("files/" + model.audio);
        })
        .fail(function() {
            page("/");
        });
    });
    page();

    var mainContainer = $("#main-container");
    var resizeHandler = function() {
        $(".centered-image").each(function() {
            $(this).css({
                "top"  : 0.5 * ($(window).height() - $(this).height()),
                "left" : 0.5 * ($(window).width() -  $(this).width())
            });
        });
    };

    $(window).resize(resizeHandler);
    $(window).resize();

    // TODO: avoid this
    $(".status-icon").on("transitionend", function() {
        $(this).removeClass("fadeout");
        $(this).hide();
    });
});

<commit_msg>Added more information to social buttons<commit_after>// Делает контейнер калейдоскопа на всю страницу
$(window).on("load", function() {
    Typekit.load();

    setTimeout(function() {
        $("#melinda-logo").addClass("fadein");

        setTimeout(function() {
            $("#melinda-logo").addClass("fadeout");
            $("#bar-layer").addClass("shown");
        }, 2000);
    }, 500);

    $("#howto-button").click(function() {
        $("#howto-layer").show(0);
        $("#kaleidoscope-layer").css({
            "-webkit-filter" : "blur(5px)"
        });
    });

    $("#howto-layer").click(function() {
        $("#howto-layer").hide();
           $("#kaleidoscope-layer").css({
            "-webkit-filter" : ""
        });
    });

    function updateURL() {
        var url = window.location.host;

        if(window.location.pathname !== "/") {
            url += window.location.pathname;
        }

        var description = "Melinda lets you create Scopes: interactive kaleidoscopic visualizations that are moving along with the music. #melinda #grapheme";
        var title = "Check this out!";
        var shortDescription = "Check this out! #melinda #grapheme";

        $("#scope-address").val(url);

        $("#facebook-button").attr({
            "href" : "http://www.facebook.com/sharer/sharer.php?s=100&p[url]=" + encodeURIComponent(location.href)
                    + "&p[title]=" + encodeURIComponent(title)
                    + "&p[summary]=" + encodeURIComponent(description)
        });

        $("#twitter-button").attr({
            "href" : "http://twitter.com/share?url=" + encodeURIComponent(location.href)
                    + "&text=" + encodeURIComponent(shortDescription)
        });

        $("#vk-button").attr({
            "href" : "http://vk.com/share.php?url=" + encodeURIComponent(location.href)
                    + "&title=" + encodeURIComponent(title)
                    + "&description=" + encodeURIComponent(description)
                    + "&image="
        });

    }

    var kaleidoscopeLayer = $('#kaleidoscope-layer');
    var dragdropLayer = $("#dragdrop-layer");

    window.scope = new Graphemescope( kaleidoscopeLayer[0] );
    window.model = {};

    var createNewScope = function(callback) {
        $.ajax({
            type : "PUT",
            data : window.model,
            url  : "/scopes"
        })
        .done(function(data) {
            model = data;
            page.show("/" + model._id, {}, false);
            updateURL();
            callback();
        })
        .fail(function(err) {
            callback(err);
        });
    };

    dragdropLayer.click(function() {

        if( scope.analyser.isPaused() ) {
            $("#play-image").show(0);
            $("#play-image").addClass("fadeout");

            scope.analyser.play();
        } else {
            $("#pause-image").show(0);
            $("#pause-image").addClass("fadeout");

            scope.analyser.pause();
        }
    });

    dragdropLayer.mousemove(function() {
        var factorx = event.pageX / $(window).width();
        var factory = event.pageY / $(window).height();

        if(scope.analyser.isPaused() ) {
            scope.kaleidoscope.angleTarget = factorx;
            scope.kaleidoscope.zoomTarget  = 1.0 + 0.5 * factory;
        }
    });

    new DragDrop(dragdropLayer[0], function(files) {
        if(files.length <= 0) return;

        var formData = new FormData();
        formData.append('file', files[0]);

        createNewScope(function(err) {
            jQuery.ajax('/files', {
                type : "POST",
                processData: false,
                contentType: false,
                data: formData
            })
            .done(function(data) {
                var imageSrc = "files/" + data._id;

                var type = files[0].type.substring(0, 5);

                if(type === "audio") {
                    console.log("Set audio");

                    $.post('scopes/' + model._id, {
                       'audio' : data._id
                    }).done(function() {

                        model.audio = data._id;
                        scope.setAudio("files/" + data._id);
                    });
                }

                if(type === "image") {
                    console.log("Set image");

                    $.post('scopes/' + model._id, {
                       'image' : data._id
                    }).done(function() {

                        model.image = data._id;
                        scope.setImage("files/" + data._id);
                    });
                }
            });
        });
    });

    page("/*", function(req, next) {
        updateURL();
        next();
    });

    page('/:id?', function(req) {
        var id = req.params['id'] || "default";

        $.get("/scopes/" + id)
        .done(function(data) {
            window.model = data;

            scope.setImage("files/" + model.image);
            scope.setAudio("files/" + model.audio);
        })
        .fail(function() {
            page("/");
        });
    });
    page();

    var mainContainer = $("#main-container");
    var resizeHandler = function() {
        $(".centered-image").each(function() {
            $(this).css({
                "top"  : 0.5 * ($(window).height() - $(this).height()),
                "left" : 0.5 * ($(window).width() -  $(this).width())
            });
        });
    };

    $(window).resize(resizeHandler);
    $(window).resize();

    // TODO: avoid this
    $(".status-icon").on("transitionend", function() {
        $(this).removeClass("fadeout");
        $(this).hide();
    });
});

<|endoftext|>


<commit_before>/**
 *
 * @license
 * Copyright (C) 2016 Joseph Roque
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @author Joseph Roque
 * @file NavigationHome.js
 * @providesModule NavigationHome
 * @description Allows the user to confirm their starting and ending location for navigation.
 *
 * @flow
 */
'use strict';

// React imports
import React from 'react';
import {
  StyleSheet,
  Text,
  View,
} from 'react-native';

// Type imports
import type {
  CampusDestination,
} from 'types';

// Type definition for component props.
type Props = {
  destination: CampusDestination,
}

class NavigationHome extends React.Component {

  /**
   * Properties which the parent component should make available to this component.
   */
  static propTypes = {
    destination: React.PropTypes.object.isRequired,
  };

  constructor(props: Props) {
    super(props);

    // Explicitly bind 'this' to methods that require it
    (this:any)._isDestinationBuilding = this._isDestinationBuilding.bind(this);
  }

  /**
   * Returns true if the destination for navigation is a building, false if it is a room.
   *
   * @returns {boolean} true if this.props.destination.roomName is null or undefined, false otherwise
   */
  _isDestinationBuilding(): boolean {
    return this.props.destination.roomName != null;
  }

  /**
   * Renders the user's upcoming classes for the day and a list of buildings on campus.
   *
   * @returns {ReactElement<any>} the hierarchy of views to render.
   */
  render(): ReactElement<any> {
    return (
      <View style={_styles.container}>
        <Text>{this.props.destination.buildingCode}</Text>
        <Text>{this.props.destination.roomName}</Text>
      </View>
    );
  }
}

// Private styles for component
const _styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});

module.exports = NavigationHome;
<commit_msg>Render views to select building/room for start point<commit_after>/**
 *
 * @license
 * Copyright (C) 2016 Joseph Roque
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @author Joseph Roque
 * @file NavigationHome.js
 * @providesModule NavigationHome
 * @description Allows the user to confirm their starting and ending location for navigation.
 *
 * @flow
 */
'use strict';

// React imports
import React from 'react';
import {
  Dimensions,
  LayoutAnimation,
  Navigator,
  Platform,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';

// Type imports
import type {
  Building,
  CampusDestination,
  Route,
} from 'types';

// Type definition for component props.
type Props = {
  destination: CampusDestination,
}

// Type definition for component state.
type State = {
  findLocationOnMap: boolean,
  startingPoint: {buildingCode: string, roomName: string},
}

// Imports
const BuildingGrid = require('BuildingGrid');
const Constants = require('Constants');
const Preferences = require('Preferences');
const RoomList = require('RoomList');
const SectionHeader = require('SectionHeader');
const TranslationUtils = require('TranslationUtils');

const {width} = Dimensions.get('window');

/** Represents the route to select a building. */
const BUILDING_SELECT = 0;

/** Represents the route to select a room in a building. */
const ROOM_SELECT = 1;

class NavigationHome extends React.Component {

  /**
   * Properties which the parent component should make available to this component.
   */
  static propTypes = {
    destination: React.PropTypes.object.isRequired,
  };

  state: State;

  /**
   * Pass props and declares initial state.
   *
   * @param {Props} props properties passed from container to this component.
   */
  constructor(props: Props) {
    super(props);
    this.state = {
      findLocationOnMap: false,
      startingPoint: {},
    };

    // Explicitly bind 'this' to methods that require it
    (this:any)._setFindLocationOnmap = this._setFindLocationOnmap.bind(this);
  }

  /**
   * Sets the transition between two views in the navigator.
   *
   * @returns {Object} a configuration for the transition between scenes.
   */
  _configureScene(): Object {
    return Navigator.SceneConfigs.PushFromRight;
  }

  /**
   * Switches between views to find the user's location with the GPS or by selecting a building.
   *
   * @param {boolean} findLocationOnMap true to use GPS, false to use building
   */
  _setFindLocationOnmap(findLocationOnMap: boolean): void {
    LayoutAnimation.easeInEaseOut();
    this.setState({
      findLocationOnMap: findLocationOnMap,
    });
  }

  /**
   * Sets the selected building.
   *
   * @param {Building} building details of the selected building
   */
  _onBuildingSelected(building: Building): void {
    this.setState({
      startingPoint: {buildingCode: building.code},
    });
    this.refs.Navigator.push({id: ROOM_SELECT, data: {building: building}});
  }

  /**
   * Sets the selected room.
   *
   * @param {string} buildingCode unique building code.
   * @param {string} roomName     name of the room within the building.
   */
  _onRoomSelected(buildingCode: string, roomName: string): void {
    this.setState({
      startingPoint: {buildingCode: buildingCode, roomName: roomName},
    });
  }

  /**
   * Depending on the route id provided, displays either a BuildingGrid or a RoomList.
   *
   * @param {Route} route id to determine view and data to pass to the view.
   * @returns {ReactElement<any>} views to render
   */
  _renderBuildingOrRoom(route: Route): ReactElement < any > {
    // Get current language for translations
    const Translations: Object = TranslationUtils.getTranslations(Preferences.getSelectedLanguage());

    if (route.id === BUILDING_SELECT) {
      return (
        <View style={_styles.container}>
          <SectionHeader
              sectionIcon={'store'}
              sectionIconClass={'material'}
              sectionName={Translations.building_directory} />
          <View style={_styles.separator} />
          <BuildingGrid selectBuilding={this._onBuildingSelected.bind(this)} />
        </View>
      );
    } else if (route.id === ROOM_SELECT) {
      // Get icon for back button
      let backIconName: string;
      let backIconClass: string;
      if (Platform.OS === 'ios') {
        backIconName = 'ios-arrow-back';
        backIconClass = 'ionicon';
      } else {
        backIconName = 'arrow-back';
        backIconClass = 'material';
      }

      return (
        <View style={_styles.container}>
          <TouchableOpacity onPress={() => this.refs.Navigator.pop()}>
            <SectionHeader
                sectionIcon={backIconName}
                sectionIconClass={backIconClass}
                sectionName={Translations.return_to_buildings} />
          </TouchableOpacity>
          <View style={_styles.separator} />
          <RoomList
              buildingCode={route.data.building.code}
              roomSelected={this._onRoomSelected.bind(this)}
              rooms={route.data.building.rooms} />
        </View>
      );
    } else {
      throw new Error('Invalid route. Can only select room and building. Route is ' + route.id);
    }
  }

  /**
   * Displays views to describe the user's selected starting location, and their destination.
   *
   * @returns {ReactElement<any>} a set of views and icons.
   */
  _renderDestination(): ReactElement < any > {
    // Get current language for translations
    const Translations: Object = TranslationUtils.getTranslations(Preferences.getSelectedLanguage());

    let startingPoint: string;
    if (this.state.startingPoint.buildingCode) {
      if (this.state.startingPoint.roomName) {
        startingPoint = (String:any).format(
          Translations.x_greater_than_y,
          this.state.startingPoint.buildingCode,
          this.state.startingPoint.roomName
        );
      } else {
        startingPoint = (String:any).format(
          Translations.x_greater_than_y,
          this.state.startingPoint.buildingCode,
          Translations.lobby
        );
      }
    } else {
      startingPoint = Translations.choose_starting_point;
    }

    let destination: string;
    if (this.props.destination.roomName) {
      destination = (String:any).format(
        Translations.x_greater_than_y,
        this.props.destination.buildingCode,
        this.props.destination.roomName
      );
    } else {
      destination = (String:any).format(
        Translations.x_greater_than_y,
        this.props.destination.buildingCode,
        Translations.lobby
      );
    }

    return (
      <View>
        <SectionHeader
            backgroundOverride={Constants.Colors.garnet}
            sectionIcon={'near-me'}
            sectionIconClass={'material'}
            sectionName={startingPoint} />
        <SectionHeader
            sectionIcon={'place'}
            sectionIconClass={'material'}
            sectionName={destination} />
        <Text style={_styles.instruction}>{Translations.select_building_or_locate}</Text>
        <View style={_styles.separator} />
      </View>
    );
  }

  /**
   * Renders a set of views so the user can select their starting location.
   *
   * @returns {ReactElement<any>} either a navigator for narrowing user location with building/rooms, or a map.
   */
  _renderStartingLocation(): ReactElement < any > {
    // Get current language for translations
    const Translations: Object = TranslationUtils.getTranslations(Preferences.getSelectedLanguage());

    if (this.state.findLocationOnMap) {
      return (
        <TouchableOpacity onPress={() => this._setFindLocationOnmap(!this.state.findLocationOnMap)}>
          <SectionHeader
              backgroundOverride={Constants.Colors.garnet}
              sectionIcon={'store'}
              sectionIconClass={'material'}
              sectionName={Translations.pick_location} />
        </TouchableOpacity>
      );
    } else {
      return (
        <View style={_styles.container}>
          <Navigator
              configureScene={this._configureScene}
              initialRoute={{id: BUILDING_SELECT}}
              ref='Navigator'
              renderScene={this._renderBuildingOrRoom.bind(this)}
              style={_styles.container} />
          <TouchableOpacity onPress={() => this._setFindLocationOnmap(!this.state.findLocationOnMap)}>
            <SectionHeader
                backgroundOverride={Constants.Colors.garnet}
                sectionIcon={'map'}
                sectionIconClass={'material'}
                sectionName={Translations.locate_me} />
          </TouchableOpacity>
        </View>
      );
    }
  }

  /**
   * Renders the user's upcoming classes for the day and a list of buildings on campus.
   *
   * @returns {ReactElement<any>} the hierarchy of views to render.
   */
  render(): ReactElement<any> {
    return (
      <View style={_styles.container}>
        {this._renderDestination()}
        {this._renderStartingLocation()}
      </View>
    );
  }
}

// Private styles for component
const _styles = StyleSheet.create({
  container: {
    backgroundColor: Constants.Colors.garnet,
    flex: 1,
  },
  instruction: {
    color: Constants.Colors.primaryWhiteText,
    textAlign: 'center',
    fontSize: Constants.Text.Large,
    margin: 10,
  },
  separator: {
    height: StyleSheet.hairlineWidth,
    width: width,
    backgroundColor: 'white',
  },
});

module.exports = NavigationHome;
<|endoftext|>


<commit_before>#!/usr/bin/env node

/*jslint node: true */
/*global require */

module.exports = function () {
    "use strict";

    var settings = require("./settings");

    var childProcess = require("child_process");

    var nodeGearman = require("node-gearman");

    var gearmanLibrary = require("./library/gearman")(nodeGearman);
    var gearman = gearmanLibrary.setUpGearman(settings.gearman.hostname, settings.gearman.port);

    var manager = require("./library/manager")(childProcess, gearman);
    manager.setUpSyncUserProfileOnPostsFromUserWorker();
};

module.exports();
<commit_msg>fix code style of the search worker.js<commit_after>#!/usr/bin/env node

/*jslint node: true */

module.exports = function () {
    "use strict";

    var settings = require("./settings"),
        childProcess = require("child_process"),
        nodeGearman = require("node-gearman"),
        gearmanLibrary = require("./library/gearman")(nodeGearman),
        gearman = gearmanLibrary.setUpGearman(settings.gearman.hostname, settings.gearman.port),
        manager = require("./library/manager")(childProcess, gearman);

    manager.setUpSyncUserProfileOnPostsFromUserWorker();
};

module.exports();
<|endoftext|>


<commit_before>$(document).ready(function () {
  $('#columns .tweets').empty();  // Remove dummy content.

  $('.not-signed-in #the-sign-in-menu').popover({
    placement: 'below',
    trigger: 'manual'
  }).popover('show');
});

// __END__  {{{1
// vim: expandtab shiftwidth=2 softtabstop=2
// vim: foldmethod=marker
<commit_msg>Update character count for new tweet<commit_after>$(document).ready(function () {
  $('#columns .tweets').empty();  // Remove dummy content.

  $('.not-signed-in #the-sign-in-menu').popover({
    placement: 'below',
    trigger: 'manual'
  }).popover('show');

  var update_character_count = function () {
    $('#character-count').text(140 - $(this).val().length);  // FIXME
  };
  $('#status')
    .keydown(update_character_count)
    .keyup(update_character_count);
});

// __END__  {{{1
// vim: expandtab shiftwidth=2 softtabstop=2
// vim: foldmethod=marker
<|endoftext|>


<commit_before>(function (Q, $, window, document, undefined) {

/**
 * Places Tools
 * @module Places-tools
 */

var Users = Q.Users;
var Streams = Q.Streams;
var Places = Q.Places;

/**
 * Allows the logged-in user to add his own locations and select among these locations
 * @class Places location
 * @constructor
 * @param {Object} [options] used to pass options
 * @param {String} [options.publisherId=Q.Users.loggedInUserId()] Override the publisherId
 *  for saving new locations.
 * @param {Object} [options.geocode] Default google location object, if available
 * @param {Places.Coordinates} [options.location] Provide a location to start off with.
 *  Can be anything that is accepted by Places.Coordinates constructor.
 * @param {Boolean} [options.showCurrent=true] Whether to allow user to select current location
 * @param {Boolean} [options.showLocations=true] Whether to allow user to select their saved locations
 * @param {Boolean} [options.showAddress=true] Whether to allow user to enter a custom address
 * @param {Boolean} [options.showAreas=false] Whether to show Places/areas tool for selected location
 * @param {Q.Event} [options.onChoose] User selected some valid location. First parameter is Places.Coordinates object.
 */
Q.Tool.define("Places/location", function (options) {
	var tool = this;
	var state = this.state;
	var $te = $(tool.element);

	Q.addStylesheet('Q/plugins/Places/css/location.css');

	// change location event
	$te.on(Q.Pointer.click, "[data-location], .Places_location_preview_tool", function () {
		tool.toggle(this);
	});

	tool.Q.onStateChanged('location').set(function () {
		Q.handle(state.onChoose, tool, [state.location]);
	});

	// if showAreas - add Places/areas tool if not exist
	if(state.showAreas){
		state.onChoose.set(function(location){
			var placesAreas = tool.$(".Q_tool.Places_areas_tool")[0];
			placesAreas = placesAreas ? Q.Tool.from(placesAreas, "Places/areas") : null;

			if (Q.isEmpty(location)) {
				if (Q.typeOf(placesAreas) === "Q.Tool") {
					Q.Tool.remove(placesAreas.element);
				}
			} else {
				if (!placesAreas) {
					$("
").tool("Places/areas", {
						location: location
					}).appendTo($te).activate();
				} else {
					placesAreas.state.location = location;
					placesAreas.refresh();
				}
			}
		}, tool);
	}

	tool.refresh();
},

{ // default options here
	geocode: null,
	onChoose: new Q.Event(function (coordinates) {
		this.state.location = coordinates;
	}, 'Places/location'),
	location: null, // currently selected location
	showCurrent: true,
	showLocations: true,
	showAddress: true,
	showAreas: false
},

{ // methods go here
	/**
	 * Refresh the display
	 * @method refresh
	 */
	refresh: function () {
		var tool = this;
		var state = tool.state;
		var $te = $(tool.element);

		// location empty - render standard location select template
		if (Q.isEmpty(state.location)) {
			tool.selectLocation();
			return;
		}

		// location already set in state - just type it
		Places.Coordinates.from(state.location).geocode(function (err, results) {
			var fem = Q.firstErrorMessage(err);
			if (fem) {
				// if something wrong with location
				// render standard location select template
				tool.selectLocation();

				return console.warn(fem);
			}

			var result = results[0];
			var address = result.formatted_address || result.address;
			$te.html(address).addClass("Q_selected");
			Q.handle(state.onChoose, tool, [this, result.geometry.location]);
		});
	},
	/**
	 * Render template with locations, so user can select one of them
	 * @method selectLocation
	 */
	selectLocation: function(){
		var tool = this;
		var state = tool.state;
		var $te = $(tool.element);
		var userId = Users.loggedInUserId();

		Q.Text.get('Places/content', function (err, text) {
			Q.Template.render('Places/location/select', Q.extend({
				text: text
			}, state), function (err, html) {
				$te.html(html).activate(function () {

					// set address tool
					tool.$(".Places_location_address")
					.tool('Places/address', {
						onChoose: _onChoose
					}, 'Places_address', tool.prefix)
					.activate(function () {
						tool.addressTool = this;
					});

					// set showLocations state.
					if (state.showLocations && userId) {
						tool.$(".Places_location_related")
							.tool('Streams/related', {
								publisherId: userId,
								streamName: 'Places/user/locations',
								relationType: 'Places/locations',
								isCategory: true,
								editable: false,
								realtime: true,
								sortable: false
							}, tool.prefix + 'relatedLocations')
							.activate(function () {
								tool.relatedTool = this;
							});
					}

					function _onChoose(place) {
						if (!place || !place.id) {
							return Q.handle(state.onChoose, tool, [null, null]);
						}
						Places.Coordinates.from({
							placeId: place.id
						}).geocode(function (err, results) {
							var msg = Q.firstErrorMessage(err);
							if (msg) {
								throw new Q.Error(msg);
							}

							var result = results[0];
							if (!result || !userId) {
								return;
							}
							var attributes = {
								types: result.types,
								latitude: result.geometry.location.lat(),
								longitude: result.geometry.location.lng(),
								locationType: result.geometry.type,
								venue: place.name
							};
							if (result.place_id) {
								attributes.placeId = result.place_id;
							}
							var textConfirm = text.location.confirm;
							Q.confirm(textConfirm.message, function (shouldSave) {
								if (!shouldSave) {
									return;
								}
								var textAdd = text.location.add;
								Q.prompt(textAdd.title, function (title) {
									if (!title) {
										return;
									}
									var publisherId = state.publisherId || userId;
									Streams.create({
										publisherId: publisherId,
										type: 'Places/location',
										title: title,
										attributes: attributes,
										readLevel: 0,
										writeLevel: 0,
										adminLevel: 0
									}, function (err) {
										if (!err) {
											var sf = this.fields;
											tool.relatedTool.state.onRefresh.setOnce(
											function (previews, map, entering, exiting, updating) {
												var key = Q.firstKey(entering);
												var index = map[key];
												var preview = previews[index];
												Q.Pointer.canceledClick = false;
												tool.toggle(preview.element);
											});
										}
									}, {
										publisherId: userId,
										streamName: 'Places/user/locations',
										type: 'Places/locations'
									});
								}, {
									title: textAdd.title,
									placeholder: textAdd.placeholder,
									ok: textAdd.ok
								});
							}, {
								title: textConfirm.title,
								ok: textConfirm.ok,
								cancel: textConfirm.cancel
							});

							this.venue = place.name;
							var description = place.description;
							if (description.indexOf(',') >= 0) {
								this.venue += description.substr(description.indexOf(','));
							}

							$te.find(".Q_selected").removeClass("Q_selected");
							$(tool.addressTool.element).addClass('Q_selected');
							Q.handle(state.onChoose, tool, [this, result.geometry.location]);
						});
					}
				});
			}, {tool: tool});
		});
	},
	/**
	 * Get current geolocation
	 * @method getCurrentPosition
	 * @param {function} [success] Callback for success
	 * @param {function} [fail] Callback for fail
	 */
	getCurrentPosition: function (success, fail) {
		var tool = this;

		navigator.geolocation.getCurrentPosition(function (pos) {
			Q.handle(success, tool, [pos]);
		}, function (err) {
			Q.handle(fail, tool, [err]);
			Q.alert("Places.location.getCurrentPosition: ERROR(" + err.code + "): " + err.message);

			return false;
		}, {
			enableHighAccuracy: true, // need to set true to make it work consistently, it doesn't seem to make it any more accurate
			timeout: 5000,
			maximumAge: 0
		});
	},

	toggle: function (elem) {
		var tool = this;
		var state = this.state;
		var $te = $(tool.element);
		var $this = $(elem);

		if ($this.hasClass('Q_selected')) {
			return false;
		}

		// toggle Q_selected class
		$te.find(".Q_selected").removeClass("Q_selected");
		$this.addClass('Q_selected');

		var $olt = $this.find(tool.addressTool.element);
		if ($olt.length) {
			$olt.plugin('Q/placeholders', function () {
				tool.addressTool.filter.setText('');
				tool.addressTool.filter.$input.plugin('Q/clickfocus');
			});
		}

		var selector = $this.attr("data-location");
		if (selector === 'current') {
			tool.getCurrentPosition(function (pos) {
				var crd = pos.coords;
				if (!crd) {
					Q.alert("Places/location tool: could not obtain location", pos);
					return false;
				}
				Places.Coordinates.from({
					latitude: crd.latitude,
					longitude: crd.longitude
				}).geocode(function (err, results) {
					var loc = Q.getObject([0, 'geometry', 'location'], results);
					Q.handle(state.onChoose, tool, [this, loc]);
				});
			});

			return;
		} else if (selector === 'address') {
			// if address selected just repeat onChoose event of Places/address tool
			Q.handle(
				tool.addressTool.state.onChoose,
				tool.addressTool,
				[tool.addressTool.place]
			);
			return;
		}

		// related location selected
		var locationPreviewTool = Q.Tool.from($this, "Streams/preview");
		var ls = locationPreviewTool.state;
		Streams.get(ls.publisherId, ls.streamName, function () {
			Places.Coordinates.from(this).geocode(function (err, results) {
				var loc = Q.getObject([0, 'geometry', 'location'], results);
				Q.handle(state.onChoose, tool, [this, loc]);
			});
		});
	}
});

Q.Template.set('Places/location/select',
	'{{#if showCurrent}}' +
		'
{{text.location.myCurrentLocation}}
' +
	'{{/if}}' +
	'{{#if showLocations}}' +
		'

' +
	'{{/if}}' +
	'{{#if showAddress}}' +
		'
' +
			'{{text.location.enterAddress}}' +
			'

' +
		'
' +
	'{{/if}}'
);
})(Q, jQuery, window, document);<commit_msg>Execute onChoose event with location=null if error happen when user select "Current location"<commit_after>(function (Q, $, window, document, undefined) {

/**
 * Places Tools
 * @module Places-tools
 */

var Users = Q.Users;
var Streams = Q.Streams;
var Places = Q.Places;

/**
 * Allows the logged-in user to add his own locations and select among these locations
 * @class Places location
 * @constructor
 * @param {Object} [options] used to pass options
 * @param {String} [options.publisherId=Q.Users.loggedInUserId()] Override the publisherId
 *  for saving new locations.
 * @param {Object} [options.geocode] Default google location object, if available
 * @param {Places.Coordinates} [options.location] Provide a location to start off with.
 *  Can be anything that is accepted by Places.Coordinates constructor.
 * @param {Boolean} [options.showCurrent=true] Whether to allow user to select current location
 * @param {Boolean} [options.showLocations=true] Whether to allow user to select their saved locations
 * @param {Boolean} [options.showAddress=true] Whether to allow user to enter a custom address
 * @param {Boolean} [options.showAreas=false] Whether to show Places/areas tool for selected location
 * @param {Q.Event} [options.onChoose] User selected some valid location. First parameter is Places.Coordinates object.
 */
Q.Tool.define("Places/location", function (options) {
	var tool = this;
	var state = this.state;
	var $te = $(tool.element);

	Q.addStylesheet('Q/plugins/Places/css/location.css');

	// change location event
	$te.on(Q.Pointer.click, "[data-location], .Places_location_preview_tool", function () {
		tool.toggle(this);
	});

	tool.Q.onStateChanged('location').set(function () {
		Q.handle(state.onChoose, tool, [state.location]);
	});

	// if showAreas - add Places/areas tool if not exist
	if(state.showAreas){
		state.onChoose.set(function(location){
			var placesAreas = tool.$(".Q_tool.Places_areas_tool")[0];
			placesAreas = placesAreas ? Q.Tool.from(placesAreas, "Places/areas") : null;

			if (Q.isEmpty(location)) {
				if (Q.typeOf(placesAreas) === "Q.Tool") {
					Q.Tool.remove(placesAreas.element);
				}
			} else {
				if (!placesAreas) {
					$("
").tool("Places/areas", {
						location: location
					}).appendTo($te).activate();
				} else {
					placesAreas.state.location = location;
					placesAreas.refresh();
				}
			}
		}, tool);
	}

	tool.refresh();
},

{ // default options here
	geocode: null,
	onChoose: new Q.Event(function (coordinates) {
		this.state.location = coordinates;
	}, 'Places/location'),
	location: null, // currently selected location
	showCurrent: true,
	showLocations: true,
	showAddress: true,
	showAreas: false
},

{ // methods go here
	/**
	 * Refresh the display
	 * @method refresh
	 */
	refresh: function () {
		var tool = this;
		var state = tool.state;
		var $te = $(tool.element);

		// location empty - render standard location select template
		if (Q.isEmpty(state.location)) {
			tool.selectLocation();
			return;
		}

		// location already set in state - just type it
		Places.Coordinates.from(state.location).geocode(function (err, results) {
			var fem = Q.firstErrorMessage(err);
			if (fem) {
				// if something wrong with location
				// render standard location select template
				tool.selectLocation();

				return console.warn(fem);
			}

			var result = results[0];
			var address = result.formatted_address || result.address;
			$te.html(address).addClass("Q_selected");
			Q.handle(state.onChoose, tool, [this, result.geometry.location]);
		});
	},
	/**
	 * Render template with locations, so user can select one of them
	 * @method selectLocation
	 */
	selectLocation: function(){
		var tool = this;
		var state = tool.state;
		var $te = $(tool.element);
		var userId = Users.loggedInUserId();

		Q.Text.get('Places/content', function (err, text) {
			Q.Template.render('Places/location/select', Q.extend({
				text: text
			}, state), function (err, html) {
				$te.html(html).activate(function () {

					// set address tool
					tool.$(".Places_location_address")
					.tool('Places/address', {
						onChoose: _onChoose
					}, 'Places_address', tool.prefix)
					.activate(function () {
						tool.addressTool = this;
					});

					// set showLocations state.
					if (state.showLocations && userId) {
						tool.$(".Places_location_related")
							.tool('Streams/related', {
								publisherId: userId,
								streamName: 'Places/user/locations',
								relationType: 'Places/locations',
								isCategory: true,
								editable: false,
								realtime: true,
								sortable: false
							}, tool.prefix + 'relatedLocations')
							.activate(function () {
								tool.relatedTool = this;
							});
					}

					function _onChoose(place) {
						if (!place || !place.id) {
							return Q.handle(state.onChoose, tool, [null, null]);
						}
						Places.Coordinates.from({
							placeId: place.id
						}).geocode(function (err, results) {
							var msg = Q.firstErrorMessage(err);
							if (msg) {
								throw new Q.Error(msg);
							}

							var result = results[0];
							if (!result || !userId) {
								return;
							}
							var attributes = {
								types: result.types,
								latitude: result.geometry.location.lat(),
								longitude: result.geometry.location.lng(),
								locationType: result.geometry.type,
								venue: place.name
							};
							if (result.place_id) {
								attributes.placeId = result.place_id;
							}
							var textConfirm = text.location.confirm;
							Q.confirm(textConfirm.message, function (shouldSave) {
								if (!shouldSave) {
									return;
								}
								var textAdd = text.location.add;
								Q.prompt(textAdd.title, function (title) {
									if (!title) {
										return;
									}
									var publisherId = state.publisherId || userId;
									Streams.create({
										publisherId: publisherId,
										type: 'Places/location',
										title: title,
										attributes: attributes,
										readLevel: 0,
										writeLevel: 0,
										adminLevel: 0
									}, function (err) {
										if (!err) {
											var sf = this.fields;
											tool.relatedTool.state.onRefresh.setOnce(
											function (previews, map, entering, exiting, updating) {
												var key = Q.firstKey(entering);
												var index = map[key];
												var preview = previews[index];
												Q.Pointer.canceledClick = false;
												tool.toggle(preview.element);
											});
										}
									}, {
										publisherId: userId,
										streamName: 'Places/user/locations',
										type: 'Places/locations'
									});
								}, {
									title: textAdd.title,
									placeholder: textAdd.placeholder,
									ok: textAdd.ok
								});
							}, {
								title: textConfirm.title,
								ok: textConfirm.ok,
								cancel: textConfirm.cancel
							});

							this.venue = place.name;
							var description = place.description;
							if (description.indexOf(',') >= 0) {
								this.venue += description.substr(description.indexOf(','));
							}

							$te.find(".Q_selected").removeClass("Q_selected");
							$(tool.addressTool.element).addClass('Q_selected');
							Q.handle(state.onChoose, tool, [this, result.geometry.location]);
						});
					}
				});
			}, {tool: tool});
		});
	},
	/**
	 * Get current geolocation
	 * @method getCurrentPosition
	 * @param {function} [success] Callback for success
	 * @param {function} [fail] Callback for fail
	 */
	getCurrentPosition: function (success, fail) {
		var tool = this;

		navigator.geolocation.getCurrentPosition(function (pos) {
			Q.handle(success, tool, [pos]);
		}, function (err) {
			Q.handle(fail, tool, [err]);
			Q.alert("Places.location.getCurrentPosition: ERROR(" + err.code + "): " + err.message);

			return false;
		}, {
			enableHighAccuracy: true, // need to set true to make it work consistently, it doesn't seem to make it any more accurate
			timeout: 5000,
			maximumAge: 0
		});
	},

	toggle: function (elem) {
		var tool = this;
		var state = this.state;
		var $te = $(tool.element);
		var $this = $(elem);

		if ($this.hasClass('Q_selected')) {
			return false;
		}

		// toggle Q_selected class
		$te.find(".Q_selected").removeClass("Q_selected");
		$this.addClass('Q_selected');

		var $olt = $this.find(tool.addressTool.element);
		if ($olt.length) {
			$olt.plugin('Q/placeholders', function () {
				tool.addressTool.filter.setText('');
				tool.addressTool.filter.$input.plugin('Q/clickfocus');
			});
		}

		var selector = $this.attr("data-location");
		if (selector === 'current') {
			tool.getCurrentPosition(function (pos) {
				var crd = pos.coords;
				if (!crd) {
					Q.alert("Places/location tool: could not obtain location", pos);
					return false;
				}
				Places.Coordinates.from({
					latitude: crd.latitude,
					longitude: crd.longitude
				}).geocode(function (err, results) {
					var loc = Q.getObject([0, 'geometry', 'location'], results);
					Q.handle(state.onChoose, tool, [this, loc]);
				});
			}, function (err) {
				Q.handle(state.onChoose, tool, [null, null]);
			});

			return;
		} else if (selector === 'address') {
			// if address selected just repeat onChoose event of Places/address tool
			Q.handle(
				tool.addressTool.state.onChoose,
				tool.addressTool,
				[tool.addressTool.place]
			);
			return;
		}

		// related location selected
		var locationPreviewTool = Q.Tool.from($this, "Streams/preview");
		var ls = locationPreviewTool.state;
		Streams.get(ls.publisherId, ls.streamName, function () {
			Places.Coordinates.from(this).geocode(function (err, results) {
				var loc = Q.getObject([0, 'geometry', 'location'], results);
				Q.handle(state.onChoose, tool, [this, loc]);
			});
		});
	}
});

Q.Template.set('Places/location/select',
	'{{#if showCurrent}}' +
		'
{{text.location.myCurrentLocation}}
' +
	'{{/if}}' +
	'{{#if showLocations}}' +
		'

' +
	'{{/if}}' +
	'{{#if showAddress}}' +
		'
' +
			'{{text.location.enterAddress}}' +
			'

' +
		'
' +
	'{{/if}}'
);
})(Q, jQuery, window, document);<|endoftext|>


<commit_before>//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Range Slider form widget
//>>label: Range Slider
//>>group: Forms
//>>css.structure: ../css/structure/jquery.mobile.forms.rangeslider.css
//>>css.theme: ../css/themes/default/jquery.mobile.theme.css

define( [ "jquery", "../../jquery.mobile.core", "../../jquery.mobile.widget", "./textinput", "../../jquery.mobile.buttonMarkup", "./reset", "./slider" ], function( $ ) {
//>>excludeEnd("jqmBuildExclude");
(function( $, undefined ) {
	$.widget( "mobile.rangeslider", $.mobile.widget, {
		widgetEventPrefix: "rangeslider",

		options: {
			theme: null,
			trackTheme: null,
			disabled: false,
			initSelector: ":jqmData(role='rangeslider')",
			mini: false,
			highlight: true
		},

		_create: function() {
			var sliders, secondLabel
			$el = this.element,
			inputFirst = $el.find( "input:first" ),
			inputLast = $el.find( "input:last" ),
			label = $el.find( "label:first" ),
			sliderFirst = $el.find( "div.ui-slider:first" ),
			sliderLast = $el.find( "div.ui-slider:last" );

			if($el.find( "label" ).length > 1 ) {
				secondLabel = $el.find( "label:last" ).hide();
			}

			inputFirst.addClass( "ui-rangeslider-first" );
			inputFirst.after( " - " );
			inputLast.addClass( "ui-rangeslider-last" );
			$el.addClass( "ui-rangeslider" ).append( "
" );
			sliders = $el.find( ".ui-rangeslider-sliders" );
			sliderFirst.appendTo( sliders );
			sliderLast.appendTo( sliders );
			label.prependTo($el);

			$.extend( this, {
				inputFirst: inputFirst,
				inputLast: inputLast,
				sliderFirst: sliderFirst,
				targetVal: null,
				sliderTarget:false,
				sliders: sliders,
				sliderLast: sliderLast,
				proxy:false
			});

			this.refresh();
			this._on( this.element.find( "input.ui-slider-input" ), {
				"slidebeforestart": function( event ){
					var min = parseFloat( this.inputFirst.val(), 10 ),
						max = parseFloat( this.inputLast.val(), 10 ),
						first = ($(event.target).is(this.inputFirst))? true:false
						otherSlider = (first)? this.inputLast: this.inputFirst;
					if($(event.originalEvent.target).hasClass("ui-slider")){
						this.sliderTarget = true;
						this.targetVal = $(event.target).val();
					}
				},
				"slidestop": function(){
					this.proxy = false;
					this.element.find("input").trigger("vmouseup");
				},
				"slidedrag":function(event){
					var min = parseFloat( this.inputFirst.val(), 10 ),
						max = parseFloat( this.inputLast.val(), 10 ),
						first = ($(event.target).is(this.inputFirst))? true:false
						otherSlider = (first)? this.inputLast: this.inputFirst;
					if((this.proxy == "first" && first) || (this.proxy == "last" && !first)){
						otherSlider.data("mobileSlider").dragging = true;
						otherSlider.data("mobileSlider").refresh(event);
						return false;
					}
				},
				"change": "_change",
				"blur": "_change",
				"keyup": "_change"
			});
			this._on( this.element.find( ".ui-slider-handle" ), {
				"vmousedown": function( event ){
					var first = $(event.target).closest( ".ui-slider" ).is( ":first-child" );
					this.sliderFirst.css( "z-index", first ? 1 : "" );
				}
			});
		},

		_setOption: function( options ){
			this.superApply( options );
			this.refresh();
		},

		refresh: function() {
			var $el = this.element,
				o = this.options;

			$el.find( "input" ).slider({
				theme: o.theme,
				trackTheme: o.trackTheme,
				disabled: o.disabled,
				mini: o.mini,
				highlight: o.highlight
			}).slider( "refresh" );
			this._updateHighlight();
		},

		_change: function( event ) {
			if( event.type == "keyup" ){
				this._updateHighlight();
				return false;
			}

			var min = parseFloat( this.inputFirst.val(), 10 ),
				max = parseFloat( this.inputLast.val(), 10 ),
				first = $( event.target ).hasClass( "ui-rangeslider-first" ),
				thisSlider = first? this.inputFirst: this.inputLast,
				otherSlider = first? this.inputLast: this.inputFirst;
					if( min > max && !this.sliderTarget)  {
						thisSlider.val(first ? max: min).slider( "refresh" );
					} else if ( min > max) {
			            thisSlider.val(this.targetVal).slider("refresh");
			            setTimeout(function(){
			              otherSlider.val(first? min: max).slider("refresh");
			            },0);
			            this.proxy = (first)? "first":"last";
					}
					this._updateHighlight();
		},

		_updateHighlight: function() {
			var min = parseInt(this.sliderFirst.find( ".ui-slider-handle" )[0].style.left, 10),
				max = parseInt(this.sliderLast.find( ".ui-slider-handle" )[0].style.left, 10),
				width = (max - min);

			this.element.find( ".ui-slider-bg" ).css({
				"margin-left": min + "%",
				"width": width + "%"
			});
		},

		_destroy: function() {
			this.element.removeClass( "ui-rangeslider ui-mini" ).find("label").show();
			this.element.find( ".ui-rangeslider-dash" ).remove();
			this.inputFirst.after(this.sliderFirst);
			this.inputLast.after(this.sliderLast);
			this.sliders.remove();
			this.element.find( "input" ).removeClass( "ui-rangeslider-first ui-rangeslider-last" ).slider( "destroy" );
		}

	});

$.widget( "mobile.rangeslider", $.mobile.rangeslider, $.mobile.behaviors.formReset );

//auto self-init widgets
$( document ).bind( "pagecreate create", function( e ) {
	$.mobile.rangeslider.prototype.enhanceWithin( e.target, true );
});

})( jQuery );
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");<commit_msg>Range Slider: fixed bug in dragging after clicking on track.<commit_after>//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Range Slider form widget
//>>label: Range Slider
//>>group: Forms
//>>css.structure: ../css/structure/jquery.mobile.forms.rangeslider.css
//>>css.theme: ../css/themes/default/jquery.mobile.theme.css

define( [ "jquery", "../../jquery.mobile.core", "../../jquery.mobile.widget", "./textinput", "../../jquery.mobile.buttonMarkup", "./reset", "./slider" ], function( $ ) {
//>>excludeEnd("jqmBuildExclude");
(function( $, undefined ) {
	$.widget( "mobile.rangeslider", $.mobile.widget, {
		widgetEventPrefix: "rangeslider",

		options: {
			theme: null,
			trackTheme: null,
			disabled: false,
			initSelector: ":jqmData(role='rangeslider')",
			mini: false,
			highlight: true
		},

		_create: function() {
			var sliders, secondLabel
			$el = this.element,
			inputFirst = $el.find( "input:first" ),
			inputLast = $el.find( "input:last" ),
			label = $el.find( "label:first" ),
			sliderFirst = $el.find( "div.ui-slider:first" ),
			sliderLast = $el.find( "div.ui-slider:last" );

			if($el.find( "label" ).length > 1 ) {
				secondLabel = $el.find( "label:last" ).hide();
			}

			inputFirst.addClass( "ui-rangeslider-first" );
			inputFirst.after( " - " );
			inputLast.addClass( "ui-rangeslider-last" );
			$el.addClass( "ui-rangeslider" ).append( "
" );
			sliders = $el.find( ".ui-rangeslider-sliders" );
			sliderFirst.appendTo( sliders );
			sliderLast.appendTo( sliders );
			label.prependTo($el);

			$.extend( this, {
				inputFirst: inputFirst,
				inputLast: inputLast,
				sliderFirst: sliderFirst,
				targetVal: null,
				sliderTarget:false,
				sliders: sliders,
				sliderLast: sliderLast,
				proxy:false
			});

			this.refresh();
			this._on( this.element.find( "input.ui-slider-input" ), {
				"slidebeforestart": function( event ){
					var min = parseFloat( this.inputFirst.val(), 10 ),
						max = parseFloat( this.inputLast.val(), 10 ),
						first = ($(event.target).is(this.inputFirst))? true:false
						otherSlider = (first)? this.inputLast: this.inputFirst;

					this.sliderTarget = false;
					if($(event.originalEvent.target).hasClass("ui-slider")){
						this.sliderTarget = true;
						this.targetVal = $(event.target).val();
					}

				},
				"slidestop": function(){
					this.proxy = false;
					this.element.find("input").trigger("vmouseup");
				},
				"slidedrag":function(event){
					var min = parseFloat( this.inputFirst.val(), 10 ),
						max = parseFloat( this.inputLast.val(), 10 ),
						first = ($(event.target).is(this.inputFirst))? true:false,
						otherSlider = (first)? this.inputLast: this.inputFirst;
						this.sliderTarget = false;
					if((this.proxy == "first" && first) || (this.proxy == "last" && !first)){
						otherSlider.data("mobileSlider").dragging = true;
						otherSlider.data("mobileSlider").refresh($.proxy(event,(first)? this.inputLast:this.inputFirst));
						return false;

					}
				},
				"change": "_change",
				"blur": "_change",
				"keyup": "_change"
			});
			this._on( this.element.find( ".ui-slider-handle" ), {
				"vmousedown": function( event ){
					var first = $(event.target).closest( ".ui-slider" ).is( ":first-child" );
					this.sliderFirst.css( "z-index", first ? 1 : "" );
				}
			});
		},

		_setOption: function( options ){
			this.superApply( options );
			this.refresh();
		},

		refresh: function() {
			var $el = this.element,
				o = this.options;

			$el.find( "input" ).slider({
				theme: o.theme,
				trackTheme: o.trackTheme,
				disabled: o.disabled,
				mini: o.mini,
				highlight: o.highlight
			}).slider( "refresh" );
			this._updateHighlight();
		},

		_change: function( event ) {
			if( event.type == "keyup" ){
				this._updateHighlight();
				return false;
			}

			var min = parseFloat( this.inputFirst.val(), 10 ),
				max = parseFloat( this.inputLast.val(), 10 ),
				first = $( event.target ).hasClass( "ui-rangeslider-first" ),
				thisSlider = first? this.inputFirst: this.inputLast,
				otherSlider = first? this.inputLast: this.inputFirst;
					if( min > max && !this.sliderTarget)  {
						thisSlider.val(first ? max: min).slider( "refresh" );
						//this.proxy = false;
					} else if ( min > max) {
			            thisSlider.val(this.targetVal).slider("refresh");
			            setTimeout(function(){
			              otherSlider.val(first? min: max).slider("refresh");
			            },0);
			            this.proxy = (first)? "first":"last";
					}
					this._updateHighlight();
		},

		_updateHighlight: function() {
			var min = parseInt(this.sliderFirst.find( ".ui-slider-handle" )[0].style.left, 10),
				max = parseInt(this.sliderLast.find( ".ui-slider-handle" )[0].style.left, 10),
				width = (max - min);

			this.element.find( ".ui-slider-bg" ).css({
				"margin-left": min + "%",
				"width": width + "%"
			});
		},

		_destroy: function() {
			this.element.removeClass( "ui-rangeslider ui-mini" ).find("label").show();
			this.element.find( ".ui-rangeslider-dash" ).remove();
			this.inputFirst.after(this.sliderFirst);
			this.inputLast.after(this.sliderLast);
			this.sliders.remove();
			this.element.find( "input" ).removeClass( "ui-rangeslider-first ui-rangeslider-last" ).slider( "destroy" );
		}

	});

$.widget( "mobile.rangeslider", $.mobile.rangeslider, $.mobile.behaviors.formReset );

//auto self-init widgets
$( document ).bind( "pagecreate create", function( e ) {
	$.mobile.rangeslider.prototype.enhanceWithin( e.target, true );
});

})( jQuery );
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");<|endoftext|>


<commit_before>(function (Q, $, window, document, undefined) {

/**
 * Places Tools
 * @module Places-tools
 */

var Users = Q.Users;
var Streams = Q.Streams;
var Places = Q.Places;

/**
 * Allows the logged-in user to indicate their location
 * @class Places location
 * @constructor
 * @param {Object} [options] used to pass options
 * @param {array} [options.miles] array of { miles: title } pairs, by default is generated from Places/nearby/miles config
 * @param {array} [options.defaultMiles] override the key in the miles array to select by default. Defaults to "Places/nearby/defaultMiles" config
 * @param {String} [options.updateButton="Update my location"] the title of the update button
 * @param {Object} [options.map] options for the map
 * @param {Number} [options.map.delay=300] how many milliseconds to delay showing the map, e.g. because the container is animating
 * @param {Q.Event} [options.onReady] this event occurs when the tool interface is ready
 * @param {Q.Event} [options.onSet] this event occurs when the location is set somehow
 * @param {Q.Event} [options.onUnset] this event occurs when the location is unset
 * @param {Q.Event} [options.onUpdate] this event occurs when the location is updated via the tool
 */

Q.Tool.define("Places/location", function (options) {
	var tool = this;
	var state = tool.state;
	var $te = $(tool.element);
	if (!Users.loggedInUser) {
		tool.element.style.display = 'none';
		console.warn("Don't render Places/location when user is not logged in");
		return;
	}
	var publisherId = Users.loggedInUser.id;
	var streamName = "Places/user/location";

	if (!state.miles) {
		state.miles = {};
		var pnm = Places.nearby.miles;
		for (var i=0, l=pnm.length; i<l; ++i) {
			var m = pnm[i];
			state.miles[m] = m + (m === 1 ? ' mile' : ' miles');
		}
	}
	if (state.defaultMiles === undefined) {
		state.defaultMiles = Places.nearby.defaultMiles;
	}

	Q.Template.render('Places/location', state, function (err, html) {
		tool.element.innerHTML = html;
		$te.find('.Places_location_container')
		.addClass('Places_location_checking');

		var pipe = Q.pipe(['info', 'show'], function (params) {
			_showMap.apply(this, params.info);
		});

		Streams.Stream
		.onRefresh(publisherId, streamName)
		.set(function () {
			var miles = this.get('miles');
			var latitude = this.get('latitude');
			var longitude = this.get('longitude');
			if (miles) {
				tool.$('.Places_location_miles').val(miles);
			};
			pipe.fill('info')(latitude, longitude, miles, state.onSet.handle);
			state.stream = this; // in case it was missing before
		});

		Streams.retainWith(tool)
		.get(publisherId, streamName, function (err) {
			if (!err) {
				var stream = state.stream = this;
				var miles = stream.get('miles');
				var latitude = stream.get('latitude');
				var longitude = stream.get('longitude');
				if (miles) {
					tool.$('.Places_location_miles').val(miles);
				}
			}
			if (!latitude || !longitude || !miles) {
				$te.removeClass('Places_location_obtained')
					.addClass('Places_location_obtaining');
				$te.find('.Places_location_container')
					.removeClass('Places_location_checking');
				Q.handle(state.onUnset, tool, [err, stream]);
				if (!state.onReady.occurred) {
					Q.handle(state.onReady, tool, [err, stream]);
				}
			}
			setTimeout(function () {
				pipe.fill('show')();
			}, state.map.delay);

			if (stream && Q.getter.usingCached) {
				stream.refresh();
			}
		});

		tool.$('.Places_location_miles').on('change', function () {
			_submit();
		});

		tool.$('.Places_location_set, .Places_location_update_button')
		.on(Q.Pointer.click, function () {
			var $this = $(this);
			$this.addClass('Places_obtaining');
			if (!navigator.geolocation) {
				return geolocationFailed();
			}
			var timeout = setTimeout(geolocationFailed, state.timeout);
			var handledFail = false;
			Places.loadGoogleMaps(function () {
				navigator.geolocation.getCurrentPosition(
				function (geo) {
					clearTimeout(timeout);
					if (handledFail) return;
					var geocoder = new google.maps.Geocoder();
					geocoder.geocode({'latLng': {
						lat: geo.coords.latitude,
						lng: geo.coords.longitude
					}}, function(results, status) {
						var country, state, placeName;
						if (status == google.maps.GeocoderStatus.OK && results[0]) {
							country = getComponent(results, 'country');
							state = getComponent(results, 'administrative_area_level_1');
							placeName = getComponent(results, 'locality')
								|| getComponent(results, 'sublocality');
						}
						_submit(null, Q.extend({
							placeName: placeName,
							state: state,
							country: country
						}, true, geo.coords));
					});
				}, function () {
					clearTimeout(timeout);
					if (handledFail) return;
					geolocationFailed();
				}, {
					maximumAge: 300000,
					timeout: state.timeout
				});
			});

			function geolocationFailed() {
				handledFail = true;
				Q.prompt("Please enter your zipcode:",
				function (zipcode, dialog) {
					if (zipcode) {
						_submit(zipcode);
					}
				}, {
					title: "My Location",
					ok: "Update",
					onClose: function () {
						$this.removeClass('Places_obtaining');
					}
				});
			}

			function getComponent(results, desiredType) {
				for (var i = 0; i < results[0].address_components.length; i++) {
					var shortname = results[0].address_components[i].short_name;
					var longname = results[0].address_components[i].long_name;
					var type = results[0].address_components[i].types;
					if (type.indexOf(desiredType) != -1) {
						if (!isNullOrWhitespace(shortname)) {
						    return shortname;
						}
						return longname;
					}
			    }
			}

			function isNullOrWhitespace(text) {
			    if (text == null) {
			        return true;
			    }
			    return text.replace(/\s/gi, '').length < 1;
			}
		});
	});

	function _submit(zipcode, fields) {
		fields = Q.extend({}, {
			subscribe: true,
			unsubscribe: true,
			miles: tool.$('.Places_location_miles').val(),
			timezone: (new Date()).getTimezoneOffset() / 60,
			defaultMiles: state.defaultMiles
		});
		if (zipcode) {
			fields.zipcode = zipcode;
		}
		Q.req('Places/geolocation', [], function (err, data) {
			var msg = Q.firstErrorMessage(err, data && data.errors);
			if (msg) {
				return alert(msg);
			}
			Streams.Stream.refresh(publisherId, streamName, function () {
				var miles = this.get('miles');
				var latitude = this.get('latitude');
				var longitude = this.get('longitude');
				if (miles) {
					tool.$('.Places_location_miles').val(miles);
				};
				if (latitude && longitude) {
					Q.handle(state.onUpdate, tool, [latitude, longitude, miles]);
				}
			}, {
				messages: 1,
				evenIfNotRetained: true
			});
		}, {
			method: 'post',
			fields: fields
		});
	}

	var previous = {};
	function _showMap(latitude, longitude, miles, callback) {

		if (latitude == undefined
		|| longitude == undefined
		|| !miles) {
			return;
		}
		if (latitude == previous.latitude
		&& longitude == previous.longitude
		&& miles == previous.miles) {
			return;
		}
		previous = {
			latitude: latitude,
			longitude: longitude,
			miles: miles
		};

		Places.loadGoogleMaps(function () {
			$te.removeClass('Places_location_obtaining')
				.addClass('Places_location_obtained');
			$te.find('.Places_location_container')
				.removeClass('Places_location_checking');
			setTimeout(function () {
				tool.$('.Places_location_map_container').show();
				tool.$('.Places_location_update').slideDown(800);
				setTimeout(function () {
					_showLocationAndCircle();
				}, 300);
			}, 0);
			if (!state.onReady.occurred) {
				Q.handle(state.onReady, tool, [null, state.stream]);
			}
		});

		function _showLocationAndCircle() {
			var element = tool.$('.Places_location_map')[0];
			var map = state.map = new google.maps.Map(element, {
				center: new google.maps.LatLng(latitude, longitude),
				zoom: 12 - Math.floor(Math.log(miles) / Math.log(2)),
				mapTypeId: google.maps.MapTypeId.ROADMAP,
				draggable: false,
				panControl: false,
				disableDoubleClickZoom: true,
				zoomControl: false,
				scaleControl: false,
				disableDefaultUI: true,
				scrollwheel: false,
				navigationControl: false
			});

			// Create marker
			var marker = new google.maps.Marker({
				map: map,
				position: new google.maps.LatLng(latitude, longitude),
				title: 'My location'
			});

			// Add circle overlay and bind to marker
			var circle = new google.maps.Circle({
			  map: map,
			  radius: miles*1609.34,
			  fillColor: '#0000AA'
			});
			circle.bindTo('center', marker, 'position');

			Q.handle(callback, tool, [latitude, longitude, miles, map]);
		}
	}
},

{ // default options here
	updateButton: 'Update my location',
	map: {
		delay: 300,
		prompt: Q.url('plugins/Places/img/map.png')
	},
	timeout: 10000,
	onReady: new Q.Event(),
	onSet: new Q.Event(),
	onUnset: new Q.Event(),
	onUpdate: new Q.Event()
},

{ // methods go here

});

Q.Template.set('Places/location',
	'
'
		+ 'I\'m interested in things taking place within'
		+ '<select name="miles" class="Places_location_miles">'
			+ '{{#each miles}}'
				+ '{{option @key this ../defaultMiles}}'
			+ '{{/each}}'
		+ '</select>'
		+ ' of '
		+ '
'
			+ ''
		+ '
'
		+ '
'
			+ '
'
				+ '

'
			+ '
'
			+ '
'
				+ '<button class="Places_location_update_button Q_button">'
					+ '{{updateButton}}'
				+ '</button>'
			+ '
'
		+ '
'
	+ '
'
);

})(Q, jQuery, window, document);<commit_msg>Small fix to a recent refactor of Places/location tool<commit_after>(function (Q, $, window, document, undefined) {

/**
 * Places Tools
 * @module Places-tools
 */

var Users = Q.Users;
var Streams = Q.Streams;
var Places = Q.Places;

/**
 * Allows the logged-in user to indicate their location
 * @class Places location
 * @constructor
 * @param {Object} [options] used to pass options
 * @param {array} [options.miles] array of { miles: title } pairs, by default is generated from Places/nearby/miles config
 * @param {array} [options.defaultMiles] override the key in the miles array to select by default. Defaults to "Places/nearby/defaultMiles" config
 * @param {String} [options.updateButton="Update my location"] the title of the update button
 * @param {Object} [options.map] options for the map
 * @param {Number} [options.map.delay=300] how many milliseconds to delay showing the map, e.g. because the container is animating
 * @param {Q.Event} [options.onReady] this event occurs when the tool interface is ready
 * @param {Q.Event} [options.onSet] this event occurs when the location is set somehow
 * @param {Q.Event} [options.onUnset] this event occurs when the location is unset
 * @param {Q.Event} [options.onUpdate] this event occurs when the location is updated via the tool
 */

Q.Tool.define("Places/location", function (options) {
	var tool = this;
	var state = tool.state;
	var $te = $(tool.element);
	if (!Users.loggedInUser) {
		tool.element.style.display = 'none';
		console.warn("Don't render Places/location when user is not logged in");
		return;
	}
	var publisherId = Users.loggedInUser.id;
	var streamName = "Places/user/location";

	if (!state.miles) {
		state.miles = {};
		var pnm = Places.nearby.miles;
		for (var i=0, l=pnm.length; i<l; ++i) {
			var m = pnm[i];
			state.miles[m] = m + (m === 1 ? ' mile' : ' miles');
		}
	}
	if (state.defaultMiles === undefined) {
		state.defaultMiles = Places.nearby.defaultMiles;
	}

	Q.Template.render('Places/location', state, function (err, html) {
		tool.element.innerHTML = html;
		$te.find('.Places_location_container')
		.addClass('Places_location_checking');

		var pipe = Q.pipe(['info', 'show'], function (params) {
			_showMap.apply(this, params.info);
		});

		Streams.Stream
		.onRefresh(publisherId, streamName)
		.set(function () {
			var miles = this.get('miles');
			var latitude = this.get('latitude');
			var longitude = this.get('longitude');
			if (miles) {
				tool.$('.Places_location_miles').val(miles);
			};
			pipe.fill('info')(latitude, longitude, miles, state.onSet.handle);
			state.stream = this; // in case it was missing before
		});

		Streams.retainWith(tool)
		.get(publisherId, streamName, function (err) {
			if (!err) {
				var stream = state.stream = this;
				var miles = stream.get('miles');
				var latitude = stream.get('latitude');
				var longitude = stream.get('longitude');
				if (miles) {
					tool.$('.Places_location_miles').val(miles);
				}
			}
			if (!latitude || !longitude || !miles) {
				$te.removeClass('Places_location_obtained')
					.addClass('Places_location_obtaining');
				$te.find('.Places_location_container')
					.removeClass('Places_location_checking');
				Q.handle(state.onUnset, tool, [err, stream]);
				if (!state.onReady.occurred) {
					Q.handle(state.onReady, tool, [err, stream]);
				}
			}
			setTimeout(function () {
				pipe.fill('show')();
			}, state.map.delay);

			if (stream && Q.getter.usingCached) {
				stream.refresh();
			}
		});

		tool.$('.Places_location_miles').on('change', function () {
			_submit();
		});

		tool.$('.Places_location_set, .Places_location_update_button')
		.on(Q.Pointer.click, function () {
			var $this = $(this);
			$this.addClass('Places_obtaining');
			if (!navigator.geolocation) {
				return geolocationFailed();
			}
			var timeout = setTimeout(geolocationFailed, state.timeout);
			var handledFail = false;
			Places.loadGoogleMaps(function () {
				navigator.geolocation.getCurrentPosition(
				function (geo) {
					clearTimeout(timeout);
					if (handledFail) return;
					var geocoder = new google.maps.Geocoder();
					geocoder.geocode({'latLng': {
						lat: geo.coords.latitude,
						lng: geo.coords.longitude
					}}, function(results, status) {
						var country, state, placeName;
						if (status == google.maps.GeocoderStatus.OK && results[0]) {
							country = getComponent(results, 'country');
							state = getComponent(results, 'administrative_area_level_1');
							placeName = getComponent(results, 'locality')
								|| getComponent(results, 'sublocality');
						}
						_submit(null, Q.extend({
							placeName: placeName,
							state: state,
							country: country
						}, true, geo.coords));
					});
				}, function () {
					clearTimeout(timeout);
					if (handledFail) return;
					geolocationFailed();
				}, {
					maximumAge: 300000,
					timeout: state.timeout
				});
			});

			function geolocationFailed() {
				handledFail = true;
				Q.prompt("Please enter your zipcode:",
				function (zipcode, dialog) {
					if (zipcode) {
						_submit(zipcode);
					}
				}, {
					title: "My Location",
					ok: "Update",
					onClose: function () {
						$this.removeClass('Places_obtaining');
					}
				});
			}

			function getComponent(results, desiredType) {
				for (var i = 0; i < results[0].address_components.length; i++) {
					var shortname = results[0].address_components[i].short_name;
					var longname = results[0].address_components[i].long_name;
					var type = results[0].address_components[i].types;
					if (type.indexOf(desiredType) != -1) {
						if (!isNullOrWhitespace(shortname)) {
						    return shortname;
						}
						return longname;
					}
			    }
			}

			function isNullOrWhitespace(text) {
			    if (text == null) {
			        return true;
			    }
			    return text.replace(/\s/gi, '').length < 1;
			}
		});
	});

	function _submit(zipcode, fields) {
		fields = Q.extend({}, fields, {
			subscribe: true,
			unsubscribe: true,
			miles: tool.$('.Places_location_miles').val(),
			timezone: (new Date()).getTimezoneOffset() / 60,
			defaultMiles: state.defaultMiles
		});
		if (zipcode) {
			fields.zipcode = zipcode;
		}
		Q.req('Places/geolocation', [], function (err, data) {
			var msg = Q.firstErrorMessage(err, data && data.errors);
			if (msg) {
				return alert(msg);
			}
			Streams.Stream.refresh(publisherId, streamName, function () {
				var miles = this.get('miles');
				var latitude = this.get('latitude');
				var longitude = this.get('longitude');
				if (miles) {
					tool.$('.Places_location_miles').val(miles);
				};
				if (latitude && longitude) {
					Q.handle(state.onUpdate, tool, [latitude, longitude, miles]);
				}
			}, {
				messages: 1,
				evenIfNotRetained: true
			});
		}, {
			method: 'post',
			fields: fields
		});
	}

	var previous = {};
	function _showMap(latitude, longitude, miles, callback) {

		if (latitude == undefined
		|| longitude == undefined
		|| !miles) {
			return;
		}
		if (latitude == previous.latitude
		&& longitude == previous.longitude
		&& miles == previous.miles) {
			return;
		}
		previous = {
			latitude: latitude,
			longitude: longitude,
			miles: miles
		};

		Places.loadGoogleMaps(function () {
			$te.removeClass('Places_location_obtaining')
				.addClass('Places_location_obtained');
			$te.find('.Places_location_container')
				.removeClass('Places_location_checking');
			setTimeout(function () {
				tool.$('.Places_location_map_container').show();
				tool.$('.Places_location_update').slideDown(800);
				setTimeout(function () {
					_showLocationAndCircle();
				}, 300);
			}, 0);
			if (!state.onReady.occurred) {
				Q.handle(state.onReady, tool, [null, state.stream]);
			}
		});

		function _showLocationAndCircle() {
			var element = tool.$('.Places_location_map')[0];
			var map = state.map = new google.maps.Map(element, {
				center: new google.maps.LatLng(latitude, longitude),
				zoom: 12 - Math.floor(Math.log(miles) / Math.log(2)),
				mapTypeId: google.maps.MapTypeId.ROADMAP,
				draggable: false,
				panControl: false,
				disableDoubleClickZoom: true,
				zoomControl: false,
				scaleControl: false,
				disableDefaultUI: true,
				scrollwheel: false,
				navigationControl: false
			});

			// Create marker
			var marker = new google.maps.Marker({
				map: map,
				position: new google.maps.LatLng(latitude, longitude),
				title: 'My location'
			});

			// Add circle overlay and bind to marker
			var circle = new google.maps.Circle({
			  map: map,
			  radius: miles*1609.34,
			  fillColor: '#0000AA'
			});
			circle.bindTo('center', marker, 'position');

			Q.handle(callback, tool, [latitude, longitude, miles, map]);
		}
	}
},

{ // default options here
	updateButton: 'Update my location',
	map: {
		delay: 300,
		prompt: Q.url('plugins/Places/img/map.png')
	},
	timeout: 10000,
	onReady: new Q.Event(),
	onSet: new Q.Event(),
	onUnset: new Q.Event(),
	onUpdate: new Q.Event()
},

{ // methods go here

});

Q.Template.set('Places/location',
	'
'
		+ 'I\'m interested in things taking place within'
		+ '<select name="miles" class="Places_location_miles">'
			+ '{{#each miles}}'
				+ '{{option @key this ../defaultMiles}}'
			+ '{{/each}}'
		+ '</select>'
		+ ' of '
		+ '
'
			+ ''
		+ '
'
		+ '
'
			+ '
'
				+ '

'
			+ '
'
			+ '
'
				+ '<button class="Places_location_update_button Q_button">'
					+ '{{updateButton}}'
				+ '</button>'
			+ '
'
		+ '
'
	+ '
'
);

})(Q, jQuery, window, document);<|endoftext|>


<commit_before>(function (Q, $, window, document, undefined) {

/**
 * Places Tools
 * @module Places-tools
 */

var Users = Q.Users;
var Streams = Q.Streams;
var Places = Q.Places;

/**
 * Allows the logged-in user to locations to a publisher and select among already added locations
 * @class Places location
 * @constructor
 * @param {Object} [options] used to pass options
 * @param {String} [options.publisherId=Q.Users.loggedInUserId()] Override the publisherId
 *  for saving new locations.
 * @param {Object} [options.geocode] Default google location object, if available
 * @param {Places.Coordinates} [options.location] Provide a location to start off with.
 *  Can be anything that is accepted by Places.Coordinates constructor.
 * @param {Boolean} [options.showCurrent=true] Whether to allow user to select current location
 * @param {Boolean} [options.showLocations=true] Whether to allow user to select their saved locations
 * @param {Boolean} [options.showAddress=true] Whether to allow user to enter a custom address
 * @param {Boolean} [options.showAreas=false] Whether to show Places/areas tool for selected location
 * @param {Q.Event} [options.onChoose] User selected some valid location. First parameter is Places.Coordinates object.
 */
Q.Tool.define("Places/location", function (options) {
	var tool = this;
	var state = this.state;
	var $te = $(tool.element);

	Q.addStylesheet('Q/plugins/Places/css/location.css');

	// change location event
	$te.on(Q.Pointer.click, "[data-location], .Places_location_preview_tool", function () {
		tool.toggle(this);
	});

	tool.Q.onStateChanged('location').set(function () {
		Q.handle(state.onChoose, tool, [state.location]);
	});

	// if showAreas - add Places/areas tool if not exist
	if(state.showAreas){
		state.onChoose.set(function(location){
			var placesAreas = tool.$(".Q_tool.Places_areas_tool")[0];
			placesAreas = placesAreas ? Q.Tool.from(placesAreas, "Places/areas") : null;

			if (Q.isEmpty(location)) {
				if (Q.typeOf(placesAreas) === "Q.Tool") {
					Q.Tool.remove(placesAreas.element);
				}

				return false;
			}

			if (!placesAreas) {
				$("
").tool("Places/areas", {
					location: location
				}).appendTo($te).activate();

				return true;
			}

			placesAreas.state.location = location;
			placesAreas.refresh();

			return true;
		}, tool);
	}

	tool.refresh();
},

{ // default options here
	publisherId: null,
	geocode: null,
	onChoose: new Q.Event(function (coordinates) {
		this.state.location = coordinates;
	}, 'Places/location'),
	location: null, // currently selected location
	showCurrent: true,
	showLocations: true,
	showAddress: true,
	showAreas: false
},

{ // methods go here
	/**
	 * Refresh the display
	 * @method refresh
	 */
	refresh: function () {
		var tool = this;
		var state = tool.state;
		var $te = $(tool.element);

		// location empty - render standard location select template
		if (Q.isEmpty(state.location)) {
			tool.selectLocation();
			return;
		}

		// location already set in state - just type it
		Places.Coordinates.from(state.location).geocode(function (err, results) {
			var fem = Q.firstErrorMessage(err);
			if (fem) {
				// if something wrong with location
				// render standard location select template
				tool.selectLocation();

				return console.warn(fem);
			}

			var result = results[0];
			var address = result.formatted_address || result.address;
			$te.html(address).addClass("Q_selected");
			Q.handle(state.onChoose, tool, [this, result.geometry.location]);
		});
	},
	/**
	 * Render template with locations, so user can select one of them
	 * @method selectLocation
	 */
	selectLocation: function(){
		var tool = this;
		var state = this.state;
		var $te = $(tool.element);
		var userId = state.publisherId || Users.loggedInUserId();

		Q.Text.get('Places/content', function (err, text) {
			Q.Template.render('Places/location/select', Q.extend({
				text: text
			}, state), function (err, html) {
				$te.html(html).activate(function () {

					// set address tool
					tool.$(".Places_location_address")
					.tool('Places/address', {
						onChoose: _onChoose
					}, 'Places_address', tool.prefix)
					.activate(function () {
						tool.addressTool = this;
						var $toolParent = $(tool.addressTool.element).closest("[data-location=address]");

						// wait when included Q/filter tool activated
						this.state.onFilterActivated.set(function () {
							// start toggle locations when address tool input focused.
							this.state.onFocus.set(function () {
								tool.toggle($toolParent);
							}, tool);
						}, tool);
					});

					// set showLocations state.
					if (state.showLocations && userId) {
						// if logged user is not a publisher of Places/user/locations
						// need to participate this user to this category to allow
						// get messages about changes
						if (userId !== Users.loggedInUserId()) {
							Streams.Stream.join(userId, 'Places/user/locations');
						}

						tool.$(".Places_location_related")
							.tool('Streams/related', {
								publisherId: userId,
								streamName: 'Places/user/locations',
								relationType: 'Places/locations',
								isCategory: true,
								editable: false,
								realtime: true,
								sortable: false
							}, tool.prefix + 'relatedLocations')
							.activate(function () {
								tool.relatedTool = this;
						});
					}

					function _onChoose(place) {
						if (!place || !place.id) {
							return Q.handle(state.onChoose, tool, [null, null]);
						}
						Places.Coordinates.from({
							placeId: place.id
						}).geocode(function (err, results) {
							var msg = Q.firstErrorMessage(err);
							if (msg) {
								throw new Q.Error(msg);
							}

							var result = results[0];
							if (!result || !userId) {
								return;
							}
							var attributes = {
								types: result.types,
								latitude: result.geometry.location.lat(),
								longitude: result.geometry.location.lng(),
								locationType: result.geometry.type,
								venue: place.name
							};
							if (result.place_id) {
								attributes.placeId = result.place_id;
							}

							var textConfirm = text.location.confirm;
							Q.confirm(textConfirm.message, function (shouldSave) {
								if (!shouldSave) {
									return;
								}
								var textAdd = text.location.add;
								Q.prompt(textAdd.title, function (title) {
									if (!title) {
										return;
									}

									Streams.create({
										publisherId: userId,
										type: 'Places/location',
										title: title,
										attributes: attributes,
										readLevel: 0,
										writeLevel: 0,
										adminLevel: 0
									}, function (err) {
										if (err) {
											return;
										}

										tool.relatedTool.state.onRefresh.setOnce(function (previews, map, entering, exiting, updating) {
											var key = Q.firstKey(entering);
											var index = map[key];
											var preview = previews[index];
											Q.Pointer.canceledClick = false;
											tool.toggle(preview.element);
										});
									}, {
										publisherId: userId,
										streamName: 'Places/user/locations',
										type: 'Places/locations'
									});
								}, {
									title: textAdd.title,
									placeholder: textAdd.placeholder,
									ok: textAdd.ok
								});
							}, {
								title: textConfirm.title,
								ok: textConfirm.ok,
								cancel: textConfirm.cancel
							});

							this.venue = place.name;
							var description = place.description;
							if (description.indexOf(',') >= 0) {
								this.venue += description.substr(description.indexOf(','));
							}

							$te.find(".Q_selected").removeClass("Q_selected");
							$(tool.addressTool.element).addClass('Q_selected');
							this.stream = null;
							Q.handle(state.onChoose, tool, [this, result.geometry.location]);
						});
					}
				});
			}, {tool: tool});
		});
	},
	/**
	 * Get current geolocation
	 * @method getCurrentPosition
	 * @param {function} [success] Callback for success
	 * @param {function} [fail] Callback for fail
	 */
	getCurrentPosition: function (success, fail) {
		var tool = this;

		navigator.geolocation.getCurrentPosition(function (pos) {
			Q.handle(success, tool, [pos]);
		}, function (err) {
			Q.handle(fail, tool, [err]);
			Q.alert("Places.location.getCurrentPosition: ERROR(" + err.code + "): " + err.message);

			return false;
		}, {
			enableHighAccuracy: false, // need to set true to make it work consistently, it doesn't seem to make it any more accurate
			timeout: 5000,
			maximumAge: 0
		});
	},
	/**
	 * Make some needed actions when user select some other location.
	 * @method toggle
	 * @param {HTMLElement} elem Selected currently element
	 */
	toggle: function (elem) {
		var tool = this;
		var state = this.state;
		var $te = $(tool.element);
		var $this = $(elem);

		if ($this.hasClass('Q_selected')) {
			return false;
		}

		// toggle Q_selected class
		$te.find(".Q_selected").removeClass("Q_selected");
		$this.addClass('Q_selected');

		var $olt = $this.find(tool.addressTool.element);
		if ($olt.length) {
			$olt.plugin('Q/placeholders', function () {
				tool.addressTool.filter.setText('');
				tool.addressTool.filter.$input.plugin('Q/clickfocus');
			});
		}

		var selector = $this.attr("data-location");
		if (selector === 'current') {
			tool.getCurrentPosition(function (pos) {
				var crd = pos.coords;
				if (!crd) {
					Q.alert("Places/location tool: could not obtain location", pos);
					return false;
				}
				Places.Coordinates.from({
					latitude: crd.latitude,
					longitude: crd.longitude
				}).geocode(function (err, results) {
					var loc = Q.getObject([0, 'geometry', 'location'], results);
					Q.handle(state.onChoose, tool, [this, loc]);
				});
			}, function (err) {
				Q.handle(state.onChoose, tool, [null, null]);
			});

			return;
		} else if (selector === 'address') {
			// if address selected just repeat onChoose event of Places/address tool
			Q.handle(
				tool.addressTool.state.onChoose,
				tool.addressTool,
				[tool.addressTool.place]
			);
			return;
		}

		// related location selected
		var locationPreviewTool = Q.Tool.from($this, "Streams/preview");
		var ls = locationPreviewTool.state;
		Streams.get(ls.publisherId, ls.streamName, function () {
			var locationStream = this;
			Places.Coordinates.from(locationStream).geocode(function (err, results) {
				var loc = Q.getObject([0, 'geometry', 'location'], results);
				this.stream = locationStream;
				Q.handle(state.onChoose, tool, [this, loc]);
			});
		});
	}
});

Q.Template.set('Places/location/select',
	'{{#if showCurrent}}' +
		'
{{text.location.myCurrentLocation}}
' +
	'{{/if}}' +
	'{{#if showLocations}}' +
		'

' +
	'{{/if}}' +
	'{{#if showAddress}}' +
		'
' +
			'{{text.location.enterAddress}}' +
			'

' +
		'
' +
	'{{/if}}'
);
})(Q, jQuery, window, document);<commit_msg>Current Location will flash Q_working while obtaining location<commit_after>(function (Q, $, window, document, undefined) {

/**
 * Places Tools
 * @module Places-tools
 */

var Users = Q.Users;
var Streams = Q.Streams;
var Places = Q.Places;

/**
 * Allows the logged-in user to locations to a publisher and select among already added locations
 * @class Places location
 * @constructor
 * @param {Object} [options] used to pass options
 * @param {String} [options.publisherId=Q.Users.loggedInUserId()] Override the publisherId
 *  for saving new locations.
 * @param {Object} [options.geocode] Default google location object, if available
 * @param {Places.Coordinates} [options.location] Provide a location to start off with.
 *  Can be anything that is accepted by Places.Coordinates constructor.
 * @param {Boolean} [options.showCurrent=true] Whether to allow user to select current location
 * @param {Boolean} [options.showLocations=true] Whether to allow user to select their saved locations
 * @param {Boolean} [options.showAddress=true] Whether to allow user to enter a custom address
 * @param {Boolean} [options.showAreas=false] Whether to show Places/areas tool for selected location
 * @param {Q.Event} [options.onChoose] User selected some valid location. First parameter is Places.Coordinates object.
 */
Q.Tool.define("Places/location", function (options) {
	var tool = this;
	var state = this.state;
	var $te = $(tool.element);

	Q.addStylesheet('Q/plugins/Places/css/location.css');

	// change location event
	$te.on(Q.Pointer.click, "[data-location], .Places_location_preview_tool", function () {
		tool.toggle(this);
	});

	tool.Q.onStateChanged('location').set(function () {
		Q.handle(state.onChoose, tool, [state.location]);
	});

	// if showAreas - add Places/areas tool if not exist
	if(state.showAreas){
		state.onChoose.set(function(location){
			var placesAreas = tool.$(".Q_tool.Places_areas_tool")[0];
			placesAreas = placesAreas ? Q.Tool.from(placesAreas, "Places/areas") : null;

			if (Q.isEmpty(location)) {
				if (Q.typeOf(placesAreas) === "Q.Tool") {
					Q.Tool.remove(placesAreas.element);
				}

				return false;
			}

			if (!placesAreas) {
				$("
").tool("Places/areas", {
					location: location
				}).appendTo($te).activate();

				return true;
			}

			placesAreas.state.location = location;
			placesAreas.refresh();

			return true;
		}, tool);
	}

	tool.refresh();
},

{ // default options here
	publisherId: null,
	geocode: null,
	onChoose: new Q.Event(function (coordinates) {
		this.state.location = coordinates;
	}, 'Places/location'),
	location: null, // currently selected location
	showCurrent: true,
	showLocations: true,
	showAddress: true,
	showAreas: false
},

{ // methods go here
	/**
	 * Refresh the display
	 * @method refresh
	 */
	refresh: function () {
		var tool = this;
		var state = tool.state;
		var $te = $(tool.element);

		// location empty - render standard location select template
		if (Q.isEmpty(state.location)) {
			tool.selectLocation();
			return;
		}

		// location already set in state - just type it
		Places.Coordinates.from(state.location).geocode(function (err, results) {
			var fem = Q.firstErrorMessage(err);
			if (fem) {
				// if something wrong with location
				// render standard location select template
				tool.selectLocation();

				return console.warn(fem);
			}

			var result = results[0];
			var address = result.formatted_address || result.address;
			$te.html(address).addClass("Q_selected");
			Q.handle(state.onChoose, tool, [this, result.geometry.location]);
		});
	},
	/**
	 * Render template with locations, so user can select one of them
	 * @method selectLocation
	 */
	selectLocation: function(){
		var tool = this;
		var state = this.state;
		var $te = $(tool.element);
		var userId = state.publisherId || Users.loggedInUserId();

		Q.Text.get('Places/content', function (err, text) {
			Q.Template.render('Places/location/select', Q.extend({
				text: text
			}, state), function (err, html) {
				$te.html(html).activate(function () {

					// set address tool
					tool.$(".Places_location_address")
					.tool('Places/address', {
						onChoose: _onChoose
					}, 'Places_address', tool.prefix)
					.activate(function () {
						tool.addressTool = this;
						var $toolParent = $(tool.addressTool.element).closest("[data-location=address]");

						// wait when included Q/filter tool activated
						this.state.onFilterActivated.set(function () {
							// start toggle locations when address tool input focused.
							this.state.onFocus.set(function () {
								tool.toggle($toolParent);
							}, tool);
						}, tool);
					});

					// set showLocations state.
					if (state.showLocations && userId) {
						// if logged user is not a publisher of Places/user/locations
						// need to participate this user to this category to allow
						// get messages about changes
						if (userId !== Users.loggedInUserId()) {
							Streams.Stream.join(userId, 'Places/user/locations');
						}

						tool.$(".Places_location_related")
							.tool('Streams/related', {
								publisherId: userId,
								streamName: 'Places/user/locations',
								relationType: 'Places/locations',
								isCategory: true,
								editable: false,
								realtime: true,
								sortable: false
							}, tool.prefix + 'relatedLocations')
							.activate(function () {
								tool.relatedTool = this;
						});
					}

					function _onChoose(place) {
						if (!place || !place.id) {
							return Q.handle(state.onChoose, tool, [null, null]);
						}
						Places.Coordinates.from({
							placeId: place.id
						}).geocode(function (err, results) {
							var msg = Q.firstErrorMessage(err);
							if (msg) {
								throw new Q.Error(msg);
							}

							var result = results[0];
							if (!result || !userId) {
								return;
							}
							var attributes = {
								types: result.types,
								latitude: result.geometry.location.lat(),
								longitude: result.geometry.location.lng(),
								locationType: result.geometry.type,
								venue: place.name
							};
							if (result.place_id) {
								attributes.placeId = result.place_id;
							}

							var textConfirm = text.location.confirm;
							Q.confirm(textConfirm.message, function (shouldSave) {
								if (!shouldSave) {
									return;
								}
								var textAdd = text.location.add;
								Q.prompt(textAdd.title, function (title) {
									if (!title) {
										return;
									}

									Streams.create({
										publisherId: userId,
										type: 'Places/location',
										title: title,
										attributes: attributes,
										readLevel: 0,
										writeLevel: 0,
										adminLevel: 0
									}, function (err) {
										if (err) {
											return;
										}

										tool.relatedTool.state.onRefresh.setOnce(function (previews, map, entering, exiting, updating) {
											var key = Q.firstKey(entering);
											var index = map[key];
											var preview = previews[index];
											Q.Pointer.canceledClick = false;
											tool.toggle(preview.element);
										});
									}, {
										publisherId: userId,
										streamName: 'Places/user/locations',
										type: 'Places/locations'
									});
								}, {
									title: textAdd.title,
									placeholder: textAdd.placeholder,
									ok: textAdd.ok
								});
							}, {
								title: textConfirm.title,
								ok: textConfirm.ok,
								cancel: textConfirm.cancel
							});

							this.venue = place.name;
							var description = place.description;
							if (description.indexOf(',') >= 0) {
								this.venue += description.substr(description.indexOf(','));
							}

							$te.find(".Q_selected").removeClass("Q_selected");
							$(tool.addressTool.element).addClass('Q_selected');
							this.stream = null;
							Q.handle(state.onChoose, tool, [this, result.geometry.location]);
						});
					}
				});
			}, {tool: tool});
		});
	},
	/**
	 * Get current geolocation
	 * @method getCurrentPosition
	 * @param {function} [success] Callback for success
	 * @param {function} [fail] Callback for fail
	 */
	getCurrentPosition: function (success, fail) {
		var tool = this;

		navigator.geolocation.getCurrentPosition(function (pos) {
			Q.handle(success, tool, [pos]);
		}, function (err) {
			Q.handle(fail, tool, [err]);
			Q.alert("Places.location.getCurrentPosition: ERROR(" + err.code + "): " + err.message);

			return false;
		}, {
			enableHighAccuracy: false, // need to set true to make it work consistently, it doesn't seem to make it any more accurate
			timeout: 5000,
			maximumAge: 0
		});
	},
	/**
	 * Make some needed actions when user select some other location.
	 * @method toggle
	 * @param {HTMLElement} elem Selected currently element
	 */
	toggle: function (elem) {
		var tool = this;
		var state = this.state;
		var $te = $(tool.element);
		var $this = $(elem);

		if ($this.hasClass('Q_selected')) {
			return false;
		}

		// toggle Q_selected class
		$te.find(".Q_selected").removeClass("Q_selected");
		$this.addClass('Q_selected');

		var $olt = $this.find(tool.addressTool.element);
		if ($olt.length) {
			$olt.plugin('Q/placeholders', function () {
				tool.addressTool.filter.setText('');
				tool.addressTool.filter.$input.plugin('Q/clickfocus');
			});
		}

		var selector = $this.attr("data-location");
		if (selector === 'current') {
			$this.addClass('Q_working');
			tool.getCurrentPosition(function (pos) {
				var crd = pos.coords;
				if (!crd) {
					Q.alert("Places/location tool: could not obtain location", pos);
					return false;
				}
				Places.Coordinates.from({
					latitude: crd.latitude,
					longitude: crd.longitude
				}).geocode(function (err, results) {
					var loc = Q.getObject([0, 'geometry', 'location'], results);
					Q.handle(state.onChoose, tool, [this, loc]);
				});
			}, function (err) {
				Q.handle(state.onChoose, tool, [null, null]);
				$this.removeClass('Q_working');
			});

			return;
		} else {
			tool.$('[data-location="current"]').removeClass('Q_working');
			if (selector === 'address') {
				// if address selected just repeat onChoose event of Places/address tool
				Q.handle(
					tool.addressTool.state.onChoose,
					tool.addressTool,
					[tool.addressTool.place]
				);
				return;
			}
		}

		// related location selected
		var locationPreviewTool = Q.Tool.from($this, "Streams/preview");
		var ls = locationPreviewTool.state;
		Streams.get(ls.publisherId, ls.streamName, function () {
			var locationStream = this;
			Places.Coordinates.from(locationStream).geocode(function (err, results) {
				var loc = Q.getObject([0, 'geometry', 'location'], results);
				this.stream = locationStream;
				Q.handle(state.onChoose, tool, [this, loc]);
			});
		});
	}
});

Q.Template.set('Places/location/select',
	'{{#if showCurrent}}' +
		'
{{text.location.myCurrentLocation}}
' +
	'{{/if}}' +
	'{{#if showLocations}}' +
		'

' +
	'{{/if}}' +
	'{{#if showAddress}}' +
		'
' +
			'{{text.location.enterAddress}}' +
			'

' +
		'
' +
	'{{/if}}'
);
})(Q, jQuery, window, document);<|endoftext|>


<commit_before>'use strict';

angular.module('myApp.Referee', ['ngRoute'])

.controller('RefereeCtrl', [function() {

}])

.controller('ArticleCtrl', [function() {

}])

.controller('TimelineCtrl', [function() {

}])

.controller('SuggCtrl', [function() {

}]);
<commit_msg>referee controller timeline post<commit_after>'use strict';

angular.module('myApp.referee', ['ngRoute','ngResource'])
.factory('suggFactory', function($resource){
    return {
       resource : function()
        {

return $resource('localhost:3000/suggestion', {
    get: {
      method: 'GET' // Get all suggestions
    }
  });
        }
    }

})

.controller('ArticleCtrl', [function() {

}])

.controller('SuggCtrl', function($scope, $routeParams,$http, RefereeSuggFactory) {

    loadSugg();

    function loadSugg(){
        RefereeSuggFactory.suggs().success(function(suggestion){
            $scope.sugg = suggestion;
        });
    }
})

.controller('SuggACtrl', function($scope, $routeParams,$http, RefereeSuggFactory) {

    loadSuggA();

    function loadSuggA(){
        RefereeSuggFactory.suggsA().success(function(suggestiona){
            $scope.suggA = suggestiona;
        });
    }
})

// photos instagram liké :
.controller('RefereeCtrl', function($scope, $routeParams,$http, RefereeSuggFactory) {

    loadInstaLiked();

    function loadInstaLiked(){
        RefereeSuggFactory.instaLiked().success(function(instaLiked){
            $scope.instaLiked = instaLiked;
        });
    }
})

.controller('TimelineCtrl', [function() {

}]);

<|endoftext|>