<commit_before>var HyperNotes = HyperNotes || {};

HyperNotes.Template = {
  noteSummary: ' \

 \

 \

 \
           \

 \

 \
          ${note.title} \

 \

 \
          {{if note.location.unparsed}} \
          @${note.location.unparsed} \
          {{/if}} \

 \

 \
          ${note.start.unparsed} \
          {{if note.end.unparsed }} \
           - ${note.end.unparsed} \
          {{/if}} \

 \

 \
          {{if note.tags.length}} \

 \
            {{each note.tags}} \

${$value}
 \
            {{/each}} \

 \
          {{/if}} \

 \

 \

 \
        <input class="note-input" type="text" value="${label}" name="label" /> \

 \

 \
  ',

  timeMap: ' \

 \

 \

 \

 \

 \

 \
  ',

  thread: ' \

 \

${thread.title}
 \

${thread.description}
 \

 \

Quick Add and Edit
 \

 \
          <input id="new-note" placeholder="Add note then enter to save, use #... for tag, ^...^ for dates, @...@ for location" type="text" /> \

 \
 \

 \

 \

 \

 \

 \
  ',
};

<commit_msg>[js/template][xs]: fix to thread view js template (follow up to 033c351c53d488aabc41c9f1b5ddecb33f7f7844).<commit_after>var HyperNotes = HyperNotes || {};

HyperNotes.Template = {
  noteSummary: ' \

 \

 \

 \
           \

 \

 \
          ${note.title} \

 \

 \
          {{if note.location.unparsed}} \
          @${note.location.unparsed} \
          {{/if}} \

 \

 \
          ${note.start} \
          {{if note.end}} \
           - ${note.end} \
          {{/if}} \

 \

 \
          {{if note.tags.length}} \

 \
            {{each note.tags}} \

${$value}
 \
            {{/each}} \

 \
          {{/if}} \

 \

 \

 \
        <input class="note-input" type="text" value="${label}" name="label" /> \

 \

 \
  ',

  timeMap: ' \

 \

 \

 \

 \

 \

 \
  ',

  thread: ' \

 \

${thread.title}
 \

${thread.description}
 \

 \

Quick Add and Edit
 \

 \
          <input id="new-note" placeholder="Add note then enter to save, use #... for tag, ^...^ for dates, @...@ for location" type="text" /> \

 \
 \

 \

 \

 \

 \

 \
  ',
};

<|endoftext|>


<commit_before>$(document).ready(function() {
    functions.allcomments();
    $(".button-collapse").sideNav();
    $('.materialboxed').materialbox();
    $('select').material_select();
  	$('#textarea1').trigger('autoresize');
<<<<<<< HEAD
   	$(".select_archivo").change(function() {
    	if (!$('.select_archivo:checked')){
    		$("#toggle_file").fadeOut();
    		$("#edit_file").attr('enctype', '');
       	}else{
    		$("#toggle_file").fadeIn();
    		$("#edit_file").attr('enctype', 'multipart/form-data');
    	}
  	});
});
=======
    $('.modal-trigger').leanModal();
    $("#sub_archivo").click(function(event) {
  		event.preventDefault();
  		$("#file").trigger('click');
    });

    $('#type').val('0');
    $('#type').change(function(){
        //console.log($('#type').val());
        var format = $('#type').val();
        functions.filter(format);
    });

    $('#addComment').on('click', function () {
        var data = $('#formComment').serialize();
        functions.comment(data);
    })
});
>>>>>>> 6cc8f30fbca7b3e6ce554e897a862372a03d7f7a
<commit_msg>Adelantos<commit_after>$(document).ready(function() {
    functions.allcomments();
    $(".button-collapse").sideNav();
    $('.materialboxed').materialbox();
    $('select').material_select();
  	$('#textarea1').trigger('autoresize');
   	$(".select_archivo").change(function() {
    	if (!$('.select_archivo:checked')){
    		$("#toggle_file").fadeOut();
    		$("#edit_file").attr('enctype', '');
       	}else{
    		$("#toggle_file").fadeIn();
    		$("#edit_file").attr('enctype', 'multipart/form-data');
    	}
  	});
    $('.modal-trigger').leanModal();
    $("#sub_archivo").click(function(event) {
  		event.preventDefault();
  		$("#file").trigger('click');
    });

    $('#type').val('0');
    $('#type').change(function(){
        //console.log($('#type').val());
        var format = $('#type').val();
        functions.filter(format);
    });

    $('#addComment').on('click', function () {
        var data = $('#formComment').serialize();
        functions.comment(data);
    });
});<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2013 Google Inc. All Rights Reserved
 *
 * 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.
 */

var touchManager = TouchManager.create({});
touchManager.install(document);
var gestureManager = GestureManager.create();

MODEL({
  name: 'ModelListController',
  properties: [
    {
      name: 'search',
      view: { model_: 'TextFieldView', onKeyMode: true }
    },
    {
      name: 'dao',
      factory: function() {
        var newDAO = MDAO.create({model:Model});

        // This is to make sure getPrototype is called, even if the model object has been created
        // without a .create or .getPrototype having been called yet.
        for ( var key in UNUSED_MODELS ) this.X[key].getPrototype && this.X[key].getPrototype();
        for ( var key in USED_MODELS ) this.X[key].getPrototype && this.X[key].getPrototype();

        // All models are now in USED_MODELS
        for ( var key in USED_MODELS ) {
          var m = this.X[key];
          if ( ! m.getPrototype ) continue;
          m.getPrototype();
          newDAO.put(m);
        };

        return newDAO;
      }
    },
    {
      name: 'filteredDAO',
      model_: 'DAOProperty',
      view: {
        model_: 'DAOListView', //'ScrollView',
        rowView: 'ModelDescriptionRowView',
        //useSelection: true // clicks are happening, listen for selection$ changes
      },

      dynamicValue: function() {
        return this.dao.orderBy(this.order)
            .where(CONTAINS_IC(Model.NAME, this.search));
      }
    }
  ]
});

MODEL({ name: 'ModelDescriptionRowView', extendsModel: 'DetailView', templates: [
  function toHTML() {/*

$$name{mode:'read-only'}: $$help{mode: 'read-only'}

  */}
]});

MODEL({
  name: 'ControllerView',
  extendsModel: 'DetailView',

  templates: [
    function toHTML() {/*

$$search

$$filteredDAO

    */}
  ]
});

/** A display-only on-line help view. **/
MODEL({
  name: 'DocView',
  extendsModel: 'View',

  properties: [
    {
      name: 'data',
      type: 'Model',
      postSet: function(old, nu) {
        // replace our content in the DOM
        this.updateHTML();
      }
    }
  ],

  methods: {
    // TODO: make this a template
    toInnerHTML: function() {
      var model = this.data;
      var out   = [];

      if (!model || !model.properties) return;

      out.push('
');
      out.push(model.help);
      out.push('
');

      for ( var i = 0 ; i < model.properties.length ; i++ ) {
        var prop = model.properties[i];

        if ( prop.hidden ) continue;

        out.push('
');
        out.push(prop.label);
        out.push('

');
        if ( prop.subType /*&& value instanceof Array*/ && prop.type.indexOf('[') != -1 ) {
          var subModel = this.X[prop.subType];
          var subView  = DocView.create({model: subModel});
          if ( subModel != model )
            out.push(subView.toHTML());
        } else {
          out.push(prop.help);
        }
        out.push('
');
      }
      return out.join('');
    }
  }
});

MODEL({
  name: 'DocBrowserController',
  extendsModel: 'Model',

  methods: {
    init: function() {
      // spawn and populate subcontext
      //this.X = this.X.sub(); // TODO: fix context propagation
      this.X.selection$ = SimpleValue.create();

      this.SUPER();

      // Push selection value out to the context so others can use it
      this.selection$ = this.X.selection$;
    }
  },

  properties: [
    {
      name: 'modelList',
      factory: function() {
        return this.X.ModelListController.create();
      },
      view: {
        model_: 'ControllerView',
        model: ModelListController
      }
    },
    {
      name: 'selection',
      view: 'DocView'
    }
  ]
});

MODEL({
  name: 'DocBrowserView',
  extendsModel: 'DetailView',

  templates: [
    function toHTML()    {/*

$$modelList

$$selection

    */}
  ]
});

<commit_msg>Added URL support for easy link browsing<commit_after>/**
 * @license
 * Copyright 2013 Google Inc. All Rights Reserved
 *
 * 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.
 */

var touchManager = TouchManager.create({});
touchManager.install(document);
var gestureManager = GestureManager.create();

MODEL({
  name: 'ModelListController',
  properties: [
    {
      name: 'search',
      view: { model_: 'TextFieldView', onKeyMode: true }
    },
    {
      name: 'dao',
      factory: function() {
        var newDAO = MDAO.create({model:Model});

        // This is to make sure getPrototype is called, even if the model object
        // has been created without a .create or .getPrototype having been called
        // yet.
        for ( var key in UNUSED_MODELS ) {
          this.X[key].getPrototype && this.X[key].getPrototype();
        }
        for ( var key in USED_MODELS ) {
          this.X[key].getPrototype && this.X[key].getPrototype();
        }

        // All models are now in USED_MODELS
        for ( var key in USED_MODELS ) {
          var m = this.X[key];
          if ( ! m.getPrototype ) continue;
          m.getPrototype();
          newDAO.put(m);
        };

        return newDAO;
      }
    },
    {
      name: 'filteredDAO',
      model_: 'DAOProperty',
      view: {
        model_: 'DAOListView', //'ScrollView',
        rowView: 'ModelDescriptionRowView',
      },

      dynamicValue: function() {
        return this.dao.orderBy(this.order)
            .where(CONTAINS_IC(Model.NAME, this.search));
      }
    }
  ]
});

MODEL({ name: 'ModelDescriptionRowView', extendsModel: 'DetailView', templates: [
  function toHTML() {/*

$$name{mode:'read-only'}

  */}
]});

MODEL({
  name: 'ControllerView',
  extendsModel: 'DetailView',

  templates: [
    function toHTML() {/*

$$search

$$filteredDAO

    */}
  ]
});

/** A display-only on-line help view. **/
MODEL({
  name: 'DocView',
  extendsModel: 'View',

  properties: [
    {
      name: 'data',
      type: 'Model',
      help: 'The model for which to show documentation.',
      postSet: function(old, nu) {
        // replace our content in the DOM
        this.updateHTML();
      }
    },
//    {
//      name: 'introduction',
//      type:
//    }
  ],
  templates: [
    function toInnerHTML()    {/*
<%    if (this.data) {  %>

<%=this.data.name%>

<%        if (this.data.extendsModel) { %>

Extends <a href="#<%=this.data.extendsModel%>"><%=this.data.extendsModel%>

<%        } else { %>

Extends Model

<%        } %>

<%=this.data.help%>

<%        for ( var i = 0 ; i < this.data.properties.length ; i++ ) {
            var prop = this.data.properties[i];
            if ( prop.hidden ) continue;  %>

                <%=prop.label%>

<%            if ( prop.subType && prop.type.indexOf('[') != -1 ) {
                var subModel = this.X[prop.subType];
                var subView  = this.X.DocView.create({model: subModel});
                if ( subModel != this.data ) %>
                  <%=subView.toHTML()%>
<%              } else {    %>
                  <%=prop.help%>
<%              } %>

<%          } %>

<%    } %>
    */}
  ]

});

MODEL({
  name: 'DocBrowserController',
  extendsModel: 'Model',

  methods: {
    init: function() {
      // spawn and populate subcontext
      //this.X = this.X.sub(); // TODO: fix context propagation
      this.X.selection$ = SimpleValue.create();

      this.SUPER();

      // Push selection value out to the context so others can use it
      this.selection$ = this.X.selection$;

      // hack in URL support
      this.X.selection$.addListener(this.onSelectionChange);
      window.addEventListener('hashchange', function() {
        this.selection = this.X[location.hash.substring(1)];
      }.bind(this));
    }
  },

  listeners: [
    {
     name: 'onSelectionChange',
     code: function(evt) {
        location.hash = "#" + this.X.selection$.value.name;
     }
    }
  ],

  properties: [
    {
      name: 'modelList',
      factory: function() {
        return this.X.ModelListController.create();
      },
      view: {
        model_: 'ControllerView',
        model: ModelListController
      }
    },
    {
      name: 'selection',
      view: 'DocView'
    }
  ]
});

MODEL({
  name: 'DocBrowserView',
  extendsModel: 'DetailView',

  templates: [
    function toHTML()    {/*

$$modelList

$$selection

    */}
  ]
});

<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved
 *
 * 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.
 */

var touchManager = TouchManager.create({});
touchManager.install(document);
var gestureManager = GestureManager.create();

MODEL({
  name: 'ModelListController',
  properties: [
    {
      name: 'search',
			postSet: function() { console.log("Search change: "+this.search); }
    },
    {
      name: 'searchView',
      factory: function() {
        return this.X.mdTextFieldView.create({ data$: this.search$, label:'Search', onKeyMode: true, displayWidth: 20 });
      }
    },
    {
      name: 'dao',
      factory: function() {
        var newDAO = this.X.MDAO.create({model:Model});

        // This is to make sure getPrototype is called, even if the model object
        // has been created without a .create or .getPrototype having been called
        // yet.
        for ( var key in UNUSED_MODELS ) {
          this.X[key].getPrototype && this.X[key].getPrototype();
        }
        for ( var key in USED_MODELS ) {
          this.X[key].getPrototype && this.X[key].getPrototype();
        }

        // All models are now in USED_MODELS
        for ( var key in USED_MODELS ) {
          var m = this.X[key];
          if ( ! m.getPrototype ) continue;
          m.getPrototype();
          newDAO.put(m);
        };

        return newDAO;
      }
    },
    {
      name: 'filteredDAO',
      model_: 'DAOProperty',

      dynamicValue: function() {
        return this.dao.orderBy(this.order)
            .where(CONTAINS_IC(Model.NAME, this.search));
      }
    },
    {
      name: 'filteredDAOView',
      factory: function() {
        return this.X.DAOListView.create({ data$: this.filteredDAO$, rowView: 'ModelDescriptionRowView' });
      }
    }
  ]
});

MODEL({
  name: 'ModelDescriptionRowView',
  extendsModel: 'View',

  properties: [
    {
      name: 'data',
      help: 'The Model to describe',
      preSet: function(old,nu) {
        if (old) Events.unfollow(old.name$, this.modelName$);
        Events.follow(nu.name$, this.modelName$);
        return nu;
      }
    },
    {
      name: 'modelName',
      help: 'The Model to describe'
    },
  ],

  methods: {
    init: function() {
      // set up context // TODO: template is compile before we create subcontext
      this.X = this.X.sub({name:'ModelDescriptionRowView_X'});
      this.X.documentationViewParentModel = SimpleValue.create();

      this.SUPER();
    }
  },
  templates: [ // TODO: the data gets set on the modelNameView... screws it up
    function toInnerHTML() {/*

$$modelName{model_:'DocRefView', ref$: this.modelName$}

    */}
  ]
});

MODEL({
  name: 'ControllerView',
  extendsModel: 'DetailView',

  methods: {
    initHTML: function() {
      this.data.searchView.initHTML();
      this.data.filteredDAOView.initHTML();
    }
  },

  templates: [
    function toHTML() {/*

<%=this.data.searchView.toHTML()%>

<%=this.data.filteredDAOView.toHTML()%>

    */}
  ]
});

MODEL({
  name: 'DocBrowserController',
  extendsModel: 'Model',

  documentation: function() {  /*

Some documentation for the $$DOC{ref:'.'} model.

This should be expaneded to explain some of the interesting properties found here, such as $$DOC{ref:'.modelList'}.

We can also mention how invalid references are caught $$DOC{ref:'modelList'}.

And here's a normal property view in the same template: $$data{ mode: 'read-only' }

Though you'd often want to link to related models, like $$DOC{ref:'DocModelBodyView'}, or even specific features on them, like $$DOC{ref:'DocModelView.data', text:'DocModelView's data property'}.

Reference to a method argument: $$DOC{ref:'DocBrowserController.testMethod.args.testy'}

This won't work since 'properties' here will resolve to the DocBrowserController.PROPERTIES feature: $$DOC{ref:'DocBrowserController.properties.modelListView'}. Only use direct access for layers below Model.feature.

  */},

  methods: {
    init: function() {
      /* This is a method documentation comment: spawn and populate sub contexts. */

      // search context uses a selection value to indicate the chosen Model to display
      this.SearchContext = this.X.sub({}, 'searchX');
      this.SearchContext.selection$ = this.SearchContext.SimpleValue.create(); // holds a Model definition

      // detail context needs a documentViewParentModel to indicate what model it is rooted at
      this.DetailContext = this.X.sub({}, 'detailX');
      this.DetailContext.documentViewParentModel = this.DetailContext.SimpleValue.create();
      this.DetailContext.documentViewRef = this.DetailContext.DocRef.create();
      //Events.follow(this.SearchContext.selection$, this.DetailContext.documentViewParentModel);

      this.X.documentViewRequestNavigation = function(ref) {
        if (ref.valid) {
          // TODO: navigate to feature sub-view as well
          this.selection = ref.resolvedModelChain[0]; // TODO: tighten up this update chain
          this.DetailContext.documentViewParentModel.set(ref.resolvedModelChain[0]);
          this.DetailContext.documentViewRef.ref = ref.resolvedRef;
          this.SearchContext.selection$.set(this.DetailContext.documentViewParentModel.get());
          location.hash = "#" + ref.resolvedRef;
        }
      }.bind(this);

      /////////////////////////// Context setup ^
      this.SUPER();
      /////////////////////////// this.init v

      // when the hash changes set the documentViewParentModel and this.selection
      window.addEventListener('hashchange', function() {
        this.DetailContext.documentViewRef.ref = location.hash.substring(1);
        if (this.DetailContext.documentViewRef.valid) {
          this.DetailContext.documentViewParentModel.set(
               this.DetailContext.documentViewRef.resolvedModelChain[0]);
          this.SearchContext.selection$.set(this.DetailContext.documentViewParentModel.get());

        }
      }.bind(this));

      // initialization from hash
      if (location.hash === '#' || location.hash === '#undefined' || location.hash.length === 0) location.hash = 'DevDocumentation_Welcome';
      this.DetailContext.documentViewRef.ref = location.hash.substring(1);
      if (this.DetailContext.documentViewRef.valid) {
        this.DetailContext.documentViewParentModel.set(
             this.DetailContext.documentViewRef.resolvedModelChain[0]);
        this.SearchContext.selection$.set(this.DetailContext.documentViewParentModel.get());
      }

      var testArg = this.X.Arg.create({name: 'testy'});
      testArg.documentation = this.X.Documentation.create({
        body: function() { /*
          Argument $$DOC{ref:'.'} documentation.
          */ }
      });
      this.model_.methods[1].args.push(testArg);
    },

    testMethod: function(a1, b2) {
      return a1 + b2;
    }
  },

  listeners: [
    {
      name: 'onReadyToScroll',
      code: function(evt) {

      }
    }
  ],

  properties: [
    {
      name: 'modelList',
      factory: function() {
        return this.SearchContext.ModelListController.create();
      }
    },
    {
      name: 'modelListView',
      factory: function() {
        return this.SearchContext.ControllerView.create({ model: ModelListController,
                                                          data$: this.modelList$ });
      }
    },
    {
      name: 'selectionView',
      factory: function() {
        return this.DetailContext.DocModelView.create({ model: Model, data: this.DetailContext.documentViewRef });
      }
    },
  ]

});

MODEL({
  name: 'DocBrowserView',
  extendsModel: 'DetailView',

	methods: {
	 initHTML: function() {
	   this.data.modelListView.initHTML();
	   this.data.selectionView.initHTML();
	 }
	},

//  templates: [
//    function toHTML()    {/*
//

//
FOAM Documentation Browser

//

//
<%=this.data.modelListView.toHTML()%>

//
<%=this.data.selectionView.toHTML()%>

//

//

//    */}
//  ]

  templates: [
    function CSS() {/*
      body {
        margin: 0px;
        font-family: 'Roboto', sans-serif;
        font-size: inherit;

        background-color: #e0e0e0;
        position: relative;
      }

      .docbrowser-header {
        height: 90px;
        position: relative;
        color: #fff;
        z-index: 1;
      }

      .docbrowser-header-inner {
        background-color: #5555FF;
        position: absolute;
        height: 120px;
        width: 100%;
      }

      .docbrowser-header-flex-container {
        display: flex;
        justify-content: space-around;
        margin: 0 50px;
      }
      .docbrowser-header-contents {
        flex-grow: 1;
        max-width: 1280px;

        display: flex;
        justify-content: space-between;
      }

      .docbrowser-title {
        font-weight: lighter;
        font-size: 250%;
        margin-top: 20px;
      }
      .docbrowser-tabs {
        font-size: 120%;
        font-weight: lighter;
        margin-top: 40px;
        margin-right: 20px;
      }
      .docbrowser-tab {
        margin-left: 50px;
      }
      .docbrowser-tab.enabled {
        font-weight: normal;
      }

      .outer-container {
        margin: 0 30px;
        z-index: 2;
        position: relative;
      }
      .outer-flex-container {
        display: flex;
        justify-content: space-around;
        margin-bottom: 60px;
        width: 100%;
        height: 83%;
      }
      .inner-container {
        background-color: #fff;
        border: 1px solid #888;
        border-radius: 12px;
        flex-grow: 1;
        max-width: 1280px;
        padding: 15px;
        box-shadow: 0px 5px 5px #888888;
				display:flex;
      }

      input {
        font-family: inherit;
        font-size: inherit;
      }

      p {
        padding-bottom: 0.5em;
      }
      li {
        padding-bottom: 0.5em;
      }

      div.listPane {
				min-width: 200px;
				flex-basis: 200px;
				order: 1;
        padding: 1em;
				flex-grow: 0;
				overflow-x: hidden;

				display: flex;
			  flex-direction: column;
      }

      div.detailPane {
        order: 2;
				flex-grow: 10;
        overflow-y: scroll;
        padding: 1em;
      }

			div.detailPane div.chapters h2 {
				font-size: 110%;
			}

			div.search-field-container {
				flex-grow: 0;
				order: 1;
			}

			div.list-container {
				order: 2;
				flex-grow: 1;
			  overflow-y:scroll;
				overflow-x:hidden;
			}
			div.list-container span.docLink {
				border-bottom: none;
			}

			div.members {
        padding-left: 2em;
      }
      div.memberList {
        padding-left: 2em;
      }

      div.inherited {
        color: #666666;
      }

			p.browse-list-entry {
				font-size:100%;
				font-weight: bold;
				line-height: 150%
			}

      span.docLink {
        cursor: pointer;
				color: #000077;
        border-bottom: 0.1em dotted #999;
      }

      span.docLinkNoDocumentation {
        color: #770000;

      }

      .light {
        color: #444;
      }
    */},
    function toHTML() {/*
      <div id="<%= this.id %>">

FOAM Documentation

        <div id="<%= this.id %>-outer-container" class="outer-container">

            <div id="<%= this.id %>-inner-container" class="inner-container">

<%=this.data.modelListView.toHTML()%>

<%=this.data.selectionView.toHTML()%>

    */}
  ]

});

<commit_msg>DocBrowser more CSS improvements<commit_after>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved
 *
 * 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.
 */

var touchManager = TouchManager.create({});
touchManager.install(document);
var gestureManager = GestureManager.create();

MODEL({
  name: 'ModelListController',
  properties: [
    {
      name: 'search',
			postSet: function() { console.log("Search change: "+this.search); }
    },
    {
      name: 'searchView',
      factory: function() {
        return this.X.mdTextFieldView.create({ data$: this.search$, label:'Search', onKeyMode: true, displayWidth: 20 });
      }
    },
    {
      name: 'dao',
      factory: function() {
        var newDAO = this.X.MDAO.create({model:Model});

        // This is to make sure getPrototype is called, even if the model object
        // has been created without a .create or .getPrototype having been called
        // yet.
        for ( var key in UNUSED_MODELS ) {
          this.X[key].getPrototype && this.X[key].getPrototype();
        }
        for ( var key in USED_MODELS ) {
          this.X[key].getPrototype && this.X[key].getPrototype();
        }

        // All models are now in USED_MODELS
        for ( var key in USED_MODELS ) {
          var m = this.X[key];
          if ( ! m.getPrototype ) continue;
          m.getPrototype();
          newDAO.put(m);
        };

        return newDAO;
      }
    },
    {
      name: 'filteredDAO',
      model_: 'DAOProperty',

      dynamicValue: function() {
        return this.dao.orderBy(this.order)
            .where(CONTAINS_IC(Model.NAME, this.search));
      }
    },
    {
      name: 'filteredDAOView',
      factory: function() {
        return this.X.DAOListView.create({ data$: this.filteredDAO$, rowView: 'ModelDescriptionRowView' });
      }
    }
  ]
});

MODEL({
  name: 'ModelDescriptionRowView',
  extendsModel: 'View',

  properties: [
    {
      name: 'data',
      help: 'The Model to describe',
      preSet: function(old,nu) {
        if (old) Events.unfollow(old.name$, this.modelName$);
        Events.follow(nu.name$, this.modelName$);
        return nu;
      }
    },
    {
      name: 'modelName',
      help: 'The Model to describe'
    },
  ],

  methods: {
    init: function() {
      // set up context // TODO: template is compile before we create subcontext
      this.X = this.X.sub({name:'ModelDescriptionRowView_X'});
      this.X.documentationViewParentModel = SimpleValue.create();

      this.SUPER();
    }
  },
  templates: [ // TODO: the data gets set on the modelNameView... screws it up
    function toInnerHTML() {/*

$$modelName{model_:'DocRefView', ref$: this.modelName$}

    */}
  ]
});

MODEL({
  name: 'ControllerView',
  extendsModel: 'DetailView',

  methods: {
    initHTML: function() {
      this.data.searchView.initHTML();
      this.data.filteredDAOView.initHTML();
    }
  },

  templates: [
    function toHTML() {/*

<%=this.data.searchView.toHTML()%>

<%=this.data.filteredDAOView.toHTML()%>

    */}
  ]
});

MODEL({
  name: 'DocBrowserController',
  extendsModel: 'Model',

  documentation: function() {  /*

Some documentation for the $$DOC{ref:'.'} model.

This should be expaneded to explain some of the interesting properties found here, such as $$DOC{ref:'.modelList'}.

We can also mention how invalid references are caught $$DOC{ref:'modelList'}.

And here's a normal property view in the same template: $$data{ mode: 'read-only' }

Though you'd often want to link to related models, like $$DOC{ref:'DocModelBodyView'}, or even specific features on them, like $$DOC{ref:'DocModelView.data', text:'DocModelView's data property'}.

Reference to a method argument: $$DOC{ref:'DocBrowserController.testMethod.args.testy'}

This won't work since 'properties' here will resolve to the DocBrowserController.PROPERTIES feature: $$DOC{ref:'DocBrowserController.properties.modelListView'}. Only use direct access for layers below Model.feature.

  */},

  methods: {
    init: function() {
      /* This is a method documentation comment: spawn and populate sub contexts. */

      // search context uses a selection value to indicate the chosen Model to display
      this.SearchContext = this.X.sub({}, 'searchX');
      this.SearchContext.selection$ = this.SearchContext.SimpleValue.create(); // holds a Model definition

      // detail context needs a documentViewParentModel to indicate what model it is rooted at
      this.DetailContext = this.X.sub({}, 'detailX');
      this.DetailContext.documentViewParentModel = this.DetailContext.SimpleValue.create();
      this.DetailContext.documentViewRef = this.DetailContext.DocRef.create();
      //Events.follow(this.SearchContext.selection$, this.DetailContext.documentViewParentModel);

      this.X.documentViewRequestNavigation = function(ref) {
        if (ref.valid) {
          // TODO: navigate to feature sub-view as well
          this.selection = ref.resolvedModelChain[0]; // TODO: tighten up this update chain
          this.DetailContext.documentViewParentModel.set(ref.resolvedModelChain[0]);
          this.DetailContext.documentViewRef.ref = ref.resolvedRef;
          this.SearchContext.selection$.set(this.DetailContext.documentViewParentModel.get());
          location.hash = "#" + ref.resolvedRef;
        }
      }.bind(this);

      /////////////////////////// Context setup ^
      this.SUPER();
      /////////////////////////// this.init v

      // when the hash changes set the documentViewParentModel and this.selection
      window.addEventListener('hashchange', function() {
        this.DetailContext.documentViewRef.ref = location.hash.substring(1);
        if (this.DetailContext.documentViewRef.valid) {
          this.DetailContext.documentViewParentModel.set(
               this.DetailContext.documentViewRef.resolvedModelChain[0]);
          this.SearchContext.selection$.set(this.DetailContext.documentViewParentModel.get());

        }
      }.bind(this));

      // initialization from hash
      if (location.hash === '#' || location.hash === '#undefined' || location.hash.length === 0) location.hash = 'DevDocumentation_Welcome';
      this.DetailContext.documentViewRef.ref = location.hash.substring(1);
      if (this.DetailContext.documentViewRef.valid) {
        this.DetailContext.documentViewParentModel.set(
             this.DetailContext.documentViewRef.resolvedModelChain[0]);
        this.SearchContext.selection$.set(this.DetailContext.documentViewParentModel.get());
      }

      var testArg = this.X.Arg.create({name: 'testy'});
      testArg.documentation = this.X.Documentation.create({
        body: function() { /*
          Argument $$DOC{ref:'.'} documentation.
          */ }
      });
      this.model_.methods[1].args.push(testArg);
    },

    testMethod: function(a1, b2) {
      return a1 + b2;
    }
  },

  listeners: [
    {
      name: 'onReadyToScroll',
      code: function(evt) {

      }
    }
  ],

  properties: [
    {
      name: 'modelList',
      factory: function() {
        return this.SearchContext.ModelListController.create();
      }
    },
    {
      name: 'modelListView',
      factory: function() {
        return this.SearchContext.ControllerView.create({ model: ModelListController,
                                                          data$: this.modelList$ });
      }
    },
    {
      name: 'selectionView',
      factory: function() {
        return this.DetailContext.DocModelView.create({ model: Model, data: this.DetailContext.documentViewRef });
      }
    },
  ]

});

MODEL({
  name: 'DocBrowserView',
  extendsModel: 'DetailView',

	methods: {
	 initHTML: function() {
	   this.data.modelListView.initHTML();
	   this.data.selectionView.initHTML();
	 }
	},

//  templates: [
//    function toHTML()    {/*
//

//
FOAM Documentation Browser

//

//
<%=this.data.modelListView.toHTML()%>

//
<%=this.data.selectionView.toHTML()%>

//

//

//    */}
//  ]

  templates: [
    function CSS() {/*
      body {
        margin: 0px;
        font-family: 'Roboto', sans-serif;
        font-size: inherit;

        background-color: #e0e0e0;
        position: relative;
      }

      .docbrowser-header {
        height: 90px;
        position: relative;
        color: #fff;
        z-index: 1;
      }

      .docbrowser-header-inner {
        background-color: #5555FF;
        position: absolute;
        height: 120px;
        width: 100%;
      }

      .docbrowser-header-flex-container {
        display: flex;
        justify-content: space-around;
        margin: 0 50px;
      }
      .docbrowser-header-contents {
        flex-grow: 1;
        max-width: 1280px;

        display: flex;
        justify-content: space-between;
      }

      .docbrowser-title {
        font-weight: lighter;
        font-size: 250%;
        margin-top: 20px;
      }
      .docbrowser-tabs {
        font-size: 120%;
        font-weight: lighter;
        margin-top: 40px;
        margin-right: 20px;
      }
      .docbrowser-tab {
        margin-left: 50px;
      }
      .docbrowser-tab.enabled {
        font-weight: normal;
      }

      .outer-container {
        margin: 0 30px;
        z-index: 2;
        position: relative;
      }
      .outer-flex-container {
        display: flex;
        justify-content: space-around;
        margin-bottom: 60px;
        width: 100%;
        height: 83%;
      }
      .inner-container {
        background-color: #fff;
        border: 1px solid #888;
        border-radius: 12px;
        flex-grow: 1;
        max-width: 1280px;
        padding: 15px;
        box-shadow: 0px 5px 5px #888888;
				display:flex;
      }

      input {
        font-family: inherit;
        font-size: inherit;
      }

      p {
        padding-bottom: 0.5em;
      }
      li {
        padding-bottom: 0.5em;
      }

      div.listPane {
				min-width: 200px;
				flex-basis: 200px;
				order: 1;
        padding: 1em;
				flex-grow: 0;
				overflow-x: hidden;

				display: flex;
			  flex-direction: column;
      }

      div.detailPane {
        order: 2;
				flex-grow: 10;
        overflow-y: scroll;
        padding: 1em;
      }

			div.detailPane div.chapters h2 {
				font-size: 110%;
			}

			div.search-field-container {
				flex-grow: 0;
				order: 1;
			}

			div.list-container {
				order: 2;
				flex-grow: 1;
			  overflow-y:scroll;
				overflow-x:hidden;
			}
			div.list-container span.docLink {
				border-bottom: none;
			}

			div.members {
        padding-left: 2em;
      }
      div.memberList {
        padding-left: 2em;
      }

			div.chapters div.memberList {
				padding-left: 0;
			}

      div.inherited {
        color: #666666;
      }

			p.browse-list-entry {
				font-size:100%;
				font-weight: bold;
				line-height: 150%
			}

      span.docLink {
        cursor: pointer;
				color: #000077;
        border-bottom: 0.1em dotted #999;
      }

      span.docLinkNoDocumentation {
        color: #770000;

      }

      .light {
        color: #444;
      }
    */},
    function toHTML() {/*
      <div id="<%= this.id %>">

FOAM Documentation

        <div id="<%= this.id %>-outer-container" class="outer-container">

            <div id="<%= this.id %>-inner-container" class="inner-container">

<%=this.data.modelListView.toHTML()%>

<%=this.data.selectionView.toHTML()%>

    */}
  ]

});

<|endoftext|>


<commit_before>(function(red, $) {
var cjs = red.cjs, _ = cjs._;
}(red, jQuery));
/*
(function(Euclase) {
var array_utils = Euclase._array_utils;
$.widget(
"euc.euc_cell_view",
{
	// default options
	options: {
		cell: null,
		debug: false,
		parent_update_queue: Euclase._update_queue
	},
	_create: function() {
		var self = this,
			options = self.options,
			element = self.element,
			cell = options.cell;

		if(cell.update_queue!=null) {
			self.option("parent_update_queue", cell.update_queue);
		}

		self.update_queue = options.parent_update_queue.add_queue({type: "Cell", element: element});

		var king_cell = null;
		if(Euclase.environment) {
			king_cell = $("div#king_cell");
		}

		self.display = $("<div />")	.addClass("cell_display")
									.appendTo(element)
									.editablelabel({
										manualValueChange: true,
										defaultValue: cell.attr("default_display"),
										otherClickables: "#king_cell",
										charLimit: 10
									});
		self.display.bind("valuechange", function(event) {
			var old_value = event.oldValue,
				new_value = event.newValue;
			if(Euclase.environment) {
				Euclase.environment.command("change_cell", {cell: cell, new_value: new_value, old_value: old_value});
			}
			else {
				cell.option("text", new_value);
			}
		});
		self.display.bind("startedediting", function(event) {
			if(king_cell) {
				king_cell.euc_environment_king_cell("option", {
					"editingCell": element
				});
			}
		});
		self.display.bind("stoppedediting", function(event) {
			if(king_cell) {
				king_cell.euc_environment_king_cell("option", {
					"editingCell": null
				});
			}
		});

		self.update_queue.add(function() {
			self.display.editablelabel("option", {value: cell.attr("text"), defaultValue: cell.attr("default_display")});
		}, {name: "Update cell text", object: cell});

		self.update_queue.add(function() {
			var errors = cell.attr("errors");
			if(errors == null) errors = [];
			self._set_errors(errors);
		}, {name: "Update cell errors", object: cell});
	},
	destroy: function() {
		var self = this,
			options = self.options;

		options.parent_update_queue.remove(self.update_queue);
		$.Widget.prototype.destroy.apply(self, arguments); // default destroy
		self.display.editablelabel("destroy");
		self.display.remove();
	},
	_set_errors: function(errors) {
		var self = this;

		if(errors.length == 0) {
			self.display.removeClass("error");
		}
		else {
			self.display.addClass("error");
		}
	},
	accept: function() {
		this.display.editablelabel("confirmValue");
	},
	cancel: function() {
		this.display.editablelabel("cancel");
	}

});
})(Euclase);
*/
<commit_msg>Adding cell view<commit_after>(function(red, $) {
var cjs = red.cjs, _ = cjs._;

$.widget("red.cell", {

});

}(red, jQuery));
/*
(function(Euclase) {
var array_utils = Euclase._array_utils;
$.widget(
"euc.euc_cell_view",
{
	// default options
	options: {
		cell: null,
		debug: false,
		parent_update_queue: Euclase._update_queue
	},
	_create: function() {
		var self = this,
			options = self.options,
			element = self.element,
			cell = options.cell;

		if(cell.update_queue!=null) {
			self.option("parent_update_queue", cell.update_queue);
		}

		self.update_queue = options.parent_update_queue.add_queue({type: "Cell", element: element});

		var king_cell = null;
		if(Euclase.environment) {
			king_cell = $("div#king_cell");
		}

		self.display = $("<div />")	.addClass("cell_display")
									.appendTo(element)
									.editablelabel({
										manualValueChange: true,
										defaultValue: cell.attr("default_display"),
										otherClickables: "#king_cell",
										charLimit: 10
									});
		self.display.bind("valuechange", function(event) {
			var old_value = event.oldValue,
				new_value = event.newValue;
			if(Euclase.environment) {
				Euclase.environment.command("change_cell", {cell: cell, new_value: new_value, old_value: old_value});
			}
			else {
				cell.option("text", new_value);
			}
		});
		self.display.bind("startedediting", function(event) {
			if(king_cell) {
				king_cell.euc_environment_king_cell("option", {
					"editingCell": element
				});
			}
		});
		self.display.bind("stoppedediting", function(event) {
			if(king_cell) {
				king_cell.euc_environment_king_cell("option", {
					"editingCell": null
				});
			}
		});

		self.update_queue.add(function() {
			self.display.editablelabel("option", {value: cell.attr("text"), defaultValue: cell.attr("default_display")});
		}, {name: "Update cell text", object: cell});

		self.update_queue.add(function() {
			var errors = cell.attr("errors");
			if(errors == null) errors = [];
			self._set_errors(errors);
		}, {name: "Update cell errors", object: cell});
	},
	destroy: function() {
		var self = this,
			options = self.options;

		options.parent_update_queue.remove(self.update_queue);
		$.Widget.prototype.destroy.apply(self, arguments); // default destroy
		self.display.editablelabel("destroy");
		self.display.remove();
	},
	_set_errors: function(errors) {
		var self = this;

		if(errors.length == 0) {
			self.display.removeClass("error");
		}
		else {
			self.display.addClass("error");
		}
	},
	accept: function() {
		this.display.editablelabel("confirmValue");
	},
	cancel: function() {
		this.display.editablelabel("cancel");
	}

});
})(Euclase);
*/
<|endoftext|>


<commit_before>function parseHash() {
  var output = {};
  var pairs = window.location.hash.substring(1).split("&");
  pairs.forEach(function(pair) {
    var parts = pair.split("=", 2),
        key = parts[0],
        value = parts[1];
    output[key] = value;
  });
  return output;
}

function initViewer(url, params) {
  var req = new XMLHttpRequest();
  req.onload = function() {
    var options = JSON.parse(req.responseText);
    options.layers.forEach(function(layer) {
      layer.URL = url + "/../" + layer.URL;
    });

    document.title = options.name + " \u00b7 GroupXIV microphotography viewer"

    var map = GroupXIV({
      viewport: "viewer",
      scale: options.scale,
      tileSize: options.tileSize,
      layers: options.layers,
    });

    if(params.x && params.y && params.z) {
      var center = map.unproject([parseInt(params.x), parseInt(params.y)], map.getMaxZoom() - 1),
          zoom = parseInt(params.z);
      map.setView(center, zoom);
    }

    map.on('moveend', function(e) {
      var center = map.project(map.getCenter(), map.getMaxZoom() - 1),
          zoom = map.getZoom();
      window.location.hash = "#url=" + url + "&x=" + center.x + "&y=" + center.y + "&z=" + zoom;
    });

    return map;
  };
  req.open("get", url, true);
  req.send();
}

function pageLoad() {
  var params = parseHash();
  initViewer(params["url"], params);
}
<commit_msg>React to changes in #hash.<commit_after>function parseHash() {
  var output = {};
  var pairs = window.location.hash.substring(1).split("&");
  pairs.forEach(function(pair) {
    var parts = pair.split("=", 2),
        key = parts[0],
        value = parts[1];
    output[key] = value;
  });
  return output;
}

function initViewer(url, params) {
  var req = new XMLHttpRequest();
  req.onload = function() {
    var options = JSON.parse(req.responseText);
    options.layers.forEach(function(layer) {
      layer.URL = url + "/../" + layer.URL;
    });

    document.title = options.name + " \u00b7 GroupXIV microphotography viewer"

    var map = GroupXIV({
      viewport: "viewer",
      scale: options.scale,
      tileSize: options.tileSize,
      layers: options.layers,
    });

    function moveMap(params) {
      if(params.x && params.y && params.z) {
        var center = map.unproject([parseInt(params.x), parseInt(params.y)], map.getMaxZoom() - 1),
            zoom = parseInt(params.z);
        map.setView(center, zoom);
      }
    }

    map.on('moveend', function(e) {
      var center = map.project(map.getCenter(), map.getMaxZoom() - 1),
          zoom = map.getZoom();
      history.replaceState(null, null, "#url=" + url +
        "&x=" + (center.x|0) + "&y=" + (center.y|0) + "&z=" + zoom);
    });

    moveMap(params);
    window.onhashchange = function() {
      var params = parseHash();
      if(params["url"] != url) {
        window.location.reload();
      } else {
        moveMap(params);
      }
    }
  };
  req.open("get", url, true);
  req.send();
}

function pageLoad() {
  var params = parseHash();
  initViewer(params["url"], params);
}
<|endoftext|>


<commit_before>const removeHead = ([l, ...ls]) => ls
const isAlt = cb => e => e.keyIdentifier === 'Alt' && cb()
const isEsc = cb => e => e.keyCode === 27 && cb()

const setLocal = (k,v) => localStorage.setItem(`__flint.state.${k}`, JSON.stringify(v))
const getLocal = (k,d) => JSON.parse(localStorage.getItem(`__flint.state.${k}`)) || d

const round = Math.round

let highlighter

function positionHighlight(node) {
  const bounds = node.getBoundingClientRect()
  const winW = window.innerWidth
  const winH = window.innerHeight
  const width = round(bounds.right - bounds.left)
  const height = round(bounds.bottom - bounds.top)
  let opacity = 1

  if (width >= winW && height >= winH)
    opacity = 0.2

  highlighter.setAttribute('style', `
    top: ${round(bounds.top)}px;
    left: ${round(bounds.left)}px;
    width: ${width}px;
    height: ${height}px;
    opacity: ${opacity};
  `)
}

function hideHighlight() {
  highlighter.setAttribute('style', '')
}

function findPath(node) {
  if (!node || !node.getAttribute) return null
  const flintid = node.__flintID
  if (!flintid) return findPath(node.parentNode)
  positionHighlight(node)
  return flintid
}

function tempActive(views) {
  return views.filter(v => !v.temp).length > 0
}

function pathActive(views, path) {
  return views.filter(v => v.path == path).length > 0
}

function removeTemp(views) {
  return views.filter(v => !v.temp).map(v => ({ ...v, highlight: false }))
}

function addTemp(views, path) {
  return [{ path, highlight: false, temp: true }].concat(views)
}

function setClosing(views, path) {
  return views.map(v => {
    if (v.path == path) v.closing = true
    return v
  })
}

function highlightPath(views, path) {
  return views.map((v) => {
    if (v.path == path) v.highlight = true
    return v
  })
}

function toggleView(views, path) {
  if (pathActive(views, path)) {
    return views.map(v => {
      if (v.path == path) v.temp = true
      return v
    })
  }
  else {
    let added = { temp: false, highlight: false, closing: false, path }
    return [].concat([added], views)
  }
}

function internal() {
  return window._Flint
}

function writeBack(path, data) {
  const I = internal()
  const name  = data[1][0]
  const current = I.getCache[path][name]
  let value = data[1][1]

  if (typeof current == 'number') {
    value = +value
  }

  I.setCache(path, name, value)
  I.inspectorRefreshing = path
  I.getInitialStates[path]()
  I.viewsAtPath[path].forceUpdate()
  I.inspectorRefreshing = null
}

view Inspector {
  let clickOff, hoverOff, lastTarget
  let hudActive = false
  let views = []
  let keys = {}

  on.mount(() => {
    hoverOff = on.mousemove(window, mouseMove)
    if (highlighter) return
    highlighter = document.createElement('div')
    highlighter.className = "_flintHighlighter"
    document.body.appendChild(highlighter)
  })

  function inspect(target) {
    internal().isInspecting = true
    let path = findPath(target)
    views = removeTemp(views)
    views = pathActive(views, path) ?
      highlightPath(views, path) :
      addTemp(views, path)
  }

  function mouseMove({ target }) {
    if (lastTarget != target) {
      lastTarget = target
      if (hudActive) inspect(lastTarget)
    }
  }

  function closeLast() {
    if (!views.length) return
    views = removeHead(views)
  }

  function close(path, e) {
    if (e) e.stopPropagation()
    views = setClosing(views, path)

    on.delay(200, () => {
      views = views.filter(v => path != v.path)
    })
  }

  function glue(e) {
    views = toggleView(removeTemp(views), findPath(e.target))
    return false
  }

  function showInspect() {
    inspect(lastTarget)
    hudActive = true
    clickOff = on.click(window, glue)
  }

  function hideInspect() {
    internal().isInspecting = false
    hudActive = false
    hideHighlight()
    clickOff && clickOff()
    views = removeTemp(views)
  }

  function onWriteBack(path, data) {
    writeBack(path, data)
    view.update()
  }

  on.keydown(window, isAlt(showInspect))
  on.keyup(window, isAlt(hideInspect))
  on.keyup(window, isEsc(closeLast))

  <Inspector.View
    repeat={views}
    key={_.path}
    {..._}
    writeBack={onWriteBack}
    onClose={e => close(_.path, e)}
  />

  $ = {
    position: 'fixed',
    top: 0, right: 0,
    padding: 2
  }
}
<commit_msg>react key<commit_after>const removeHead = ([l, ...ls]) => ls
const isAlt = cb => e => e.keyIdentifier === 'Alt' && cb()
const isEsc = cb => e => e.keyCode === 27 && cb()

const setLocal = (k,v) => localStorage.setItem(`__flint.state.${k}`, JSON.stringify(v))
const getLocal = (k,d) => JSON.parse(localStorage.getItem(`__flint.state.${k}`)) || d

const round = Math.round

let highlighter

function positionHighlight(node) {
  const bounds = node.getBoundingClientRect()
  const winW = window.innerWidth
  const winH = window.innerHeight
  const width = round(bounds.right - bounds.left)
  const height = round(bounds.bottom - bounds.top)
  let opacity = 1

  if (width >= winW && height >= winH)
    opacity = 0.2

  highlighter.setAttribute('style', `
    top: ${round(bounds.top)}px;
    left: ${round(bounds.left)}px;
    width: ${width}px;
    height: ${height}px;
    opacity: ${opacity};
  `)
}

function hideHighlight() {
  highlighter.setAttribute('style', '')
}

function findPath(node) {
  if (!node || !node.getAttribute) return null
  const flintid = node.__flintID
  if (!flintid) return findPath(node.parentNode)
  positionHighlight(node)
  return flintid
}

function tempActive(views) {
  return views.filter(v => !v.temp).length > 0
}

function pathActive(views, path) {
  return views.filter(v => v.path == path).length > 0
}

function removeTemp(views) {
  return views.filter(v => !v.temp).map(v => ({ ...v, highlight: false }))
}

function addTemp(views, path) {
  return [{ path, highlight: false, temp: true }].concat(views)
}

function setClosing(views, path) {
  return views.map(v => {
    if (v.path == path) v.closing = true
    return v
  })
}

function highlightPath(views, path) {
  return views.map((v) => {
    if (v.path == path) v.highlight = true
    return v
  })
}

function toggleView(views, path) {
  if (pathActive(views, path)) {
    return views.map(v => {
      if (v.path == path) v.temp = true
      return v
    })
  }
  else {
    let added = { temp: false, highlight: false, closing: false, path }
    return [].concat([added], views)
  }
}

function internal() {
  return window._Flint
}

function writeBack(path, data) {
  const I = internal()
  const name  = data[1][0]
  const current = I.getCache[path][name]
  let value = data[1][1]

  if (typeof current == 'number') {
    value = +value
  }

  I.setCache(path, name, value)
  I.inspectorRefreshing = path
  I.getInitialStates[path]()
  I.viewsAtPath[path].forceUpdate()
  I.inspectorRefreshing = null
}

let activeKey = null
let activeView = null
let reactKey = null
getReactKey = el =>
  Object.keys(el).filter(k => k.indexOf('__reactInternalInst')==0)[0]

let getReactId = el => {
  if (!reactKey) reactKey = getReactKey(el)
  window.abc = el
  if (!el[reactKey]) return
  let current = el[reactKey]._currentElement
  if (!current) return null

  let key = current.key
  let split = key.split('$')
  return split[split.length - 1]
}

view Inspector {
  let clickOff, hoverOff, lastTarget
  let hudActive = false
  let views = []
  let keys = {}

  on.mount(() => {
    hoverOff = on.mousemove(window, mouseMove)
    if (highlighter) return
    highlighter = document.createElement('div')
    highlighter.className = "_flintHighlighter"
    document.body.appendChild(highlighter)
  })

  function inspect(target) {
    internal().isInspecting = true
    let path = findPath(target)
    views = removeTemp(views)
    views = pathActive(views, path) ?
      highlightPath(views, path) :
      addTemp(views, path)
  }

  function mouseMove({ target }) {
    if (lastTarget != target) {
      lastTarget = target
      activeKey = getReactId(target)
      activeView = target.classList.toString()
        .split(' ')
        .filter(s => s.substr(0,4) != 'View')
        .filter(s => s.charAt(0).toUpperCase() == s.charAt(0))[0]

      if (hudActive) inspect(lastTarget)
    }
  }

  function closeLast() {
    if (!views.length) return
    views = removeHead(views)
  }

  function close(path, e) {
    if (e) e.stopPropagation()
    views = setClosing(views, path)

    on.delay(200, () => {
      views = views.filter(v => path != v.path)
    })
  }

  function glue(e) {
    views = toggleView(removeTemp(views), findPath(e.target))
    return false
  }

  function showInspect() {
    inspect(lastTarget)
    console.log('editing', activeKey, activeView)
    _DT.messageEditor({ type: 'editView', key: activeKey, view: activeView })
    hudActive = true
    clickOff = on.click(window, glue)
  }

  function hideInspect() {
    internal().isInspecting = false
    hudActive = false
    hideHighlight()
    clickOff && clickOff()
    views = removeTemp(views)
  }

  function onWriteBack(path, data) {
    writeBack(path, data)
    view.update()
  }

  on.keydown(window, isAlt(showInspect))
  on.keyup(window, isAlt(hideInspect))
  on.keyup(window, isEsc(closeLast))

  <Inspector.View
    repeat={views}
    key={_.path}
    {..._}
    writeBack={onWriteBack}
    onClose={e => close(_.path, e)}
  />

  $ = {
    position: 'fixed',
    top: 0, right: 0,
    padding: 2
  }
}
<|endoftext|>


<commit_before>/**
 * Copyright 2006 - 2010 Eric D. Hough (http://ehough.com)
 *
 * This file is part of TubePress (http://tubepress.org) and is released
 * under the General Public License (GPL) version 3
 *
 * Shrink your JS: http://developer.yahoo.com/yui/compressor/
 */

/* caching script loader */
jQuery.getScript = function (url, callback, cache) {
	jQuery.ajax({ type: "GET", url: url, success: callback, dataType: "script", cache: cache });
};

/* http://jquery.malsup.com/fadetest.html */
jQuery.fn.fadeTo = function(speed, to, callback) {
	return this.animate({opacity: to}, speed, function() {
        	if (to == 1 && jQuery.browser.msie)
        	    this.style.removeAttribute('filter');
        	if (jQuery.isFunction(callback))
        	    callback();
    	});
};

/* this is meant to be called from the user's HTML page */
var safeTubePressInit = function () {
	try {
		TubePress.init(getTubePressBaseUrl());
  	} catch (f) {
		alert("TubePress failed to initialize: " + f.message);
  	}
};

/* append our init method to after all the other (potentially full of errors) ready blocks have
 * run. http://stackoverflow.com/questions/1890512/handling-errors-in-jquerydocument-ready */
if (!jQuery.browser.msie) {
	var oldReady = jQuery.ready, TubePress;
	jQuery.ready = function () {
			try {
				oldReady.apply(this, arguments);
			} catch (e) { }
			safeTubePressInit();
	};
} else {
	jQuery().ready(function () {
		safeTubePressInit();
	});
}

/**
 * Main TubePress module. Handles click listeners, swapping embedded Flash, lazy-loading libraries, etc.
 */
TubePress = (function () {

	var init, loadEmbeddedJs, parseRels, loadPlayerJs, triggerPlayerLoadedEvent, clickListener,
			swapEmbedded, deepConstructObject, callPlayerJs, fluidThumbs;

	/* Primary setup function for TubePress. Meant to run once on page load. */
	init = function (baseUrl) {

		/* Call tubepress_<playername>_init() when the player JS is loaded */
		jQuery(document).bind('tubepressPlayerLoaded', function (x, playerName, baseUrl) {
			var funcName = 'tubepress_' + playerName + '_player_init',
				f = function () {
					window[funcName](baseUrl);
				};
			TubePressUtils.callWhenTrue(function () {
				return typeof window[funcName] === 'function';
			}, f);
		});

		loadEmbeddedJs(baseUrl);
		loadPlayerJs(baseUrl);
		jQuery("a[id^='tubepress_']").click(clickListener);
	};

	/* loads up JS necessary for dealing with embedded Flash implementations that we find on the page */
	loadEmbeddedJs = function (baseUrl) {
		var embeddedNames = parseRels(1), i, emptyFunc = function () {};
		for (i = 0; i < embeddedNames.length; i = i + 1) {
			jQuery.getScript(baseUrl + "/ui/lib/embedded_flash/" + embeddedNames[i] + "/" + embeddedNames[i] + ".js", emptyFunc, true);
		}
	};

	/* loads up JS necessary for dealing with TubePress players that we find on the page */
	loadPlayerJs = function (baseUrl) {
		var playerNames = parseRels(2), i;
		for (i = 0; i < playerNames.length; i = i + 1) {
			var name = playerNames[i];
			jQuery.getScript(baseUrl + "/ui/lib/players/" + name + "/" + name + ".js",
				triggerPlayerLoadedEvent(name, baseUrl), true);
		}
	};

	parseRels = function (index) {
		var returnValue = [];
		jQuery("a[rel^='tubepress_']").each(function () {
			var thisName = jQuery(this).attr("rel").split("_")[index];
			if (jQuery.inArray(thisName, returnValue) === -1) {
				returnValue.push(thisName);
			}
		});
		return returnValue;
	};

	triggerPlayerLoadedEvent = function (name, baseUrl) {
		jQuery(document).trigger('tubepressPlayerLoaded', [name, baseUrl]);
	};

	/* thumbnail click listener */
	clickListener = function () {
		var rel_split	= jQuery(this).attr("rel").split("_"),
		galleryId		= getGalleryIdFromRelSplit(rel_split),
		playerName   	= getPlayerNameFromRelSplit(rel_split),
		embeddedName 	= getEmbeddedNameFromRelSplit(rel_split),
		videoId 		= getVideoIdFromIdAttr(jQuery(this).attr("id"));

		/* swap the gallery's embedded object */
		swapEmbedded(galleryId, videoId, embeddedName);

		/* then call the player to load up / play the video */
		callPlayerJs(galleryId, videoId, embeddedName, playerName);
	};

	/**
	 * Swaps out the embedded Flash player with a replacement.
	 * This function is very carefully constructed to work with both IE 7-8 and FF.
	 * Modify at your own risk!!
	*/
	swapEmbedded = function (galleryId, videoId, embeddedName) {
		var wrapperId = "#tubepress_embedded_object_" + galleryId,
			wrapper = jQuery(wrapperId), newHtml, oldHtml, oldId;

		/* if we can't find the embedded object, just bail */
		if (wrapper.length === 0) {
			return;
		}

		/* Vimeo is special. */
		if (embeddedName === 'vimeo') {
			oldHtml = wrapper.html();
			wrapper.empty();
			oldId = oldHtml.match(/\/video\/([0-9]+).*/)[1];
			wrapper.html(oldHtml.replace(oldId, videoId));
			return;
		}

		var matcher     = window["tubepress_" + embeddedName + "_matcher"](),
		    paramName 	= window["tubepress_" + embeddedName + "_param"](),
			obj 		= jQuery(wrapperId + " > object"),
			oldVideoId 	= obj.children("param[name='" + paramName + "']").attr("value").match(matcher)[1];

		/* remove anything AdBlock plus sticks in there */
		obj.siblings().remove();

		/* save the params but remove them from the DOM for now */
		var params = obj.children("param");
		params.remove();

		/* create the new embedded object */
		newHtml = deepConstructObject(wrapper, params).replace(new RegExp(oldVideoId, 'g'), videoId);

		/* add it back in */
		wrapper.html(newHtml);

		/* now pat yourself on the back */
	};

	callPlayerJs = function (galleryId, videoId, embeddedName, playerName) {
		if ((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i))) {
			return;
		}
		var playerFunctionName = "tubepress_" + playerName + "_player";
		window[playerFunctionName](galleryId, videoId);
	};

	deepConstructObject = function (wrapper, params) {

		//http://blog.stevenlevithan.com/archives/faster-trim-javascript
		var newHtml = wrapper.html().replace(/\s\s*$/, '');

		/* chop off the closing </object>. Don't change this unless you want to break IE */
		newHtml = newHtml.substring(0, newHtml.length - 9);

		/* now add back the params, but this time with the new video ID */
		params.each(function () {
			newHtml += '<param name="' + this.name + '" value="' + this.value + '" />';
		});

		/* re-close the object */
		newHtml += '</object>';
		return newHtml;
	};

	/* http://www.sohtanaka.com/web-design/smart-columns-w-css-jquery/ */
	fluidThumbs = function (gallerySelector, columnWidth) {
		var gallery = jQuery(gallerySelector);
		gallery.css({ 'width' : "100%"});
		var 	colWrap = gallery.width(),
			colNum = Math.floor(colWrap / columnWidth),
			colFixed = Math.floor(colWrap / colNum),
			thumbs = jQuery(gallerySelector + ' div.tubepress_thumb');
		gallery.css({ 'width' : colWrap });
		thumbs.css({ 'width' : colFixed});
	};

	getEmbeddedNameFromRelSplit = function (relSplit) {
		return relSplit[1];
	};

	getPlayerNameFromRelSplit = function (relSplit) {
		return relSplit[2];
	};

	getGalleryIdFromRelSplit = function (relSplit) {
		return relSplit[3];
	};

	getVideoIdFromIdAttr = function (id) {
		var end = id.lastIndexOf("_");
		return id.substring(16, end);
	}

	/* return only public functions */
	return {
		init				: init,
		deepConstructObject 		: deepConstructObject,
		clickListener 			: clickListener,
		fluidThumbs 			: fluidThumbs,
		getEmbeddedNameFromRelSplit 	: getEmbeddedNameFromRelSplit,
		getPlayerNameFromRelSplit 	: getPlayerNameFromRelSplit,
		getGalleryIdFromRelSplit 	: getGalleryIdFromRelSplit,
		getVideoIdFromIdAttr 		: getVideoIdFromIdAttr
	};
}());

/**
 * Handles some DOM and network related tasks
 */
TubePressUtils = (function () {

	/**
	 * Waits until the given test is true (tests every .4 seconds),
	 * and then executes the given callback.
	 */
	callWhenTrue = function (test, callback) {

		/* if the test doesn't pass, try again in .4 seconds */
		if (!test()) {
			var futureTest = function () {
				callWhenTrue(test, callback);
			};
			setTimeout(futureTest, 400);
			return;
		}
		/* the test passed, so call the callback */
		callback();
	};

	getWaitCall = function (scriptPath, test, callback) {
		var futureCallback = function () {
			callWhenTrue(test, callback);
		};
		jQuery.getScript(scriptPath, futureCallback, true);
	};

	loadCss = function (path) {
		var fileref = document.createElement("link");

		fileref.setAttribute("rel", "stylesheet");
		fileref.setAttribute("type", "text/css");
		fileref.setAttribute("href", path);
		document.getElementsByTagName("head")[0].appendChild(fileref);
	};

	/* return only public functions */
	return {
		callWhenTrue 	: callWhenTrue,
		getWaitCall 	: getWaitCall,
		loadCss 	: loadCss
	};
}());

/**
 * Functions for handling Ajax pagination.
 */
TubePressAjax = (function () {

	initPagination = function (galleryId) {
		var clickCallback = function () {
			processRequest(jQuery(this), galleryId);
		};

		jQuery("#tubepress_gallery_" + galleryId + " div.pagination a").click(clickCallback);
	};

	processRequest = function (anchor, galleryId) {
		var baseUrl 			= getTubePressBaseUrl(),
			shortcode 			= window["getUrlEncodedShortcodeForTubePressGallery" + galleryId](),
			page 				= anchor.attr("rel"),
			thumbnailArea 		= "#tubepress_gallery_" + galleryId + "_thumbnail_area",
			postLoadCallback 	= function () {
				postAjaxGallerySetup(thumbnailArea, galleryId);
			},
			pageToLoad 			= baseUrl + "/env/pro/lib/ajax/responder.php?shortcode=" + shortcode + "&tubepress_" + page + "&tubepress_galleryId=" + galleryId,
			remotePageSelector 	= thumbnailArea + " > *",
			loadFunction 		= function () {
				jQuery(thumbnailArea).load(pageToLoad + " " + remotePageSelector, postLoadCallback);
			};

		/* fade out the old stuff */
		jQuery(thumbnailArea).fadeTo('fast', '.01');

		/* use a tiny delay here to prevent the new content from showing up before we're done fading */
		setTimeout(loadFunction, 100);
	};

	postAjaxGallerySetup = function (thumbnailArea, galleryId) {
		jQuery().trigger('tubepressNewThumbnailsLoaded');
		TubePress.fluidThumbs("#tubepress_gallery_" + galleryId, 120);
		jQuery("a[id^='tubepress_']").click(TubePress.clickListener);
		initPagination(galleryId);
		jQuery(thumbnailArea).fadeTo('fast', 1);
	};

	/* return only public functions */
	return { initPagination :   initPagination };
}());
<commit_msg>Major refactoring of tubepress.js<commit_after>/**
 * Copyright 2006 - 2010 Eric D. Hough (http://ehough.com)
 *
 * This file is part of TubePress (http://tubepress.org) and is released
 * under the General Public License (GPL) version 3
 *
 * Shrink your JS: http://developer.yahoo.com/yui/compressor/
 */

/* caching script loader */
jQuery.getScript = function (url, callback, cache) {
	jQuery.ajax({ type: "GET", url: url, success: callback, dataType: "script", cache: cache });
};

/* http://jquery.malsup.com/fadetest.html */
jQuery.fn.fadeTo = function (speed, to, callback) {
	return this.animate({opacity: to}, speed, function () {
        	if (to == 1 && jQuery.browser.msie) {
        		this.style.removeAttribute('filter');
        	}
        	if (jQuery.isFunction(callback))
        	    callback();
    	});
};

/* this is meant to be called from the user's HTML page */
var safeTubePressInit = function () {
	try {
		TubePressGallery.init(getTubePressBaseUrl());
  	} catch (f) {
		alert("TubePress failed to initialize: " + f.message);
  	}
};

/* append our init method to after all the other (potentially full of errors) ready blocks have
 * run. http://stackoverflow.com/questions/1890512/handling-errors-in-jquerydocument-ready */
if (!jQuery.browser.msie) {
	var oldReady = jQuery.ready, TubePress;
	jQuery.ready = function () {
			try {
				oldReady.apply(this, arguments);
			} catch (e) { }
			safeTubePressInit();
	};
} else {
	jQuery().ready(function () {
		safeTubePressInit();
	});
}

/**
 * Main TubePress gallery module.
 */
TubePressGallery = (function () {

	var init, initClickListeners, fluidThumbs;

	/* Primary setup function for TubePress. Meant to run once on page load. */
	init = function (baseUrl) {
		TubePressPlayers.init(baseUrl);
		TubePressEmbedded.init(baseUrl);
		TubePressGallery.initClickListeners();
	};

	initClickListeners = function () {
		jQuery("a[id^='tubepress_']").click(clickListener);
	}

	/* thumbnail click listener */
	clickListener = function () {
		var rel_split	= jQuery(this).attr("rel").split("_"),
		galleryId		= TubePressAnchors.getGalleryIdFromRelSplit(rel_split),
		playerName   	= TubePressAnchors.getPlayerNameFromRelSplit(rel_split),
		embeddedName 	= TubePressAnchors.getEmbeddedNameFromRelSplit(rel_split),
		videoId 		= TubePressAnchors.getVideoIdFromIdAttr(jQuery(this).attr("id"));

		/* swap the gallery's embedded object */
		TubePressEmbedded.swap(galleryId, videoId, embeddedName);

		/* then call the player to load up / play the video */
		TubePressPlayers.invokePlayer(galleryId, videoId, embeddedName, playerName);
	};

	/* http://www.sohtanaka.com/web-design/smart-columns-w-css-jquery/ */
	fluidThumbs = function (gallerySelector, columnWidth) {
		var gallery 	= jQuery(gallerySelector),
			colWrap 	= gallery.width(),
			colNum 		= Math.floor(colWrap / columnWidth),
			colFixed 	= Math.floor(colWrap / colNum),
			thumbs 		= jQuery(gallerySelector + ' div.tubepress_thumb');

		gallery.css({ 'width' : "100%"});
		gallery.css({ 'width' : colWrap });
		thumbs.css({ 'width' : colFixed});
	};

	/* return only public functions */
	return {
		init						: init,
		initClickListeners 			: initClickListeners,
		fluidThumbs 				: fluidThumbs
	};
}());

/* analyzes HTML anchor objects */
TubePressAnchors = (function () {

	findAllEmbeddedNames = function () {
		return parseRels(1);
	};

	findAllPlayerNames = function () {
		return parseRels(2);
	}

	getEmbeddedNameFromRelSplit = function (relSplit) {
		return relSplit[1];
	};

	getPlayerNameFromRelSplit = function (relSplit) {
		return relSplit[2];
	};

	getGalleryIdFromRelSplit = function (relSplit) {
		return relSplit[3];
	};

	getVideoIdFromIdAttr = function (id) {
		var end = id.lastIndexOf("_");
		return id.substring(16, end);
	}

	parseRels = function (index) {
		var returnValue = [];
		jQuery("a[rel^='tubepress_']").each(function () {
			var thisName = jQuery(this).attr("rel").split("_")[index];
			if (jQuery.inArray(thisName, returnValue) === -1) {
				returnValue.push(thisName);
			}
		});
		return returnValue;
	};

	return {
		findAllEmbeddedNames		: findAllEmbeddedNames,
		findAllPlayerNames			: findAllPlayerNames,
		getEmbeddedNameFromRelSplit	: getEmbeddedNameFromRelSplit,
		getPlayerNameFromRelSplit	: getPlayerNameFromRelSplit,
		getGalleryIdFromRelSplit	: getGalleryIdFromRelSplit,
		getVideoIdFromIdAttr		: getVideoIdFromIdAttr
	};

}());

/* deals with the embedded video player */
TubePressEmbedded = (function () {

	var init;

	/* loads up JS necessary for dealing with embedded Flash implementations that we find on the page */
	init = function (baseUrl) {
		var embeddedNames = TubePressAnchors.findAllEmbeddedNames(), i, emptyFunc = function () {};
		for (i = 0; i < embeddedNames.length; i = i + 1) {

			/* vimeo has no extra JS */
			if (embeddedNames[i] === 'vimeo') { continue; }

			jQuery.getScript(baseUrl + "/ui/lib/embedded_flash/" + embeddedNames[i] + "/" + embeddedNames[i] + ".js", emptyFunc, true);
		}
	};

	/**
	 * Swaps out the embedded Flash player with a replacement.
	 * This function is very carefully constructed to work with both IE 7-8 and FF.
	 * Modify at your own risk!!
	*/
	swap = function (galleryId, videoId, embeddedName) {
		var wrapperId = "#tubepress_embedded_object_" + galleryId,
			wrapper = jQuery(wrapperId), newHtml, oldHtml, oldId;

		/* if we can't find the embedded object, just bail */
		if (wrapper.length === 0) {
			return;
		}

		/* Vimeo is special. */
		if (embeddedName === 'vimeo') {
			oldHtml = wrapper.html();
			wrapper.empty();
			oldId = oldHtml.match(/\/video\/([0-9]+).*/)[1];
			wrapper.html(oldHtml.replace(oldId, videoId));
			return;
		}

		var matcher     = window["tubepress_" + embeddedName + "_matcher"](),
		    paramName 	= window["tubepress_" + embeddedName + "_param"](),
			obj 		= jQuery(wrapperId + " > object"),
			oldVideoId 	= obj.children("param[name='" + paramName + "']").attr("value").match(matcher)[1];

		/* remove anything AdBlock plus sticks in there */
		obj.siblings().remove();

		/* save the params but remove them from the DOM for now */
		var params = obj.children("param");
		params.remove();

		/* create the new embedded object */
		newHtml = getEmbeddedObjectClone(wrapper, params).replace(new RegExp(oldVideoId, 'g'), videoId);

		/* add it back in */
		wrapper.html(newHtml);

		/* now pat yourself on the back */
	};

	getEmbeddedObjectClone = function (wrapper, params) {

		//http://blog.stevenlevithan.com/archives/faster-trim-javascript
		var newHtml = wrapper.html().replace(/\s\s*$/, '');

		/* chop off the closing </object>. Don't change this unless you want to break IE */
		newHtml = newHtml.substring(0, newHtml.length - 9);

		/* now add back the params, but this time with the new video ID */
		params.each(function () {
			newHtml += '<param name="' + this.name + '" value="' + this.value + '" />';
		});

		/* re-close the object */
		newHtml += '</object>';
		return newHtml;
	};

	return {
		init : init,
		swap : swap
	};

}());

/* handles player-related functionality (popup, Shadowbox, etc) */
TubePressPlayers = (function () {

	var init, playerInit;

	init = function (baseUrl) {

		/* loads up JS necessary for dealing with TubePress players that we find on the page */
		var playerNames = TubePressAnchors.findAllPlayerNames(), i;
		for (i = 0; i < playerNames.length; i = i + 1) {
			var name = playerNames[i];
			jQuery.getScript(baseUrl + "/ui/lib/players/" + name + "/" + name + ".js",
				playerInit(name, baseUrl));
		}
	};

	invokePlayer = function (galleryId, videoId, embeddedName, playerName) {
		if ((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i))) {
			return;
		}
		var playerFunctionName = "tubepress_" + playerName + "_player";
		window[playerFunctionName](galleryId, videoId);
	};

	playerInit = function (name, baseUrl) {

		/* Call tubepress_<playername>_init() when the player JS is loaded */
		var funcName = 'tubepress_' + playerName + '_player_init',
			f = function () {
				window[funcName](baseUrl);
			};
		TubePressJS.callWhenTrue(function () {
			return typeof window[funcName] === 'function';
		}, f);
	};

	return {
		init 			: init,
		invokePlayer	: invokePlayer
	};

}());

TubePressEvents = (function () {

	return {
		NEW_THUMBS_LOADED = "tubepressNewThumbnailsLoaded"
	};

}());

/**
 * Handles some DOM and network related tasks
 */
TubePressJS = (function () {

	/**
	 * Waits until the given test is true (tests every .4 seconds),
	 * and then executes the given callback.
	 */
	callWhenTrue = function (test, callback) {

		/* if the test doesn't pass, try again in .4 seconds */
		if (!test()) {
			var futureTest = function () {
				callWhenTrue(test, callback);
			};
			setTimeout(futureTest, 400);
			return;
		}
		/* the test passed, so call the callback */
		callback();
	};

	getWaitCall = function (scriptPath, test, callback) {
		var futureCallback = function () {
			callWhenTrue(test, callback);
		};
		jQuery.getScript(scriptPath, futureCallback, true);
	};

	loadCss = function (path) {
		var fileref = document.createElement("link");

		fileref.setAttribute("rel", "stylesheet");
		fileref.setAttribute("type", "text/css");
		fileref.setAttribute("href", path);
		document.getElementsByTagName("head")[0].appendChild(fileref);
	};

	/* return only public functions */
	return {
		callWhenTrue	: callWhenTrue,
		getWaitCall 	: getWaitCall,
		loadCss 		: loadCss
	};
}());

/**
 * Functions for handling Ajax pagination.
 */
TubePressAjaxPagination = (function () {

	/* initializes pagination HTML for Ajax. */
	init = function (galleryId) {
		var clickCallback = function () {
			processRequest(jQuery(this), galleryId);
		};

		jQuery("#tubepress_gallery_" + galleryId + " div.pagination a").click(clickCallback);
	};

	processRequest = function (anchor, galleryId) {
		var baseUrl 			= getTubePressBaseUrl(),
			shortcode 			= window["getUrlEncodedShortcodeForTubePressGallery" + galleryId](),
			page 				= anchor.attr("rel"),
			thumbnailArea 		= "#tubepress_gallery_" + galleryId + "_thumbnail_area",
			postLoadCallback 	= function () {
				postAjaxGallerySetup(thumbnailArea, galleryId);
			},
			pageToLoad 			= baseUrl + "/env/pro/lib/ajax/responder.php?shortcode=" + shortcode + "&tubepress_" + page + "&tubepress_galleryId=" + galleryId,
			remotePageSelector 	= thumbnailArea + " > *",
			loadFunction 		= function () {
				jQuery(thumbnailArea).load(pageToLoad + " " + remotePageSelector, postLoadCallback);
			};

		/* fade out the old stuff */
		jQuery(thumbnailArea).fadeTo('fast', '.01');

		/* use a tiny delay here to prevent the new content from showing up before we're done fading */
		setTimeout(loadFunction, 100);
	};

	/* post thumbnail load setup */
	postAjaxGallerySetup = function (thumbnailArea, galleryId) {
		jQuery().trigger(TubePressEvents.NEW_THUMBS_LOADED);
		TubePressGallery.fluidThumbs("#tubepress_gallery_" + galleryId, 120);
		TubePressGallery.initClickListeners();
		init(galleryId);
		jQuery(thumbnailArea).fadeTo('fast', 1);
	};

	/* return only public functions */
	return { init : init };
}());
<|endoftext|>


<commit_before>const gulp = require('gulp');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const colors = require('ansi-colors');
const logger = require('fancy-log');
const watchify = require('watchify');
const browserify = require('browserify');
const uglify = require('gulp-uglify');
const size = require('gulp-size');
const tsify = require('tsify');
const concat = require('gulp-concat');
const exec = require('child_process').exec;
const fs = require('fs');

require('../gulp/cssProject.js')(__dirname);

const browserifyOpts = (entries, debug) => ({
  entries: entries,
  standalone: 'Lichess',
  debug: debug
});
const destinationPath = '../../public/compiled/';
const destination = () => gulp.dest(destinationPath);
const fileBaseName = 'lichess.site';

const abFile = process.env.LILA_AB_FILE;

const jqueryFill = () => gulp.src('src/jquery.fill.js')
  .pipe(buffer())
  .pipe(uglify())
  .pipe(gulp.dest('./dist'));

const ab = () => {
  if (abFile) return gulp.src(abFile)
    .pipe(buffer())
    .pipe(uglify())
    .pipe(gulp.dest('./dist'));
  else {
    logger.info(colors.yellow('Building without AB file'));
    return gulp.src('.');
  }
};

const stockfishPexe = () => gulp.src([
  require.resolve('stockfish.pexe/stockfish.nmf'),
  require.resolve('stockfish.pexe/stockfish.pexe'),
  require.resolve('stockfish.pexe/stockfish.bc')
]).pipe(gulp.dest('../../public/vendor/stockfish.pexe'));

const stockfishJs = () => gulp.src([
  require.resolve('stockfish.js/stockfish.wasm.js'),
  require.resolve('stockfish.js/stockfish.wasm'),
  require.resolve('stockfish.js/stockfish.js')
]).pipe(gulp.dest('../../public/vendor/stockfish.js'));

const stockfishWasm = () => gulp.src([
  require.resolve('stockfish.wasm/stockfish.js'),
  require.resolve('stockfish.wasm/stockfish.js.mem'),
  require.resolve('stockfish.wasm/stockfish.wasm'),
  require.resolve('stockfish.wasm/stockfish.worker.js')
]).pipe(gulp.dest('../../public/vendor/stockfish.wasm/'));

const stockfishMvWasm = () => gulp.src([
  require.resolve('stockfish-mv.wasm/stockfish.js'),
  require.resolve('stockfish-mv.wasm/stockfish.js.mem'),
  require.resolve('stockfish-mv.wasm/stockfish.wasm'),
  require.resolve('stockfish-mv.wasm/pthread-main.js')
]).pipe(gulp.dest('../../public/vendor/stockfish-mv.wasm/'));

const prodSource = () => browserify(browserifyOpts('src/index.ts', false))
  .plugin(tsify)
  .bundle()
  .pipe(source(`${fileBaseName}.source.min.js`))
  .pipe(buffer())
  .pipe(uglify())
  .pipe(gulp.dest('./dist'));

const devSource = () => browserify(browserifyOpts('src/index.ts', true))
  .plugin(tsify)
  .bundle()
  .pipe(source(`${fileBaseName}.js`))
  .pipe(destination());

function makeDependencies(filename) {
  return function bundleDeps() {
    return gulp.src([
  '../../public/javascripts/vendor/jquery.min.js',
  './dist/jquery.fill.js',
  './dep/powertip.min.js',
  './dep/howler.min.js',
  './dep/mousetrap.min.js',
  './dist/consolemsg.js',
  ...(abFile ? ['./dist/ab.js'] : []),
])
      .pipe(concat(filename))
      .pipe(destination());
  };
}

function makeBundle(filename) {
  return function bundleItAll() {
    return gulp.src([
      destinationPath + 'lichess.deps.js',
      './dist/' + filename,
    ])
      .pipe(concat(filename.replace('source.', '')))
      .pipe(destination());
  };
}

const gitSha = (cb) => exec("git rev-parse -q --short HEAD", function (err, stdout) {
  if (err) throw err;
  if (!fs.existsSync('./dist')) fs.mkdirSync('./dist');
  var date = new Date().toISOString().split('.')[0];
  fs.writeFileSync('./dist/consolemsg.js',
    'window.lichess=window.lichess||{};console.info("Lichess is open source! https://github.com/ornicar/lila");' +
    `lichess.info = "Assets built ${date} from sha ${stdout.trim()}";`);
  cb();
});

const standalonesJs = () => gulp.src([
  'util.js', 'trans.js', 'tv.js', 'puzzle.js', 'user.js', 'coordinate.js', 'captcha.js', 'embed-analyse.js'
].map(f => `src/standalones/${f}`))
  .pipe(buffer())
  .pipe(uglify())
  .pipe(destination());

const userMod = () => browserify(browserifyOpts('./src/user-mod.js', false))
  .bundle()
  .pipe(source('user-mod.js'))
  .pipe(buffer())
  .pipe(uglify())
  .pipe(destination());

const tasks = [gitSha, jqueryFill, ab, standalonesJs, userMod, stockfishWasm, stockfishMvWasm, stockfishPexe, stockfishJs];

const dev = gulp.series(tasks.concat([devSource]));

const deps = makeDependencies('lichess.deps.js');

gulp.task('prod', gulp.series(tasks, deps, prodSource, makeBundle(`${fileBaseName}.source.min.js`)));
gulp.task('dev', gulp.series(deps, dev));
gulp.task('default', gulp.series(deps, dev, () => gulp.watch('src/**/*.js', dev)));

gulp.task('deps', gulp.series(tasks, deps));
<commit_msg>fix ui/site tasks build<commit_after>const gulp = require('gulp');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const colors = require('ansi-colors');
const logger = require('fancy-log');
const watchify = require('watchify');
const browserify = require('browserify');
const uglify = require('gulp-uglify');
const size = require('gulp-size');
const tsify = require('tsify');
const concat = require('gulp-concat');
const exec = require('child_process').exec;
const fs = require('fs');

require('../gulp/cssProject.js')(__dirname);

const browserifyOpts = (entries, debug) => ({
  entries: entries,
  standalone: 'Lichess',
  debug: debug
});
const destinationPath = '../../public/compiled/';
const destination = () => gulp.dest(destinationPath);
const fileBaseName = 'lichess.site';

const abFile = process.env.LILA_AB_FILE;

const jqueryFill = () => gulp.src('src/jquery.fill.js')
  .pipe(buffer())
  .pipe(uglify())
  .pipe(gulp.dest('./dist'));

const ab = () => {
  if (abFile) return gulp.src(abFile)
    .pipe(buffer())
    .pipe(uglify())
    .pipe(gulp.dest('./dist'));
  else {
    logger.info(colors.yellow('Building without AB file'));
    return gulp.src('.');
  }
};

const stockfishPexe = () => gulp.src([
  require.resolve('stockfish.pexe/stockfish.nmf'),
  require.resolve('stockfish.pexe/stockfish.pexe'),
  require.resolve('stockfish.pexe/stockfish.bc')
]).pipe(gulp.dest('../../public/vendor/stockfish.pexe'));

const stockfishJs = () => gulp.src([
  require.resolve('stockfish.js/stockfish.wasm.js'),
  require.resolve('stockfish.js/stockfish.wasm'),
  require.resolve('stockfish.js/stockfish.js')
]).pipe(gulp.dest('../../public/vendor/stockfish.js'));

const stockfishWasm = () => gulp.src([
  require.resolve('stockfish.wasm/stockfish.js'),
  require.resolve('stockfish.wasm/stockfish.js.mem'),
  require.resolve('stockfish.wasm/stockfish.wasm'),
  require.resolve('stockfish.wasm/stockfish.worker.js')
]).pipe(gulp.dest('../../public/vendor/stockfish.wasm/'));

const stockfishMvWasm = () => gulp.src([
  require.resolve('stockfish-mv.wasm/stockfish.js'),
  require.resolve('stockfish-mv.wasm/stockfish.js.mem'),
  require.resolve('stockfish-mv.wasm/stockfish.wasm'),
  require.resolve('stockfish-mv.wasm/pthread-main.js')
]).pipe(gulp.dest('../../public/vendor/stockfish-mv.wasm/'));

const prodSource = () => browserify(browserifyOpts('src/index.ts', false))
  .plugin(tsify)
  .bundle()
  .pipe(source(`${fileBaseName}.source.min.js`))
  .pipe(buffer())
  .pipe(uglify())
  .pipe(gulp.dest('./dist'));

const devSource = () => browserify(browserifyOpts('src/index.ts', true))
  .plugin(tsify)
  .bundle()
  .pipe(source(`${fileBaseName}.js`))
  .pipe(destination());

function makeDependencies(filename) {
  return function bundleDeps() {
    return gulp.src([
  '../../public/javascripts/vendor/jquery.min.js',
  './dist/jquery.fill.js',
  './dep/powertip.min.js',
  './dep/howler.min.js',
  './dep/mousetrap.min.js',
  './dist/consolemsg.js',
  ...(abFile ? ['./dist/ab.js'] : []),
])
      .pipe(concat(filename))
      .pipe(destination());
  };
}

function makeBundle(filename) {
  return function bundleItAll() {
    return gulp.src([
      destinationPath + 'lichess.deps.js',
      './dist/' + filename,
    ])
      .pipe(concat(filename.replace('source.', '')))
      .pipe(destination());
  };
}

const gitSha = (cb) => exec("git rev-parse -q --short HEAD", function (err, stdout) {
  if (err) throw err;
  if (!fs.existsSync('./dist')) fs.mkdirSync('./dist');
  var date = new Date().toISOString().split('.')[0];
  fs.writeFileSync('./dist/consolemsg.js',
    'window.lichess=window.lichess||{};console.info("Lichess is open source! https://github.com/ornicar/lila");' +
    `lichess.info = "Assets built ${date} from sha ${stdout.trim()}";`);
  cb();
});

const standalonesJs = () => gulp.src([
  'util.js', 'trans.js', 'tv.js', 'puzzle.js', 'user.js', 'coordinate.js', 'captcha.js', 'embed-analyse.js'
].map(f => `src/standalones/${f}`))
  .pipe(buffer())
  .pipe(uglify())
  .pipe(destination());

const userMod = () => browserify(browserifyOpts('./src/user-mod.js', false))
  .bundle()
  .pipe(source('user-mod.js'))
  .pipe(buffer())
  .pipe(uglify())
  .pipe(destination());

const deps = makeDependencies('lichess.deps.js');

const tasks = [gitSha, jqueryFill, ab, standalonesJs, userMod, stockfishWasm, stockfishMvWasm, stockfishPexe, stockfishJs, deps];

const dev = gulp.series(tasks.concat([devSource]));

gulp.task('prod', gulp.series(tasks, prodSource, makeBundle(`${fileBaseName}.source.min.js`)));
gulp.task('dev', gulp.series(tasks, dev));
gulp.task('default', gulp.series(tasks, dev, () => gulp.watch('src/**/*.js', dev)));
<|endoftext|>


<commit_before>module.exports {
  entry: {
    app: './index.js'
  },

  module: {
    loaders: [{
      test: /\.js$/,
      loader: 'babel',
    }]
  },
}
<commit_msg>clean: remove unwanted files<commit_after><|endoftext|>


<commit_before>const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const autoprefixer = require('autoprefixer');

const themePath = path.join(__dirname, 'theme.json');

module.exports = {
  entry: {
    main: path.join(__dirname, 'app.js'),
    splash: path.join(__dirname, 'splash.js'),
  },

  output: {
    path: '/',
    filename: '[name]-[chunkhash].js',
    publicPath: '/',
  },

  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('development'),
    }),
    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'index.html'),
      favicon: path.join(__dirname, 'favicon.ico'),
      inject: 'body',
    }),
    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'index.html'),
      favicon: path.join(__dirname, 'favicon.ico'),
      inject: 'body',
      filename: 'splash.html',
      chunks: ['splash']
    }),
    new ExtractTextPlugin('main-[contenthash].css'),
    new ExtractTextPlugin('splash-[contenthash].css'),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin(),
    new webpack.optimize.AggressiveMergingPlugin(),
  ],

  sassLoader: {
    precision: 8,
  },

  postcss: [
    autoprefixer({
      browsers: [
        'Android >= 4',
        'Chrome >= 20',
        'Firefox >= 24',
        'Explorer >= 9',
        'Edge >= 1',
        'iOS >= 6',
        'Opera >= 12',
        'Safari >= 6',
      ],
    }),
  ],
  devtool: '#inline-source-map',
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel',
      },
      {
        test: /\.scss$/,
        loader: ExtractTextPlugin.extract(
          'style',
          `css?modules!postcss!sass!jsontosass?path=${themePath}`
        ),
      },
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract("style-loader", "css-loader!sass-loader"),
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loader: "file-loader?name=[name].[ext]",
      }
    ],
  },
};
<commit_msg>Rmove UglifyJsPlugin from development webpack config<commit_after>const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const autoprefixer = require('autoprefixer');

const themePath = path.join(__dirname, 'theme.json');

module.exports = {
  entry: {
    main: path.join(__dirname, 'app.js'),
    splash: path.join(__dirname, 'splash.js'),
  },

  output: {
    path: '/',
    filename: '[name]-[chunkhash].js',
    publicPath: '/',
  },

  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('development'),
    }),
    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'index.html'),
      favicon: path.join(__dirname, 'favicon.ico'),
      inject: 'body',
    }),
    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'index.html'),
      favicon: path.join(__dirname, 'favicon.ico'),
      inject: 'body',
      filename: 'splash.html',
      chunks: ['splash']
    }),
    new ExtractTextPlugin('main-[contenthash].css'),
    new ExtractTextPlugin('splash-[contenthash].css'),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.AggressiveMergingPlugin(),
  ],

  sassLoader: {
    precision: 8,
  },

  postcss: [
    autoprefixer({
      browsers: [
        'Android >= 4',
        'Chrome >= 20',
        'Firefox >= 24',
        'Explorer >= 9',
        'Edge >= 1',
        'iOS >= 6',
        'Opera >= 12',
        'Safari >= 6',
      ],
    }),
  ],
  devtool: '#inline-source-map',
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel',
      },
      {
        test: /\.scss$/,
        loader: ExtractTextPlugin.extract(
          'style',
          `css?modules!postcss!sass!jsontosass?path=${themePath}`
        ),
      },
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract("style-loader", "css-loader!sass-loader"),
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loader: "file-loader?name=[name].[ext]",
      }
    ],
  },
};
<|endoftext|>


<commit_before>// This is just a modification of the integer difference problem presented elsewhere
var arrayPairSum = function (k, array) {
  var hash  = {},
      pairs = [];

  // Loop through the array once, storing the results in an object for a
  // time complexity of O(n) - the naive solution consists of two for loops
  // which results in a complexity of O(n^2)
  array.forEach(function (number) {
    hash[number] = hash[number] + 1 || 1;

    for (var i = 0; i < (hash[k - number] || 0); i++) {
      pairs.push([number, k - number]);
    }
  });

  return pairs;
};
<commit_msg>Implement fix for the issue mentioned in #13.<commit_after>// This is just a modification of the integer difference problem presented elsewhere
var arrayPairSum = function (k, array) {
  var hash  = {},
      pairs = [];

  // Loop through the array once, storing the results in an object for a
  // time complexity of O(n) - the naive solution consists of two for loops
  // which results in a complexity of O(n^2)
  array.forEach(function (number) {
    for (var i = 0; i < (hash[k - number] || 0); i++) {
      pairs.push([number, k - number]);
    }

    hash[number] = hash[number] + 1 || 1;
  });

  return pairs;
};
<|endoftext|>