<commit_before>  $(function(){
    var $doc = $(document);
    var $half_h = $(".pp-half-height");
    var $full_h = $(".pp-full-height");
    var $plus_h = $(".pp-full-height-plus");
    var $sections = $(".pp-section");
    var $slow = $(".pp-section .pp-slow");
    var $fast = $(".pp-section .pp-fast");
    var $goup = $(".pp-section .pp-go-up");
    var $godown = $(".pp-section .pp-go-down");
    var $stay = $(".pp-section .pp-go-down");

    var resize_cb = function(){
      var viewport_h = window.innerHeight;
      $half_h.each(function(){
        var $t = $(this);
        var height_minus_percent = $t.attr('data-height-minus-percent');
        height_minus_percent = height_minus_percent ? height_minus_percent : 0;
        var height_minus_fixed   = $t.attr('data-height-minus');
        height_minus_fixed = height_minus_fixed ? height_minus_fixed : 0;
        var height_minus = (height_minus_percent * window.innerHeight / 100) + height_minus_fixed;
        $t.css({"height": (viewport_h/2) - height_minus});
      });
      $full_h.each(function(){
        var $t = $(this);
        var height_minus_percent = $t.attr('data-height-minus-percent');
        height_minus_percent = height_minus_percent ? height_minus_percent : 0;
        var height_minus_fixed   = $t.attr('data-height-minus');
        height_minus_fixed = height_minus_fixed ? height_minus_fixed : 0;
        var height_minus = (height_minus_percent * window.innerHeight / 100) + height_minus_fixed;
        $t.css({"height": viewport_h - height_minus});
      });
      $plus_h.each(function(){
        var $t = $(this);
        $t.css({"height": viewport_h*1.5});
      });
    };

    var section_onposition_cb = function(){
        var $t = $(this);
    }

    var scroll_section_cb = function(){
        var viewport_h = window.innerHeight;
        var viewport_w = window.innerWidth;

        var min = viewport_h - (viewport_h*1.5)
        var max = 0;

        var $t = $(this);
        var $section_y = $doc.scrollTop() - $t.offset().top;
        var $half_section_y = ($doc.scrollTop() - $t.offset().top)/2;
        if(Math.abs($section_y) <= viewport_h){
          var $slt  = $t.find(".pp-slowest");
          var $slr  = $t.find(".pp-slower");
          var $sl   = $t.find(".pp-slow");
          var $fa   = $t.find(".pp-fast");
          var $stst = $t.find(".pp-slowest-stay");
          var $sst  = $t.find(".pp-slow-stay");
          var $fst  = $t.find(".pp-fast-stay");
          var $gup  = $t.find(".pp-go-up");
          var $gdo  = $t.find(".pp-go-down");
          var $rtl  = $t.find(".pp-right-to-left");
          var $rtlst  = $t.find(".pp-right-to-left-stay");
          var $rtlslow = $t.find(".pp-right-to-left-slow");
          var $rtlslower = $t.find(".pp-right-to-left-slower");
          var $rtlslowerst = $t.find(".pp-right-to-left-slower-stay");
          var $rtlslowest = $t.find(".pp-right-to-left-slowest");
          var $rtlfast = $t.find(".pp-right-to-left-fast");
          var $rtlfaster = $t.find(".pp-right-to-left-faster");
          var $rtlfastest = $t.find(".pp-right-to-left-fastest");
          var $ltr  = $t.find(".pp-left-to-right");
          var $ltrslow    = $t.find(".pp-left-to-right-slow");
          var $ltrslowst  = $t.find(".pp-left-to-right-slow-stay");
          var $ltrslower  = $t.find(".pp-left-to-right-slower");
          var $ltrslowerst = $t.find(".pp-left-to-right-slower-stay");
          var $ltrslowest = $t.find(".pp-left-to-right-slowest");
          var $ltrfast    = $t.find(".pp-left-to-right-fast");
          var $ltrfaster  = $t.find(".pp-left-to-right-faster");
          var $ltrfastest = $t.find(".pp-left-to-right-fastest");
          var $gr   = $t.find(".pp-grow");
          var $sh   = $t.find(".pp-shrink");
          var $grs  = $t.find(".pp-grow-stay");
          var $shs  = $t.find(".pp-shrink-stay");
          var $fi   = $t.find(".pp-fade-in");
          var $fo   = $t.find(".pp-fade-out");
          var $vc   = $t.find(".pp-vertical-center");
          var $vc2  = $t.find(".pp-vertical-center-2");
          var $rot90   = $t.find(".pp-rotate-90");
          var $rot90c  = $t.find(".pp-rotate-90-ccw");
          var $rot90s   = $t.find(".pp-rotate-90-stay");
          var $rot90cs  = $t.find(".pp-rotate-90-ccw-stay");
          $slt.css({"top": $section_y*0.8});
          $slr.css({"top": $section_y*0.72});
          $sl.css({"top": $section_y*0.5});
          $fa.css({"top": ($section_y*-0.5) - viewport_h * 0.5});
          $stst.css({"top": Math.max($half_section_y*0.8, $section_y)});
          $sst.css({"top": Math.max($half_section_y*0.5, $section_y)});
          $fst.css({"top": Math.max($half_section_y*-0.2, $section_y)});
          $vc.css({"top": Math.max(($t.height()-$vc.height())/2, 0)});
          $vc2.css({"top": Math.max(($t.height()-$vc2.height())/2, 0)});
          $rot90.css({"transform": "rotate("+(Math.min(Math.max(90*($section_y/viewport_h),-90),90))+"deg)"});
          $rot90c.css({"transform": "rotate("+(Math.min(Math.max(-90*($section_y/viewport_h),-90),90))+"deg)"});
          $rot90s.css({"transform": "rotate("+(Math.min(Math.max(90*($section_y/viewport_h),-90),0))+"deg)"});
          $rot90cs.css({"transform": "rotate("+(Math.min(Math.max(-90*($section_y/viewport_h),0),90))+"deg)"});
          //$gup.css({"top": Math.max($half_section_y/2, $section_y)});
          //$gdo.css({"top": Math.max($half_section_y, $section_y)});
          $ltr.css({"left": $section_y*viewport_w*0.5/viewport_h});
          $rtlst.css({"left": Math.max(-$section_y*viewport_w*0.3/viewport_h, 0)});
          $ltrslow.css({"left": $section_y*viewport_w*0.3/viewport_h});
          $ltrslowst.css({"left": Math.min($section_y*viewport_w*0.3/viewport_h, 0)});
          $ltrslower.css({"left": $section_y*viewport_w*0.1/viewport_h});
          $ltrslowerst.css({"left": Math.min($section_y*viewport_w*0.1/viewport_h, 0)});
          $ltrslowest.css({"left": $section_y*viewport_w*0.05/viewport_h});
          $ltrfast.css({"left": $section_y*viewport_w*0.7/viewport_h});
          $ltrfaster.css({"left": $section_y*viewport_w*0.9/viewport_h});
          $ltrfastest.css({"left": $section_y*viewport_w*0.95/viewport_h});
          $rtl.css({"left": -$section_y*viewport_w*0.5/viewport_h});
          $rtlslow.css({"left": -$section_y*viewport_w*0.3/viewport_h});
          $rtlslower.css({"left": -$section_y*viewport_w*0.1/viewport_h});
          $rtlslowerst.css({"left": Math.max(-$section_y*viewport_w*0.1/viewport_h, 0)});
          $rtlslowest.css({"left": -$section_y*viewport_w*0.05/viewport_h});
          $rtlfast.css({"left": -$section_y*viewport_w*0.7/viewport_h});
          $rtlfaster.css({"left": -$section_y*viewport_w*0.9/viewport_h});
          $rtlfastest.css({"left": -$section_y*viewport_w*0.95/viewport_h});
          $gr.css({"transform": "scale("+(Math.min(Math.max(1+($section_y/viewport_h)*2,0.5),2))+","+(Math.min(Math.max(1+($section_y/viewport_h)*2,0.5),2))+")"});
          $sh.css({"transform": "scale("+(Math.max(1-($section_y/viewport_h)*2,0.3))+","+(Math.max(1-($section_y/viewport_h)*2,0.3))+")"});
          $grs.css({"transform": "scale("+(Math.min(Math.max(1+($section_y/viewport_h)*2,0.4),1))+","+(Math.min(Math.max(1+($section_y/viewport_h)*2,0.4),1))+")"});
          $shs.css({"transform": "scale("+(Math.max(1-($section_y/viewport_h)*2,1))+","+(Math.max(1-($section_y/viewport_h)*2,1))+")"});
          $fi.css({"opacity": 1+($section_y/viewport_h)});
          $fo.css({"opacity": 1-($section_y/viewport_h)*2});
          if(!$t.hasClass("pp-on-viewport")){
            $t.addClass("pp-on-viewport");
            var onentercb = $t.attr('data-pp-onenterviewport');
            if(onentercb){
              eval($t.attr('data-pp-onenterviewport')+";");
            }
          }
        } else {
          // la section está fuera de la vista
          //$t.find(".pp-move").css({"top": 0});
          //$t.find(".pp-background").css({"top": 0});
          if($t.hasClass("pp-on-viewport")){
            $t.removeClass("pp-on-viewport");
            var onexitcb = $t.attr('data-pp-onexitviewport');
            if(onexitcb){
              eval($t.attr('data-pp-onexitviewport')+";");
            }
          }
        }
    }
    var scroll_cb = function(ev){
      var viewport_h = window.innerHeight;
      $sections.each(scroll_section_cb);
      if(ev) ev.preventDefault();
    }

    $(window).resize(resize_cb);
    $(document).scroll(scroll_cb);
    resize_cb();
    scroll_cb();
  });

function _throttle(delay, func){
  var throttle_timeout = false;
    return function(){
        if(throttle_timeout){
        } else {
          throttle_timeout = setTimeout(function(){
            func();
            throttle_timeout = false;
          },delay);
        }
      };
}
<commit_msg>Acumulación de transformaciones CSS<commit_after>  $(function(){
    var $doc = $(document);
    var $half_h = $(".pp-half-height");
    var $full_h = $(".pp-full-height");
    var $plus_h = $(".pp-full-height-plus");
    var $sections = $(".pp-section");
    var $slow = $(".pp-section .pp-slow");
    var $fast = $(".pp-section .pp-fast");
    var $goup = $(".pp-section .pp-go-up");
    var $godown = $(".pp-section .pp-go-down");
    var $stay = $(".pp-section .pp-go-down");

    var resize_cb = function(){
      var viewport_h = window.innerHeight;
      $half_h.each(function(){
        var $t = $(this);
        var height_minus_percent = $t.attr('data-height-minus-percent');
        height_minus_percent = height_minus_percent ? height_minus_percent : 0;
        var height_minus_fixed   = $t.attr('data-height-minus');
        height_minus_fixed = height_minus_fixed ? height_minus_fixed : 0;
        var height_minus = (height_minus_percent * window.innerHeight / 100) + height_minus_fixed;
        $t.css({"height": (viewport_h/2) - height_minus});
      });
      $full_h.each(function(){
        var $t = $(this);
        var height_minus_percent = $t.attr('data-height-minus-percent');
        height_minus_percent = height_minus_percent ? height_minus_percent : 0;
        var height_minus_fixed   = $t.attr('data-height-minus');
        height_minus_fixed = height_minus_fixed ? height_minus_fixed : 0;
        var height_minus = (height_minus_percent * window.innerHeight / 100) + height_minus_fixed;
        $t.css({"height": viewport_h - height_minus});
      });
      $plus_h.each(function(){
        var $t = $(this);
        $t.css({"height": viewport_h*1.5});
      });
    };

    var section_onposition_cb = function(){
        var $t = $(this);
    }

    var scroll_section_cb = function(){
        var viewport_h = window.innerHeight;
        var viewport_w = window.innerWidth;

        var min = viewport_h - (viewport_h*1.5)
        var max = 0;

        var $t = $(this);
        var $section_y = $doc.scrollTop() - $t.offset().top;
        var $half_section_y = ($doc.scrollTop() - $t.offset().top)/2;
        if(Math.abs($section_y) <= viewport_h){
          var $slt  = $t.find(".pp-slowest");
          var $slr  = $t.find(".pp-slower");
          var $sl   = $t.find(".pp-slow");
          var $fa   = $t.find(".pp-fast");
          var $stst = $t.find(".pp-slowest-stay");
          var $sst  = $t.find(".pp-slow-stay");
          var $fst  = $t.find(".pp-fast-stay");
          var $gup  = $t.find(".pp-go-up");
          var $gdo  = $t.find(".pp-go-down");
          var $rtl  = $t.find(".pp-right-to-left");
          var $rtlslow = $t.find(".pp-right-to-left-slow");
          var $rtlst  = $t.find(".pp-right-to-left-stay");
          var $rtlslower = $t.find(".pp-right-to-left-slower");
          var $rtlslowerst = $t.find(".pp-right-to-left-slower-stay");
          var $rtlslowest = $t.find(".pp-right-to-left-slowest");
          var $rtlfast = $t.find(".pp-right-to-left-fast");
          var $rtlfaster = $t.find(".pp-right-to-left-faster");
          var $rtlfastest = $t.find(".pp-right-to-left-fastest");
          var $ltr  = $t.find(".pp-left-to-right");
          var $ltrslow    = $t.find(".pp-left-to-right-slow");
          var $ltrslowst  = $t.find(".pp-left-to-right-slow-stay");
          var $ltrslower  = $t.find(".pp-left-to-right-slower");
          var $ltrslowerst = $t.find(".pp-left-to-right-slower-stay");
          var $ltrslowest = $t.find(".pp-left-to-right-slowest");
          var $ltrfast    = $t.find(".pp-left-to-right-fast");
          var $ltrfaster  = $t.find(".pp-left-to-right-faster");
          var $ltrfastest = $t.find(".pp-left-to-right-fastest");
          var $gr   = $t.find(".pp-grow");
          var $sh   = $t.find(".pp-shrink");
          var $grs  = $t.find(".pp-grow-stay");
          var $shs  = $t.find(".pp-shrink-stay");
          var $fi   = $t.find(".pp-fade-in");
          var $fo   = $t.find(".pp-fade-out");
          var $vc   = $t.find(".pp-vertical-center");
          var $vc2  = $t.find(".pp-vertical-center-2");
          var $rot90   = $t.find(".pp-rotate-90");
          var $rot90c  = $t.find(".pp-rotate-90-ccw");
          var $rot90s   = $t.find(".pp-rotate-90-stay");
          var $rot90cs  = $t.find(".pp-rotate-90-ccw-stay");
          $slt.css({"top": $section_y*0.8});
          $slr.css({"top": $section_y*0.72});
          $sl.css({"top": $section_y*0.5});
          $fa.css({"top": ($section_y*-0.5) - viewport_h * 0.5});
          $stst.css({"top": Math.max($half_section_y*0.8, $section_y)});
          $sst.css({"top": Math.max($half_section_y*0.5, $section_y)});
          $fst.css({"top": Math.max($half_section_y*-0.2, $section_y)});
          $vc.css({"top": Math.max(($t.height()-$vc.height())/2, 0)});
          $vc2.css({"top": Math.max(($t.height()-$vc2.height())/2, 0)});
          $rot90.addClass("pp-transformed").data({"pp-transform-rotate": "rotate("+(Math.min(Math.max(90*($section_y/viewport_h),-90),90))+"deg)"});
          $rot90c.addClass("pp-transformed").data({"pp-transform-rotate": "rotate("+(Math.min(Math.max(-90*($section_y/viewport_h),-90),90))+"deg)"});
          $rot90s.addClass("pp-transformed").data({"pp-transform-rotate": "rotate("+(Math.min(Math.max(90*($section_y/viewport_h),-90),0))+"deg)"});
          $rot90cs.addClass("pp-transformed").data({"pp-transform-rotate": "rotate("+(Math.min(Math.max(-90*($section_y/viewport_h),0),90))+"deg)"});
          //$gup.css({"top": Math.max($half_section_y/2, $section_y)});
          //$gdo.css({"top": Math.max($half_section_y, $section_y)});
          $ltr.css({"left": $section_y*viewport_w*0.5/viewport_h});
          $rtlst.css({"left": Math.max(-$section_y*viewport_w*0.3/viewport_h, 0)});
          $ltrslow.css({"left": $section_y*viewport_w*0.3/viewport_h});
          $ltrslowst.css({"left": Math.min($section_y*viewport_w*0.3/viewport_h, 0)});
          $ltrslower.css({"left": $section_y*viewport_w*0.1/viewport_h});
          $ltrslowerst.css({"left": Math.min($section_y*viewport_w*0.1/viewport_h, 0)});
          $ltrslowest.css({"left": $section_y*viewport_w*0.05/viewport_h});
          $ltrfast.css({"left": $section_y*viewport_w*0.7/viewport_h});
          $ltrfaster.css({"left": $section_y*viewport_w*0.9/viewport_h});
          $ltrfastest.css({"left": $section_y*viewport_w*0.95/viewport_h});
          $rtl.css({"left": -$section_y*viewport_w*0.5/viewport_h});
          $rtlslow.css({"left": -$section_y*viewport_w*0.3/viewport_h});
          $rtlslower.css({"left": -$section_y*viewport_w*0.1/viewport_h});
          $rtlslowerst.css({"left": Math.max(-$section_y*viewport_w*0.1/viewport_h, 0)});
          $rtlslowest.css({"left": -$section_y*viewport_w*0.05/viewport_h});
          $rtlfast.css({"left": -$section_y*viewport_w*0.7/viewport_h});
          $rtlfaster.css({"left": -$section_y*viewport_w*0.9/viewport_h});
          $rtlfastest.css({"left": -$section_y*viewport_w*0.95/viewport_h});
          $gr.addClass("pp-transformed").data({"pp-transform-scale": "scale("+(Math.min(Math.max(1+($section_y/viewport_h)*2,0.5),2))+","+(Math.min(Math.max(1+($section_y/viewport_h)*2,0.5),2))+")"});
          $sh.addClass("pp-transformed").data({"pp-transform-scale": "scale("+(Math.max(1-($section_y/viewport_h)*2,0.3))+","+(Math.max(1-($section_y/viewport_h)*2,0.3))+")"});
          $grs.addClass("pp-transformed").data({"pp-transform-scale": "scale("+(Math.min(Math.max(1+($section_y/viewport_h)*2,0.4),1))+","+(Math.min(Math.max(1+($section_y/viewport_h)*2,0.4),1))+")"});
          $shs.addClass("pp-transformed").data({"pp-transform-scale": "scale("+(Math.max(1-($section_y/viewport_h)*2,1))+","+(Math.max(1-($section_y/viewport_h)*2,1))+")"});
          $fi.css({"opacity": 1+($section_y/viewport_h)});
          $fo.css({"opacity": 1-($section_y/viewport_h)*2});

          // apply all transformations
          var $transf = $t.find(".pp-transformed");
          $transf.each(function(){
            $this = $(this);
            var rule =
              ($this.data('pp-transform-scale')?$this.data('pp-transform-scale')+" ":"")+
              ($this.data('pp-transform-rotate')?$this.data('pp-transform-rotate')+" ":"")
            ;
            $this.css({"transform": rule});
          })

          if(!$t.hasClass("pp-on-viewport")){
            $t.addClass("pp-on-viewport");
            var onentercb = $t.attr('data-pp-onenterviewport');
            if(onentercb){
              eval($t.attr('data-pp-onenterviewport')+";");
            }
          }
        } else {
          // la section está fuera de la vista
          //$t.find(".pp-move").css({"top": 0});
          //$t.find(".pp-background").css({"top": 0});
          if($t.hasClass("pp-on-viewport")){
            $t.removeClass("pp-on-viewport");
            var onexitcb = $t.attr('data-pp-onexitviewport');
            if(onexitcb){
              eval($t.attr('data-pp-onexitviewport')+";");
            }
          }
        }
    }
    var scroll_cb = function(ev){
      var viewport_h = window.innerHeight;
      $sections.each(scroll_section_cb);
      if(ev) ev.preventDefault();
    }

    $(window).resize(resize_cb);
    $(document).scroll(scroll_cb);
    resize_cb();
    scroll_cb();
  });

function _throttle(delay, func){
  var throttle_timeout = false;
    return function(){
        if(throttle_timeout){
        } else {
          throttle_timeout = setTimeout(function(){
            func();
            throttle_timeout = false;
          },delay);
        }
      };
}
<|endoftext|>


<commit_before>/*
 * fixmystreet.js
 * FixMyStreet JavaScript used by all cobrands.
 * With the JavaScript written more proper like.
 */

(function($){

/*
 Deal with changes to category by asking for details from the server.
 */
$(function(){

    var $html = $('html');

    // Add a class to the whole page saying JavaScript is enabled (for CSS and so on)
    $html.removeClass('no-js').addClass('js');

    // Preload the new report pin
    if ( typeof fixmystreet !== 'undefined' && typeof fixmystreet.pin_prefix !== 'undefined' ) {
        document.createElement('img').src = fixmystreet.pin_prefix + 'pin-green.png';
    } else {
        document.createElement('img').src = '/i/pin-green.png';
    }

    // Focus on postcode box on front page
    $('#pc').focus();

    // In case we've come here by clicking back to a form that disabled a submit button
    $('input[type=submit]').removeAttr('disabled');

    // Questionnaire hide/showings
    if (!$('#been_fixed_no').prop('checked') && !$('#been_fixed_unknown').prop('checked')) {
        $('#another_qn').hide();
    }
    $('#been_fixed_no').click(function() {
        $('#another_qn').show('fast');
    });
    $('#been_fixed_unknown').click(function() {
        $('#another_qn').show('fast');
    });
    $('#been_fixed_yes').click(function() {
        $('#another_qn').hide('fast');
    });

    // Form validation

    // FIXME - needs to use translated string
    jQuery.validator.addMethod('validCategory', function(value, element) {
        return this.optional(element) || value != '-- Pick a category --'; }, translation_strings.category );

    jQuery.validator.addMethod('validName', function(value, element) {
        var validNamePat = /\ba\s*n+on+((y|o)mo?u?s)?(ly)?\b/i;
        return this.optional(element) || value.length > 5 && value.match( /\S/ ) && value.match( /\s/ ) && !value.match( validNamePat ); }, translation_strings.category );

    var form_submitted = 0;
    var submitted = false;

    $("form.validate").each(function(){
      $(this).validate({
        rules: validation_rules,
        messages: translation_strings,
        onkeyup: false,
        onfocusout: false,
        errorElement: 'div',
        errorClass: 'form-error',
        // we do this to stop things jumping around on blur
        success: function (err) { if ( form_submitted ) { err.addClass('label-valid').removeClass('label-valid-hidden').html( ' ' ); } else { err.addClass('label-valid-hidden'); } },
        errorPlacement: function( error, element ) {
            // Different for old/new style design
            if ($('.form-field').length) {
                element.parent('div.form-field').before( error );
            } else {
                element.before( error );
            }
        },
        submitHandler: function(form) {
            if (form.submit_problem) {
                $('input[type=submit]', form).prop("disabled", true);
            }

            form.submit();
        },
        // make sure we can see the error message when we focus on invalid elements
        showErrors: function( errorMap, errorList ) {
            if ( submitted && errorList.length ) {
               $(window).scrollTop( $(errorList[0].element).offset().top - 120 );
            }
            this.defaultShowErrors();
            submitted = false;
        },
        invalidHandler: function(form, validator) { submitted = true; }
      });
    });

    $('input[type=submit]').click( function(e) { form_submitted = 1; } );

    /* set correct required status depending on what we submit
    * NB: need to add things to form_category as the JS updating
    * of this we do after a map click removes them */
    $('#submit_sign_in').click( function(e) {
        $('#form_category').addClass('required validCategory').removeClass('valid');
        $('#form_name').removeClass();
        $('#form_first_name').removeClass();
        $('#form_last_name').removeClass();
        $('#form_fms_extra_title').removeClass();
    } );

    $('#submit_register').click( function(e) {
        $('#form_category').addClass('required validCategory').removeClass('valid');
        $('#form_name').addClass('required');
        if ( $('#mapForm').length ) {
            $('#form_name').addClass('validName');
        }
        $('#form_first_name').addClass('required');
        $('#form_last_name').addClass('required');
        $('#form_fms_extra_title').addClass('required');
    } );

    $('#problem_submit > input[type="submit"]').click( function(e) {
        $('#form_category').addClass('required validCategory').removeClass('valid');
        $('#form_name').addClass('required');
        if ( $('#mapForm').length ) {
            $('#form_name').addClass('validName');
        }
        $('#form_first_name').addClass('required');
        $('#form_last_name').addClass('required');
        $('#form_fms_extra_title').addClass('required');
    } );

    $('#update_post').click( function(e) {
        $('#form_name').addClass('required').removeClass('valid');
    } );

    // Geolocation
    if (geo_position_js.init()) {
        var link ='

Ser localizado automáticamente
 Encuéntrame
';
        $('form[action="/alert/list"]').append(link.replace('LINK','alert/list'));
        if ($('body.frontpage').length) {
            $('#postcodeForm').after(link.replace('LINK','around'));
        } else{
            $('#postcodeForm').append(link.replace('LINK','around'));
        }
        $('#geolocate_link').click(function(e) {
            var $link = $(this);
            e.preventDefault();
            // Spinny thing!
            if($('.mobile').length){
                $link.append(' ');
            }else{
                var spincolor = $('').css("color","white").css("color") === $('#front-main').css("background-color")? 'white' : 'black';
                $link.append(' ');
            }
            geo_position_js.getCurrentPosition(function(pos) {
                $link.find('img').remove();
                var latitude = pos.coords.latitude;
                var longitude = pos.coords.longitude;
                var page = $link.attr('href').substr(1);
                location.href = '/' + page + '?latitude=' + latitude + ';longitude=' + longitude;
            }, function(err) {
                $link.find('img').remove();
                if (err.code == 1) { // User said no
                    $link.html(translation_strings.geolocation_declined);
                } else if (err.code == 2) { // No position
                    $link.html(translation_strings.geolocation_no_position);
                } else if (err.code == 3) { // Too long
                    $link.html(translation_strings.geolocation_no_result);
                } else { // Unknown
                    $link.html(translation_strings.geolocation_unknown);
                }
            }, {
                enableHighAccuracy: true,
                timeout: 10000
            });
        });
    }

    // Delegation is necessary because #form_category may be replaced during the lifetime of the page
    $("#problem_form").on("change.category", "select#form_category", function(){
        var args = {
            category: $(this).val()
        };

        if ( typeof fixmystreet !== 'undefined' ) {
            args.latitude = fixmystreet.latitude;
            args.longitude = fixmystreet.longitude;
        } else {
            args.latitude = $('input[name="latitude"]').val();
            args.longitude = $('input[name="longitude"]').val();
        }

        $.getJSON('/report/new/category_extras', args, function(data) {
            var $category_meta = $('#category_meta');
            if ( data.category_extra ) {
                if ( $category_meta.length ) {
                    $category_meta.html( data.category_extra );
                } else {
                    $('#form_category_row').after( data.category_extra );
                }
            } else {
                $category_meta.empty();
            }
        });
    });

    // Map form doesn't work in some browsers with HTML5 validation and hidden form, so
    // we disable validation by default, and add it in the JS case.
    // For some reason, the removeAttr doesn't work if we place it at beginning.
    $('#mapForm').removeAttr('novalidate');
});

})(jQuery);

<commit_msg>: para Ser localizado automáticamente:<commit_after>/*
 * fixmystreet.js
 * FixMyStreet JavaScript used by all cobrands.
 * With the JavaScript written more proper like.
 */

(function($){

/*
 Deal with changes to category by asking for details from the server.
 */
$(function(){

    var $html = $('html');

    // Add a class to the whole page saying JavaScript is enabled (for CSS and so on)
    $html.removeClass('no-js').addClass('js');

    // Preload the new report pin
    if ( typeof fixmystreet !== 'undefined' && typeof fixmystreet.pin_prefix !== 'undefined' ) {
        document.createElement('img').src = fixmystreet.pin_prefix + 'pin-green.png';
    } else {
        document.createElement('img').src = '/i/pin-green.png';
    }

    // Focus on postcode box on front page
    $('#pc').focus();

    // In case we've come here by clicking back to a form that disabled a submit button
    $('input[type=submit]').removeAttr('disabled');

    // Questionnaire hide/showings
    if (!$('#been_fixed_no').prop('checked') && !$('#been_fixed_unknown').prop('checked')) {
        $('#another_qn').hide();
    }
    $('#been_fixed_no').click(function() {
        $('#another_qn').show('fast');
    });
    $('#been_fixed_unknown').click(function() {
        $('#another_qn').show('fast');
    });
    $('#been_fixed_yes').click(function() {
        $('#another_qn').hide('fast');
    });

    // Form validation

    // FIXME - needs to use translated string
    jQuery.validator.addMethod('validCategory', function(value, element) {
        return this.optional(element) || value != '-- Pick a category --'; }, translation_strings.category );

    jQuery.validator.addMethod('validName', function(value, element) {
        var validNamePat = /\ba\s*n+on+((y|o)mo?u?s)?(ly)?\b/i;
        return this.optional(element) || value.length > 5 && value.match( /\S/ ) && value.match( /\s/ ) && !value.match( validNamePat ); }, translation_strings.category );

    var form_submitted = 0;
    var submitted = false;

    $("form.validate").each(function(){
      $(this).validate({
        rules: validation_rules,
        messages: translation_strings,
        onkeyup: false,
        onfocusout: false,
        errorElement: 'div',
        errorClass: 'form-error',
        // we do this to stop things jumping around on blur
        success: function (err) { if ( form_submitted ) { err.addClass('label-valid').removeClass('label-valid-hidden').html( ' ' ); } else { err.addClass('label-valid-hidden'); } },
        errorPlacement: function( error, element ) {
            // Different for old/new style design
            if ($('.form-field').length) {
                element.parent('div.form-field').before( error );
            } else {
                element.before( error );
            }
        },
        submitHandler: function(form) {
            if (form.submit_problem) {
                $('input[type=submit]', form).prop("disabled", true);
            }

            form.submit();
        },
        // make sure we can see the error message when we focus on invalid elements
        showErrors: function( errorMap, errorList ) {
            if ( submitted && errorList.length ) {
               $(window).scrollTop( $(errorList[0].element).offset().top - 120 );
            }
            this.defaultShowErrors();
            submitted = false;
        },
        invalidHandler: function(form, validator) { submitted = true; }
      });
    });

    $('input[type=submit]').click( function(e) { form_submitted = 1; } );

    /* set correct required status depending on what we submit
    * NB: need to add things to form_category as the JS updating
    * of this we do after a map click removes them */
    $('#submit_sign_in').click( function(e) {
        $('#form_category').addClass('required validCategory').removeClass('valid');
        $('#form_name').removeClass();
        $('#form_first_name').removeClass();
        $('#form_last_name').removeClass();
        $('#form_fms_extra_title').removeClass();
    } );

    $('#submit_register').click( function(e) {
        $('#form_category').addClass('required validCategory').removeClass('valid');
        $('#form_name').addClass('required');
        if ( $('#mapForm').length ) {
            $('#form_name').addClass('validName');
        }
        $('#form_first_name').addClass('required');
        $('#form_last_name').addClass('required');
        $('#form_fms_extra_title').addClass('required');
    } );

    $('#problem_submit > input[type="submit"]').click( function(e) {
        $('#form_category').addClass('required validCategory').removeClass('valid');
        $('#form_name').addClass('required');
        if ( $('#mapForm').length ) {
            $('#form_name').addClass('validName');
        }
        $('#form_first_name').addClass('required');
        $('#form_last_name').addClass('required');
        $('#form_fms_extra_title').addClass('required');
    } );

    $('#update_post').click( function(e) {
        $('#form_name').addClass('required').removeClass('valid');
    } );

    // Geolocation
    if (geo_position_js.init()) {
        var link ='

Ser localizado automáticamente:
 Encuéntrame
';
        $('form[action="/alert/list"]').append(link.replace('LINK','alert/list'));
        if ($('body.frontpage').length) {
            $('#postcodeForm').after(link.replace('LINK','around'));
        } else{
            $('#postcodeForm').append(link.replace('LINK','around'));
        }
        $('#geolocate_link').click(function(e) {
            var $link = $(this);
            e.preventDefault();
            // Spinny thing!
            if($('.mobile').length){
                $link.append(' ');
            }else{
                var spincolor = $('').css("color","white").css("color") === $('#front-main').css("background-color")? 'white' : 'black';
                $link.append(' ');
            }
            geo_position_js.getCurrentPosition(function(pos) {
                $link.find('img').remove();
                var latitude = pos.coords.latitude;
                var longitude = pos.coords.longitude;
                var page = $link.attr('href').substr(1);
                location.href = '/' + page + '?latitude=' + latitude + ';longitude=' + longitude;
            }, function(err) {
                $link.find('img').remove();
                if (err.code == 1) { // User said no
                    $link.html(translation_strings.geolocation_declined);
                } else if (err.code == 2) { // No position
                    $link.html(translation_strings.geolocation_no_position);
                } else if (err.code == 3) { // Too long
                    $link.html(translation_strings.geolocation_no_result);
                } else { // Unknown
                    $link.html(translation_strings.geolocation_unknown);
                }
            }, {
                enableHighAccuracy: true,
                timeout: 10000
            });
        });
    }

    // Delegation is necessary because #form_category may be replaced during the lifetime of the page
    $("#problem_form").on("change.category", "select#form_category", function(){
        var args = {
            category: $(this).val()
        };

        if ( typeof fixmystreet !== 'undefined' ) {
            args.latitude = fixmystreet.latitude;
            args.longitude = fixmystreet.longitude;
        } else {
            args.latitude = $('input[name="latitude"]').val();
            args.longitude = $('input[name="longitude"]').val();
        }

        $.getJSON('/report/new/category_extras', args, function(data) {
            var $category_meta = $('#category_meta');
            if ( data.category_extra ) {
                if ( $category_meta.length ) {
                    $category_meta.html( data.category_extra );
                } else {
                    $('#form_category_row').after( data.category_extra );
                }
            } else {
                $category_meta.empty();
            }
        });
    });

    // Map form doesn't work in some browsers with HTML5 validation and hidden form, so
    // we disable validation by default, and add it in the JS case.
    // For some reason, the removeAttr doesn't work if we place it at beginning.
    $('#mapForm').removeAttr('novalidate');
});

})(jQuery);

<|endoftext|>


<commit_before>/**
 * Grid of metabolites.
 * @author Stefan Verhoeven
 */
Ext.define('Esc.magmaweb.view.metabolite.List', {
  extend: 'Ext.grid.Panel',
  alias: 'widget.metabolitelist',
  requires: [
    'Ext.ux.grid.FiltersFeature', 'Esc.chemdoodle.Column',
    'Ext.toolbar.Paging', 'Ext.grid.column.Boolean',
    'Ext.grid.column.Action', 'Ext.selection.CheckboxModel',
    'Ext.grid.column.Number', 'Ext.grid.column.Template'
  ],
  store: 'Metabolites',
  viewConfig: {
    emptyText: 'No structures available: Add structures or relax filters'
  },
  selType: 'checkboxmodel',
  selModel: {
    allowDeselect: true,
    mode: 'SINGLE',
    showHeaderCheckbox: false
  },
  dockedItems: [{
    xtype: 'pagingtoolbar',
    store: 'Metabolites',   // same store GridPanel is using
    dock: 'bottom',
    displayInfo: true,
    items: [{
      xtype: 'combo',
      width: 170,
      store: [
        [10, '10 molecules per page'],
        [25, '25 molecules per page'],
        [50, '50 molecules per page'],
        [100, '100 molecules per page'],
        [250, '250 molecules per page'],
        [500, '500 molecules per page'],
        [1000, '1000 molecules per page']
      ],
      forceSelection: true,
      triggerAction: 'all',
      action: 'pagesizeCombo'
    }]
  }],
  initComponent: function() {
    Ext.log({}, 'Init met grid');
    var me = this;
    var molcol = Ext.create('Esc.chemdoodle.Column', {
      text: 'Molecule', dataIndex: 'mol',
      width: 162,
      initCanvas: function(id, width, height, value, record) {
        var c = new ChemDoodle.ViewerCanvas(id, width, height);
        c.loadMolecule(ChemDoodle.readMOL(value));
        var tip = Ext.create('Ext.tip.ToolTip', {
          target: id,
          html: null,
          listeners: {
            render: function(tip) {
              var c = new ChemDoodle.ViewerCanvas(id+'-'+tip.id, 300, 300);
              c.loadMolecule(ChemDoodle.readMOL(value));
            }
          }
        });
        tip.update('<canvas id="'+id+'-'+tip.id+'"></canvas>');
      }
    });

    var mfilters = Ext.create('Ext.ux.grid.FiltersFeature',{
      id: 'mfilter',
      encode: true
    });

    this.addEvents([
        /**
         * @event metabolize
         * Fired after metabolize column action is clicked
         * @param {Ext.data.Model} record The record to metabolize
         */
        'metabolize'
    ]);

    Ext.apply(this, {
      columns: [
        {text: 'ID', dataIndex: 'metid', hidden: true},
        {text: 'Scans', dataIndex: 'nhits', filter: {
            type: 'numeric', value:{gt:0}, active: true
        }},
        {text: 'Assigned', dataIndex: 'assigned', hidden: false, xtype:'booleancolumn', trueText:'Yes', falseText:'No', filter: { type: 'boolean' }},
        {text: 'Candidate score', dataIndex: 'score', hidden: true, filter: { type: 'numeric' }, xtype: 'numbercolumn', format: '0.00000'},
        molcol,
        {text: 'Smiles', dataIndex: 'smiles', hidden:true},
        {text: 'Formula', dataIndex: 'molformula', filter: { type: 'string' }},
        {text: 'Monoisotopic mass', dataIndex: 'mim', filter: { type: 'numeric' }, hidden: false, xtype: 'numbercolumn', format: '0.00000'},
        {text: 'ΔMass (ppm)', dataIndex: 'deltappm', hidden: true, filter: { type: 'numeric' }, xtype: 'numbercolumn', format: '0.00000'},
        {text: 'Name', dataIndex: 'origin', flex:1, filter: { type: 'string' }},
        {
            text: 'Reaction sequence', dataIndex: 'reactionsequence', flex:1, filter: { type: 'string' },
            hidden: true,
            xtype: 'templatecolumn', tpl: '
<tpl for="reactionsequence">
{.}
</tpl>
'
        },
        {text: 'Refscore', dataIndex: 'probability', filter: { type: 'numeric' }, xtype: 'numbercolumn', format: '0.00000'},
        {text: 'Level', dataIndex: 'level', filter: { type: 'list',  options: ['0','1','2','3'] }, hidden:true},
        {text: 'LogP', dataIndex: 'logp', filter: { type: 'numeric' }, hidden: true, xtype: 'numbercolumn', format: '0.00000'},
        {text: 'Reference', dataIndex: 'reference', filter: { type: 'string' }, sortable: false },
        {text: 'Query', dataIndex: 'isquery', xtype:'booleancolumn', hidden: true, trueText:'Yes', falseText:'No', filter: { type: 'boolean' }},
        {xtype: 'actioncolumn', width:30, text:'Commands', hidden: true,
            items: [{
                tooltip: 'Metabolize',
                iconCls: 'metabolize-col',
                handler: function(grid, rowIndex) {
                    me.fireEvent('metabolize', me.getStore().getAt(rowIndex));
                }
            }]
        }
      ],
      plugins: [molcol],
      features: [mfilters]
    });
    this.callParent(arguments);
  },
  /**
   * @return {Ext.ux.grid.FiltersFeature}
   * @private
   */
  getFilter: function() {
	return this.getView().getFeature('mfilter');
  },
  /**
   * Clears all filters applied to metabolites
   */
  clearFilters: function() {
    this.getFilter().clearFilters();
  },
  /**
   * Get column with scores.
   *
   * Column should only be shown when a scan has been selected.
   *
   * @return {Ext.grid.column.Column}
   */
  getFragmentScoreColumn: function() {
      return this.columns.filter(function(c) { return (c.dataIndex == "score");})[0];
  },
  /**
   * Get column with deltappm.
   *
   * Column should only be shown when a scan has been selected.
   *
   * @return {Ext.grid.column.Column}
   */
  getFragmentDeltaPpmColumn: function() {
      return this.columns.filter(function(c) { return (c.dataIndex == "deltappm");})[0];
  },
  /**
   * Get column with commands.
   *
   * @return {Ext.grid.column.Action}
   */
  getCommandsColumn: function() {
      return this.columns.filter(function(c) { return (c.text == "Commands");})[0];
  },
  /**
   * Hides column with scores/deltappm and removes sort in header column.
   */
  hideFragmentScoreColumn: function() {
    var sortCls = [
        Ext.baseCSSPrefix + 'column-header-sort-ASC',
        Ext.baseCSSPrefix + 'column-header-sort-DESC'
    ];
    var score = this.getFragmentScoreColumn();
    score.hide();
    score.removeCls(sortCls);
    var deltappm = this.getFragmentDeltaPpmColumn()
    deltappm.hide();
    deltappm.removeCls(sortCls);
  },
  /**
   * Shows column with scores/deltappm.
   */
  showFragmentScoreColumn: function() {
    this.getFragmentScoreColumn().show();
    this.getFragmentDeltaPpmColumn().show();
  },
  /**
   * JSON encoded the filter data as query
   * @return {String}
   */
  getFilterQuery: function() {
	  var filter = this.getFilter();
	  return filter.buildQuery(filter.getFilterData());
  },
  /**
   * Array of dataindexes currently visible. In order they appear.
   * @return {Array}
   */
  getVisiblColumnIndices: function() {
	  return this.getView().getHeaderCt().getVisibleGridColumns().map(function(v) {return v.dataIndex}).filter(function(v) { return v});
  },
  hideCommandsColumn: function() {
	  this.getCommandsColumn().hide();
  },
  setPageSize: function(size) {
	  Ext.ComponentQuery.query('component[action=pagesizeCombo]')[0].select(size);
  }
});
<commit_msg>Renamed column header Smiles to Inchikey in Molecules panel. Fixes #168.<commit_after>/**
 * Grid of metabolites.
 * @author Stefan Verhoeven
 */
Ext.define('Esc.magmaweb.view.metabolite.List', {
  extend: 'Ext.grid.Panel',
  alias: 'widget.metabolitelist',
  requires: [
    'Ext.ux.grid.FiltersFeature', 'Esc.chemdoodle.Column',
    'Ext.toolbar.Paging', 'Ext.grid.column.Boolean',
    'Ext.grid.column.Action', 'Ext.selection.CheckboxModel',
    'Ext.grid.column.Number', 'Ext.grid.column.Template'
  ],
  store: 'Metabolites',
  viewConfig: {
    emptyText: 'No structures available: Add structures or relax filters'
  },
  selType: 'checkboxmodel',
  selModel: {
    allowDeselect: true,
    mode: 'SINGLE',
    showHeaderCheckbox: false
  },
  dockedItems: [{
    xtype: 'pagingtoolbar',
    store: 'Metabolites',   // same store GridPanel is using
    dock: 'bottom',
    displayInfo: true,
    items: [{
      xtype: 'combo',
      width: 170,
      store: [
        [10, '10 molecules per page'],
        [25, '25 molecules per page'],
        [50, '50 molecules per page'],
        [100, '100 molecules per page'],
        [250, '250 molecules per page'],
        [500, '500 molecules per page'],
        [1000, '1000 molecules per page']
      ],
      forceSelection: true,
      triggerAction: 'all',
      action: 'pagesizeCombo'
    }]
  }],
  initComponent: function() {
    Ext.log({}, 'Init met grid');
    var me = this;
    var molcol = Ext.create('Esc.chemdoodle.Column', {
      text: 'Molecule', dataIndex: 'mol',
      width: 162,
      initCanvas: function(id, width, height, value, record) {
        var c = new ChemDoodle.ViewerCanvas(id, width, height);
        c.loadMolecule(ChemDoodle.readMOL(value));
        var tip = Ext.create('Ext.tip.ToolTip', {
          target: id,
          html: null,
          listeners: {
            render: function(tip) {
              var c = new ChemDoodle.ViewerCanvas(id+'-'+tip.id, 300, 300);
              c.loadMolecule(ChemDoodle.readMOL(value));
            }
          }
        });
        tip.update('<canvas id="'+id+'-'+tip.id+'"></canvas>');
      }
    });

    var mfilters = Ext.create('Ext.ux.grid.FiltersFeature',{
      id: 'mfilter',
      encode: true
    });

    this.addEvents([
        /**
         * @event metabolize
         * Fired after metabolize column action is clicked
         * @param {Ext.data.Model} record The record to metabolize
         */
        'metabolize'
    ]);

    Ext.apply(this, {
      columns: [
        {text: 'ID', dataIndex: 'metid', hidden: true},
        {text: 'Scans', dataIndex: 'nhits', filter: {
            type: 'numeric', value:{gt:0}, active: true
        }},
        {text: 'Assigned', dataIndex: 'assigned', hidden: false, xtype:'booleancolumn', trueText:'Yes', falseText:'No', filter: { type: 'boolean' }},
        {text: 'Candidate score', dataIndex: 'score', hidden: true, filter: { type: 'numeric' }, xtype: 'numbercolumn', format: '0.00000'},
        molcol,
        {text: 'Inchikey', dataIndex: 'smiles', hidden:true},
        {text: 'Formula', dataIndex: 'molformula', filter: { type: 'string' }},
        {text: 'Monoisotopic mass', dataIndex: 'mim', filter: { type: 'numeric' }, hidden: false, xtype: 'numbercolumn', format: '0.00000'},
        {text: 'ΔMass (ppm)', dataIndex: 'deltappm', hidden: true, filter: { type: 'numeric' }, xtype: 'numbercolumn', format: '0.00000'},
        {text: 'Name', dataIndex: 'origin', flex:1, filter: { type: 'string' }},
        {
            text: 'Reaction sequence', dataIndex: 'reactionsequence', flex:1, filter: { type: 'string' },
            hidden: true,
            xtype: 'templatecolumn', tpl: '
<tpl for="reactionsequence">
{.}
</tpl>
'
        },
        {text: 'Refscore', dataIndex: 'probability', filter: { type: 'numeric' }, xtype: 'numbercolumn', format: '0.00000'},
        {text: 'Level', dataIndex: 'level', filter: { type: 'list',  options: ['0','1','2','3'] }, hidden:true},
        {text: 'LogP', dataIndex: 'logp', filter: { type: 'numeric' }, hidden: true, xtype: 'numbercolumn', format: '0.00000'},
        {text: 'Reference', dataIndex: 'reference', filter: { type: 'string' }, sortable: false },
        {text: 'Query', dataIndex: 'isquery', xtype:'booleancolumn', hidden: true, trueText:'Yes', falseText:'No', filter: { type: 'boolean' }},
        {xtype: 'actioncolumn', width:30, text:'Commands', hidden: true,
            items: [{
                tooltip: 'Metabolize',
                iconCls: 'metabolize-col',
                handler: function(grid, rowIndex) {
                    me.fireEvent('metabolize', me.getStore().getAt(rowIndex));
                }
            }]
        }
      ],
      plugins: [molcol],
      features: [mfilters]
    });
    this.callParent(arguments);
  },
  /**
   * @return {Ext.ux.grid.FiltersFeature}
   * @private
   */
  getFilter: function() {
	return this.getView().getFeature('mfilter');
  },
  /**
   * Clears all filters applied to metabolites
   */
  clearFilters: function() {
    this.getFilter().clearFilters();
  },
  /**
   * Get column with scores.
   *
   * Column should only be shown when a scan has been selected.
   *
   * @return {Ext.grid.column.Column}
   */
  getFragmentScoreColumn: function() {
      return this.columns.filter(function(c) { return (c.dataIndex == "score");})[0];
  },
  /**
   * Get column with deltappm.
   *
   * Column should only be shown when a scan has been selected.
   *
   * @return {Ext.grid.column.Column}
   */
  getFragmentDeltaPpmColumn: function() {
      return this.columns.filter(function(c) { return (c.dataIndex == "deltappm");})[0];
  },
  /**
   * Get column with commands.
   *
   * @return {Ext.grid.column.Action}
   */
  getCommandsColumn: function() {
      return this.columns.filter(function(c) { return (c.text == "Commands");})[0];
  },
  /**
   * Hides column with scores/deltappm and removes sort in header column.
   */
  hideFragmentScoreColumn: function() {
    var sortCls = [
        Ext.baseCSSPrefix + 'column-header-sort-ASC',
        Ext.baseCSSPrefix + 'column-header-sort-DESC'
    ];
    var score = this.getFragmentScoreColumn();
    score.hide();
    score.removeCls(sortCls);
    var deltappm = this.getFragmentDeltaPpmColumn()
    deltappm.hide();
    deltappm.removeCls(sortCls);
  },
  /**
   * Shows column with scores/deltappm.
   */
  showFragmentScoreColumn: function() {
    this.getFragmentScoreColumn().show();
    this.getFragmentDeltaPpmColumn().show();
  },
  /**
   * JSON encoded the filter data as query
   * @return {String}
   */
  getFilterQuery: function() {
	  var filter = this.getFilter();
	  return filter.buildQuery(filter.getFilterData());
  },
  /**
   * Array of dataindexes currently visible. In order they appear.
   * @return {Array}
   */
  getVisiblColumnIndices: function() {
	  return this.getView().getHeaderCt().getVisibleGridColumns().map(function(v) {return v.dataIndex}).filter(function(v) { return v});
  },
  hideCommandsColumn: function() {
	  this.getCommandsColumn().hide();
  },
  setPageSize: function(size) {
	  Ext.ComponentQuery.query('component[action=pagesizeCombo]')[0].select(size);
  }
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.json2',
  name: 'Deserializer',
  imports: [
    'classloader',
  ],
  properties: [
    {
      class: 'Boolean',
      name: 'parseFunctions',
      value: true
    }
  ],
  methods: [
    function aparseString(x, str) {
      return this.aparse(x, JSON.parse(str));
    },
    async function aparse(x, v) {
      var type = foam.typeOf(v);

      if ( type == foam.Object ) {
        if ( ! foam.Undefined.isInstance(v["$UNDEF"]) ) return undefined;
        if ( ! foam.Undefined.isInstance(v["$DATE$"]) ) {
          var d = new Date();
          d.setTime(v["$DATE"]);
          return d;
        }
        if ( ! foam.Undefined.isInstance(v["$REGEXP$"]) ) {
          return new RegExp(v["$REGEXP$"]);
        }
        if ( ! foam.Undefined.isInstance(v["$FUNC$"]) ) {
          if ( this.parseFunctions ) {
            var name = v.name;
            var args = v.args;
            var body = v.body;
            var async = v.async;
            var constructor = async ? AsyncFunction : Function;
            var f = constructor.apply(null, args.concat(body));
            if ( name ) foam.Function.setName(f, name);
            return f;
          }

          return null;
        }
        if ( ! foam.Undefined.isInstance(v["$MMETHOD$"]) ) {
          if ( this.parseFunctions ) {
            var map = v["map"];
            var defaultMethod = v["default"];

            return defaultMethod ?
              foam.mmethod(map, defaultMethod) :
              foam.mmethod(map);
          }
        }
        if ( ! foam.Undefined.isInstance(v["$CLS$"]) ) {
          // Defines a class referenced by $CLS$ key
          return await x.aref(v["$CLS$"]);
          return foam.lookup(v["$CLS$"]);
        }
        if ( ! foam.Undefined.isInstance(v["$INST$"]) ) {
          // Is an instance of the class defined by $INST$ key
          var cls = v["$INST$"];
        }

        var keys = Object.keys(v);
        var args = {}
        for ( var i = 0 ; i < keys.length ; i++ ) {
          if ( keys[i] == '$INST$' ) continue;

          args[keys[i]] = await this.aparse(x, v[keys[i]]);
        }

        return cls ?
          await x.acreate(cls, args) :
          args;

      } else if ( type == foam.Array ) {
        for ( var i = 0 ; i < v.length ; i++ ) {
          v[i] = await this.aparse(x, v[i]);
        }
        return v;
/*      } else if ( type == foam.Null ) {
      } else if ( type == foam.Number ) {
      } else if ( type == foam.String ) {
      } else if ( type == foam.Boolean ) { */
      } else {
        return v;
      }
    }
  ]
});
<commit_msg>json2.Deserializer - Use aref/acreate and make deserialization recursively asynchronous.<commit_after>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.json2',
  name: 'Deserializer',
  imports: [
    'aref',
    'acreate'
  ],
  properties: [
    {
      class: 'Boolean',
      name: 'parseFunctions',
      value: true
    },
    {
      name: 'asyncFunctionConstructor',
      factory: function() {
        return (async function(){}).constructor;
      }
    }
  ],
  methods: [
    function aparseString(x, str) {
      return this.aparse(x, JSON.parse(str));
    },
    async function aparse(x, v) {
      var type = foam.typeOf(v);

      if ( type == foam.Object ) {
        if ( ! foam.Undefined.isInstance(v["$UNDEF"]) ) return undefined;
        if ( ! foam.Undefined.isInstance(v["$DATE$"]) ) {
          var d = new Date();
          d.setTime(v["$DATE"]);
          return d;
        }
        if ( ! foam.Undefined.isInstance(v["$REGEXP$"]) ) {
          return new RegExp(v["$REGEXP$"]);
        }
        if ( ! foam.Undefined.isInstance(v["$FUNC$"]) ) {
          if ( this.parseFunctions ) {
            var name = v.name;
            var args = v.args;
            var body = v.body;
            var async = v.async;
            var constructor = async ? this.asyncFunctionConstructor : Function;
            var f = constructor.apply(null, args.concat(body));
            if ( name ) foam.Function.setName(f, name);
            return f;
          }

          return null;
        }
        if ( ! foam.Undefined.isInstance(v["$MMETHOD$"]) ) {
          if ( this.parseFunctions ) {
            var map = v["map"];
            var defaultMethod = v["default"];

            return defaultMethod ?
              foam.mmethod(map, defaultMethod) :
              foam.mmethod(map);
          }
        }
        if ( ! foam.Undefined.isInstance(v["$CLS$"]) ) {
          // Defines a class referenced by $CLS$ key
          return this.aref(v["$CLS$"]);
          return foam.lookup(v["$CLS$"]);
        }
        if ( ! foam.Undefined.isInstance(v["$INST$"]) ) {
          // Is an instance of the class defined by $INST$ key
          var cls = v["$INST$"];
        }

        var keys = Object.keys(v);
        var args = {}
        for ( var i = 0 ; i < keys.length ; i++ ) {
          if ( keys[i] == '$INST$' ) continue;

          args[keys[i]] = await this.aparse(x, v[keys[i]]);
        }

        return cls ?
          await this.acreate(cls, args) :
          args;

      } else if ( type == foam.Array ) {
        for ( var i = 0 ; i < v.length ; i++ ) {
          v[i] = await this.aparse(x, v[i]);
        }
        return v;
/*      } else if ( type == foam.Null ) {
      } else if ( type == foam.Number ) {
      } else if ( type == foam.String ) {
      } else if ( type == foam.Boolean ) { */
      } else {
        return v;
      }
    }
  ]
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2016 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.
 */

foam.CLASS({
  package: 'foam.u2.stack',
  name: 'StackView',
  extends: 'foam.u2.View',

  requires: [
    'foam.u2.stack.Stack'
  ],

  exports: [ 'data as stack' ],

  properties: [
    {
      name: 'data',
      factory: function() { return this.Stack.create(); }
    },
    {
      class: 'Boolean',
      name: 'showActions',
      value: true
    }
  ],

  css: '%CUSTOMCSS%',

  methods: [
    // TODO: Why is this init() instead of initE()? Investigate and maybe fix.
    function init() {
      this.setNodeName('div');
      this.addClass(this.myClass());

      if ( this.showActions ) {
        this.start('actions')
          .add(this.data.cls_.getAxiomsByClass(foam.core.Action))
        .end();
      }

      this.add(this.slot(function(s) {
        if ( ! s ) return this.E('span');

        var view   = s[0];
        var parent = s[1];

        var X;
        // If parent is a Context (should be a better way to test this)
        if ( parent.isContext ) {
          X = parent;
        } else if ( parent ) {
          // I'm not sure how this is a good idea, KGR
          // TODO: find all places we do this and see if we can replace
          // with case 1 above.

          // Do a bit of a dance with the context, to ensure that exports from
          // "parent" are available to "view"
          X = this.__subSubContext__.createSubContext(parent);
        } else {
          X = this.__subSubContext__;
        }

        return foam.u2.ViewSpec.createView(view, null, this, X);

      }, this.data$.dot('top')));
    }
  ]
});
<commit_msg>Fix NPE in StackView.<commit_after>/**
 * @license
 * Copyright 2016 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.
 */

foam.CLASS({
  package: 'foam.u2.stack',
  name: 'StackView',
  extends: 'foam.u2.View',

  requires: [
    'foam.u2.stack.Stack'
  ],

  exports: [ 'data as stack' ],

  properties: [
    {
      name: 'data',
      factory: function() { return this.Stack.create(); }
    },
    {
      class: 'Boolean',
      name: 'showActions',
      value: true
    }
  ],

  css: '%CUSTOMCSS%',

  methods: [
    // TODO: Why is this init() instead of initE()? Investigate and maybe fix.
    function init() {
      this.setNodeName('div');
      this.addClass(this.myClass());

      if ( this.showActions ) {
        this.start('actions')
          .add(this.data.cls_.getAxiomsByClass(foam.core.Action))
        .end();
      }

      this.add(this.slot(function(s) {
        if ( ! s ) return this.E('span');

        var view   = s[0];
        var parent = s[1];

        var X;
        // If parent is a Context (should be a better way to test this)
        if ( parent && parent.isContext ) {
          X = parent;
        } else if ( parent ) {
          // I'm not sure how this is a good idea, KGR
          // TODO: find all places we do this and see if we can replace
          // with case 1 above.

          // Do a bit of a dance with the context, to ensure that exports from
          // "parent" are available to "view"
          X = this.__subSubContext__.createSubContext(parent);
        } else {
          X = this.__subSubContext__;
        }

        return foam.u2.ViewSpec.createView(view, null, this, X);

      }, this.data$.dot('top')));
    }
  ]
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2016 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.
 */

foam.CLASS({
  package: 'foam.u2.view',
  name: 'ChoiceView',
  extends: 'foam.u2.View',

  documentation: `
    Wraps a tag that represents a singular choice. That is,
    this controller shows the user a fixed, probably small set of
    choices, and the user picks one.
    The choices are [value, label] pairs. this.choice is the current
    pair, this.data the current value. this.text is the current label,
    this.label is the label for the whole view (eg. "Medal Color", not
    "Gold").
    The choices can be provided either as an array (this.choices) or as
    a DAO plus the function this.objToChoice which turns objects from the
    DAO into [value, label] pairs.
    this.selectSpec is a ViewSpec for the inner view. It defaults to
    foam.u2.tag.Select.
  `,

  properties: [
    {
      class: 'String',
      name: 'name',
      factory: function() { return "select"; }
    },
    {
      class: 'String',
      name: 'label',
      documentation: 'User-visible label. Not to be confused with "text", ' +
          'which is the user-visible name of the currently selected choice.'
    },
    {
      name: 'choice',
      // 'choice' is the canonical source of truth. Updating 'choice' is
      // responsible for updating 'index', 'data', and 'text'. Updating any
      // of those properties calls back to updating 'choice'.
      documentation: 'The current choice. (That is, a [value, text] pair.)',
      postSet: function(o, n) {
        if ( o === n || this.feedback_ ) return;

        this.feedback_ = true;

        try {
          if ( ! n && this.placeholder ) {
            this.data  = this.defaultValue;
            this.text  = this.placeholder;
            this.index = -1;
          } else {
            this.data  = n && n[0];
            this.text  = n && n[1];
            this.index = this.findIndexOfChoice(n);
          }
        } finally {
          this.feedback_ = false;
        }
      }
    },
    {
      name: 'choices',
      documentation: 'Array of [value, text] choices. You can pass in just ' +
          'an array of strings, which are expanded to [str, str]. Can also ' +
          'be a map, which results in [key, value] pairs listed in ' +
          'enumeration order.',
      factory: function() { return []; },
      adapt: function(old, nu) {
        if ( typeof nu === 'object' && ! Array.isArray(nu) ) {
          var out = [];
          for ( var key in nu ) {
            if ( nu.hasOwnProperty(key) ) out.push([ key, nu[key] ]);
          }
          if ( this.dynamicSize ) {
            this.size = Math.min(out.length, this.maxSize);
          }
          return out;
        }

        nu = foam.Array.shallowClone(nu);

        // Upgrade single values to [value, value].
        for ( var i = 0; i < nu.length; i++ ) {
          if ( ! Array.isArray(nu[i]) ) {
            nu[i] = [ nu[i], nu[i] ];
          }
        }

        if ( this.dynamicSize ) this.size = Math.min(nu.length, this.maxSize);
        return nu;
      }
    },
    {
      class: 'Int',
      name: 'index',
      documentation: 'The index of the current choice in the choices array.',
      transient: true,
      value: -1,
      preSet: function(old, nu) {
        if ( this.choices.length === 0 && this.dao ) return nu;
        if ( nu < 0 && this.placeholder ) return nu;
        if ( nu < 0 || this.choices.length === 0 ) return 0;
        if ( nu >= this.choices.length ) return this.choices.length - 1;
        return nu;
      },
      postSet: function(o, n) {
        if ( o !== n ) this.choice = n === -1 ? null : this.choices[n];
      }
    },
    {
      class: 'String',
      name: 'placeholder',
      factory: function() { return undefined; },
      documentation: 'When provided the placeholder will be prepended to the selection list, and selected if the choices array is empty or no choice in the choices array is selected.'
    },
    {
      class: 'Function',
      name: 'objToChoice',
      documentation: 'A function which adapts an object from the DAO to a ' +
          '[key, value] choice. Required when a DAO is provided.'
    },
    {
      class: 'foam.dao.DAOProperty',
      name: 'dao'
    },
    {
      name: 'text',
      postSet: function(o, n) {
        if ( o !== n ) this.choice = this.findChoiceByText(n);
      }
    },
    {
      name: 'data',
      postSet: function(o, n) {
        if ( o !== n ) this.choice = this.findChoiceByData(n) || [n, n];
      }
    },
    {
      class: 'foam.u2.ViewSpec',
      name: 'selectSpec',
      value: { class: 'foam.u2.tag.Select' }
    },
    {
      class: 'Boolean',
      name: 'alwaysFloatLabel'
    },
    {
      name: 'view_'
    },
    'feedback_',
    'defaultValue',
    {
      class: 'Int',
      name: 'size',
      documentation: `The number of entries in the HTML 'select' element that
        should be visible.`
    },
    {
      class: 'Boolean',
      name: 'dynamicSize',
      documentation: `The size of the select element (ie: the number of entries
        shown at one time) should match the number of entries in the list. If
        set to true, the 'size' property will be ignored. However, the 'maxSize'
        property will still be respected.`
    },
    {
      class: 'Int',
      name: 'maxSize',
      documentation: `The size of the select element should never be greater
        than this number.`,
      value: Number.MAX_SAFE_INTEGER
    }
  ],

  methods: [
    function init() {
      this.onDetach(this.choices$.sub(this.onChoicesUpdate));
    },

    function initE() {
      var self = this;

      // If no item is selected, and data has not been provided, select the 0th
      // entry.
      if ( this.data == null && ! this.index ) {
        this.index = 0;
      }

      this.onDAOUpdate();

      this.add(this.slot(function(mode) {
        if ( mode !== foam.u2.DisplayMode.RO ) {
          return self.E()
            .start(self.selectSpec, {
              data$:            self.index$,
              label$:           self.label$,
              alwaysFloatLabel: self.alwaysFloatLabel,
              choices$:         self.choices$,
              placeholder$:     self.placeholder$,
              mode$:            self.mode$,
              size$:            self.size$
            })
              .attrs({ name: self.name })
              .enableClass('selection-made', self.index$.map((index) => index !== -1))
            .end();
        } else {
          return self.E().add(self.text$);
        }
      }));

      this.dao$proxy.on.sub(this.onDAOUpdate);
    },

    function findIndexOfChoice(choice) {
      if ( ! choice ) return -1;
      var choices = this.choices;
      var data    = choice[0];
      for ( var i = 0 ; i < choices.length ; i++ ) {
        if ( foam.util.equals(choices[i][0], data) ) return i;
      }
      var text = choice[1];
      for ( var i = 0 ; i < choices.length ; i++ ) {
        if ( choices[i][1] === text ) return i;
      }
      return -1;
    },

    function findChoiceByData(data) {
      var choices = this.choices;
      for ( var i = 0 ; i < choices.length ; i++ ) {
        if ( foam.util.equals(choices[i][0], data) ) return choices[i];
      }
      return null;
    },

    function findChoiceByText(text) {
      var choices = this.choices;
      for ( var i = 0 ; i < choices.length ; i++ ) {
        if ( choices[i][1] === text ) return choices[i];
      }
      return null;
    },

    function fromProperty(p) {
      this.SUPER(p);
      this.defaultValue = p.value;
    }
  ],

  listeners: [
    {
      name: 'onChoicesUpdate',
      isFramed: true,
      code: function() {
        var d = this.data;
        if ( this.choices.length ) {
          var choice = this.findChoiceByData(d);
          this.choice = choice === null ? this.findChoiceByData(this.defaultValue) : choice;
        }
      }
    },
    {
      name: 'onDAOUpdate',
      isFramed: true,
      code: function() {
        if ( ! foam.dao.DAO.isInstance(this.dao) ) return;

        var p = this.mode === foam.u2.DisplayMode.RW ?
          this.dao.select().then(s => s.array) :
          this.dao.find(this.data).then(o => o ? [o] : []);

        p.then(function(a) {
          this.choices = a.map(this.objToChoice);
          if ( this.data == null && this.index === -1 ) this.index = this.placeholder ? -1 : 0;
        }.bind(this));
      }
    }
  ],

  reactions: [
    ['', 'propertyChange.mode', 'onDAOUpdate']
  ]
});
<commit_msg>allow ChoiceView to take in async label functions in objToChoice<commit_after>/**
 * @license
 * Copyright 2016 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.
 */

foam.CLASS({
  package: 'foam.u2.view',
  name: 'ChoiceView',
  extends: 'foam.u2.View',

  documentation: `
    Wraps a tag that represents a singular choice. That is,
    this controller shows the user a fixed, probably small set of
    choices, and the user picks one.
    The choices are [value, label] pairs. this.choice is the current
    pair, this.data the current value. this.text is the current label,
    this.label is the label for the whole view (eg. "Medal Color", not
    "Gold").
    The choices can be provided either as an array (this.choices) or as
    a DAO plus the function this.objToChoice which turns objects from the
    DAO into [value, label] pairs.
    this.selectSpec is a ViewSpec for the inner view. It defaults to
    foam.u2.tag.Select.
  `,

  properties: [
    {
      class: 'String',
      name: 'name',
      factory: function() { return "select"; }
    },
    {
      class: 'String',
      name: 'label',
      documentation: 'User-visible label. Not to be confused with "text", ' +
          'which is the user-visible name of the currently selected choice.'
    },
    {
      name: 'choice',
      // 'choice' is the canonical source of truth. Updating 'choice' is
      // responsible for updating 'index', 'data', and 'text'. Updating any
      // of those properties calls back to updating 'choice'.
      documentation: 'The current choice. (That is, a [value, text] pair.)',
      postSet: function(o, n) {
        if ( o === n || this.feedback_ ) return;

        this.feedback_ = true;

        try {
          if ( ! n && this.placeholder ) {
            this.data  = this.defaultValue;
            this.text  = this.placeholder;
            this.index = -1;
          } else {
            this.data  = n && n[0];
            this.text  = n && n[1];
            this.index = this.findIndexOfChoice(n);
          }
        } finally {
          this.feedback_ = false;
        }
      }
    },
    {
      name: 'choices',
      documentation: 'Array of [value, text] choices. You can pass in just ' +
          'an array of strings, which are expanded to [str, str]. Can also ' +
          'be a map, which results in [key, value] pairs listed in ' +
          'enumeration order.',
      factory: function() { return []; },
      adapt: function(old, nu) {
        if ( typeof nu === 'object' && ! Array.isArray(nu) ) {
          var out = [];
          for ( var key in nu ) {
            if ( nu.hasOwnProperty(key) ) out.push([ key, nu[key] ]);
          }
          if ( this.dynamicSize ) {
            this.size = Math.min(out.length, this.maxSize);
          }
          return out;
        }

        nu = foam.Array.shallowClone(nu);

        // Upgrade single values to [value, value].
        for ( var i = 0; i < nu.length; i++ ) {
          if ( ! Array.isArray(nu[i]) ) {
            nu[i] = [ nu[i], nu[i] ];
          }
        }

        if ( this.dynamicSize ) this.size = Math.min(nu.length, this.maxSize);
        return nu;
      }
    },
    {
      class: 'Int',
      name: 'index',
      documentation: 'The index of the current choice in the choices array.',
      transient: true,
      value: -1,
      preSet: function(old, nu) {
        if ( this.choices.length === 0 && this.dao ) return nu;
        if ( nu < 0 && this.placeholder ) return nu;
        if ( nu < 0 || this.choices.length === 0 ) return 0;
        if ( nu >= this.choices.length ) return this.choices.length - 1;
        return nu;
      },
      postSet: function(o, n) {
        if ( o !== n ) this.choice = n === -1 ? null : this.choices[n];
      }
    },
    {
      class: 'String',
      name: 'placeholder',
      factory: function() { return undefined; },
      documentation: 'When provided the placeholder will be prepended to the selection list, and selected if the choices array is empty or no choice in the choices array is selected.'
    },
    {
      class: 'Function',
      name: 'objToChoice',
      documentation: 'A function which adapts an object from the DAO to a ' +
          '[key, value] choice. Required when a DAO is provided.'
    },
    {
      class: 'foam.dao.DAOProperty',
      name: 'dao'
    },
    {
      name: 'text',
      postSet: function(o, n) {
        if ( o !== n ) this.choice = this.findChoiceByText(n);
      }
    },
    {
      name: 'data',
      postSet: function(o, n) {
        if ( o !== n ) this.choice = this.findChoiceByData(n) || [n, n];
      }
    },
    {
      class: 'foam.u2.ViewSpec',
      name: 'selectSpec',
      value: { class: 'foam.u2.tag.Select' }
    },
    {
      class: 'Boolean',
      name: 'alwaysFloatLabel'
    },
    {
      name: 'view_'
    },
    'feedback_',
    'defaultValue',
    {
      class: 'Int',
      name: 'size',
      documentation: `The number of entries in the HTML 'select' element that
        should be visible.`
    },
    {
      class: 'Boolean',
      name: 'dynamicSize',
      documentation: `The size of the select element (ie: the number of entries
        shown at one time) should match the number of entries in the list. If
        set to true, the 'size' property will be ignored. However, the 'maxSize'
        property will still be respected.`
    },
    {
      class: 'Int',
      name: 'maxSize',
      documentation: `The size of the select element should never be greater
        than this number.`,
      value: Number.MAX_SAFE_INTEGER
    }
  ],

  methods: [
    function init() {
      this.onDetach(this.choices$.sub(this.onChoicesUpdate));
    },

    function initE() {
      var self = this;

      // If no item is selected, and data has not been provided, select the 0th
      // entry.
      if ( this.data == null && ! this.index ) {
        this.index = 0;
      }

      this.onDAOUpdate();

      this.add(this.slot(function(mode) {
        if ( mode !== foam.u2.DisplayMode.RO ) {
          return self.E()
            .start(self.selectSpec, {
              data$:            self.index$,
              label$:           self.label$,
              alwaysFloatLabel: self.alwaysFloatLabel,
              choices$:         self.choices$,
              placeholder$:     self.placeholder$,
              mode$:            self.mode$,
              size$:            self.size$
            })
              .attrs({ name: self.name })
              .enableClass('selection-made', self.index$.map((index) => index !== -1))
            .end();
        } else {
          return self.E().add(self.text$);
        }
      }));

      this.dao$proxy.on.sub(this.onDAOUpdate);
    },

    function findIndexOfChoice(choice) {
      if ( ! choice ) return -1;
      var choices = this.choices;
      var data    = choice[0];
      for ( var i = 0 ; i < choices.length ; i++ ) {
        if ( foam.util.equals(choices[i][0], data) ) return i;
      }
      var text = choice[1];
      for ( var i = 0 ; i < choices.length ; i++ ) {
        if ( choices[i][1] === text ) return i;
      }
      return -1;
    },

    function findChoiceByData(data) {
      var choices = this.choices;
      for ( var i = 0 ; i < choices.length ; i++ ) {
        if ( foam.util.equals(choices[i][0], data) ) return choices[i];
      }
      return null;
    },

    function findChoiceByText(text) {
      var choices = this.choices;
      for ( var i = 0 ; i < choices.length ; i++ ) {
        if ( choices[i][1] === text ) return choices[i];
      }
      return null;
    },

    function fromProperty(p) {
      this.SUPER(p);
      this.defaultValue = p.value;
    }
  ],

  listeners: [
    {
      name: 'onChoicesUpdate',
      isFramed: true,
      code: function() {
        var d = this.data;
        if ( this.choices.length ) {
          var choice = this.findChoiceByData(d);
          this.choice = choice === null ? this.findChoiceByData(this.defaultValue) : choice;
        }
      }
    },
    {
      name: 'onDAOUpdate',
      isFramed: true,
      code: function() {
        if ( ! foam.dao.DAO.isInstance(this.dao) ) return;

        var p = this.mode === foam.u2.DisplayMode.RW ?
          this.dao.select().then(s => s.array) :
          this.dao.find(this.data).then(o => o ? [o] : []);

        p.then(function(a) {
          var choices = a.map(this.objToChoice);
          var choiceLabels = a.map((o) => { return this.objToChoice(o)[1]});
          Promise.all(choiceLabels).then(function(resolvedChoiceLabels) {
            for ( let i = 0; i < choices.length; i++ ) {
              choices[i][1] = resolvedChoiceLabels[i];
            }
            this.choices = choices;
          }.bind(this));
          if ( this.data == null && this.index === -1 ) this.index = this.placeholder ? -1 : 0;
        }.bind(this));
      }
    }
  ],

  reactions: [
    ['', 'propertyChange.mode', 'onDAOUpdate']
  ]
});
<|endoftext|>


<commit_before>define([
	"intern!object",
	"intern/chai!assert",
	"dojo/dom-geometry",
	"dojo/dom-class",
	"delite/register",
	"deliteful/LinearLayout"
], function (registerSuite, assert, domGeom, domClass, register) {
	var container, node;
	var htmlContent =
		"<d-linear-layout id='dlayout' vertical='false' style='width:999px; height:999px'>" +
			"
A

B
" +
			"
C
</d-linear-layout>";
	registerSuite({
		name: " Direction Switch",
		setup: function () {
			container = document.createElement("div");
			document.body.appendChild(container);
			container.innerHTML = htmlContent;
			register.parse(container);
			node = document.getElementById("dlayout");
			node.validateRendering();
		},
		"Horizontal LinearLayout 3 Equal Width" : function () {
			var children = node.getChildren();
			assert.deepEqual(3, children.length);
			var box1 = domGeom.getMarginBox(children[0]);
			var box2 = domGeom.getMarginBox(children[1]);
			var box3 = domGeom.getMarginBox(children[2]);
			assert.deepEqual(box1.w, 333);
			assert.deepEqual(box2.w, 333);
			assert.deepEqual(box3.w, 333);
		},

		"Vertical LinearLayout 3 Equal Height" : function () {
			node.vertical = true;
			node.validateRendering();
			var children = node.getChildren();
			assert.deepEqual(3, children.length);
			var box1 = domGeom.getMarginBox(children[0]);
			var box2 = domGeom.getMarginBox(children[1]);
			var box3 = domGeom.getMarginBox(children[2]);
			assert.deepEqual(box1.h, 333);
			assert.deepEqual(box2.h, 333);
			assert.deepEqual(box3.h, 333);
		},
		teardown : function () {
			container.parentNode.removeChild(container);
		}

	});
});
<commit_msg>Fix #123 (2): Horizontal LinearLayout tests failing on Safari 6.0.5<commit_after>define([
	"intern!object",
	"intern/chai!assert",
	"dojo/dom-geometry",
	"dojo/dom-class",
	"delite/register",
	"deliteful/LinearLayout"
], function (registerSuite, assert, domGeom, domClass, register) {
	var container, node;
	var htmlContent =
		"<d-linear-layout id='dlayout' vertical='false' style='width:999px; height:999px'>" +
			"
A

B
" +
			"
C
</d-linear-layout>";
	registerSuite({
		name: " Direction Switch",
		setup: function () {
			container = document.createElement("div");
			document.body.appendChild(container);
			container.innerHTML = htmlContent;
			register.parse(container);
			node = document.getElementById("dlayout");
			node.validateRendering();
		},
		"Horizontal LinearLayout 3 Equal Width" : function () {
			var children = node.getChildren();
			assert.deepEqual(3, children.length);
			var box1 = domGeom.getMarginBox(children[0]);
			var box2 = domGeom.getMarginBox(children[1]);
			var box3 = domGeom.getMarginBox(children[2]);
			assert.isTrue(box1.w === 333 || box1.w === 332);
			assert.isTrue(box2.w === 333 || box2.w === 332);
			assert.isTrue(box3.w === 333 || box3.w === 332);
		},

		"Vertical LinearLayout 3 Equal Height" : function () {
			node.vertical = true;
			node.validateRendering();
			var children = node.getChildren();
			assert.deepEqual(3, children.length);
			var box1 = domGeom.getMarginBox(children[0]);
			var box2 = domGeom.getMarginBox(children[1]);
			var box3 = domGeom.getMarginBox(children[2]);
			assert.isTrue(box1.h === 333 || box1.h === 332);
			assert.isTrue(box2.h === 333 || box2.h === 332);
			assert.isTrue(box3.h === 333 || box3.h === 332);
		},
		teardown : function () {
			container.parentNode.removeChild(container);
		}

	});
});
<|endoftext|>


<commit_before>"use strict";

describe("Configuration", function() {
    var Configuration, $httpBackend;

    beforeEach(module("bibframeEditor"));
    beforeEach(inject(function($injector) {
        Configuration = $injector.get("Configuration");
        $httpBackend = $injector.get("$httpBackend");
        $httpBackend.whenGET("./config.json").respond({
            profiles: [
                "test"
            ],
            firstClass: [
                "urn:superclass"
            ],
            schemas: [
                "schema.n3"
            ],
            resourceMap: {},
            resourceDefinitions: {},
            services: {},
            dataTypes: {},
            idBase: ""
        });
        $httpBackend.whenGET("./profiles/test.json").respond({
            resourceTemplate: [
                {
                    id: "rt-test",
                    "class": {
                        id: "rt-class-test"
                    }
                }
            ]
        });
        $httpBackend.whenGET("./schema/schema.n3").respond("");
    }));
    /**
    it("should parse configuration", function() {
        // this might be basically un-testable - flush needs to be called
        // before Configuration.initialize is completed, and possibly scope
        // $digest, but there really isn't a way I know of how to get the
        // required fakery timed correctly.
        Configuration.initialize();
        $httpBackend.flush();
    });
    */
});
<commit_msg>test stub for configuration, does seem to work with flush<commit_after>"use strict";

describe("Configuration", function() {
    var Configuration, $httpBackend;

    beforeEach(module("bibframeEditor"));
    beforeEach(inject(function($injector) {
        Configuration = $injector.get("Configuration");
        $httpBackend = $injector.get("$httpBackend");
        $httpBackend.whenGET("./config.json").respond({
            profiles: [
                "test"
            ],
            firstClass: [
                "urn:superclass"
            ],
            schemas: [
                "schema.n3"
            ],
            resourceMap: {},
            resourceDefinitions: {},
            services: {
                "foo": "bar"
            },
            dataTypes: {},
            idBase: ""
        });
        $httpBackend.whenGET("./profiles/test.json").respond({
            Profile: {
                resourceTemplate: [
                    {
                        id: "rt-test",
                        "class": {
                            id: "rt-class-test"
                        }
                    }
                ]
            }
        });
        $httpBackend.whenGET("./schema/schema.n3").respond("<rt-class-test> rdfs:subClassOf <urn:superclass> .");
        $httpBackend.whenPOST("../resource/id").respond(["0","1","2","3","4"]);
    }));

    it("should parse configuration", function() {
        Configuration.initialize();
        $httpBackend.flush();
        expect(Configuration.getConfig()).not.toBeNull();
        expect(Configuration.getFirstClass()).toEqual(["urn:superclass"]);
        expect(Configuration.getSearchServices()).toEqual({foo: "bar"});
        //@@@ should be 1?
        //expect(Configuration.getResourceOptions().length).toEqual(0);
        expect(Configuration.isInitialized()).toEqual(true);
    });

});
<|endoftext|>


<commit_before>import Vue from "vue/dist/vue.esm";
import VueRouter from 'vue-router';
Vue.config.productionTip = process.env.NODE_ENV == "development";
Vue.use(VueRouter);

import store from "../store/index";
import "../config/axios";
import "../directives/selectionchange";

import contenteditableDirective from "vue-contenteditable-directive";
Vue.use(contenteditableDirective);

import TheResourceBody from "../components/TheResourceBody";

document.addEventListener("DOMContentLoaded", () => {
  const routes = [];

  const router = new VueRouter({
    routes
  });

  const app = new Vue({
    el: "#app",
    store,
    router,
    components: {
      TheResourceBody
    }
  });

  window.app = app;
});
<commit_msg>Revert "Set up VueRouter in vue_app."<commit_after>import Vue from "vue/dist/vue.esm";
Vue.config.productionTip = process.env.NODE_ENV == "development";

import store from "../store/index";
import "../config/axios";
import "../directives/selectionchange";

import contenteditableDirective from "vue-contenteditable-directive";
Vue.use(contenteditableDirective);

import TheResourceBody from "../components/TheResourceBody";

document.addEventListener("DOMContentLoaded", () => {
  const app = new Vue({
    el: "#app",
    store,
    components: {
      TheResourceBody
    }
  });

  window.app = app;
});
<|endoftext|>