<commit_before>// Copyright 2018 Google LLC
//
// 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.

// [START functions_background_promise_node8]
// [START functions_background_async]
const fetch = require('node-fetch');

// [END functions_background_promise_node8]
// [END functions_background_async]

// [START functions_tips_infinite_retries_node8]
/**
 * Background Cloud Function that only executes within a certain time
 * period after the triggering event to avoid infinite retry loops.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.avoidInfiniteRetries = (data, context) => {
  const eventAge = Date.now() - Date.parse(context.timestamp);
  const eventMaxAge = 10000;

  // Ignore events that are too old
  if (eventAge > eventMaxAge) {
    console.log(`Dropping event ${context.eventId} with age ${eventAge} ms.`);
    return;
  }

  // Do what the function is supposed to do
  console.log(`Processing event ${context.eventId} with age ${eventAge} ms.`);
};
// [END functions_tips_infinite_retries_node8]

// [START functions_tips_retry_node8]
/**
 * Background Cloud Function that demonstrates
 * how to toggle retries using a promise
 *
 * @param {object} data The event payload.
 * @param {object} data.retry User-supplied parameter that tells the function whether to retry.
 * @param {object} context The event metadata.
 */
exports.retryPromise = (data, context) => {
  const tryAgain = !!data.retry;

  if (tryAgain) {
    throw new Error(`Retrying...`);
  } else {
    return new Error('Not retrying...');
  }
};
// [END functions_tips_retry_node8]

// [START functions_helloworld_background_node8]
/**
 * Background Cloud Function.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
// [START functions_tips_terminate_node8]
exports.helloBackground = (data, context) => {
  return `Hello ${data.name || 'World'}!`;
};
// [END functions_tips_terminate_node8]
// [END functions_helloworld_background_node8]

// [START functions_helloworld_pubsub_node8]
/**
 * Background Cloud Function to be triggered by Pub/Sub.
 * This function is exported by index.js, and executed when
 * the trigger topic receives a message.
 *
 * @param {object} pubSubEvent The event payload.
 * @param {object} context The event metadata.
 */
exports.helloPubSub = (pubSubEvent, context) => {
  const name = pubSubEvent.data
    ? Buffer.from(pubSubEvent.data, 'base64').toString()
    : 'World';

  console.log(`Hello, ${name}!`);
};
// [END functions_helloworld_pubsub_node8]

// [START functions_helloworld_storage_node8]
/**
 * Background Cloud Function to be triggered by Cloud Storage.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.helloGCS = (data, context) => {
  const file = data;
  if (file.resourceState === 'not_exists') {
    console.log(`File ${file.name} deleted.`);
  } else if (file.metageneration === '1') {
    // metageneration attribute is updated on metadata changes.
    // on create value is 1
    console.log(`File ${file.name} uploaded.`);
  } else {
    console.log(`File ${file.name} metadata updated.`);
  }
};
// [END functions_helloworld_storage_node8]

// [START functions_helloworld_storage_generic_node8]
/**
 * Generic background Cloud Function to be triggered by Cloud Storage.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.helloGCSGeneric = (data, context) => {
  const file = data;
  console.log(`  Event ${context.eventId}`);
  console.log(`  Event Type: ${context.eventType}`);
  console.log(`  Bucket: ${file.bucket}`);
  console.log(`  File: ${file.name}`);
  console.log(`  Metageneration: ${file.metageneration}`);
  console.log(`  Created: ${file.timeCreated}`);
  console.log(`  Updated: ${file.updated}`);
};
// [END functions_helloworld_storage_generic_node8]

// [START functions_firebase_rtdb_node8]
/**
 * Triggered by a change to a Firebase RTDB reference.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.helloRTDB = (data, context) => {
  const triggerResource = context.resource;

  const pathParams = data.params;
  if (pathParams) {
    console.log(`Parameters:`);
    Object.entries(pathParams).forEach(([param, value]) => {
      console.log(`  ${param}: ${value}`);
    });
  }

  console.log(`Function triggered by change to: ${triggerResource}`);
  console.log(`Admin?: ${!!data.admin}`);
  console.log(`Delta:`);
  console.log(JSON.stringify(data.delta, null, 2));
};
// [END functions_firebase_rtdb_node8]

// [START functions_firebase_firestore_node8]
/**
 * Triggered by a change to a Firestore document.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.helloFirestore = (data, context) => {
  const triggerResource = context.resource;

  console.log(`Function triggered by change to: ${triggerResource}`);
  console.log(`Event type: ${context.eventType}`);

  if (data.oldValue && Object.keys(data.oldValue).length) {
    console.log(`\nOld value:`);
    console.log(JSON.stringify(data.oldValue, null, 2));
  }

  if (data.value && Object.keys(data.value).length) {
    console.log(`\nNew value:`);
    console.log(JSON.stringify(data.value, null, 2));
  }
};
// [END functions_firebase_firestore_node8]

// [START functions_firebase_auth_node8]
/**
 * Triggered by creation or deletion of a Firebase Auth user object.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.helloAuth = (data, context) => {
  try {
    console.log(
      `Function triggered by creation or deletion of user: ${data.uid}`
    );
    console.log(`Created at: ${data.metadata.createdAt}`);

    if (data.email) {
      console.log(`Email: ${data.email}`);
    }
  } catch (err) {
    console.error(err);
  }
};
// [END functions_firebase_auth_node8]

// [START functions_firebase_analytics_node8]
/**
 * Triggered by a Google Analytics for Firebase log event.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.helloAnalytics = (data, context) => {
  const {resource} = context;
  console.log(`Function triggered by the following event: ${resource}`);

  const [analyticsEvent] = data.eventDim;
  console.log(`Name: ${analyticsEvent.name}`);
  console.log(`Timestamp: ${new Date(analyticsEvent.timestampMicros / 1000)}`);

  const userObj = data.userDim;
  console.log(`Device Model: ${userObj.deviceInfo.deviceModel}`);
  console.log(`Location: ${userObj.geoInfo.city}, ${userObj.geoInfo.country}`);
};
// [END functions_firebase_analytics_node8]

// [START functions_background_promise_node8]
/**
 * Background Cloud Function that returns a Promise. Note that we don't pass
 * a "callback" argument to the function.
 *
 * @param {object} data The Cloud Functions event data.
 * @returns {Promise}
 */
exports.helloPromise = (data) => {
  return fetch(data.endpoint);
};
// [END functions_background_promise_node8]

// [START functions_firebase_reactive_node8]
const Firestore = require('@google-cloud/firestore');

const firestore = new Firestore({
  projectId: process.env.GCP_PROJECT,
});

// Converts strings added to /messages/{pushId}/original to uppercase
exports.makeUpperCase = (data, context) => {
  const {resource} = context;
  const affectedDoc = firestore.doc(resource.split('/documents/')[1]);

  const curValue = data.value.fields.original.stringValue;
  const newValue = curValue.toUpperCase();
  console.log(`Replacing value: ${curValue} --> ${newValue}`);

  return affectedDoc.set({
    original: newValue,
  });
};
// [END functions_firebase_reactive_node8]

// [START functions_firebase_remote_config_node8]
/**
 * Triggered by a change to a Firebase Remote Config value.
 *
 * @param {object} data The Cloud Functions event data.
 */
exports.helloRemoteConfig = (data) => {
  console.log(`Update type: ${data.updateType}`);
  console.log(`Origin: ${data.updateOrigin}`);
  console.log(`Version: ${data.versionNumber}`);
};
// [END functions_firebase_remote_config_node8]

// [START functions_background_async]
/**
 * Background Cloud Function demonstrates use of async/await.
 *
 * @param {object} data The event payload.
 */
exports.helloAsync = async (data) => {
  const result = await fetch('https://www.example.com');
  return result;
};
// [END functions_background_async]
<commit_msg>Background function: return on completion (#1760)<commit_after>// Copyright 2018 Google LLC
//
// 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.

// [START functions_background_promise_node8]
// [START functions_background_async]
const fetch = require('node-fetch');

// [END functions_background_promise_node8]
// [END functions_background_async]

// [START functions_tips_infinite_retries_node8]
/**
 * Background Cloud Function that only executes within a certain time
 * period after the triggering event to avoid infinite retry loops.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.avoidInfiniteRetries = (data, context) => {
  const eventAge = Date.now() - Date.parse(context.timestamp);
  const eventMaxAge = 10000;

  // Ignore events that are too old
  if (eventAge > eventMaxAge) {
    console.log(`Dropping event ${context.eventId} with age ${eventAge} ms.`);
    return;
  }

  // Do what the function is supposed to do
  console.log(`Processing event ${context.eventId} with age ${eventAge} ms.`);
};
// [END functions_tips_infinite_retries_node8]

// [START functions_tips_retry_node8]
/**
 * Background Cloud Function that demonstrates
 * how to toggle retries using a promise
 *
 * @param {object} data The event payload.
 * @param {object} data.retry User-supplied parameter that tells the function whether to retry.
 * @param {object} context The event metadata.
 */
exports.retryPromise = (data, context) => {
  const tryAgain = !!data.retry;

  if (tryAgain) {
    throw new Error(`Retrying...`);
  } else {
    return new Error('Not retrying...');
  }
};
// [END functions_tips_retry_node8]

// [START functions_helloworld_background_node8]
/**
 * Background Cloud Function.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
// [START functions_tips_terminate_node8]
exports.helloBackground = (data, context) => {
  return `Hello ${data.name || 'World'}!`;
};
// [END functions_tips_terminate_node8]
// [END functions_helloworld_background_node8]

// [START functions_helloworld_pubsub_node8]
/**
 * Background Cloud Function to be triggered by Pub/Sub.
 * This function is exported by index.js, and executed when
 * the trigger topic receives a message.
 *
 * @param {object} pubSubEvent The event payload.
 * @param {object} context The event metadata.
 */
exports.helloPubSub = (pubSubEvent, context) => {
  const name = pubSubEvent.data
    ? Buffer.from(pubSubEvent.data, 'base64').toString()
    : 'World';

  console.log(`Hello, ${name}!`);
  return;
};
// [END functions_helloworld_pubsub_node8]

// [START functions_helloworld_storage_node8]
/**
 * Background Cloud Function to be triggered by Cloud Storage.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.helloGCS = (data, context) => {
  const file = data;
  if (file.resourceState === 'not_exists') {
    console.log(`File ${file.name} deleted.`);
  } else if (file.metageneration === '1') {
    // metageneration attribute is updated on metadata changes.
    // on create value is 1
    console.log(`File ${file.name} uploaded.`);
  } else {
    console.log(`File ${file.name} metadata updated.`);
  }
};
// [END functions_helloworld_storage_node8]

// [START functions_helloworld_storage_generic_node8]
/**
 * Generic background Cloud Function to be triggered by Cloud Storage.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.helloGCSGeneric = (data, context) => {
  const file = data;
  console.log(`  Event ${context.eventId}`);
  console.log(`  Event Type: ${context.eventType}`);
  console.log(`  Bucket: ${file.bucket}`);
  console.log(`  File: ${file.name}`);
  console.log(`  Metageneration: ${file.metageneration}`);
  console.log(`  Created: ${file.timeCreated}`);
  console.log(`  Updated: ${file.updated}`);
};
// [END functions_helloworld_storage_generic_node8]

// [START functions_firebase_rtdb_node8]
/**
 * Triggered by a change to a Firebase RTDB reference.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.helloRTDB = (data, context) => {
  const triggerResource = context.resource;

  const pathParams = data.params;
  if (pathParams) {
    console.log(`Parameters:`);
    Object.entries(pathParams).forEach(([param, value]) => {
      console.log(`  ${param}: ${value}`);
    });
  }

  console.log(`Function triggered by change to: ${triggerResource}`);
  console.log(`Admin?: ${!!data.admin}`);
  console.log(`Delta:`);
  console.log(JSON.stringify(data.delta, null, 2));
};
// [END functions_firebase_rtdb_node8]

// [START functions_firebase_firestore_node8]
/**
 * Triggered by a change to a Firestore document.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.helloFirestore = (data, context) => {
  const triggerResource = context.resource;

  console.log(`Function triggered by change to: ${triggerResource}`);
  console.log(`Event type: ${context.eventType}`);

  if (data.oldValue && Object.keys(data.oldValue).length) {
    console.log(`\nOld value:`);
    console.log(JSON.stringify(data.oldValue, null, 2));
  }

  if (data.value && Object.keys(data.value).length) {
    console.log(`\nNew value:`);
    console.log(JSON.stringify(data.value, null, 2));
  }
};
// [END functions_firebase_firestore_node8]

// [START functions_firebase_auth_node8]
/**
 * Triggered by creation or deletion of a Firebase Auth user object.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.helloAuth = (data, context) => {
  try {
    console.log(
      `Function triggered by creation or deletion of user: ${data.uid}`
    );
    console.log(`Created at: ${data.metadata.createdAt}`);

    if (data.email) {
      console.log(`Email: ${data.email}`);
    }
  } catch (err) {
    console.error(err);
  }
};
// [END functions_firebase_auth_node8]

// [START functions_firebase_analytics_node8]
/**
 * Triggered by a Google Analytics for Firebase log event.
 *
 * @param {object} data The event payload.
 * @param {object} context The event metadata.
 */
exports.helloAnalytics = (data, context) => {
  const {resource} = context;
  console.log(`Function triggered by the following event: ${resource}`);

  const [analyticsEvent] = data.eventDim;
  console.log(`Name: ${analyticsEvent.name}`);
  console.log(`Timestamp: ${new Date(analyticsEvent.timestampMicros / 1000)}`);

  const userObj = data.userDim;
  console.log(`Device Model: ${userObj.deviceInfo.deviceModel}`);
  console.log(`Location: ${userObj.geoInfo.city}, ${userObj.geoInfo.country}`);
};
// [END functions_firebase_analytics_node8]

// [START functions_background_promise_node8]
/**
 * Background Cloud Function that returns a Promise. Note that we don't pass
 * a "callback" argument to the function.
 *
 * @param {object} data The Cloud Functions event data.
 * @returns {Promise}
 */
exports.helloPromise = (data) => {
  return fetch(data.endpoint);
};
// [END functions_background_promise_node8]

// [START functions_firebase_reactive_node8]
const Firestore = require('@google-cloud/firestore');

const firestore = new Firestore({
  projectId: process.env.GCP_PROJECT,
});

// Converts strings added to /messages/{pushId}/original to uppercase
exports.makeUpperCase = (data, context) => {
  const {resource} = context;
  const affectedDoc = firestore.doc(resource.split('/documents/')[1]);

  const curValue = data.value.fields.original.stringValue;
  const newValue = curValue.toUpperCase();
  console.log(`Replacing value: ${curValue} --> ${newValue}`);

  return affectedDoc.set({
    original: newValue,
  });
};
// [END functions_firebase_reactive_node8]

// [START functions_firebase_remote_config_node8]
/**
 * Triggered by a change to a Firebase Remote Config value.
 *
 * @param {object} data The Cloud Functions event data.
 */
exports.helloRemoteConfig = (data) => {
  console.log(`Update type: ${data.updateType}`);
  console.log(`Origin: ${data.updateOrigin}`);
  console.log(`Version: ${data.versionNumber}`);
};
// [END functions_firebase_remote_config_node8]

// [START functions_background_async]
/**
 * Background Cloud Function demonstrates use of async/await.
 *
 * @param {object} data The event payload.
 */
exports.helloAsync = async (data) => {
  const result = await fetch('https://www.example.com');
  return result;
};
// [END functions_background_async]
<|endoftext|>


<commit_before>/* Placeholder for phpr().post() */

/*
Proposed syntax 1 (winner):

$(‘#form’).phpr().post(‘blog:on_comment’, { });

$(‘.serialize_everything_inside_me’).phpr().post(‘blog:on_comment’, { });

$.phpr().post(‘blog:on_comment’, { });
$.phpr({override_phpr_options}).post(‘blog:on_comment’).send({override_post_options});
*/

/*
Parameters: {

action: ‘blog:on:comment’,

success: function,

data: { },

fail: function,

done: function,

complete: function,

prepare: function

}

Methods: (# functions provided by $.deferred)

	action(name:String)

	form(selector:String) - (NREQ - passed from framework)

	prepare(callback:Function) - “onBeforePost” equivalent

	update(selector:*, partialName:String) - can be object or called many for multiples

	data(field:*, value:String) - can be object for called many multiples

	getData() - returns serialized and supplied data values

	getForm() - returns form object

	queue(value:Boolean) - allow this request to queue if locked

	#done(callback:Function) - Gets a jQuery promise, passing callback to success

	#fail(callback:Function)

	#always(callback:Function) - Fires if success or fail

	complete(callback:Function) - Fires after partials update

	loadingIndicator(param:Bool|Obj)

	post(params:Object = {})

	put(params:Object = {})

	delete(params:Object = {}) Note: conflict < es5.

	animation(callback:Function<element:jQuery, html:String>) - Allow custom handler to show the new content returned via AJAX

	lock(value:Boolean) - Blocks the UI from multiple requests. Sets busy=true.

	promise - Returns a jQuery promise extended with PHPR

*/

(function($) {

	PHPR.post = function(handler, options) {

		var o = {},
			_deferred = $.Deferred(),
			_handler = handler,
			_options = options,
			_data = {},
			_form = null;

		o.requestObj = null;

		//
		// Services
		//

		o.success = function(func) {
			_deferred.done(func);
			return this;
		}

		o.error = function(func) {
			_deferred.fail(func);
			return this;
		}

		o.complete = function(func) {
			_deferred.always(func);
			return this;
		}

		o.afterUpdate = function(func) {
			_options.afterUpdate = func;
			return this;
		}

		o.handler = o.action = function(value) {
			_handler = handler;
			return this;
		}

		o.confirm = function(value) {
			_options.confirm = value;
			return this;
		}

		o.alert = function(value) {
			_options.alert = value;
			return this;
		}

		o.prepare = function(value) {
			_options.prepare = value;
			return this;
		}

		o.update = function(element, partial) {
			if (partial)
				_options.update[element] = partial;
			else
				_options.update = element;
			return this;
		}

		o.data = function(field, value) {
			if (typeof field == "object")
				_options.data = field;
			else if (typeof value != "undefined")
				_options.data[field] = value;
			return this;
		}

		o.queue = function(value) {
			_options.lock = !value;
			return this;
		}

		//
		// Static
		//

		o.handleError = function(message) {
			alert(message);
		}

		//
		// Options
		//

		o.setOption = function(option, value) {
			_options[option] = value;
			return this;
		}

		o.getOption = function(option) {
			return _options[option];
		}

		o.getDefaultOptions = function() {
			return {
				action: 'core:on_null',
				data: {},
				update: {},
				done: null,
				fail: null,
				afterUpdate: null,
				always: null,
				prepare: null,
				selectorMode: true,
				lock: true,
				alert: null,
				confirm: null,
				animation: function(element, html) {
					element.html(html);
				}
			};
		}

		o.buildOptions = function() {
			var options = $.extend(true, o.getDefaultOptions(), _options);

			if (_handler)
				options.action = _handler;

			options.data = (_form)
				? $.extend(true, _serialize_params(_form), _data)
				: _data;

			return _options = options;
		}

		//
		// Form Element
		//

		o.setFormElement = function(form) {
			form = (!form) ? jQuery('<form></form>') : form;
			form = (form instanceof jQuery) ? form : jQuery(form);
			form = (form.is('form')) ? form : form.closest('form');
			form = (form.attr('id')) ? jQuery('form#'+form.attr('id')) : form.attr('id', 'form_element');
			_form = form;
			return this;
		}

		o.getFormElement = function() {
			return _form;
		}

		o.getFormUrl = function() {
			return (_form) ? _form.attr('action') : window.location.href;
		}

		//
		// Send request
		//

		o.send = function() {
			var options = o.buildOptions();

			if (options.prepare && !context.prepare())
				return;

			if (options.alert)
				return alert(options.alert);

			if (options.confirm && !confirm(options.confirm))
				return;

			// Show loading indicator
			if (PHPR.indicator)
				PHPR.indicator.showIndicator();

			// Prepare the request
			o.requestObj = new PHPR.request(o.getFormUrl(), _handler, options);

			// On Complete
			o.requestObj.always(function(requestObj){

				// Hide loading indicator
				if (PHPR.indicator)
					PHPR.indicator.hideIndicator();

				options.always && options.always(requestObj);
			});

			// On Success
			o.requestObj.done(function(requestObj){
				o.updatePartials();
				options.done && options.done(requestObj);
			});

			// On Failure
			o.requestObj.fail(function(requestObj){
				if (options.fail && !options.fail(requestObj))
					return;

				if (requestObj.error)
					o.handleError(requestObj.error);
			});

			// Execute the request
			return o.requestObj.send();
		}

		//
		// Update partials
		//

		o.updatePartials = function() {
			var oHtml = o.requestObj.html,
				pattern = />>[^<>]*<</g,
				patches = oHtml.match(pattern) || [],
				updateElements = [];

			for (var i = 0, l = patches.length; i < l; ++i) {
				var index = oHtml.indexOf(patches[i]) + patches[i].length;

				var html = (i < patches.length-1)
					? oHtml.slice(index, oHtml.indexOf(patches[i+1]))
					: oHtml.slice(index);

				var id = patches[i].slice(2, patches[i].length-2);

				if (id) {
					var element;

					if (_options.selectorMode)
						element = $(id);
					else
						element = $('#' + id);

					if (!_options.animation(element, html))
						element.html(html);

					updateElements.push(id);
				}
			}

			// If update element is a string, set update element to self.text
			_options.update && typeof(_options.update) === 'string' && $('#' + _options.update).html(self.text);

			$.each(updateElements, function(k, v) {
				$(window).trigger('onAfterAjaxUpdate', v);
			});

			_options.afterUpdate && _options.afterUpdate();
		}

		//
		// Internals
		//

		var _serialize_params = function(element) {
			var params = {};

			$.each(element.serializeArray(), function(index, value) {
				if (value.name.substr(value.name.length - 2, 2) === '[]') {
					var name = value.name.substr(0, value.name.length - 2);

					if (!params[name]) {
						params[name] = [];
					}

					params[name].push(value.value);
				}
				else {
					params[value.name] = value.value;
				}
			});

			return params;
		}

		// Promote the post object with a promise
		return _deferred.promise(o);
	}

})(jQuery);
<commit_msg>Allow post obj to be overridden by the user<commit_after>/* Placeholder for phpr().post() */

/*
Proposed syntax 1 (winner):

$(‘#form’).phpr().post(‘blog:on_comment’, { });

$(‘.serialize_everything_inside_me’).phpr().post(‘blog:on_comment’, { });

$.phpr().post(‘blog:on_comment’, { });
$.phpr({override_phpr_options}).post(‘blog:on_comment’).send({override_post_options});
*/

/*
Parameters: {

action: ‘blog:on:comment’,

success: function,

data: { },

fail: function,

done: function,

complete: function,

prepare: function

}

Methods: (# functions provided by $.deferred)

	action(name:String)

	form(selector:String) - (NREQ - passed from framework)

	prepare(callback:Function) - “onBeforePost” equivalent

	update(selector:*, partialName:String) - can be object or called many for multiples

	data(field:*, value:String) - can be object for called many multiples

	getData() - returns serialized and supplied data values

	getForm() - returns form object

	queue(value:Boolean) - allow this request to queue if locked

	#done(callback:Function) - Gets a jQuery promise, passing callback to success

	#fail(callback:Function)

	#always(callback:Function) - Fires if success or fail

	complete(callback:Function) - Fires after partials update

	loadingIndicator(param:Bool|Obj)

	post(params:Object = {})

	put(params:Object = {})

	delete(params:Object = {}) Note: conflict < es5.

	animation(callback:Function<element:jQuery, html:String>) - Allow custom handler to show the new content returned via AJAX

	lock(value:Boolean) - Blocks the UI from multiple requests. Sets busy=true.

	promise - Returns a jQuery promise extended with PHPR

*/

(function($) {

	PHPR.post = function(handler, options) {

		var o = {},
			_deferred = $.Deferred(),
			_handler = handler,
			_options = options || {},
			_data = {},
			_form = null;

		o.requestObj = null;

		//
		// Services
		//

		o.success = function(func) {
			_deferred.done(func);
			return this;
		}

		o.error = function(func) {
			_deferred.fail(func);
			return this;
		}

		o.complete = function(func) {
			_deferred.always(func);
			return this;
		}

		o.afterUpdate = function(func) {
			_options.afterUpdate = func;
			return this;
		}

		o.handler = o.action = function(value) {
			_handler = handler;
			return this;
		}

		o.confirm = function(value) {
			_options.confirm = value;
			return this;
		}

		o.alert = function(value) {
			_options.alert = value;
			return this;
		}

		o.prepare = function(value) {
			_options.prepare = value;
			return this;
		}

		o.update = function(element, partial) {
			if (partial)
				_options.update[element] = partial;
			else
				_options.update = element;
			return this;
		}

		o.data = function(field, value) {
			if (typeof field == "object")
				_data = field;
			else if (typeof value != "undefined")
				_data[field] = value;
			return this;
		}

		o.queue = function(value) {
			_options.lock = !value;
			return this;
		}

		//
		// Static
		//

		o.popupError = function(requestObj) {
			alert(requestObj.error);
		}

		//
		// Options
		//

		o.getDefaultOptions = function() {
			return {
				action: 'core:on_null',
				data: {},
				update: {},
				done: null,
				fail: null,
				afterUpdate: null,
				always: null,
				prepare: null,
				selectorMode: true,
				lock: true,
				alert: null,
				confirm: null,
				animation: function(element, html) {
					element.html(html);
				}
			};
		}

		o.setOption = function(option, value) {
			_options[option] = value;
			return this;
		}

		o.getOption = function(option) {
			return _options[option];
		}

		o.buildOptions = function() {
			var options = $.extend(true, o.getDefaultOptions(), _options);

			if (_handler)
				options.action = _handler;

			options.data = (_form)
				? $.extend(true, _serialize_params(_form), _data)
				: _data;

			return _options = options;
		}

		//
		// Form Element
		//

		o.setFormElement = function(form) {
			form = (!form) ? jQuery('<form></form>') : form;
			form = (form instanceof jQuery) ? form : jQuery(form);
			form = (form.is('form')) ? form : form.closest('form');
			form = (form.attr('id')) ? jQuery('form#'+form.attr('id')) : form.attr('id', 'form_element');
			_form = form;
			return this;
		}

		o.getFormElement = function() {
			return _form;
		}

		o.getFormUrl = function() {
			return (_form) ? _form.attr('action') : window.location.href;
		}

		//
		// Send request
		//

		o.send = function() {
			var options = o.buildOptions();

			if (options.prepare && !context.prepare())
				return;

			if (options.alert)
				return alert(options.alert);

			if (options.confirm && !confirm(options.confirm))
				return;

			// Show loading indicator
			if (PHPR.indicator)
				PHPR.indicator.showIndicator();

			// Prepare the request
			o.requestObj = PHPR.request(o.getFormUrl(), _handler, options);

			// On Complete
			o.requestObj.always(function(requestObj){

				// Hide loading indicator
				if (PHPR.indicator)
					PHPR.indicator.hideIndicator();

				options.always && options.always(requestObj);
			});

			// On Success
			o.requestObj.done(function(requestObj){
				o.updatePartials();
				options.done && options.done(requestObj);
			});

			// On Failure
			o.requestObj.fail(function(requestObj){
				if (options.fail && !options.fail(requestObj))
					return;

				if (requestObj.error)
					o.popupError(requestObj);
			});

			// Execute the request
			return o.requestObj.send();
		}

		//
		// Update partials
		//

		o.updatePartials = function() {
			var oHtml = o.requestObj.html,
				pattern = />>[^<>]*<</g,
				patches = oHtml.match(pattern) || [],
				updateElements = [];

			for (var i = 0, l = patches.length; i < l; ++i) {
				var index = oHtml.indexOf(patches[i]) + patches[i].length;

				var html = (i < patches.length-1)
					? oHtml.slice(index, oHtml.indexOf(patches[i+1]))
					: oHtml.slice(index);

				var id = patches[i].slice(2, patches[i].length-2);

				if (id) {
					var element;

					if (_options.selectorMode)
						element = $(id);
					else
						element = $('#' + id);

					if (!_options.animation(element, html))
						element.html(html);

					updateElements.push(id);
				}
			}

			// If update element is a string, set update element to self.text
			_options.update && typeof(_options.update) === 'string' && $('#' + _options.update).html(self.text);

			$.each(updateElements, function(k, v) {
				$(window).trigger('onAfterAjaxUpdate', v);
			});

			_options.afterUpdate && _options.afterUpdate();
		}

		//
		// Internals
		//

		var _serialize_params = function(element) {
			var params = {};

			$.each(element.serializeArray(), function(index, value) {
				if (value.name.substr(value.name.length - 2, 2) === '[]') {
					var name = value.name.substr(0, value.name.length - 2);

					if (!params[name]) {
						params[name] = [];
					}

					params[name].push(value.value);
				}
				else {
					params[value.name] = value.value;
				}
			});

			return params;
		}

		// Extend the post object with DOM
		o = $.extend(true, o, PHPR.post || {});

		// Promote the post object with a promise
		return _deferred.promise(o);
	}

})(jQuery);
<|endoftext|>


<commit_before>function moveSelectAllCheckbox(bulk, selectAllState) {
  const $selectAll = $('#select-all-products').parent()[0].innerHTML;
  const $headerContainer = $('thead .bulk-checkbox');
  const $actionBarContainer = $('.data-table-bulk-actions__select-all');
  if (bulk) {
    $headerContainer.html('');
    $actionBarContainer[0].innerHTML = $selectAll;
  } else {
    $actionBarContainer.html('');
    $headerContainer[0].innerHTML = $selectAll;
  }
  $actionBarContainer.find('#select-all-products').prop('checked', selectAllState);
  $('.select-all').on('change', onSelectAll);
}

function updateSelectedItemsText (selectAllState) {
  if ([true, false].indexOf(selectAllState) === -1) {
    selectAllState = false;
  }
  const count = $('.select-item:checked').length - $('#select-all-products:checked').length;
  const $counterTextNode = $('.data-table-bulk-actions__selected-items');
  const $header = $('.data-table-bulk-actions');
  const counterText = ngettext('item selected', 'items selected', count);

  if (!count) {
    $header.addClass('single').removeClass('bulk');
    moveSelectAllCheckbox(false, selectAllState);
  } else {
    $counterTextNode.html(`${count} ${counterText}`);
    $header.addClass('bulk').removeClass('single');
    moveSelectAllCheckbox(true, selectAllState);
  }
}

function onSelectAll (e) {
  const $target = $(e.currentTarget);
  const $targetForm = $target.parents('form');
  const $items = $targetForm.find('.switch-actions');
  $items.prop('checked', $target[0].checked);
  console.log($target[0].checked);
  $target.off('change');
  updateSelectedItemsText($target[0].checked);
}

function onSubmit (e) {
  e.preventDefault();
  const a = $(e.currentTarget);
  $('#bulk-action').val(a.attr('data-action'));
  $('#bulk-actions-form').submit();
}

// -----

updateSelectedItemsText();
$('.select-all').on('click', onSelectAll);
$('.select-item').on('change', updateSelectedItemsText);
$('.bulk-actions a').on('click', onSubmit);
<commit_msg>Make action bar functional<commit_after>function moveSelectAllCheckbox(bulk, selectAllState) {
  const $selectAll = $('#select-all-products').parent()[0].innerHTML;
  const $headerContainer = $('thead .bulk-checkbox');
  const $actionBarContainer = $('.data-table-bulk-actions__select-all');
  if (bulk) {
    $headerContainer.html('');
    $actionBarContainer[0].innerHTML = $selectAll;
  } else {
    $actionBarContainer.html('');
    $headerContainer[0].innerHTML = $selectAll;
  }
  $actionBarContainer.find('#select-all-products').prop('checked', selectAllState);
  $('.select-all').on('change', onSelectAll);
}

function updateSelectedItemsText (selectAllState) {
  if ([true, false].indexOf(selectAllState) === -1) {
    selectAllState = false;
  }
  const count = $('.select-item:checked').length - $('#select-all-products:checked').length;
  const $counterTextNode = $('.data-table-bulk-actions__selected-items');
  const $header = $('.data-table-bulk-actions');
  const counterText = ngettext('item selected', 'items selected', count);

  if (!count) {
    $header.addClass('single').removeClass('bulk');
    moveSelectAllCheckbox(false, selectAllState);
  } else {
    $counterTextNode.html(`${count} ${counterText}`);
    $header.addClass('bulk').removeClass('single');
    moveSelectAllCheckbox(true, selectAllState);
  }
}

function onSelectAll (e) {
  const $target = $(e.currentTarget);
  const $targetForm = $target.parents('form');
  const $items = $targetForm.find('.switch-actions');
  $items.prop('checked', $target[0].checked);
  console.log($target[0].checked);
  $target.off('change');
  updateSelectedItemsText($target[0].checked);
}

function onSubmit (e) {
  e.preventDefault();
  const a = $(e.currentTarget);
  $('#bulk-action').val(a.attr('data-action'));
  $('#bulk-actions-form').submit();
}

// -----

updateSelectedItemsText();
$('.select-all').on('click', onSelectAll);
$('.select-item').on('change', updateSelectedItemsText);
$('.data-table-bulk-actions__action-choice a').on('click', onSubmit);
$('.data-table-bulk-actions__dropdown-container .dropdown-content a').on('click', onSubmit);
<|endoftext|>


<commit_before>var _ = require('lodash');
var UAParser = require('ua-parser-js');

module.exports = function(app) {
    /**
     * На основе http://matthewhudson.me/projects/device.js/ .
     */

    /**
     * @param {string} userAgent
     * @returns {string}
     */
    function getPlatform(userAgent) {
        userAgent = userAgent.toLowerCase();

        function find(needle) {
            return userAgent.indexOf(needle) > -1;
        }

        var iPhone = find('iphone');
        var iPod = find('ipod');
        var iPad = find('ipad');
        var android = find('android');
        var androidPhone = android && find('mobile');
        var androidTablet = android && !androidPhone;
        var windows = find('windows');
        var windowsPhone = windows && find('phone');
        var windowsTablet = windows && !windowsPhone && find('touch');
        var blackberry = find('blackberry') || find('bb10') || find('rim');
        var blackberryPhone = blackberry && !find('tablet');
        var blackberryTablet = blackberry && !blackberryPhone;
        var tizen = find('tizen');
        var tizenPhone = tizen && find('mobile');
        var tizenTablet = tizen && !tizenPhone;
        var fxOS = (find('(mobile;') || find('(tablet;')) && find('; rv:');
        var fxOSPhone = fxOS && find('mobile');
        var fxOSTablet = fxOS && find('tablet');
        var meeGo = find('meego');

        if (iPhone || iPod || androidPhone || windowsPhone || blackberryPhone || tizenPhone || fxOSPhone || meeGo) {
            return 'phone';
        }
        if (iPad || androidTablet || windowsTablet || blackberryTablet || tizenTablet || fxOSTablet) {
            return 'tablet';
        }
        return 'desktop';
    }

    /**
     * @private
     * @returns {boolean}
     */
    function museum(ua) { // @TODO вынести в конфиг
        var browser = ua.browser,
            os = ua.os;

        return (browser.name == 'Chrome' && browser.major < 21) ||
            (browser.name == 'IE' && browser.major < 9) ||
            (browser.name == 'Firefox' && browser.major < 29) ||
            (browser.name == 'Mozilla') ||
            (os.name == 'Windows' && os.version == '95') || // Если поставит нормальный браузер? Вы издеваетесь?
            (browser.name == 'Opera' && browser.major < 12) ||
            (browser.name == 'Opera Mini') ||
            (browser.name == 'Safari' && os.name == 'Android' && browser.major < 4 && parseInt(os.version, 10) < 4) ||
            (browser.name == 'Mobile Safari' && os.name == 'Android' && parseInt(os.version, 10) < 4) ||
            (browser.name == 'Safari' && os.name == 'Android' && parseInt(os.version, 10) < 4) ||
            (os.name == 'iOS' && browser.major < 7) ||
            (os.name == 'Mac OS X' && browser.name == 'Safari' && browser.major < 6) || // Олдовая сафари
            (os.name == 'Windows' && browser.name == 'Safari');
    }

    /**
     * @returns {Object} Объект, по которому можно определить браузер и операционку.
     */
    return function(userAgentString) {
        // Выставляем версию браузера.
        var parser = new UAParser();

        userAgentString = userAgentString || this.registry.hash('ua').ua || '';
        parser.setUA(userAgentString);

        var result = parser.getResult();
        var osName = (result.os && result.os.name || '').toLowerCase().replace(/ /g, '');

        var platform = getPlatform(userAgentString);
        var isDesktop = platform == 'desktop';
        var isPhone = platform == 'phone';
        var isTablet = platform == 'tablet';
        var isMobile = isPhone || isTablet;

        // Если мы в ИЕ, то этот флаг становится функцией, который возвращает соответствие версии ИЕ
        var isIE = function(version) {
            return result.browser.name == 'IE' && (version ? version == result.browser.major : true);
        };

        _.extend(result, {
            isMuseum: museum(result),
            isDesktop: isDesktop,
            isPhone: isPhone,
            isTablet: isTablet,
            isMobile: isMobile,
            isIE: isIE,
            osName: osName
        });

        return result;
    };
};
<commit_msg>fix registry usage in plugins/ua<commit_after>var _ = require('lodash');
var UAParser = require('ua-parser-js');

module.exports = function(app) {
    /**
     * На основе http://matthewhudson.me/projects/device.js/ .
     */

    /**
     * @param {string} userAgent
     * @returns {string}
     */
    function getPlatform(userAgent) {
        userAgent = userAgent.toLowerCase();

        function find(needle) {
            return userAgent.indexOf(needle) > -1;
        }

        var iPhone = find('iphone');
        var iPod = find('ipod');
        var iPad = find('ipad');
        var android = find('android');
        var androidPhone = android && find('mobile');
        var androidTablet = android && !androidPhone;
        var windows = find('windows');
        var windowsPhone = windows && find('phone');
        var windowsTablet = windows && !windowsPhone && find('touch');
        var blackberry = find('blackberry') || find('bb10') || find('rim');
        var blackberryPhone = blackberry && !find('tablet');
        var blackberryTablet = blackberry && !blackberryPhone;
        var tizen = find('tizen');
        var tizenPhone = tizen && find('mobile');
        var tizenTablet = tizen && !tizenPhone;
        var fxOS = (find('(mobile;') || find('(tablet;')) && find('; rv:');
        var fxOSPhone = fxOS && find('mobile');
        var fxOSTablet = fxOS && find('tablet');
        var meeGo = find('meego');

        if (iPhone || iPod || androidPhone || windowsPhone || blackberryPhone || tizenPhone || fxOSPhone || meeGo) {
            return 'phone';
        }
        if (iPad || androidTablet || windowsTablet || blackberryTablet || tizenTablet || fxOSTablet) {
            return 'tablet';
        }
        return 'desktop';
    }

    /**
     * @private
     * @returns {boolean}
     */
    function museum(ua) { // @TODO вынести в конфиг
        var browser = ua.browser,
            os = ua.os;

        return (browser.name == 'Chrome' && browser.major < 21) ||
            (browser.name == 'IE' && browser.major < 9) ||
            (browser.name == 'Firefox' && browser.major < 29) ||
            (browser.name == 'Mozilla') ||
            (os.name == 'Windows' && os.version == '95') || // Если поставит нормальный браузер? Вы издеваетесь?
            (browser.name == 'Opera' && browser.major < 12) ||
            (browser.name == 'Opera Mini') ||
            (browser.name == 'Safari' && os.name == 'Android' && browser.major < 4 && parseInt(os.version, 10) < 4) ||
            (browser.name == 'Mobile Safari' && os.name == 'Android' && parseInt(os.version, 10) < 4) ||
            (browser.name == 'Safari' && os.name == 'Android' && parseInt(os.version, 10) < 4) ||
            (os.name == 'iOS' && browser.major < 7) ||
            (os.name == 'Mac OS X' && browser.name == 'Safari' && browser.major < 6) || // Олдовая сафари
            (os.name == 'Windows' && browser.name == 'Safari');
    }

    /**
     * @returns {Object} Объект, по которому можно определить браузер и операционку.
     */
    function getUA(userAgentString) {
        // Выставляем версию браузера.
        var parser = new UAParser();

        userAgentString = userAgentString || app.registry.get('ua').ua || false;
        if (userAgentString) {
            parser.setUA(userAgentString);
        }

        var result = parser.getResult();
        var osName = (result.os && result.os.name || '').toLowerCase().replace(/ /g, '');

        var platform = getPlatform(userAgentString);
        var isDesktop = platform == 'desktop';
        var isPhone = platform == 'phone';
        var isTablet = platform == 'tablet';
        var isMobile = isPhone || isTablet;

        // Если мы в ИЕ, то этот флаг становится функцией, который возвращает соответствие версии ИЕ
        var isIE = function(version) {
            return result.browser.name == 'IE' && (version ? version == result.browser.major : true);
        };

        _.extend(result, {
            isMuseum: museum(result),
            isDesktop: isDesktop,
            isPhone: isPhone,
            isTablet: isTablet,
            isMobile: isMobile,
            isIE: isIE,
            osName: osName
        });

        return result;
    }

    var cache = {};

    return function(userAgentString) {
        if (!cache[userAgentString]) {
            cache[userAgentString] = getUA(userAgentString);
        }
        return cache[userAgentString];
    };
};
<|endoftext|>


<commit_before>/* vim:set ts=2 sw=2 sts=2 expandtab */
/*jshint asi: true undef: true es5: true node: true browser: true devel: true
         forin: true latedef: false globalstrict: true*/

"use strict";

var reduce = require("reducers/reduce")

function writer(swap, close, open) {
  /**
  Writer allows you to create write functions like this one:
  function html(tagName) {
    return writer(function swap(element, state) {
      element.textContent = state
    }, function close(element) {
      if (element.parentElement)
      element.parentElement.removeChild(element)
    }, function open(state) {
      return document.createElement(tagName)
    })
  }
  var h1 = html("h1")
  var input = channel()

  var element = h1(input)
  element.outerHTML // =>

  enqueue(channel, "hello")
  element.outerHTML // =>
hello

  **/

  return function write(input, output) {
    output = output || open()
    reduce(input, function(state, update) {
      if (update === null) close(output)
      else swap(output, update)
      return update
    })
    return output
  }
}

module.exports = reduce
<commit_msg>Fix type error causing reduce to be exported instead of writer.<commit_after>/* vim:set ts=2 sw=2 sts=2 expandtab */
/*jshint asi: true undef: true es5: true node: true browser: true devel: true
         forin: true latedef: false globalstrict: true*/

"use strict";

var reduce = require("reducers/reduce")

function writer(swap, close, open) {
  /**
  Writer allows you to create write functions like this one:
  function html(tagName) {
    return writer(function swap(element, state) {
      element.textContent = state
    }, function close(element) {
      if (element.parentElement)
      element.parentElement.removeChild(element)
    }, function open(state) {
      return document.createElement(tagName)
    })
  }
  var h1 = html("h1")
  var input = channel()

  var element = h1(input)
  element.outerHTML // =>

  enqueue(channel, "hello")
  element.outerHTML // =>
hello

  **/

  return function write(input, output) {
    output = output || open()
    reduce(input, function(state, update) {
      if (update === null) close(output)
      else swap(output, update)
      return update
    })
    return output
  }
}

module.exports = writer
<|endoftext|>


<commit_before>var Tag = Backbone.Model.extend();

var TagItemView = Backbone.View.extend({
  className: "tag-editor-tag",
  template: _.template('
<%= name %>
' +
      'x'),
  events: {
    'click .tag-editor-delete': 'deleteTag'
  },
  initialize: function() {
    this.listenTo(this.model, 'change', this.render);
  },
  render: function() {
    var html = this.template(this.model.toJSON());
    this.$el.html(html);
    return this;
  },
  deleteTag: function() {
    this.model.destroy();
  }
});

var Tags = Backbone.Collection.extend({
  model: Tag
});

var TagEditorView = Backbone.View.extend({
  tagRegex: /^(.*)[, ]+$/,
  sepRegex: /[, ]+/m,
  initialize: function(options) {
    this.width = options.width;
    this.itemViews = _.map(this.collection.models, function(model) {
      return new TagItemView({model: model});
    });
    this.tagInput = Backbone.$('<input class="tag-editor-input">').css('width', 0);
    this.tagMeasure = (new TagItemView({model: new Tag({name: ""})})).render().$el;
    this.tagMeasure.css({position: 'absolute', left: "-999px"});
    this.textMeasure = this.tagMeasure.find('.tag-editor-text');
    this.listenTo(this.collection, 'add', this.onAddModel);
    this.listenTo(this.collection, 'remove', this.onRemoveModel);
  },
  className: 'tag-editor-field',
  events: {
    click: 'onClick',
    'focus .tag-editor-input': 'onInputFocus',
    'blur .tag-editor-input': 'onInputBlur',
    'keydown .tag-editor-input': 'onInputKeydown',
    'keyup .tag-editor-input': 'onInputKeyup'
  },
  onClick: function() {
    this.tagInput.focus();
  },
  _indexOfTag: function(tag) {
    var i, models = this.collection.models, l = models.length, model;
    for (i = 0; i < l; i++) {
      model = models[i];
      if (model.get('name') === tag) {
        return i;
      }
    }
    return -1;
  },
  onAddModel: function(model, collection, options) {
    this.itemViews.splice(options.at, 0, new TagItemView({model: model}));
    this.render();
    this.tagInput.focus();
  },
  onRemoveModel: function(model, collection, options) {
    this.itemViews.splice(options.index, 1);
    this.render();
  },
  onInputFocus: function() {
    this.tagInput.css('font', this.textMeasure.css('font'));
  },
  onInputBlur: function() {
    var val = this.tagInput.val();
    this._insertTag(val.replace(this.sepRegex, ''));
  },
  onInputKeydown: function(e) {
    var val = this.tagInput.val(), collection = this.collection;
    if (!val && e.which == 8 /* Backspace */ && collection.length) {
      e.preventDefault();
      collection.pop();
      this.tagInput.focus();
    }
  },
  onInputKeyup: function() {
    var val = this.tagInput.val(), matches, that;
    if (val) {
      matches = this.tagRegex.exec(val);
      if (matches) {
        // We need to split tag text with separators
        // because text pasted from clipboard may contain those.
        that = this;
        _.each(matches[1].split(this.sepRegex), function(tag) {
          that._insertTag(tag);
        });
      } else {
        this._adjustInputWidth(val);
      }
    }
  },
  _adjustInputWidth: function(val) {
    var that = this;
    // To avoid juggling of input widths, we measure text width
    // with two more characters.  We use 'W' here because it is
    // a wide character.
    this.textMeasure.text(val + 'WW');
    setTimeout(function() {
      that.tagInput.css('width', that.textMeasure.width());
    }, 50);
  },
  _insertTag: function(tag) {
    if (tag && !this.collection.where({name: tag}, true)) {
      this.collection.push(new Tag({name: tag}));
    }
    this.tagInput.val('');
    this._adjustInputWidth('');
  },
  render: function() {
    var $el = this.$el;
    $el.empty();
    $el.append(this.tagMeasure);
    _(this.itemViews).each(function(itemView) {
      $el.append(itemView.render().el);
    });
    $el.append(this.tagInput);
    $el.css('width', this.width);
    this._adjustInputWidth('');
    return this;
  }
});
<commit_msg>Fix the bug in the previous commit<commit_after>var Tag = Backbone.Model.extend();

var TagItemView = Backbone.View.extend({
  className: "tag-editor-tag",
  template: _.template('
<%= name %>
' +
      'x'),
  events: {
    'click .tag-editor-delete': 'deleteTag'
  },
  initialize: function() {
    this.listenTo(this.model, 'change', this.render);
    this.listenTo(this.model, 'destroy', this.remove);
  },
  render: function() {
    var html = this.template(this.model.toJSON());
    this.$el.html(html);
    return this;
  },
  deleteTag: function(e) {
    this.model.destroy();
  }
});

var Tags = Backbone.Collection.extend({
  model: Tag
});

var TagEditorView = Backbone.View.extend({
  tagRegex: /^(.*)[, ]+$/,
  sepRegex: /[, ]+/m,
  initialize: function(options) {
    this.width = options.width;
    this.itemViews = _.map(this.collection.models, function(model) {
      return new TagItemView({model: model});
    });
    this.tagInput = Backbone.$('<input class="tag-editor-input">').css('width', 0);
    this.tagMeasure = (new TagItemView({model: new Tag({name: ""})})).render().$el;
    this.tagMeasure.css({position: 'absolute', left: "-999px"});
    this.textMeasure = this.tagMeasure.find('.tag-editor-text');
    this.listenTo(this.collection, 'add', this.onAddModel);
    this.listenTo(this.collection, 'remove', this.onRemoveModel);
  },
  className: 'tag-editor-field',
  events: {
    click: 'onClick',
    'focus .tag-editor-input': 'onInputFocus',
    'blur .tag-editor-input': 'onInputBlur',
    'keydown .tag-editor-input': 'onInputKeydown',
    'keyup .tag-editor-input': 'onInputKeyup'
  },
  onClick: function() {
    this.tagInput.focus();
  },
  _indexOfTag: function(tag) {
    var i, models = this.collection.models, l = models.length, model;
    for (i = 0; i < l; i++) {
      model = models[i];
      if (model.get('name') === tag) {
        return i;
      }
    }
    return -1;
  },
  onAddModel: function(model, collection, options) {
    this.$el.children('div:nth-child(' + (options.at + 1) + ')').after(
        new TagItemView({model: model}).render().el);
  },
  onRemoveModel: function(model, collection, options) {
    this.itemViews.splice(options.index, 1);
  },
  onInputFocus: function() {
    this.tagInput.css('font', this.textMeasure.css('font'));
  },
  onInputBlur: function() {
    var val = this.tagInput.val();
    this._insertTag(val.replace(this.sepRegex, ''));
  },
  onInputKeydown: function(e) {
    var val = this.tagInput.val(), collection = this.collection;
    if (!val && e.which == 8 /* Backspace */ && collection.length) {
      e.preventDefault();
      collection.pop().destroy();
      this.tagInput.focus();
    }
  },
  onInputKeyup: function() {
    var val = this.tagInput.val(), matches, that;
    if (val) {
      matches = this.tagRegex.exec(val);
      if (matches) {
        // We need to split tag text with separators
        // because text pasted from clipboard may contain those.
        that = this;
        _.each(matches[1].split(this.sepRegex), function(tag) {
          that._insertTag(tag);
        });
      } else {
        this._adjustInputWidth(val);
      }
    }
  },
  _adjustInputWidth: function(val) {
    var that = this;
    // To avoid juggling of input widths, we measure text width
    // with two more characters.  We use 'W' here because it is
    // a wide character.
    this.textMeasure.text(val + 'WW');
    setTimeout(function() {
      that.tagInput.css('width', that.textMeasure.width());
    }, 50);
  },
  _insertTag: function(tag) {
    if (tag && !this.collection.where({name: tag}, true)) {
      this.collection.push(new Tag({name: tag}));
    }
    this.tagInput.val('');
    this._adjustInputWidth('');
  },
  render: function() {
    var $el = this.$el;
    $el.empty();
    $el.append(this.tagMeasure);
    _(this.itemViews).each(function(itemView) {
      $el.append(itemView.render().el);
    });
    $el.append(this.tagInput);
    $el.css('width', this.width);
    this._adjustInputWidth('');
    return this;
  }
});
<|endoftext|>


<commit_before>// Copyright 2014-2015, University of Colorado Boulder

/**
 * Base class for button models, which describe the behavior of buttons when users interact with them.  Property values
 * are set by an associated listener, see ButtonListener for details.
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var PropertySet = require( 'AXON/PropertySet' );
  var sun = require( 'SUN/sun' );

  /**
   * @param {Object} [options]
   * @constructor
   */
  function ButtonModel( options ) {

    options = _.extend( {
      // {function} called on pointer down
      startCallback: function() {},
      // {function} called on pointer up, @param {boolean} over - indicates whether the pointer was released over the button
      endCallback: function( over ) {},
      // {boolean} is the button enabled?
      enabled: true
    }, options );

    var self = this;

    PropertySet.call( this, {
      over: false,  // @public - Is the pointer over the button?
      down: false, // @public - Is the pointer down?
      enabled: options.enabled  // @public - Is the button enabled?
    }, options );

    // startCallback on pointer down, endCallback on pointer up. lazyLink so they aren't called immediately.
    this.property( 'down' ).lazyLink( function( down ) {
      if ( down ) {
        options.startCallback();
      }
      else {
        options.endCallback( self.over );
      }
    } );
  }

  sun.register( 'ButtonModel', ButtonModel );

  return inherit( PropertySet, ButtonModel );
} );<commit_msg>ButtonModel should not pass options to PropertySet, https://github.com/phetsims/phet-io/issues/661<commit_after>// Copyright 2014-2015, University of Colorado Boulder

/**
 * Base class for button models, which describe the behavior of buttons when users interact with them.  Property values
 * are set by an associated listener, see ButtonListener for details.
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var PropertySet = require( 'AXON/PropertySet' );
  var sun = require( 'SUN/sun' );

  /**
   * @param {Object} [options]
   * @constructor
   */
  function ButtonModel( options ) {

    options = _.extend( {
      // {function} called on pointer down
      startCallback: function() {},
      // {function} called on pointer up, @param {boolean} over - indicates whether the pointer was released over the button
      endCallback: function( over ) {},
      // {boolean} is the button enabled?
      enabled: true
    }, options );

    var self = this;

    PropertySet.call( this, {
      over: false,  // @public - Is the pointer over the button?
      down: false, // @public - Is the pointer down?
      enabled: options.enabled  // @public - Is the button enabled?
    } );

    // startCallback on pointer down, endCallback on pointer up. lazyLink so they aren't called immediately.
    this.property( 'down' ).lazyLink( function( down ) {
      if ( down ) {
        options.startCallback();
      }
      else {
        options.endCallback( self.over );
      }
    } );
  }

  sun.register( 'ButtonModel', ButtonModel );

  return inherit( PropertySet, ButtonModel );
} );<|endoftext|>


<commit_before>var project_title = 'Terremoto Centro Italia';
var project_subtitle = 'Le immagini di più di un anno';
var images = ['27FW98irrFbbWI_CGgCebQ','bCd7O6PhM8BABuVB-q340A','1d70jY76gxQuKvQcQUzErw','8oI1aWlduJT7WcH0tdLV-g','bZXIpYhlkCOIbL4Oil3yhQ'];
var titles = ['L'Aquila 1','L'Aquila 2','L'Aquila 3','Arquata del Tronto 1','Arquata del Tronto 2'];
var content = ['','','','',''];
var xcoords = ['','','','',''];
var ycoords = ['','','','',''];
<commit_msg>Fix photostory001.js javascript<commit_after>var project_title = 'Terremoto Centro Italia';
var project_subtitle = 'Le immagini di più di un anno';
var images = ['27FW98irrFbbWI_CGgCebQ','bCd7O6PhM8BABuVB-q340A','1d70jY76gxQuKvQcQUzErw','8oI1aWlduJT7WcH0tdLV-g','bZXIpYhlkCOIbL4Oil3yhQ'];
var titles = ['L\'Aquila 1','L\'Aquila 2','L\'Aquila 3','Arquata del Tronto 1','Arquata del Tronto 2'];
var content = ['','','','',''];
var xcoords = ['','','','',''];
var ycoords = ['','','','',''];
<|endoftext|>


<commit_before>/*
 ---

 script: require.js

 description: core css and js asset loading functionality, builds on mootools ASSET

 copyright: (c) 2011 Contributors in (/AUTHORS.txt).

 license: MIT-style license in (/MIT-LICENSE.txt).

 requires:
 - MochaUI/MUI
 - Core/Request
 - More/Hash
 - More/Assets

 provides: [MUI.Require, Asset.css ]

 ...
 */

MUI.Require = new Class({

	Implements: [Options],

	options: {
		css: [],
		images: [],
		js: []
		//onload: null
	},

	initialize: function(options){
		this.setOptions(options);
		options = this.options;

		this.assetsToLoad = options.css.length + options.images.length + options.js.length;
		this.assetsLoaded = 0;

		var cssLoaded = 0;

		// Load CSS before images and JavaScript

		if (options.css.length){
			options.css.each(function(sheet){

				this.getAsset(sheet, function(){
					if (cssLoaded == options.css.length - 1){
						if (this.assetsLoaded == this.assetsToLoad - 1) this.requireOnload();
						else {
							// Add a little delay since we are relying on cached CSS from XHR request.
							this.assetsLoaded++;
							this.requireContinue.delay(50, this);
						}
					} else {
						cssLoaded++;
						this.assetsLoaded++;
					}
				}.bind(this));
			}.bind(this));
		} else if (!options.js.length && !options.images.length){
			this.options.onload();
			return true;
		} else this.requireContinue.delay(50, this); // Delay is for Safari
	},

	requireOnload: function(){
		this.assetsLoaded++;
		if (this.assetsLoaded == this.assetsToLoad){
			this.options.onload();
			return true;
		}
	},

	requireContinue: function(){
		var options = this.options;
		if (options.images.length){
			options.images.each(function(image){
				this.getAsset(image, this.requireOnload.bind(this));
			}.bind(this));
		}

		if (options.js.length){
			options.js.each(function(script){
				this.getAsset(script, this.requireOnload.bind(this));
			}.bind(this));
		}
	},

	getAsset: function(source, onload){
		// If the asset is loaded, fire the onload function.
		if (MUI.files[source] == 'loaded'){
			if (typeof onload == 'function'){
				onload();
			}
			return true;
		}

		// If the asset is loading, wait until it is loaded and then fire the onload function.
		// If asset doesn't load by a number of tries, fire onload anyway.
		else if (MUI.files[source] == 'loading'){
			var tries = 0;
			var checker = (function(){
				tries++;
				if (MUI.files[source] == 'loading' && tries < 100) return;
				clearInterval(checker);
				if (typeof onload == 'function'){
					onload();
				}
			}).periodical(50);
		} else {  // If the asset is not yet loaded or loading, start loading the asset.
			MUI.files[source] = 'loading';

			properties = {
				'onload': onload != 'undefined' ? onload : null
			};

			// Add to the onload function
			var oldonload = properties.onload;
			properties.onload = function(){
				MUI.files[source] = 'loaded';
				if (oldonload) oldonload();
			}.bind(this);

			var sourcePath = MUI.replacePaths(source);
			switch (sourcePath.match(/\.\w+$/)[0]){
				case '.js': return Asset.javascript(sourcePath, properties);
				case '.css': return Asset.css(sourcePath, properties);
				case '.jpg':
				case '.png':
				case '.gif': return Asset.image(sourcePath, properties);
			}

			alert('The required file "' + source + '" could not be loaded');
		}
	}
});

Object.append(Asset, {
	// Get the CSS with XHR before appending it to document.head so that we can have an onload callback.
	css: function(source, properties){
		properties = Object.append({
			id: null,
			media: 'screen',
			onload: null
		}, properties);

		new Request({
			method: 'get',
			url: source,
			onComplete: function(){
				newSheet = new Element('link', {
					'id': properties.id,
					'rel': 'stylesheet',
					'media': properties.media,
					'type': 'text/css',
					'href': source
				}).inject(document.head);
				properties.onload();
			}.bind(this),
			onFailure: function(){
			},
			onSuccess: function(){
			}.bind(this)
		}).send();
	},

	getCSSRule: function(selector){
		for (var ii = 0; ii < document.styleSheets.length; ii++){
			var mySheet = document.styleSheets[ii];
			var myRules = mySheet.cssRules ? mySheet.cssRules : mySheet.rules;
			selector=selector.toLowerCase();
			for (var i = 0; i < myRules.length; i++){
				if (myRules[i].selectorText.toLowerCase() == selector){
					return myRules[i];
				}
			}
		}
		return false;
	}
});<commit_msg>GH102 - Asset.css conflict with mootools standard Asset<commit_after>/*
 ---

 script: require.js

 description: core css and js asset loading functionality, builds on mootools ASSET

 copyright: (c) 2011 Contributors in (/AUTHORS.txt).

 license: MIT-style license in (/MIT-LICENSE.txt).

 requires:
 - MochaUI/MUI
 - Core/Request
 - More/Hash
 - More/Assets

 provides: [MUI.Require, Asset.css ]

 ...
 */

MUI.Require = new Class({

	Implements: [Options],

	options: {
		css: [],
		images: [],
		js: []
		//onload: null
	},

	initialize: function(options){
		this.setOptions(options);
		options = this.options;

		this.assetsToLoad = options.css.length + options.images.length + options.js.length;
		this.assetsLoaded = 0;

		var cssLoaded = 0;

		// Load CSS before images and JavaScript

		if (options.css.length){
			options.css.each(function(sheet){

				this.getAsset(sheet, function(){
					if (cssLoaded == options.css.length - 1){
						if (this.assetsLoaded == this.assetsToLoad - 1) this.requireOnload();
						else {
							// Add a little delay since we are relying on cached CSS from XHR request.
							this.assetsLoaded++;
							this.requireContinue.delay(50, this);
						}
					} else {
						cssLoaded++;
						this.assetsLoaded++;
					}
				}.bind(this));
			}.bind(this));
		} else if (!options.js.length && !options.images.length){
			this.options.onload();
			return true;
		} else this.requireContinue.delay(50, this); // Delay is for Safari
	},

	requireOnload: function(){
		this.assetsLoaded++;
		if (this.assetsLoaded == this.assetsToLoad){
			this.options.onload();
			return true;
		}
	},

	requireContinue: function(){
		var options = this.options;
		if (options.images.length){
			options.images.each(function(image){
				this.getAsset(image, this.requireOnload.bind(this));
			}.bind(this));
		}

		if (options.js.length){
			options.js.each(function(script){
				this.getAsset(script, this.requireOnload.bind(this));
			}.bind(this));
		}
	},

	getAsset: function(source, onload){
		// If the asset is loaded, fire the onload function.
		if (MUI.files[source] == 'loaded'){
			if (typeof onload == 'function'){
				onload();
			}
			return true;
		}

		// If the asset is loading, wait until it is loaded and then fire the onload function.
		// If asset doesn't load by a number of tries, fire onload anyway.
		else if (MUI.files[source] == 'loading'){
			var tries = 0;
			var checker = (function(){
				tries++;
				if (MUI.files[source] == 'loading' && tries < 100) return;
				clearInterval(checker);
				if (typeof onload == 'function'){
					onload();
				}
			}).periodical(50);
		} else {  // If the asset is not yet loaded or loading, start loading the asset.
			MUI.files[source] = 'loading';

			properties = {
				'onload': onload != 'undefined' ? onload : null
			};

			// Add to the onload function
			var oldonload = properties.onload;
			properties.onload = function(){
				MUI.files[source] = 'loaded';
				if (oldonload) oldonload();
			}.bind(this);

			var sourcePath = MUI.replacePaths(source);
			switch (sourcePath.match(/\.\w+$/)[0]){
				case '.js': return Asset.javascript(sourcePath, properties);
				case '.css': return Asset.css(sourcePath, properties);
				case '.jpg':
				case '.png':
				case '.gif': return Asset.image(sourcePath, properties);
			}

			alert('The required file "' + source + '" could not be loaded');
		}
	}
});

Object.append(Asset, {
	// Get the CSS with XHR before appending it to document.head so that we can have an onload callback.
	css: function(source, properties){
		properties = Object.append({
			id: null,
			media: 'screen',
			onload: null
		}, properties);

		new Request({
			method: 'get',
			url: source,
			onComplete: function(){
				newSheet = new Element('link', {
					'id': properties.id,
					'rel': 'stylesheet',
					'media': properties.media,
					'type': 'text/css',
					'href': source
				}).inject(document.head);
				if (typeOf(properties.onload) == 'function') properties.onload();
			}.bind(this),
			onFailure: function(){
			},
			onSuccess: function(){
			}.bind(this)
		}).send();
	},

	getCSSRule: function(selector){
		for (var ii = 0; ii < document.styleSheets.length; ii++){
			var mySheet = document.styleSheets[ii];
			var myRules = mySheet.cssRules ? mySheet.cssRules : mySheet.rules;
			selector=selector.toLowerCase();
			for (var i = 0; i < myRules.length; i++){
				if (myRules[i].selectorText.toLowerCase() == selector){
					return myRules[i];
				}
			}
		}
		return false;
	}
});<|endoftext|>


<commit_before>

context('Cluster Admin', function(){
  beforeEach(function(){
    cy.window().then(win => win.onbeforeunload = undefined)
    cy.login('admin', 'password')
  })

  it('should be able to request pods and deployments (sanity check)', function() {
    cy.request('/proxy/api/v1/pods').its('status').should('equal', 200)
    cy.request('/proxy/apis/extensions/v1beta1/deployments').its('status').should('equal', 200)
  })

  it('should see all supported actions', function() {
    cy.get('#goto-workloads').click()
    cy.get('.workloads-page')

    cy.get(`table.filter-table.workloads > tbody
      tr.Deployment_kube-system_kube-dns
      td.resource-actions > svg`)
      .scrollIntoView().click()

    cy.get('div.actions-popover div')
      .children('button.row-action')
      .each(function(button) {
        expect(button.context.className).to.match(/row-action (edit|logs|terminal|delete|scale|suspend)/)
      })
  })

  it('can launch the terminal pane from the action menu', function() {
    cy.get('#goto-workloads').click()
    cy.get('.workloads-page')

    cy.get(`table.filter-table.workloads > tbody
      tr.Deployment_kube-system_kube-dns
      td.resource-actions > svg`)
      .scrollIntoView().click()

    cy.get('div.actions-popover div')
      .children('button.row-action.terminal')
      .click()

    cy.location().should(function(location) {
      expect(location.hash).to.eq('#/workloads/kube-system/Deployment/kube-dns?view=terminal')
    })

    cy.get('.resource-tabs.terminal')
    cy.get('button.terminal-start svg').click()
    cy.wait(1000)
    cy.get('.xterm-react.terminal').should('be.visible')
    cy.get('.xterm-react.terminal .terminal.xterm').should('be.visible')
    cy.get('.xterm-react.terminal .terminal.xterm textarea').type('exit{enter}', {force: true})
    cy.get('button.terminal-start').should('be.visible')
  })

  it('can create new workload resource', function() {
    cy.get('#goto-workloads').click()
    cy.get('.workloads-page')

    cy.get('div.new-workload > button').click()
  })

  it('can launch the logs pane from the action menu', function() {
    cy.get('#goto-workloads').click()
    cy.get('.workloads-page')

    cy.get(`table.filter-table.workloads > tbody
      tr.Deployment_kube-system_kube-dns
      td.resource-actions > svg`)
      .scrollIntoView().click()

    cy.get('div.actions-popover div')
      .children('button.row-action.logs')
      .click()

    cy.location().should(function(location) {
      expect(location.hash).to.eq('#/workloads/kube-system/Deployment/kube-dns?view=logs')
    })

    cy.get('.resource-tabs.logs')
    cy.get('.xterm-react.logs').should('be.visible')
  })

  it('can autocomplete the access/resources search', function() {
    cy.get('#goto-access').click()
    cy.get('.access-page')
    cy.get('.access-page .access-tabs.resources').click({force: true})

    cy.get('.access-page .filters.resources input[name=filters]').type('{downarrow}', {force: true})

    cy.get('.filters.resources.autocomplete')
      .children('div')
      .each(function(div) {
        expect(div.context.innerText).to.match(/^(kind|role|subject|namespace):.*/)
      })

    cy.get('.access-page .filters.resources input[name=filters]').type('subject:system:masters{enter}{esc}', {force: true})
    cy.get(`table.filter-table.access > tbody
        tr.ClusterRoleBinding_-_cluster-admin`)
  })

  it('can autocomplete the access/subjects search', function() {
    cy.get('#goto-access').click()
    cy.get('.access-page')
    cy.get('.access-page .access-tabs.subjects').click({force: true})

    cy.get('.access-page .filters.subjects input[name=filters]').type('{downarrow}', {force: true})

    cy.get('.filters.subjects.autocomplete')
      .children('div')
      .each(function(div) {
        expect(div.context.innerText).to.match(/^(Group|User):.*/)
      })

    cy.get('.access-page .filters.subjects input[name=filters]').type('User:reader{enter}{esc}', {force: true})
        cy.get('.permissions.user')
  })

})<commit_msg>add initial resource-creation automation<commit_after>

context('Cluster Admin', function(){
  beforeEach(function(){
    cy.window().then(win => win.onbeforeunload = undefined)
    cy.login('admin', 'password')
  })

  it('should be able to request pods and deployments (sanity check)', function() {
    cy.request('/proxy/api/v1/pods').its('status').should('equal', 200)
    cy.request('/proxy/apis/extensions/v1beta1/deployments').its('status').should('equal', 200)
  })

  it('should see all supported actions', function() {
    cy.get('#goto-workloads').click()
    cy.get('.workloads-page')

    cy.get(`table.filter-table.workloads > tbody
      tr.Deployment_kube-system_kube-dns
      td.resource-actions > svg`)
      .scrollIntoView().click()

    cy.get('div.actions-popover div')
      .children('button.row-action')
      .each(function(button) {
        expect(button.context.className).to.match(/row-action (edit|logs|terminal|delete|scale|suspend)/)
      })
  })

  it('can launch the terminal pane from the action menu', function() {
    cy.get('#goto-workloads').click()
    cy.get('.workloads-page')

    cy.get(`table.filter-table.workloads > tbody
      tr.Deployment_kube-system_kube-dns
      td.resource-actions > svg`)
      .scrollIntoView().click()

    cy.get('div.actions-popover div')
      .children('button.row-action.terminal')
      .click()

    cy.location().should(function(location) {
      expect(location.hash).to.eq('#/workloads/kube-system/Deployment/kube-dns?view=terminal')
    })

    cy.get('.resource-tabs.terminal')
    cy.get('button.terminal-start svg').click()
    cy.wait(1000)
    cy.get('.xterm-react.terminal').should('be.visible')
    cy.get('.xterm-react.terminal .terminal.xterm').should('be.visible')
    cy.get('.xterm-react.terminal .terminal.xterm textarea').type('exit{enter}', {force: true})
    cy.get('button.terminal-start').should('be.visible')
  })

  it('can launch the logs pane from the action menu', function() {
    cy.get('#goto-workloads').click()
    cy.get('.workloads-page')

    cy.get(`table.filter-table.workloads > tbody
      tr.Deployment_kube-system_kube-dns
      td.resource-actions > svg`)
      .scrollIntoView().click()

    cy.get('div.actions-popover div')
      .children('button.row-action.logs')
      .click()

    cy.location().should(function(location) {
      expect(location.hash).to.eq('#/workloads/kube-system/Deployment/kube-dns?view=logs')
    })

    cy.get('.resource-tabs.logs')
    cy.get('.xterm-react.logs').should('be.visible')
  })

  it('can autocomplete the access/resources search', function() {
    cy.get('#goto-access').click()
    cy.get('.access-page')
    cy.get('.access-page .access-tabs.resources').click({force: true})

    cy.get('.access-page .filters.resources input[name=filters]').type('{downarrow}', {force: true})

    cy.get('.filters.resources.autocomplete')
      .children('div')
      .each(function(div) {
        expect(div.context.innerText).to.match(/^(kind|role|subject|namespace):.*/)
      })

    cy.get('.access-page .filters.resources input[name=filters]').type('subject:system:masters{enter}{esc}', {force: true})
    cy.get(`table.filter-table.access > tbody
        tr.ClusterRoleBinding_-_cluster-admin`)
  })

  it('can autocomplete the access/subjects search', function() {
    cy.get('#goto-access').click()
    cy.get('.access-page')
    cy.get('.access-page .access-tabs.subjects').click({force: true})

    cy.get('.access-page .filters.subjects input[name=filters]').type('{downarrow}', {force: true})

    cy.get('.filters.subjects.autocomplete')
      .children('div')
      .each(function(div) {
        expect(div.context.innerText).to.match(/^(Group|User):.*/)
      })

    cy.get('.access-page .filters.subjects input[name=filters]').type('User:reader{enter}{esc}', {force: true})
        cy.get('.permissions.user')
  })

  it('can create new workload resource', function() {
    cy.get('#goto-workloads').click()
    cy.get('.workloads-page')

    cy.get('div.new-workload > button').click()
    cy.get('button.selected-template').click()
    cy.get('.selected-template-item.Pod').click()
    cy.get('.replace-with-template').click()

    cy.get('body').type('{shift} ', {release: true, force: true})
    cy.get('.ace_content .ace_line:nth-of-type(5)').click(70, 7, {force: true})
    cy.get('body').type('{shift}', {release: false, force: true})
    cy.get('.ace_content .ace_line:nth-of-type(5)').click('right', {force: true})
    cy.get('textarea.ace_text-input').type('{shift} bashful',{force: true})

    cy.get('body').type('{shift} ', {release: true, force: true})
    cy.get('.ace_content .ace_line:nth-of-type(6)').click(60, 7, {force: true})
    cy.get('body').type('{shift}', {release: false, force: true})
    cy.get('.ace_content .ace_line:nth-of-type(6)').click('right', {force: true})
    cy.get('textarea.ace_text-input').type('{shift} bashful',{force: true})

    cy.get('body').type('{shift} ', {release: true, force: true})
    cy.get('.ace_content .ace_line:nth-of-type(7)').click(100, 7, {force: true})
    cy.get('body').type('{shift}', {release: false, force: true})
    cy.get('.ace_content .ace_line:nth-of-type(7)').click('right', {force: true})
    cy.get('textarea.ace_text-input').type('{shift} default',{force: true})

    cy.get('body').type('{shift} ', {release: true, force: true})
    cy.get('.ace_content .ace_line:nth-of-type(10)').click(100, 7, {force: true})
    cy.get('body').type('{shift}', {release: false, force: true})
    cy.get('.ace_content .ace_line:nth-of-type(10)').click('right', {force: true})
    cy.get('textarea.ace_text-input').type('{shift} "bash:4"',{force: true})

    cy.get('body').type('{shift} ', {release: true, force: true})
    cy.get('.ace_content .ace_line:nth-of-type(12)').click(95, 7, {force: true})
    cy.get('body').type('{shift}', {release: false, force: true})
    cy.get('.ace_content .ace_line:nth-of-type(12)').click('right', {force: true})
    cy.get('textarea.ace_text-input').type('{shift} bashful',{force: true})

    cy.get('.editor-apply button')
  })

})<|endoftext|>


<commit_before>/*
* Copyright 2013 Research In Motion Limited.
*
* 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.
*/

(function(cordova) {
	var _ID = "com.blackberry.community.barcodescanner";
	var exec = cordova.require("cordova/exec");

	var reading, canvas, timeout, fs, latestFrame = null;
	// var fsSize = 1024 * 1024;
	var codefoundCallback, errorfoundCallback;
	var sleepPrevented = false;

	function BarcodeScanner() {
		// blackberry.io.sandbox = false;
	}

	// BarcodeScanner.prototype.startRead = function (codeFound, errorFound, canvasID, successStart) {
	BarcodeScanner.prototype.startRead = function (succ, fail, args) {
		if (reading) return "Stop Scanning before scanning again";
		var canvasID  = args;
		// var frameAvailableFn = frameAvailable;

		reading = true;
		blackberry.app.lockOrientation("portrait-primary");

		var success = function (data, response) {
			var arData = data.split(" "),
				receivedEvent = arData[0]

			if(arData.length > 2){
				var i;
				for(i=2; i<arData.length; i++)
					arData[1] += " " + arData[i];
			}

			if(receivedEvent == "community.barcodescanner.frameavailable.native") {
				// var frameData = JSON.parse(arData[1])
				// frameAvailableFn(frameData)
			}
			else if(receivedEvent == "community.barcodescanner.started.native") {
				// canvas = document.getElementById(canvasID);
				// canvas.style.display = "block"
			}
			else if(receivedEvent == "community.barcodescanner.codefound.native") {
				var codeFoundData = JSON.parse(arData[1]);
				console.log(codeFoundData);
				succ(codeFoundData);
			}
			else if(receivedEvent == "community.barcodescanner.errorfound.native") {
				var errorData = JSON.parse(arData[1]);
				fail(errorData);
			}
		},
		failure = function (data, response) {
			fail(data);
		};

		// Turn on prevent sleep, if it's in the app
		if (typeof community !== "undefined" && typeof community.preventsleep !== "undefined") {
			if (!community.preventsleep.isSleepPrevented) {
				community.preventsleep.setPreventSleep(true);
				sleepPrevented = true;
			}
		}
		exec(success, failure, _ID, "startRead", null, false);
	};

	BarcodeScanner.prototype.stopRead = function (succ, fail) {
		// canvas.style.display = "none"
		reading = false;
		blackberry.app.unlockOrientation();

		var success = function (data, response) {
			var arData = data.split(" "),
				receivedEvent = arData[0]

			if(receivedEvent == "community.barcodescanner.ended.native") {
				var successData = JSON.parse(arData[1])
				succ(successData)
			}
		},
		failure = function (data, response) {
			fail(data)
		};
		// Return sleep setting to original if changed.
		if (typeof community !== "undefined" && typeof community.preventsleep !== "undefined") {
			if (sleepPrevented === true) {
				community.preventsleep.setPreventSleep(false);
				sleepPrevented = false;
			}
		}
		exec(success, failure, _ID, "stopRead", null, false)
	};

	// function readFile(filename) {
	// 	window.webkitRequestFileSystem(
	// 		window.TEMPORARY,
	// 		fsSize,
	// 		function (fs) {
	// 			fs.root.getFile(
	// 				filename,
	// 				{create: false},
	// 				function (fileEntry) {
	// 					fileEntry.file(
	// 						function (file) {
	// 							var reader = new FileReader();
	// 							reader.onloadend = function (e) {
	// 								var ctx = canvas.getContext("2d");
	// 								var img = new Image();
	// 								img.onload = function() {
	// 									ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
	// 									URL.revokeObjectURL(img.src);
	// 									img.src = null;
	// 								};
	// 								img.src = e.target.result;
	// 							};

	// 							reader.readAsDataURL(file);
	// 						},
	// 						errorHandler
	// 					);
	// 				},
	// 				errorHandler
	// 			);
	// 		}
	// 	);
	// };

	// function errorHandler(e) {
	// 	var msg = '';

	// 	switch (e.code) {
	// 		case FileError.QUOTA_EXCEEDED_ERR:
	// 		msg = 'QUOTA_EXCEEDED_ERR';
	// 		break;
	// 		case FileError.NOT_FOUND_ERR:
	// 		msg = 'NOT_FOUND_ERR';
	// 		break;
	// 		case FileError.SECURITY_ERR:
	// 		msg = 'SECURITY_ERR';
	// 		break;
	// 		case FileError.INVALID_MODIFICATION_ERR:
	// 		msg = 'INVALID_MODIFICATION_ERR';
	// 		break;
	// 		case FileError.INVALID_STATE_ERR:
	// 		msg = 'INVALID_STATE_ERR';
	// 		break;
	// 		default:
	// 		msg = 'Unknown Error';
	// 		break;
	// 	}

	// }

	// function frameAvailable(data){
	// 	latestFrame = data.frame;
	// 	timeout = setTimeout(readFile, 4, latestFrame);
	// }

	cordova.addConstructor(function() {
		if(!window.plugins) window.plugins = {};
		window.plugins.barcodeScanner = new BarcodeScanner();
	});

})(window.cordova || window.Cordova);
<commit_msg>Cleans up old code from client API<commit_after>/*
* Copyright 2013-2015 BlackBerry Limited.
*
* 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.
*/

(function(cordova) {
	var _ID = "com.blackberry.community.barcodescanner";
	var exec = cordova.require("cordova/exec");

	var reading, timeout = null;
	var codefoundCallback, errorfoundCallback;
	var sleepPrevented = false;

	function BarcodeScanner() {	}

	BarcodeScanner.prototype.startRead = function (succ, fail, args) {
		if (reading) return "Stop Scanning before scanning again";

		// blackberry.app.lockOrientation("portrait-primary");

		var success = function (data, response) {
			var arData = data.split(" "),
				receivedEvent = arData[0]

			if(arData.length > 2){
				var i;
				for(i=2; i<arData.length; i++)
					arData[1] += " " + arData[i];
			}

			if(receivedEvent == "community.barcodescanner.started.native") {
				reading = true;
			}
			else if(receivedEvent == "community.barcodescanner.codefound.native") {
				var codeFoundData = JSON.parse(arData[1]);
				console.log(codeFoundData);
				succ(codeFoundData);
			}
			else if(receivedEvent == "community.barcodescanner.errorfound.native") {
				var errorData = JSON.parse(arData[1]);
				fail(errorData);
			}
		},
		failure = function (data, response) {
			fail(data);
		};

		// Turn on prevent sleep, if it's in the app
		if (typeof community !== "undefined" && typeof community.preventsleep !== "undefined") {
			if (!community.preventsleep.isSleepPrevented) {
				community.preventsleep.setPreventSleep(true);
				sleepPrevented = true;
			}
		}
		exec(success, failure, _ID, "startRead", null, false);
	};

	BarcodeScanner.prototype.stopRead = function (succ, fail) {
		reading = false;
		blackberry.app.unlockOrientation();

		var success = function (data, response) {
			var arData = data.split(" "),
				receivedEvent = arData[0]

			if(receivedEvent == "community.barcodescanner.ended.native") {
				var successData = JSON.parse(arData[1]);
				succ(successData);
			}
		},
		failure = function (data, response) {
			fail(data)
		};
		// Return sleep setting to original if changed.
		if (typeof community !== "undefined" && typeof community.preventsleep !== "undefined") {
			if (sleepPrevented === true) {
				community.preventsleep.setPreventSleep(false);
				sleepPrevented = false;
			}
		}
		exec(success, failure, _ID, "stopRead", null, false)
	};

	cordova.addConstructor(function() {
		if(!window.plugins) window.plugins = {};
		window.plugins.barcodeScanner = new BarcodeScanner();
	});

})(window.cordova || window.Cordova);
<|endoftext|>