text:
/**
 * @author Jonathan
 */

package com.abewy.android.apps.contacts.app;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import android.app.ActionBar.OnNavigationListener;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.view.View;
import com.abewy.android.apps.contacts.R;
import com.abewy.android.apps.contacts.core.CorePrefs;
import com.abewy.android.apps.contacts.model.Group;
import com.abewy.android.extended.items.BaseType;

public class FavoritesFragmentContainer extends FragmentContainer
{
	private ArrayList<BaseType>		mGroups;
	private static int				mPosition	= 0;
	private boolean					mFirstLoad	= true;
	private Group					mFavGroup;
	private int						mFavCount;

	private OnNavigationListener	listener	= new OnNavigationListener() {

													@Override
													public boolean onNavigationItemSelected(int itemPosition, long itemId)
													{
														if (mPosition != itemPosition)
														{
															mPosition = itemPosition;
															restartLoader();
														}
														return true;
													}
												};

	@Override
	public void onViewCreated(View view, Bundle savedInstanceState)
	{
		super.onViewCreated(view, savedInstanceState);

		new LoadGroupTask().execute();
	}

	@Override
	protected int getSelectedView()
	{
		return CorePrefs.getFavoritesViewType();
	}

	@Override
	protected void setSelectedView(int viewType)
	{
		CorePrefs.setFavoritesViewType(viewType);
	}

	@Override
	protected Uri getUri()
	{
		if (mPosition > 0)
			return Data.CONTENT_URI;

		return super.getUri();
	}

	@Override
	protected String getAdditionalFilters()
	{
		if (mPosition == 0)
		{
			return " AND " + Contacts.STARRED + " = " + 1;
		}
		else
		{
			return " AND " + Data.MIMETYPE + " = ? AND " + CommonDataKinds.GroupMembership.GROUP_ROW_ID + " = ?";
		}
	}

	@Override
	protected String[] getSelectionArgs()
	{
		if (mPosition > 0)
		{
			Group group = (Group) mGroups.get(mPosition);

			return new String[]{GroupMembership.CONTENT_ITEM_TYPE, String.valueOf(group.getId())};
		}

		return null;
	}

	@Override
	protected boolean isFilterQuery()
	{
		return super.isFilterQuery() && mPosition > 0;
	}

	@Override
	protected void onLoadFinished(List<BaseType> contacts)
	{
		if (mFirstLoad)
		{
			mFavCount = contacts.size();

			if (mFavGroup != null)
			{
				mFavGroup.setSize(mFavCount);
			}
		}

		mFirstLoad = false;

		super.onLoadFinished(contacts);
	}

	@Override
	protected void filter()
	{
		((IContactFragment) mCurrent).filter(mSearchQuery);
	}

	private void onGroupsLoaded(ArrayList<BaseType> groups)
	{
		mGroups = groups;

		if (mOnFront)
			onSetToFront();
	}

	@Override
	protected void onDataChange()
	{
		super.onDataChange();

		new LoadGroupTask().execute();
	}

	private class LoadGroupTask extends AsyncTask<Void, Void, ArrayList<BaseType>>
	{
		@Override
		protected ArrayList<BaseType> doInBackground(Void... arg0)
		{
			String selection = ContactsContract.Groups.DELETED + "=?";// and " + ContactsContract.Groups.GROUP_VISIBLE + "=?";
			String[] selectionArgs = { "0" };
			Cursor cursor = getActivity().getContentResolver().query(ContactsContract.Groups.CONTENT_SUMMARY_URI,
					new String[] { ContactsContract.Groups._ID, ContactsContract.Groups.TITLE, ContactsContract.Groups.SUMMARY_COUNT }, selection,
					selectionArgs, null);

			ArrayList<BaseType> groups = new ArrayList<BaseType>();

			while (cursor.moveToNext())
			{
				Group group = new Group(cursor.getLong(0), cursor.getString(1), cursor.getInt(2));
				groups.add(group);
			}

			cursor.close();

			cursor = getActivity().getContentResolver().query(FavoritesFragmentContainer.super.getUri(), null, Contacts.STARRED + " = " + 1, null, null);

			Group fGroup = new Group(-1, getString(R.string.title_favorites), cursor.getCount());

			Collections.sort(groups, new Comparator<BaseType>() {

				@Override
				public int compare(BaseType lhs, BaseType rhs)
				{
					return lhs.getItemPrimaryLabel().compareTo(rhs.getItemPrimaryLabel());
				}
			});

			groups.add(0, fGroup);

			return groups;
		}

		@Override
		protected void onPostExecute(ArrayList<BaseType> list)
		{
			super.onPostExecute(list);

			onGroupsLoaded(list);
		}
	}

	private boolean mOnFront = false;

	@Override
	public void onSetToFront()
	{
		mOnFront = true;

		getActivity().setTitle(R.string.title_favorites);

		if (mGroups != null)
		{
			((IActionbarSpinner) getActivity()).displaySpinnerInActionBar(mGroups, mPosition, listener);
		}
	}

	@Override
	public void onSetToBack()
	{
		mOnFront = false;

		((IActionbarSpinner) getActivity()).removeSpinnerInActionBar();
	}
}


text:
A 3DS Max toolkit for editing vertex normals to make creating hair and foliage easier.

Features:

	Specify Normals - set all vertex normals to point in a specific direction

	Point Normals - make all vertex normals point away from an object

	Clone Normals - clone vertex normals from another mesh

redpajama_set_name: RedPajamaGithub


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>net.floodlightcontroller.core.web.serializers</title>
<meta name="date" content="2015-06-22">
<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev Package

Next Package

Frames

No Frames

All Classes

Package net.floodlightcontroller.core.web.serializers

Class Summary

Class
Description

ByteArrayMACSerializer

Serialize a MAC as colon-separated hexadecimal

DPIDSerializer

Serialize a DPID as colon-separated hexadecimal

IOFSwitchSerializer

Serialize a IOFSwitch for more readable information

IPv4Serializer

Serialize an IPv4Address in dotted decimal format

MacSerializer

Serialize a MAC as colon-separated hexadecimal

MatchSerializer

Serialize any Match in JSON.

OFActionListSerializer

Serialize any List of OFAction in JSON.

OFFlowModSerializer

Serialize any OFFlowMod in JSON.

OFInstructionListSerializer

Serialize any List of OFInstruction in JSON.

OFPortSerializer

Serialize a OFPort as short number

StatsReplySerializer

Serialize any OFStatsReply or OFFeaturesReply in JSON
 wrapped by a StatsReply object.

UShortSerializer

Serialize a short value as an unsigned short

VlanVidSerializer

Serialize a VlanVid as short number

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev Package

Next Package

Frames

No Frames

All Classes


text:
<resources>
    <string name="app_name">build-utils</string>
</resources>


text:
<?xml version="1.0" encoding="UTF-8"?>
<!--

    Licensed to Jasig under one or more contributor license
    agreements. See the NOTICE file distributed with this work
    for additional information regarding copyright ownership.
    Jasig licenses this file to you 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.

-->

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<!--  in this example, implementations compatible for Bedework are chosen -->
	<bean id="caldavHost" class="java.net.URI">
		<constructor-arg><value>${caldav.host}</value></constructor-arg>
	</bean>
	<bean class="org.jasig.schedassist.impl.caldav.DefaultCaldavDialectImpl">
		<property name="caldavHost" ref="caldavHost"/>
		<property name="accountHomePrefix" value="${caldav.dialect.accountHomePrefix}"/>
		<property name="accountHomeSuffix" value="${caldav.dialect.accountHomeSuffix}"/>
	</bean>

	<bean class="org.jasig.schedassist.impl.caldav.bedework.BedeworkHttpMethodInterceptorImpl"/>
	<bean class="org.jasig.schedassist.impl.caldav.bedework.BedeworkEventUtilsImpl">
		<constructor-arg ref="affiliationSource"/>
		<property name="explicitSetTimeZone" value="${caldav.explicitSetTimeZone}"/>
		<property name="timeZone" value="${caldav.systemTimeZone}"/>
	</bean>

    <bean id="credentialsProviderFactory" class="org.jasig.schedassist.impl.caldav.DefaultCredentialsProviderFactoryImpl"/>

</beans>


text:
package jcommon.graph;

import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;

/**
 * This is a simple graph holding {@link IVertex} vertices and {@link IEdge} edges connecting them.
 * It is intended to be used in a builder-style pattern and then operations such as {@link #sort()} may be called
 * on the graph.
 *
 * Of particular note is the {@link #sortAsync(ITopologicalSortCallback)} method which allows you to asynchronously and
 * in-parallel process the vertices of a graph topologically. Care is taken to prevent the processing of vertices before
 * their parent vertices have completed processing.
 *
 * @param <TVertex> Type of {@link IVertex} that vertices in this graph are.
 * @param <TValue> Type of {@link Object} that the vertices in this graph contain.
 */
public interface IGraph<TVertex extends IVertex<TValue>, TValue extends Object, TProcessedValue extends Object> {
  /**
   * Reference for an array of empty vertices that can be reused instead
   * of having to allocate a new empty array on the heap every time.
   */
  IVertex[] EMPTY_VERTICES = new IVertex[0];

  /**
   * Retrieves the set of {@link IVertex} vertices of TVertex represented by this {@link IGraph}.
   *
   * @return The set of {@link IVertex} vertices of TVertex represented by this {@link IGraph}.
   */
  Set<TVertex> getVertices();

  /**
   * Retrieves the set of {@link IEdge} edges represented by this {@link IGraph}.
   *
   * @return The set of {@link IEdge} edges represented by this {@link IGraph}.
   */
  Set<IEdge<TVertex>> getEdges();

  /**
   * More type-safe version of {@link Object#clone()}.
   *
   * @return A deep copy of this instance of {@link IGraph}.
   */
  IGraph<TVertex, TValue, TProcessedValue> copy();

  /**
   * Adds a new {@link IVertex} instance of TVertex to this {@link IGraph}.
   *
   * @param vertex The instance of {@link IVertex} of TVertex to add to this {@link IGraph}.
   * @return The current instance of {@link IGraph} for use in a builder-style pattern.
   */
  IGraph<TVertex, TValue, TProcessedValue> addVertex(TVertex vertex);

  /**
   * Removes an {@link IVertex} instance of TVertex from this {@link IGraph}.
   *
   * @param vertex The instance of {@link IVertex} of TVertex to remove from this {@link IGraph}.
   * @return The current instance of {@link IGraph} for use in a builder-style pattern.
   */
  IGraph<TVertex, TValue, TProcessedValue> removeVertex(TVertex vertex);

  /**
   * Adds a new {@link IEdge} instance to this {@link IGraph}.
   *
   * @param from An instance of {@link IVertex} of TVertex that begins the edge.
   * @param to An instance of {@link IVertex} of TVertex that the edge is pointing to.
   * @return The current instance of {@link IGraph} for use in a builder-style pattern.
   */
  IGraph<TVertex, TValue, TProcessedValue> addEdge(TVertex from, TVertex to);

  /**
   * Removes an existing edge from this {@link IGraph}.
   *
   * @param from An instance of {@link IVertex} of TVertex that begins the edge.
   * @param to An instance of {@link IVertex} of TVertex that the edge is pointing to.
   * @return The current instance of {@link IGraph} for use in a builder-style pattern.
   */
  IGraph<TVertex, TValue, TProcessedValue> removeEdge(TVertex from, TVertex to);

  /**
   * Does a simple sanity check on the structure of the graph. Should not be called until the graph has been
   * completely structured. Notably a cycle check is not done at this point. That's only detected upon a topological
   * sort of the graph.
   *
   * @return true if the graph passes a simple sanity check; false otherwise.
   */
  boolean validate();

  /**
   * Provides a topologically sorted list of {@link IVertex} vertices.
   *
   * @return A topologically sorted list of {@link IVertex} vertices in the current graph.
   * @throws CyclicGraphException A {@link CyclicGraphException} is thrown if a cycle is detected during the sort.
   *
   * @see http://en.wikipedia.org/wiki/Topological_sorting
   */
  List<TValue> sort() throws CyclicGraphException;

  /**
   * Provides a topologically sorted list of {@link IVertex} vertices.
   *
   * It's strongly recommended that you use {@link #sort()} in most cases unless you require an alternative approach to
   * the topological sorting algorithm.
   *
   * @param strategy An instance of {@link ITopologicalSortStrategy} that will perform the sort.
   * @return A topologically sorted list of {@link IVertex} vertices in the current graph.
   * @throws CyclicGraphException A {@link CyclicGraphException} is thrown if a cycle is detected during the sort.
   *
   * @see http://en.wikipedia.org/wiki/Topological_sorting
   */
  List<TValue> sort(ITopologicalSortStrategy<TVertex, TValue, TProcessedValue> strategy) throws CyclicGraphException;

  /**
   * Allows you to asynchronously and in-parallel process the vertices of a graph topologically. Care is taken to
   * prevent the processing of vertices before their parent vertices have completed processing.
   *
   * @param callback An instance of {@link ITopologicalSortCallback} that will be called to process each vertex.
   *                 This may be called concurrently depending on the makeup of the graph.
   * @return         An instance of {@link ITopologicalSortAsyncResult} that allows the caller to coordinate the
   *                 asynchronous processing of the graph.
   *
   * @see http://en.wikipedia.org/wiki/Topological_sorting
   */
  ITopologicalSortAsyncResult<TValue, TProcessedValue> sortAsync(ITopologicalSortCallback<TValue, TProcessedValue> callback);

  /**
   * Allows you to asynchronously and in-parallel process the vertices of a graph topologically. Care is taken to
   * prevent the processing of vertices before their parent vertices have completed processing.
   *
   * @param callback      An instance of {@link ITopologicalSortCallback} that will be called to process each vertex.
   *                      This may be called concurrently depending on the makeup of the graph.
   * @param errorCallback An instance of {@link ITopologicalSortErrorCallback} that will be called if an error during
   *                      processing occurs either in the
   *                      {@link ITopologicalSortCallback#handle(Object, ITopologicalSortInput, IVertex, ITopologicalSortCoordinator)} method or in the
   *                      {@link ITopologicalSortStrategy#sortAsync(java.util.concurrent.ExecutorService, IAdjacencyList, ITopologicalSortCallback, ITopologicalSortErrorCallback)}
   *                      method.
   * @return              An instance of {@link ITopologicalSortAsyncResult} that allows the caller to coordinate the
   *                      asynchronous processing of the graph.
   *
   * @see http://en.wikipedia.org/wiki/Topological_sorting
   */
  ITopologicalSortAsyncResult<TValue, TProcessedValue> sortAsync(ITopologicalSortCallback<TValue, TProcessedValue> callback, ITopologicalSortErrorCallback<TValue> errorCallback);

  /**
   * Allows you to asynchronously and in-parallel process the vertices of a graph topologically. Care is taken to
   * prevent the processing of vertices before their parent vertices have completed processing.
   *
   * It's strongly recommended that you use {@link #sortAsync(ITopologicalSortCallback)} in most cases unless you
   * require an alternative approach to the topological sorting algorithm.
   *
   * @param strategy An instance of {@link ITopologicalSortStrategy} that will perform the sort.
   * @param callback An instance of {@link ITopologicalSortCallback} that will be called to process each vertex.
   *                 This may be called concurrently depending on the makeup of the graph.
   * @return         An instance of {@link ITopologicalSortAsyncResult} that allows the caller to coordinate the
   *                 asynchronous processing of the graph.
   *
   * @see http://en.wikipedia.org/wiki/Topological_sorting
   */
  ITopologicalSortAsyncResult<TValue, TProcessedValue> sortAsync(ITopologicalSortStrategy<TVertex, TValue, TProcessedValue> strategy, ITopologicalSortCallback<TValue, TProcessedValue> callback);

  /**
   * Allows you to asynchronously and in-parallel process the vertices of a graph topologically. Care is taken to
   * prevent the processing of vertices before their parent vertices have completed processing.
   *
   * It's strongly recommended that you use {@link #sortAsync(ITopologicalSortCallback, ITopologicalSortErrorCallback)}
   * in most cases unless you require an alternative approach to the topological sorting algorithm.
   *
   * @param strategy      An instance of {@link ITopologicalSortStrategy} that will perform the sort.
   * @param callback      An instance of {@link ITopologicalSortCallback} that will be called to process each vertex.
   *                      This may be called concurrently depending on the makeup of the graph.
   * @param errorCallback An instance of {@link ITopologicalSortErrorCallback} that will be called if an error during
   *                      processing occurs either in the
   *                      {@link ITopologicalSortCallback#handle(Object, ITopologicalSortInput, IVertex, ITopologicalSortCoordinator)} method or in the
   *                      {@link ITopologicalSortStrategy#sortAsync(java.util.concurrent.ExecutorService, IAdjacencyList, ITopologicalSortCallback, ITopologicalSortErrorCallback)}
   *                      method.
   * @return              An instance of {@link ITopologicalSortAsyncResult} that allows the caller to coordinate the
   *                      asynchronous processing of the graph.
   *
   * @see http://en.wikipedia.org/wiki/Topological_sorting
   */
  ITopologicalSortAsyncResult<TValue, TProcessedValue> sortAsync(ITopologicalSortStrategy<TVertex, TValue, TProcessedValue> strategy, ITopologicalSortCallback<TValue, TProcessedValue> callback, ITopologicalSortErrorCallback<TValue> errorCallback);

  /**
   * Allows you to asynchronously and in-parallel process the vertices of a graph topologically. Care is taken to
   * prevent the processing of vertices before their parent vertices have completed processing.
   *
   * @param executor An instance of {@link ExecutorService} that will be used to submit tasks for processing vertices.
   * @param callback An instance of {@link ITopologicalSortCallback} that will be called to process each vertex.
   *                 This may be called concurrently depending on the makeup of the graph.
   * @return         An instance of {@link ITopologicalSortAsyncResult} that allows the caller to coordinate the
   *                 asynchronous processing of the graph.
   *
   * @see http://en.wikipedia.org/wiki/Topological_sorting
   */
  ITopologicalSortAsyncResult<TValue, TProcessedValue> sortAsync(ExecutorService executor, ITopologicalSortCallback<TValue, TProcessedValue> callback);

  /**
   * Allows you to asynchronously and in-parallel process the vertices of a graph topologically. Care is taken to
   * prevent the processing of vertices before their parent vertices have completed processing.
   *
   * @param executor      An instance of {@link ExecutorService} that will be used to submit tasks for processing
   *                      vertices.
   * @param callback      An instance of {@link ITopologicalSortCallback} that will be called to process each vertex.
   *                      This may be called concurrently depending on the makeup of the graph.
   * @param errorCallback An instance of {@link ITopologicalSortErrorCallback} that will be called if an error during
   *                      processing occurs either in the
   *                      {@link ITopologicalSortCallback#handle(Object, ITopologicalSortInput, IVertex, ITopologicalSortCoordinator)} method or in the
   *                      {@link ITopologicalSortStrategy#sortAsync(java.util.concurrent.ExecutorService, IAdjacencyList, ITopologicalSortCallback, ITopologicalSortErrorCallback)}
   *                      method.
   * @return              An instance of {@link ITopologicalSortAsyncResult} that allows the caller to coordinate the
   *                      asynchronous processing of the graph.
   *
   * @see http://en.wikipedia.org/wiki/Topological_sorting
   */
  ITopologicalSortAsyncResult<TValue, TProcessedValue> sortAsync(ExecutorService executor, ITopologicalSortCallback<TValue, TProcessedValue> callback, ITopologicalSortErrorCallback<TValue> errorCallback);

  /**
   * Allows you to asynchronously and in-parallel process the vertices of a graph topologically. Care is taken to
   * prevent the processing of vertices before their parent vertices have completed processing.
   *
   * It's strongly recommended that you use {@link #sortAsync(java.util.concurrent.ExecutorService, ITopologicalSortCallback)}
   * in most cases unless you require an alternative approach to the topological sorting algorithm.
   *
   * @param executor      An instance of {@link ExecutorService} that will be used to submit tasks for processing
   *                      vertices.
   * @param strategy      An instance of {@link ITopologicalSortStrategy} that will perform the sort.
   * @param callback      An instance of {@link ITopologicalSortCallback} that will be called to process each vertex.
   *                      This may be called concurrently depending on the makeup of the graph.
   * @return              An instance of {@link ITopologicalSortAsyncResult} that allows the caller to coordinate the
   *                      asynchronous processing of the graph.
   *
   * @see http://en.wikipedia.org/wiki/Topological_sorting
   */
  ITopologicalSortAsyncResult<TValue, TProcessedValue> sortAsync(ExecutorService executor, ITopologicalSortStrategy<TVertex, TValue, TProcessedValue> strategy, ITopologicalSortCallback<TValue, TProcessedValue> callback);

  /**
   * Allows you to asynchronously and in-parallel process the vertices of a graph topologically. Care is taken to
   * prevent the processing of vertices before their parent vertices have completed processing.
   *
   * It's strongly recommended that you use {@link #sortAsync(java.util.concurrent.ExecutorService, ITopologicalSortCallback, ITopologicalSortErrorCallback)}
   * in most cases unless you require an alternative approach to the topological sorting algorithm.
   *
   * @param executor      An instance of {@link ExecutorService} that will be used to submit tasks for processing
   *                      vertices.
   * @param strategy      An instance of {@link ITopologicalSortStrategy} that will perform the sort.
   * @param callback      An instance of {@link ITopologicalSortCallback} that will be called to process each vertex.
   *                      This may be called concurrently depending on the makeup of the graph.
   * @param errorCallback An instance of {@link ITopologicalSortErrorCallback} that will be called if an error during
   *                      processing occurs either in the
   *                      {@link ITopologicalSortCallback#handle(Object, ITopologicalSortInput, IVertex, ITopologicalSortCoordinator)} method or in the
   *                      {@link ITopologicalSortStrategy#sortAsync(java.util.concurrent.ExecutorService, IAdjacencyList, ITopologicalSortCallback, ITopologicalSortErrorCallback)}
   *                      method.
   * @return              An instance of {@link ITopologicalSortAsyncResult} that allows the caller to coordinate the
   *                      asynchronous processing of the graph.
   *
   * @see http://en.wikipedia.org/wiki/Topological_sorting
   */
  ITopologicalSortAsyncResult<TValue, TProcessedValue> sortAsync(ExecutorService executor, ITopologicalSortStrategy<TVertex, TValue, TProcessedValue> strategy, ITopologicalSortCallback<TValue, TProcessedValue> callback, ITopologicalSortErrorCallback<TValue> errorCallback);
}


text:
import {devAssert, devAssertElement} from '#core/assert';
import * as mode from '#core/mode';
import {pushIfNotExist, removeItem} from '#core/types/array';

import {ContextPropDef} from './prop.type';
import {throttleTail} from './scheduler';
import {Values} from './values';

// Properties set on the DOM nodes to track the context state.
const NODE_PROP = '__AMP_NODE';
const ASSIGNED_SLOT_PROP = '__AMP_ASSIGNED_SLOT';
const AMP_PREFIX = 'AMP-';

// Relevant node types.
// See https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType.
const ELEMENT_NODE = 1;
const DOCUMENT_NODE = 9;
// Includes shadow root, template, etc.
const FRAGMENT_NODE = 11;

/**
 * The structure for a group of nodes.
 *
 * @typedef {{
 *   cn: !ContextNode,
 *   match: function(!Node, !Node):boolean,
 *   weight: number,
 * }}
 */
let GroupDef;

/**
 * The context node is a sparse tree over the DOM tree. Any node that needs
 * to manage and compute state can be attached to the context node tree. The
 * tree (mostly) automatically self-manages: the new nodes and DOM mutations
 * are auto-discovered or prompted.
 *
 * @package
 * @template SID subscriber ID type(s)
 */
export class ContextNode {
  /**
   * Returns the existing context node or creates a new one.
   *
   * @param {!Node} node
   * @return {!ContextNode}
   */
  static get(node) {
    let contextNode = /** @type {!ContextNode|undefined} */ (node[NODE_PROP]);
    if (!contextNode) {
      contextNode = new ContextNode(node, null);
      if (mode.isLocalDev() || mode.isTest()) {
        // The `Object.defineProperty({enumerable: false})` helps tests, but
        // hurts performance. So this is only done in a dev/test modes.
        Object.defineProperty(node, NODE_PROP, {
          value: contextNode,
          writable: false,
          enumerable: false,
          configurable: false,
        });
      } else {
        node[NODE_PROP] = contextNode;
      }
    }
    return contextNode;
  }

  /**
   * Returns the closest available context node to the one specified. If the
   * `node` has the context node, it's returned unless `includeSelf` is set as
   * `false`.
   *
   * The DOM traversal goes at most as far as the root node (document,
   * shadow root, document fragment) or as far as the DOM tree allows. The
   * traversal follows the assigned shadow slots.
   *
   * Root nodes (document or shadow root) and AMP elements are auto-created
   * during the traversal.
   *
   * @param {!Node} node The node from which to perform the search.
   * @param {boolean=} includeSelf Whether the specified node itself should
   * be included in the search. Defaults to `true`.
   * @return {?ContextNode}
   */
  static closest(node, includeSelf = true) {
    let n = node;
    while (n) {
      // Check if a node is a candidate to be returned.
      if (n != node || includeSelf) {
        if (n[NODE_PROP]) {
          // Already a discovered node.
          return /** @type {!ContextNode} */ (n[NODE_PROP]);
        }
        const {nodeType} = n;
        if (
          // A context node is always created for a root. Due to this, a
          // non-root element is always at least attached to a root. This
          // allows for quick discovery and reattachment when new information
          // becomes available.
          nodeType == DOCUMENT_NODE ||
          nodeType == FRAGMENT_NODE ||
          // An AMP node will always have a context node backing it at some
          // point.
          (nodeType == ELEMENT_NODE &&
            devAssertElement(n).tagName.startsWith(AMP_PREFIX))
        ) {
          return ContextNode.get(n);
        }
      }
      // Navigate up the DOM tree. Notice that we do not automatically go over
      // a root node boundary.
      const assignedSlot =
        /** @type {?Node|undefined} */ (n[ASSIGNED_SLOT_PROP]) ||
        n.assignedSlot;
      if (assignedSlot) {
        n = assignedSlot;
      } else {
        n = n.parentNode;
      }
    }
    // Only disconnected nodes will return `null` here.
    return null;
  }

  /**
   * Direct slot assignment. Works the same way as shadow slots, but does not
   * require a shadow root. Automatically starts the discovery phase for the
   * affected nodes.
   *
   * See `Element.assignedSlot` API.
   *
   * @param {!Node} node The target node.
   * @param {!Node} slot The slot to which the target node is assigned.
   */
  static assignSlot(node, slot) {
    if (node[ASSIGNED_SLOT_PROP] == slot) {
      return;
    }
    node[ASSIGNED_SLOT_PROP] = slot;
    discoverContained(node);
  }

  /**
   * Unassigns the direct slot previously done by the `assignSlot` call.
   * Automatically starts the discovery phase for the affected nodes.
   *
   * @param {!Node} node The target node.
   * @param {!Node} slot The slot from which the target node is assigned.
   */
  static unassignSlot(node, slot) {
    if (node[ASSIGNED_SLOT_PROP] != slot) {
      return;
    }
    node[ASSIGNED_SLOT_PROP] = undefined;
    discoverContained(node);
  }

  /**
   * Reruns discovery on the children of the specified node, if any.
   *
   * @param {!Node} node
   */
  static rediscoverChildren(node) {
    const contextNode = /** @type {!ContextNode|undefined} */ (node[NODE_PROP]);
    contextNode?.children?.forEach(discoverContextNode);
  }

  /**
   * Creates the context node and automatically starts the discovery process.
   *
   * @param {!Node} node
   * @param {?string} name
   */
  constructor(node, name) {
    /** @const {!Node} */
    this.node = node;

    /** @const @package {?string} */
    this.name = name;

    /**
     * Whether this node is a root. The Document DOM nodes are automatically
     * considered as roots. But other nodes can become roots as well
     * (e.g. shadow roots) via `setIsRoot()` API.
     *
     * @package {boolean}
     */
    this.isRoot = node.nodeType == DOCUMENT_NODE;

    /**
     * The root context node. Always available for a DOM node connected to a
     * root node after the discovery phase.
     *
     * @package {?ContextNode}
     */
    this.root = this.isRoot ? this : null;

    /**
     * Parent should be mostly meaningless to most API clients, because
     * it's an async concept: a parent context node can can be instantiated at
     * any time and it doesn't mean that this node has to change. This is
     * why the API is declared as package-private. However, it needs to be
     * unobfuscated to avoid cross-binary issues.
     *
     * @package {?ContextNode}
     */
    this.parent = null;

    /**
     * See `parent` description.
     *
     * @package {?Array<!ContextNode>}
     */
    this.children = null;

    /** @package {?Map<string, !GroupDef>} */
    this.groups = null;

    /** @package {!Values} */
    this.values = new Values(this);

    /** @private {?Map<!SID, !./subscriber.Subscriber>} */
    this.subscribers_ = null;

    /** @private {boolean} */
    this.parentOverridden_ = false;

    /** @const @private {function()} */
    this.scheduleDiscover_ = throttleTail(
      this.discover_.bind(this),
      setTimeout
    );

    // Shadow root: track slot changes.
    if (node.nodeType == FRAGMENT_NODE) {
      node.addEventListener('slotchange', (e) => {
        const slot = /** @type {!HTMLSlotElement} */ (e.target);
        // Rediscover newly assigned nodes.
        slot.assignedNodes().forEach(discoverContained);
        // Rediscover unassigned nodes.
        ContextNode.closest(slot)?.children?.forEach(discoverContextNode);
      });
    }

    this.discover();
  }

  /**
   * Requests the discovery phase. Asynchronously finds the nearest parent for
   * this node and its root. Roots and parents set directly via `setParent()`
   * API are not discoverable.
   */
  discover() {
    if (this.isDiscoverable()) {
      this.scheduleDiscover_();
    } else if (this.name && this.children) {
      // Recursively discover the group's children.
      this.children.forEach(discoverContextNode);
    }
  }

  /**
   * @return {boolean}
   * @protected Used cross-binary.
   */
  isDiscoverable() {
    return !this.isRoot && !this.parentOverridden_;
  }

  /**
   * Sets (or unsets) the direct parent. If the parent is set, the node will no
   * longer try to discover itself.
   *
   * @param {!ContextNode|!Node|null} parent
   */
  setParent(parent) {
    const parentContext = parent?.nodeType
      ? ContextNode.get(/** @type {!Node} */ (parent))
      : /** @type {?ContextNode} */ (parent);
    this.updateTree_(parentContext, /* parentOverridden */ parent != null);
  }

  /**
   * Designates (or undesignates) the node as a root node. If the node is
   * designated as a root, it will no longer discover itself.
   *
   * @param {boolean} isRoot
   */
  setIsRoot(isRoot) {
    this.isRoot = isRoot;
    const newRoot = isRoot ? this : this.parent?.root ?? null;
    this.updateRoot(newRoot);
  }

  /**
   * @param {?ContextNode} root
   * @protected Used cross-binary.
   */
  updateRoot(root) {
    devAssert(!root || root.isRoot);
    const oldRoot = this.root;
    if (root != oldRoot) {
      // The root has changed.
      this.root = root;

      // Make sure the tree changes have been reflected for values.
      this.values.rootUpdated();

      // Make sure the tree changes have been reflected for subscribers.
      this.subscribers_?.forEach((comp) => comp.rootUpdated());

      // Propagate the root to the subtree.
      this.children?.forEach((child) => child.updateRoot(root));
    }
  }

  /**
   * @param {string} name
   * @param {function(!Node):boolean} match
   * @param {number} weight
   * @return {!ContextNode}
   */
  addGroup(name, match, weight) {
    const groups = this.groups || (this.groups = new Map());
    const {children, node} = this;
    const cn = new ContextNode(node, name);
    groups.set(name, {cn, match, weight});
    cn.setParent(this);
    children?.forEach(discoverContextNode);
    return cn;
  }

  /**
   * @param {string} name
   * @return {?ContextNode}
   */
  group(name) {
    return this.groups?.get(name)?.cn || null;
  }

  /**
   * @param {!Node} node
   * @return {?ContextNode}
   * @protected
   */
  findGroup(node) {
    const {groups} = this;
    if (!groups) {
      return null;
    }
    let found = null;
    let maxWeight = Number.NEGATIVE_INFINITY;
    groups.forEach(({cn, match, weight}) => {
      if (match(node, this.node) && weight > maxWeight) {
        found = cn;
        maxWeight = weight;
      }
    });
    return found;
  }

  /**
   * Add or update a subscriber with a specified ID. If subscriber doesn't
   * yet exist, it will be created using the specified factory. The use
   * of factory is important to reduce bundling costs for context node.
   *
   * @param {!SID} id
   * @param {typeof ./subscriber.Subscriber} Ctor
   * @param {!Function} func
   * @param {!Array<!ContextPropDef>} deps
   */
  subscribe(id, Ctor, func, deps) {
    const subscribers = this.subscribers_ || (this.subscribers_ = new Map());
    let subscriber = subscribers.get(id);
    if (!subscriber) {
      subscriber = new Ctor(this, func, deps);
      subscribers.set(id, subscriber);
    }
  }

  /**
   * Removes the subscriber previously set with `subscribe`.
   *
   * @param {!SID} id
   */
  unsubscribe(id) {
    const subscribers = this.subscribers_;
    const subscriber = subscribers?.get(id);
    if (subscriber) {
      subscriber.dispose();
      subscribers.delete(id);
    }
  }

  /**
   * Discovers the parent and the root. Runs asynchronously via scheduler.
   * @private
   */
  discover_() {
    if (!this.isDiscoverable()) {
      // The discoverability might have changed while this task was in the
      // queue.
      return;
    }
    const closestNode = ContextNode.closest(this.node, /* includeSelf */ false);
    const parent = closestNode?.findGroup(this.node) || closestNode;
    this.updateTree_(parent, /* parentOverridden */ false);
  }

  /**
   * @param {?ContextNode} parent
   * @param {boolean} parentOverridden
   * @private
   */
  updateTree_(parent, parentOverridden) {
    this.parentOverridden_ = parentOverridden;

    const oldParent = this.parent;
    if (parent != oldParent) {
      // The parent has changed.
      this.parent = parent;

      // Remove from the old parent.
      if (oldParent?.children) {
        removeItem(devAssert(oldParent.children), this);
      }

      // Add to the new parent.
      if (parent) {
        const parentChildren = parent.children || (parent.children = []);
        pushIfNotExist(parentChildren, this);

        // Check if this node has been inserted in between the parent and
        // it's other children.
        // Since the new parent (`this`) is already known, this is a very
        // fast operation.
        for (const child of parentChildren) {
          if (child != this && child.isDiscoverable()) {
            child.discover();
          }
        }
      }

      this.values.parentUpdated();
    }

    // Check the root.
    this.updateRoot(parent?.root ?? null);
  }
}

/**
 * Iterates over all context nodes that are contained within the specified
 * `node`. Only iterates over known context nodes.
 *
 * @param {!Node} node
 * @param {function(!ContextNode)} callback
 * @param {boolean=} includeSelf
 */
function forEachContained(node, callback, includeSelf = true) {
  const closest = ContextNode.closest(node, includeSelf);
  if (!closest) {
    return;
  }
  if (closest.node == node) {
    callback(closest);
  } else if (closest.children) {
    for (const child of closest.children) {
      if (node.contains(child.node)) {
        callback(child);
      }
    }
  }
}

/**
 * @param {!Node} node
 */
function discoverContained(node) {
  forEachContained(node, discoverContextNode);
}

/**
 * @param {!ContextNode} cn
 */
function discoverContextNode(cn) {
  cn.discover();
}


text:
import _ from "lodash";
import {buildHierarchies} from "../../../common/hierarchy-utils";
import {CORE_API} from "../../../common/services/core-api-utils";
import template from "./flow-filter-options.html";
import {getSelectedTagsFromPreferences, saveTagFilterPreferences} from "../../logical-flow-utils";
import {groupLogicalFlowFilterExcludedTagIdsKey} from "../../../user/services/user-preference-service";

const bindings = {
    onChange: "<",
    usedTypes: "<", // [ dataTypeId... ],
    usedTags: "<" // [ {name, id, tagUsages}... ]
};

const initialState = {
    selectedType: "ALL",
    selectedScope: "ALL",
    selectedTags: [],
    visibility: {
        tree: false
    },
    onChange: () => console.log("No change handler registered for flow-filter-options-overlay::onChange")
};

function buildHierarchyWithUsageEnrichment(vm) {
    const usedTypeIds = _.map(vm.usedTypes, "id");
    const enrichedDataTypes = _.map(
        vm.allDataTypes,
        dt => Object.assign({}, dt, {isUsed: _.includes(usedTypeIds, dt.id)}));
    const hierarchy = buildHierarchies(enrichedDataTypes, false);
    return hierarchy;
}

function controller(userPreferenceService, serviceBroker) {
    const vm = _.defaults(this, initialState);

    function loadDataTypes() {
        return serviceBroker
            .loadAppData(CORE_API.DataTypeStore.findAll)
            .then(r => vm.allDataTypes = r.data);
    }

    vm.onShowAllTypes = () => {
        vm.selectedType = "ALL";
        vm.visibility.tree = false;
        vm.notifyChanges();
    };

    vm.onShowTree = () => {
        vm.visibility.tree = true;
    };

    vm.onSelectType = (id) => {
        vm.selectedType = id;
        vm.notifyChanges()
    };

    vm.onTagsChange = () => {
        vm.notifyChanges();

        saveTagFilterPreferences(
            vm.usedTags,
            vm.selectedTags,
            groupLogicalFlowFilterExcludedTagIdsKey,
            userPreferenceService);
    };

    vm.showAllTags = () => {
        vm.selectedTags = vm.usedTags;
        vm.notifyChanges();

        saveTagFilterPreferences(
            vm.usedTags,
            vm.selectedTags,
            groupLogicalFlowFilterExcludedTagIdsKey,
            userPreferenceService);
    };

    vm.$onChanges = () => {
        if (!_.isEmpty(vm.usedTypes)) {
            loadDataTypes()
                .then(() => {
                    const hierarchy = buildHierarchyWithUsageEnrichment(vm);
                    vm.hierarchy = hierarchy;
                    vm.notifyChanges();
                });
        }

        if (!_.isEmpty(vm.usedTags)) {
            getSelectedTagsFromPreferences(
                vm.usedTags,
                groupLogicalFlowFilterExcludedTagIdsKey,
                userPreferenceService)
                .then(selectedTags => {
                    vm.selectedTags = selectedTags;
                    vm.notifyChanges();
                });
        }
    };

    vm.notifyChanges = () => {
        const options = {
            typeIds: [vm.selectedType || "ALL"],
            scope: vm.selectedScope || "ALL",
            selectedTags: vm.selectedTags || []
        };
        vm.onChange(options);
    };
    // -- BOOT ---

    vm.notifyChanges();
}

controller.$inject = [
    "UserPreferenceService",
    "ServiceBroker"
];

const component = {
    controller,
    bindings,
    template
};

export default component;


text:
class ofApp : public ofBaseApp{
    walker wk;

	public:
		void setup();
		void update();
		void draw();

		void keyPressed(int key);
		void keyReleased(int key);
		void mouseMoved(int x, int y );
		void mouseDragged(int x, int y, int button);
		void mousePressed(int x, int y, int button);
		void mouseReleased(int x, int y, int button);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);
};


text:
{# AUTOGENERATED. DO NOT EDIT. #}

{% extends "config-connector/_base.html" %}

{% block page_title %}ResourceManagerLien{% endblock %}
{% block body %}

A Lien represents an encumbrance on the actions that can be performed on a resource.

Property
Value

{{gcp_name_short}} Service Name
Cloud Resource Manager

{{gcp_name_short}} Service Documentation
/resource-manager/docs/

{{gcp_name_short}} REST Resource Name
v1.liens

{{gcp_name_short}} REST Resource Documentation
/resource-manager/reference/rest/v1/liens

{{product_name_short}} Resource Short Names
gcpresourcemanagerlien
gcpresourcemanagerliens
resourcemanagerlien

{{product_name_short}} Service Name
cloudresourcemanager.googleapis.com

{{product_name_short}} Resource Fully Qualified Name
resourcemanagerliens.resourcemanager.cnrm.cloud.google.com

    Can Be Referenced by IAMPolicy/IAMPolicyMember
    No

## Custom Resource Definition Properties

### Annotations

        Fields

        cnrm.cloud.google.com/state-into-spec

### Spec
#### Schema
```yaml
origin: string
parent:
  projectRef:
    external: string
    name: string
    namespace: string
reason: string
resourceID: string
restrictions:
- string
```

        Fields

origin

Required

string

{% verbatim %}Immutable. A stable, user-visible/meaningful string identifying the origin
of the Lien, intended to be inspected programmatically. Maximum length of
200 characters.{% endverbatim %}

parent

Required

object

{% verbatim %}{% endverbatim %}

parent.projectRef

Optional

object

{% verbatim %}{% endverbatim %}

parent.projectRef.external

Optional

string

{% verbatim %}Allowed value: string of the format `projects/{{value}}`, where {{value}} is the `number` field of a `Project` resource.{% endverbatim %}

parent.projectRef.name

Optional

string

{% verbatim %}Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names{% endverbatim %}

parent.projectRef.namespace

Optional

string

{% verbatim %}Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/{% endverbatim %}

reason

Required

string

{% verbatim %}Immutable. Concise user-visible strings indicating why an action cannot be performed
on a resource. Maximum length of 200 characters.{% endverbatim %}

resourceID

Optional

string

{% verbatim %}Immutable. Optional. The service-generated name of the resource. Used for acquisition only. Leave unset to create a new resource.{% endverbatim %}

restrictions

Required

list (string)

{% verbatim %}Immutable. The types of operations which should be blocked as a result of this Lien.
Each value should correspond to an IAM permission. The server will validate
the permissions against those for which Liens are supported.  An empty
list is meaningless and will be rejected.
e.g. ['resourcemanager.projects.delete'].{% endverbatim %}

restrictions[]

Required

string

{% verbatim %}{% endverbatim %}

### Status
#### Schema
```yaml
conditions:
- lastTransitionTime: string
  message: string
  reason: string
  status: string
  type: string
createTime: string
name: string
observedGeneration: integer
```

        Fields

        conditions

list (object)

{% verbatim %}Conditions represent the latest available observation of the resource's current state.{% endverbatim %}

        conditions[]

object

{% verbatim %}{% endverbatim %}

        conditions[].lastTransitionTime

string

{% verbatim %}Last time the condition transitioned from one status to another.{% endverbatim %}

        conditions[].message

string

{% verbatim %}Human-readable message indicating details about last transition.{% endverbatim %}

        conditions[].reason

string

{% verbatim %}Unique, one-word, CamelCase reason for the condition's last transition.{% endverbatim %}

        conditions[].status

string

{% verbatim %}Status is the status of the condition. Can be True, False, Unknown.{% endverbatim %}

        conditions[].type

string

{% verbatim %}Type is the type of the condition.{% endverbatim %}

        createTime

string

{% verbatim %}Time of creation.{% endverbatim %}

        name

string

{% verbatim %}A system-generated unique identifier for this Lien.{% endverbatim %}

        observedGeneration

integer

{% verbatim %}ObservedGeneration is the generation of the resource that was most recently observed by the Config Connector controller. If this is equal to metadata.generation, then that means that the current reported status reflects the most recent desired state of the resource.{% endverbatim %}

## Sample YAML(s)

### Typical Use Case
```yaml
# Copyright 2020 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.

apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
kind: ResourceManagerLien
metadata:
  name: resourcemanagerlien-sample
spec:
  origin: project-deletion-prohibited
  reason: This project is protected from deletion, for reasons which can be explained in this field.
  parent:
    projectRef:
      name: resourcemanagerlien-dep
  restrictions:
    - resourcemanager.projects.delete
---
apiVersion: resourcemanager.cnrm.cloud.google.com/v1beta1
kind: Project
metadata:
  annotations:
    # Replace "${ORG_ID?}" with the numeric ID for your organization
    cnrm.cloud.google.com/organization-id: "${ORG_ID?}"
    cnrm.cloud.google.com/auto-create-network: "false"
  name: resourcemanagerlien-dep
spec:
  name: ResourceManagerLien dependency
```

{% endblock %}


text: E-Checker (public -- DLT)


text:
<?php

require 'db_connect.inc.php';

$response=array();//Array to hold json information

$connect=mysqli_connect(DB_HOST,DB_USERNAME,DB_PASSWORD,DB_NAME);

if(mysqli_connect_errno()){
  //Not connected
  $response['success']=0;
  $response['message']="Cannot connect with MySql :".mysqli_connect_errno();
  //echo "Cannot connect with MySql:". mysqli_connect_errno();
  echo json_encode($response);
}else{
  //Successfully connected
  if (isset($_POST['name']) && isset($_POST['email']) && isset($_POST['password'])) {
    $name=$_POST['name'];
    $email=$_POST['email'];
    $password=$_POST['password'];
    if(!empty($name) && !empty($email) && !empty($password)){
      $password=md5($password);
      $query="SELECT * FROM `users` WHERE `email`='$email' LIMIT 1";
      $query_run=mysqli_query($connect,$query);
      if(mysqli_fetch_assoc($query_run)){
        $response['success']=0;
        $response['message']="email has already been registered.";
        //echo "email has already been registered";
        echo json_encode($response);
      }else {
        $query="INSERT INTO `users` (`id`, `name`, `password`, `email`, `last_login`) VALUES (NULL, '$name','$password','$email',CURRENT_TIMESTAMP)";
        $query_run=mysqli_query($connect,$query);
        if($query_run){
          $response['success']=1;
          $response['message']="Your Account has been created.You can login using your email";
          $subject="Survey Application Account Created";
          $message="Registration Successful !"."\r\n"."Your account has been created."."\r\n"."You can log in to your account using your email and your password.";
          $headers='From: Survey Application'."\r\n".'Reply-To: jm.prathab@gmail.com'."\r\n";
          $message = wordwrap($message, 70, "\r\n");
          mail($email,$subject,$message,$headers);
          //echo "Your Account has been created.You can login using your email";
          echo json_encode($response);
          }else{
            $response['success']=0;
            $response['message']="Oops!...Details cannot be added into Database.Try again later.";
            //echo "Details cannot be added into Database";
            echo json_encode($response);
            die();
          }
        }
      }else{
        $response['success']=0;
        $response['message']="Fields cannot be empty.";
        //echo "Fields Cannot be empty";
        echo json_encode($response);
      }
    }
  mysqli_close($connect);
}
?>
<form  action="register.php" method="post">
  Name:
<input type="text" name="name" maxlength="80">

  email:
<input type="text" name="email" maxlength="80">

  Password:
<input type="password" name="password" maxlength="40">

  <input type="Submit" name="submit" value="Submit">
</form>


text:
//enclose in a scope
(function(){

function Button( value, options )
{
	options = options || {};

	if(typeof(options) === "function")
		options = { callback: options };

	var that = this;
	var element = document.createElement("div");
	element.className = "litegui button";

	this.root = element;
	var button = document.createElement("button");
	button.className = "litebutton";
	this.content = button;
	element.appendChild(button);

	button.innerHTML = value;
	button.addEventListener("click", function(e) {
		that.click();
	});

	this.click = function()
	{
		if(options.callback)
			options.callback.call(that);
	}
}

LiteGUI.Button = Button;

/**
* SearchBox
*
* @class SearchBox
* @constructor
* @param {*} value
* @param {Object} options
*/

function SearchBox( value, options )
{
	options = options || {};
	value = value || "";
	var element = document.createElement("div");
	element.className = "litegui searchbox";
	var placeholder = (options.placeholder != null ? options.placeholder : "Search");
	element.innerHTML = "<input value='"+value+"' placeholder='"+ placeholder +"'/>";
	this.input = element.querySelector("input");
	this.root = element;
	var that = this;

	this.input.onchange = function(e) {
		var value = e.target.value;
		if(options.callback)
			options.callback.call(that,value);
	};
}

SearchBox.prototype.setValue = function(v) { this.input.value = v; this.input.onchange(); };
SearchBox.prototype.getValue = function() { return this.input.value; };

LiteGUI.SearchBox = SearchBox;

/**
* ContextMenu
*
* @class ContextMenu
* @constructor
* @param {Array} values (allows object { title: "Nice text", callback: function ... })
* @param {Object} options [optional] Some options:\
* - title: title to show on top of the menu
* - callback: function to call when an option is clicked, it receives the item information
* - ignore_item_callbacks: ignores the callback inside the item, it just calls the options.callback
* - event: you can pass a MouseEvent, this way the ContextMenu appears in that position
*/
function ContextMenu( values, options )
{
	options = options || {};
	this.options = options;
	var that = this;

	//to link a menu with its parent
	if(options.parentMenu)
	{
		if( options.parentMenu.constructor !== this.constructor )
		{
			console.error("parentMenu must be of class ContextMenu, ignoring it");
			options.parentMenu = null;
		}
		else
		{
			this.parentMenu = options.parentMenu;
			this.parentMenu.lock = true;
			this.parentMenu.current_submenu = this;
		}
	}

	if( options.event && options.event.constructor.name !== "MouseEvent" && options.event.constructor.name !== "PointerEvent" && options.event.constructor.name !== "CustomEvent" )
	{
		console.error("Event passed to ContextMenu is not of type MouseEvent or CustomEvent. Ignoring it.");
		options.event = null;
	}

	var root = document.createElement("div");
	root.className = "litecontextmenu litemenubar-panel";
	root.style.minWidth = 100;
	root.style.minHeight = 100;
	root.style.pointerEvents = "none";
	setTimeout( function() { root.style.pointerEvents = "auto"; },100); //delay so the mouse up event is not caugh by this element

	//this prevents the default context browser menu to open in case this menu was created when pressing right button
	root.addEventListener("mouseup", function(e){
		e.preventDefault(); return true;
	}, true);
	root.addEventListener("contextmenu", function(e) {
		if(e.button != 2) //right button
			return false;
		e.preventDefault();
		return false;
	},true);

	root.addEventListener("mousedown", function(e){
		if(e.button == 2)
		{
			that.close();
			e.preventDefault(); return true;
		}
	}, true);

	this.root = root;

	//title
	if(options.title)
	{
		var element = document.createElement("div");
		element.className = "litemenu-title";
		element.innerHTML = options.title;
		root.appendChild(element);
	}

	//entries
	var num = 0;
	for(var i in values)
	{
		var name = values.constructor == Array ? values[i] : i;
		if( name != null && name.constructor !== String )
			name = name.content === undefined ? String(name) : name.content;
		var value = values[i];
		this.addItem( name, value, options );
		num++;
	}

	//close on leave
	root.addEventListener("mouseleave", function(e) {
		if(that.lock)
			return;
		if(root.closing_timer)
			clearTimeout( root.closing_timer );
		root.closing_timer = setTimeout( that.close.bind(that, e), 500 );
		//that.close(e);
	});

	root.addEventListener("mouseenter", function(e) {
		if(root.closing_timer)
			clearTimeout( root.closing_timer );
	});

	function on_mouse_wheel(e)
	{
		var pos = parseInt( root.style.top );
		root.style.top = (pos + e.deltaY * 0.1).toFixed() + "px";
		e.preventDefault();
		return true;
	}

	root.addEventListener("wheel", on_mouse_wheel, true);
	root.addEventListener("mousewheel", on_mouse_wheel, true);

	//insert before checking position
	var root_document = document;
	if(options.event)
		root_document = options.event.target.ownerDocument;

	if(!root_document)
		root_document = document;
	root_document.body.appendChild(root);

	//compute best position
	var left = options.left || 0;
	var top = options.top || 0;
	if(options.event)
	{
		if( options.event.constructor.name !== "MouseEvent" && options.event.constructor.name !== "PointerEvent" && options.event.constructor.name !== "CustomEvent" )
		{
			console.warn("Event passed to ContextMenu is not of type MouseEvent");
			options.event = null;
		}
		else
		{
			left = (options.event.pageX - 10);
			top = (options.event.pageY - 10);
			if(options.title)
				top -= 20;

			if(options.parentMenu)
			{
				var rect = options.parentMenu.root.getBoundingClientRect();
				left = rect.left + rect.width;
			}

			var body_rect = document.body.getBoundingClientRect();
			var root_rect = root.getBoundingClientRect();

			if(left > (body_rect.width - root_rect.width - 10))
				left = (body_rect.width - root_rect.width - 10);
			if(top > (body_rect.height - root_rect.height - 10))
				top = (body_rect.height - root_rect.height - 10);
		}
	}

	root.style.left = left + "px";
	root.style.top = top  + "px";
}

ContextMenu.prototype.addItem = function( name, value, options )
{
	var that = this;
	options = options || {};

	var element = document.createElement("div");
	element.className = "litemenu-entry submenu";

	var disabled = false;

	if(value === null)
	{
		element.classList.add("separator");
		//element.innerHTML = "
"
		//continue;
	}
	else
	{
		element.innerHTML = value && value.title ? value.title : name;
		element.value = value;

		if(value)
		{
			if(value.disabled)
			{
				disabled = true;
				element.classList.add("disabled");
			}
			if(value.submenu || value.has_submenu)
				element.classList.add("has_submenu");
		}

		if(typeof(value) == "function")
		{
			element.dataset["value"] = name;
			element.onclick_callback = value;
		}
		else
			element.dataset["value"] = value;
	}

	this.root.appendChild(element);
	if(!disabled)
		element.addEventListener("click", inner_onclick);
	if(options.autoopen)
		element.addEventListener("mouseenter", inner_over);

	function inner_over(e)
	{
		var value = this.value;
		if(!value || !value.has_submenu)
			return;
		inner_onclick.call(this,e);
	}

	//menu option clicked
	function inner_onclick(e) {
		var value = this.value;
		var close_parent = true;

		if(that.current_submenu)
			that.current_submenu.close(e);

		//global callback
		if(options.callback)
		{
			var r = options.callback.call(that, value, options, e );
			if(r === true)
				close_parent = false;
		}

		//special cases
		if(value)
		{
			if (value.callback && !options.ignore_item_callbacks && value.disabled !== true )  //item callback
			{
				var r = value.callback.call( this, value, options, e, that );
				if(r === true)
					close_parent = false;
			}
			if(value.submenu)
			{
				if(!value.submenu.options)
					throw("ContextMenu submenu needs options");
				var submenu = new LiteGUI.ContextMenu( value.submenu.options, {
					callback: value.submenu.callback,
					event: e,
					parentMenu: that,
					ignore_item_callbacks: value.submenu.ignore_item_callbacks,
					title: value.submenu.title,
					autoopen: options.autoopen
				});
				close_parent = false;
			}
		}

		if(close_parent && !that.lock)
			that.close();
	}

	return element;
}

ContextMenu.prototype.close = function(e, ignore_parent_menu)
{
	if(this.root.parentNode)
		this.root.parentNode.removeChild( this.root );
	if(this.parentMenu && !ignore_parent_menu)
	{
		this.parentMenu.lock = false;
		this.parentMenu.current_submenu = null;
		if( e === undefined )
			this.parentMenu.close();
		else if( e && !LiteGUI.isCursorOverElement( e, this.parentMenu.root) )
			LiteGUI.trigger( this.parentMenu.root, "mouseleave", e );
	}
	if(this.current_submenu)
		this.current_submenu.close(e, true);
	if(this.root.closing_timer)
		clearTimeout( this.root.closing_timer );
}

//returns the top most menu
ContextMenu.prototype.getTopMenu = function()
{
	if( this.options.parentMenu )
		return this.options.parentMenu.getTopMenu();
	return this;
}

ContextMenu.prototype.getFirstEvent = function()
{
	if( this.options.parentMenu )
		return this.options.parentMenu.getFirstEvent();
	return this.options.event;
}

LiteGUI.ContextMenu = ContextMenu;
LiteGUI.ContextualMenu = ContextMenu; //LEGACY: REMOVE

function Checkbox( value, on_change)
{
	var that = this;
	this.value = value;

	var root = this.root = document.createElement("span");
	root.className = "litecheckbox inputfield";
	root.dataset["value"] = value;

	var element = this.element = document.createElement("span");
	element.className = "fixed flag checkbox "+(value ? "on" : "off");
	root.appendChild( element );

	root.addEventListener("click", onClick.bind(this) );

	function onClick(e) {
		this.setValue( this.root.dataset["value"] != "true" );
		e.preventDefault();
		e.stopPropagation();
	}

	this.setValue = function(v)
	{
		if(this.value === v)
			return;

		if( this.root.dataset["value"] == v.toString())
			return;

		this.root.dataset["value"] = v;
		if(v)
		{
			this.element.classList.remove("off");
			this.element.classList.add("on");
		}
		else
		{
			this.element.classList.remove("on");
			this.element.classList.add("off");
		}
		var old_value = this.value;
		this.value = v;

		if(on_change)
			on_change( v, old_value );
	}

	this.getValue = function()
	{
		return this.value;
		//return this.root.dataset["value"] == "true";
	}
}

LiteGUI.Checkbox = Checkbox;

//the tiny box to expand the children of a node
function createLitebox(state, on_change)
{
	var element = document.createElement("span");
	element.className = "listbox " + (state ? "listopen" : "listclosed");
	element.innerHTML = state ? "▼" : "►";
	element.dataset["value"] = state ? "open" : "closed";
	element.addEventListener("click", onClick );
	element.on_change_callback = on_change;

	element.setEmpty = function(v)
	{
		if(v)
			this.classList.add("empty");
		else
			this.classList.remove("empty");
	}

	element.expand = function()
	{
		this.setValue(true);
	}

	element.collapse = function()
	{
		this.setValue(false);
	}

	element.setValue = function(v)
	{
		if(this.dataset["value"] == (v ? "open" : "closed"))
			return;

		if(!v)
		{
			this.dataset["value"] = "closed";
			this.innerHTML = "►";
			this.classList.remove("listopen");
			this.classList.add("listclosed");
		}
		else
		{
			this.dataset["value"] = "open";
			this.innerHTML = "▼";
			this.classList.add("listopen");
			this.classList.remove("listclosed");
		}

		if(on_change)
			on_change( this.dataset["value"] );
	}

	element.getValue = function()
	{
		return this.dataset["value"];
	}

	function onClick(e) {
		//console.log("CLICK");
		var box = e.target;
		box.setValue( this.dataset["value"] == "open" ? false : true );
		if(this.stopPropagation)
			e.stopPropagation();
	}

	return element;
}

LiteGUI.createLitebox = createLitebox;

/**
* List
*
* @class List
* @constructor
* @param {String} id
* @param {Array} values
* @param {Object} options
*/
function List( id, items, options )
{
	options = options || {};

	var root = this.root = document.createElement("ul");
	root.id = id;
	root.className = "litelist";
	this.items = [];
	var that = this;

	this.callback = options.callback;

	//walk over every item in the list
	for(var i in items)
	{
		var item = document.createElement("li");
		item.className = "list-item";
		item.data = items[i];
		item.dataset["value"] = items[i];

		var content = "";
		if(typeof(items[i]) == "string")
			content = items[i] + "";
		else
		{
			content = (items[i].name || items[i].title || "") + "";
			if(items[i].id)
				item.id = items[i].id;
		}
		item.innerHTML = content;

		item.addEventListener("click", function() {

			var list = root.querySelectorAll(".list-item.selected");
			for(var j = 0; j < list.length; ++j)
				list[j].classList.remove("selected");
			this.classList.add("selected");
			LiteGUI.trigger( that.root, "wchanged", this );
			if(that.callback)
				that.callback( this.data  );
		});

		root.appendChild(item);
	}

	if(options.parent)
	{
		if(options.parent.root)
			options.parent.root.appendChild( root );
		else
			options.parent.appendChild( root );
	}
}

List.prototype.getSelectedItem = function()
{
	return this.root.querySelector(".list-item.selected");
}

List.prototype.setSelectedItem = function( name )
{
	var items = this.root.querySelectorAll(".list-item");
	for(var i = 0; i < items.length; i++)
	{
		var item = items[i];
		if(item.data == name)
		{
			LiteGUI.trigger( item, "click" );
			break;
		}
	}
}

LiteGUI.List = List;

/**
* Slider
*
* @class Slider
* @constructor
* @param {Number} value
* @param {Object} options
*/
function Slider(value, options)
{
	options = options || {};
	var root = this.root = document.createElement("div");
	var that = this;
	this.value = value;
	root.className = "liteslider";

	this.setValue = function(value, skip_event)
	{
		//var width = canvas.getClientRects()[0].width;
		var min = options.min || 0.0;
		var max = options.max || 1.0;
		if(value < min) value = min;
		else if(value > max) value = max;
		var range = max - min;
		var norm = (value - min) / range;
		var percentage = (norm*100).toFixed(1) + "%";
		var percentage2 = (norm*100+2).toFixed(1) + "%";
		root.style.background = "linear-gradient(to right, #999 " + percentage + ", #FC0 "+percentage2+", #333 " + percentage2 + ")";

		if(value != this.value)
		{
			this.value = value;
			if(!skip_event)
			{
				LiteGUI.trigger(this.root, "change", value );
				if(this.onChange)
					this.onChange( value );
			}
		}
	}

	function setFromX(x)
	{
		var rect = root.getBoundingClientRect();
		if(!rect)
			return;
		var width = rect.width;
		var norm = x / width;
		var min = options.min || 0.0;
		var max = options.max || 1.0;
		var range = max - min;
		that.setValue( range * norm + min );
	}

	var doc_binded = null;

	root.addEventListener("mousedown", function(e) {
		var mouseX, mouseY;
		if(e.offsetX) { mouseX = e.offsetX; mouseY = e.offsetY; }
		else if(e.layerX) { mouseX = e.layerX; mouseY = e.layerY; }
		setFromX(mouseX);
		doc_binded = root.ownerDocument;
		doc_binded.addEventListener("mousemove", onMouseMove );
		doc_binded.addEventListener("mouseup", onMouseUp );
		e.preventDefault();
		e.stopPropagation();
	});

	function onMouseMove(e)
	{
		var rect = root.getBoundingClientRect();
		if(!rect)
			return;
		var x = e.x === undefined ? e.pageX : e.x;
		var mouseX = x - rect.left;
		setFromX(mouseX);
		e.preventDefault();
		return false;
	}

	function onMouseUp(e)
	{
		var doc = doc_binded || document;
		doc_binded = null;
		doc.removeEventListener("mousemove", onMouseMove );
		doc.removeEventListener("mouseup", onMouseUp );
		e.preventDefault();
		return false;
	}

	this.setValue(value);
}

LiteGUI.Slider = Slider;

/**
* LineEditor
*
* @class LineEditor
* @constructor
* @param {Number} value
* @param {Object} options
*/

function LineEditor(value, options)
{
	options = options || {};
	var element = document.createElement("div");
	element.className = "curve " + (options.extraclass ? options.extraclass : "");
	element.style.minHeight = "50px";
	element.style.width = options.width || "100%";

	element.bgcolor = options.bgcolor || "#222";
	element.pointscolor = options.pointscolor || "#5AF";
	element.linecolor = options.linecolor || "#444";

	element.value = value || [];
	element.xrange = options.xrange || [0,1]; //min,max
	element.yrange = options.yrange || [0,1]; //min,max
	element.defaulty = options.defaulty != null ? options.defaulty : 0.5;
	element.no_trespassing = options.no_trespassing || false;
	element.show_samples = options.show_samples || 0;
	element.options = options;
	element.style.minWidth = "50px";
	element.style.minHeight = "20px";

	var canvas = document.createElement("canvas");
	canvas.width = options.width || 200;
	canvas.height = options.height || 50;
	element.appendChild( canvas );
	element.canvas = canvas;

	element.addEventListener("mousedown",onmousedown);

	element.getValueAt = function(x)
	{
		if(x < element.xrange[0] || x > element.xrange[1])
			return element.defaulty;

		var last = [ element.xrange[0], element.defaulty ];
		var f = 0;
		for(var i = 0; i < element.value.length; i += 1)
		{
			var v = element.value[i];
			if(x == v[0]) return v[1];
			if(x < v[0])
			{
				f = (x - last[0]) / (v[0] - last[0]);
				return last[1] * (1-f) + v[1] * f;
			}
			last = v;
		}

		v = [ element.xrange[1], element.defaulty ];
		f = (x - last[0]) / (v[0] - last[0]);
		return last[1] * (1-f) + v[1] * f;
	}

	element.resample = function(samples)
	{
		var r = [];
		var dx = (element.xrange[1] - element.xrange[0]) / samples;
		for(var i = element.xrange[0]; i <= element.xrange[1]; i += dx)
		{
			r.push( element.getValueAt(i) );
		}
		return r;
	}

	element.addValue = function(v)
	{
		for(var i = 0; i < element.value; i++)
		{
			var value = element.value[i];
			if(value[0] < v[0]) continue;
			element.value.splice(i,0,v);
			redraw();
			return;
		}

		element.value.push(v);
		redraw();
	}

	//value to canvas
	function convert(v)
	{
		return [ canvas.width * ( (element.xrange[1] - element.xrange[0]) * v[0] + element.xrange[0]),
			canvas.height * ((element.yrange[1] - element.yrange[0]) * v[1] + element.yrange[0])];
	}

	//canvas to value
	function unconvert(v)
	{
		return [(v[0] / canvas.width - element.xrange[0]) / (element.xrange[1] - element.xrange[0]),
				(v[1] / canvas.height - element.yrange[0]) / (element.yrange[1] - element.yrange[0])];
	}

	var selected = -1;

	element.redraw = function()
	{
		var rect = canvas.parentNode.getBoundingClientRect();
		if(rect && canvas.width != rect.width && rect.width && rect.width < 1000)
			canvas.width = rect.width;
		if(rect && canvas.height != rect.height && rect.height && rect.height < 1000)
			canvas.height = rect.height;

		var ctx = canvas.getContext("2d");
		ctx.setTransform(1, 0, 0, 1, 0, 0);
		ctx.translate(0,canvas.height);
		ctx.scale(1,-1);

		ctx.fillStyle = element.bgcolor;
		ctx.fillRect(0,0,canvas.width,canvas.height);

		ctx.strokeStyle = element.linecolor;
		ctx.beginPath();

		//draw line
		var pos = convert([element.xrange[0],element.defaulty]);
		ctx.moveTo( pos[0], pos[1] );

		for(var i in element.value)
		{
			var value = element.value[i];
			pos = convert(value);
			ctx.lineTo( pos[0], pos[1] );
		}

		pos = convert([element.xrange[1],element.defaulty]);
		ctx.lineTo( pos[0], pos[1] );
		ctx.stroke();

		//draw points
		for(var i = 0; i < element.value.length; i += 1)
		{
			var value = element.value[i];
			pos = convert(value);
			if(selected == i)
				ctx.fillStyle = "white";
			else
				ctx.fillStyle = element.pointscolor;
			ctx.beginPath();
			ctx.arc( pos[0], pos[1], selected == i ? 4 : 2, 0, Math.PI * 2);
			ctx.fill();
		}

		if(element.show_samples)
		{
			var samples = element.resample(element.show_samples);
			ctx.fillStyle = "#888";
			for(var i = 0; i < samples.length; i += 1)
			{
				var value = [ i * ((element.xrange[1] - element.xrange[0]) / element.show_samples) + element.xrange[0], samples[i] ];
				pos = convert(value);
				ctx.beginPath();
				ctx.arc( pos[0], pos[1], 2, 0, Math.PI * 2);
				ctx.fill();
			}
		}
	}

	var last_mouse = [0,0];
	function onmousedown(evt)
	{
		document.addEventListener("mousemove",onmousemove);
		document.addEventListener("mouseup",onmouseup);

		var rect = canvas.getBoundingClientRect();
		var mousex = evt.clientX - rect.left;
		var mousey = evt.clientY - rect.top;

		selected = computeSelected(mousex,canvas.height-mousey);

		if(selected == -1)
		{
			var v = unconvert([mousex,canvas.height-mousey]);
			element.value.push(v);
			sortValues();
			selected = element.value.indexOf(v);
		}

		last_mouse = [mousex,mousey];
		element.redraw();
		evt.preventDefault();
		evt.stopPropagation();
	}

	function onmousemove(evt)
	{
		var rect = canvas.getBoundingClientRect();
		var mousex = evt.clientX - rect.left;
		var mousey = evt.clientY - rect.top;

		if(mousex < 0) mousex = 0;
		else if(mousex > canvas.width) mousex = canvas.width;
		if(mousey < 0) mousey = 0;
		else if(mousey > canvas.height) mousey = canvas.height;

		//dragging to remove
		if( selected != -1 && distance( [evt.clientX - rect.left, evt.clientY - rect.top], [mousex,mousey] ) > canvas.height * 0.5 )
		{
			element.value.splice(selected,1);
			onmouseup(evt);
			return;
		}

		var dx = last_mouse[0] - mousex;
		var dy = last_mouse[1] - mousey;
		var delta = unconvert([-dx,dy]);
		if(selected != -1)
		{
			var minx = element.xrange[0];
			var maxx = element.xrange[1];

			if(element.no_trespassing)
			{
				if(selected > 0) minx = element.value[selected-1][0];
				if(selected < (element.value.length-1) ) maxx = element.value[selected+1][0];
			}

			var v = element.value[selected];
			v[0] += delta[0];
			v[1] += delta[1];
			if(v[0] < minx) v[0] = minx;
			else if(v[0] > maxx) v[0] = maxx;
			if(v[1] < element.yrange[0]) v[1] = element.yrange[0];
			else if(v[1] > element.yrange[1]) v[1] = element.yrange[1];
		}

		sortValues();
		element.redraw();
		last_mouse[0] = mousex;
		last_mouse[1] = mousey;
		onchange();

		evt.preventDefault();
		evt.stopPropagation();
	}

	function onmouseup(evt)
	{
		selected = -1;
		element.redraw();
		document.removeEventListener("mousemove",onmousemove);
		document.removeEventListener("mouseup",onmouseup);
		onchange();
		evt.preventDefault();
		evt.stopPropagation();
	}

	function onresize(e)
	{
		element.redraw();
	}

	function onchange()
	{
		if(options.callback)
			options.callback.call(element,element.value);
		else
			LiteGUI.trigger(element,"change");
	}

	function distance(a,b) { return Math.sqrt( Math.pow(b[0]-a[0],2) + Math.pow(b[1]-a[1],2) ); };

	function computeSelected(x,y)
	{
		var min_dist = 100000;
		var max_dist = 8; //pixels
		var selected = -1;
		for(var i=0; i < element.value.length; i++)
		{
			var value = element.value[i];
			var pos = convert(value);
			var dist = distance([x,y],pos);
			if(dist < min_dist && dist < max_dist)
			{
				min_dist = dist;
				selected = i;
			}
		}
		return selected;
	}

	function sortValues()
	{
		var v = null;
		if(selected != -1)
			v = element.value[selected];
		element.value.sort(function(a,b) { return a[0] - b[0]; });
		if(v)
			selected = element.value.indexOf(v);
	}

	element.redraw();
	return element;
}

LiteGUI.LineEditor = LineEditor;

function ComplexList( options )
{
	options = options || {};

	this.root = document.createElement("div");
	this.root.className = "litecomplexlist";

	this.item_code = options.item_code || "
"+LiteGUI.special_codes.tick+"<button class='trash'>"+LiteGUI.special_codes.close+"</button>
";

	if(options.height)
		this.root.style.height = LiteGUI.sizeToCSS( options.height );

	this.selected = null;
	this.onItemSelected = null;
	this.onItemToggled = null;
	this.onItemRemoved = null;
}

ComplexList.prototype.addTitle = function( text )
{
	var elem = LiteGUI.createElement("div",".listtitle",text);
	this.root.appendChild( elem );
	return elem;
}

ComplexList.prototype.addHTML = function( html, on_click )
{
	var elem = LiteGUI.createElement("div",".listtext", html );
	if(on_click)
		elem.addEventListener("mousedown", on_click);
	this.root.appendChild( elem );
	return elem;
}

ComplexList.prototype.clear = function()
{
	this.root.innerHTML = "";
}

ComplexList.prototype.addItem = function( item, text, is_enabled, can_be_removed )
{
	var title = text || item.content || item.name;
	var elem = LiteGUI.createListItem( this.item_code, { ".title": title } );
	elem.item = item;

	if(is_enabled)
		elem.classList.add("enabled");

	if(!can_be_removed)
		elem.querySelector(".trash").style.display = "none";

	var that = this;
	elem.addEventListener("mousedown", function(e){
		e.preventDefault();
		this.setSelected(true);
		if(that.onItemSelected)
			that.onItemSelected( item, elem );
	});
	elem.querySelector(".tick").addEventListener("mousedown",  function(e){
		e.preventDefault();
		elem.classList.toggle("enabled");
		if(that.onItemToggled)
			that.onItemToggled( item, elem, elem.classList.contains("enabled"));
	});

	elem.querySelector(".trash").addEventListener("mousedown",function(e){
		e.preventDefault();
		e.stopPropagation();
		e.stopImmediatePropagation();
		if(that.onItemRemoved)
			that.onItemRemoved( item, elem );
	});

	elem.setContent = function(v, is_html){
		if(is_html)
			elem.querySelector(".title").innerHTML = v;
		else
			elem.querySelector(".title").innerText = v;
	}

	elem.toggleEnabled = function(v){
		elem.classList.toggle("enabled");
	}

	elem.setSelected = function(v)
	{
		LiteGUI.removeClass( that.root, "selected" );
		if(v)
			this.classList.add("selected");
		else
			this.classList.remove("selected");
		that.selected = elem.item;
	}

	elem.show = function() { this.style.display = ""; }
	elem.hide = function() { this.style.display = "none"; }

	this.root.appendChild( elem );
	return elem;
}

LiteGUI.ComplexList = ComplexList;

})();