<commit_before>//initialize the map
var map = L.map('map').setView([42.3600825, -71.0588801], 12);

//Create baselayer - tiles
var backgroundMap = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
	attribution: 'OpenStreetMapcontributors, CC-BY-SA',
	maxZoom: 19
});

var secondLayer = L.tileLayer(' http://tile.stamen.com/toner/{z}/{x}/{y}.png', {
	maxZoom: 19
});

var layers = {
	"basic" : backgroundMap,
	"extra" : secondLayer
}

backgroundMap.addTo(map);

// map.layers = [backgroundMap, secondLayer]

L.control.layers(layers).addTo(map);

//Add markers
var brewery = L.marker([42.346868, -71.034396]).addTo(map);
brewery.addTo(map);

var aquarium = L.marker([42.359116, -71.049592]);
aquarium.addTo(map);

var hotel = L.marker([42.351340, -71.040495]);
hotel.addTo(map);

var harvard = L.marker([42.376979, -71.116617]);
harvard.addTo(map);

//Add pop-ups
// var popup = "The Harpoon Brewery.";
// brewery.bindPopup(popup);

var popup1 = "Do you sleep in the SeaPort Hotel?";
hotel.bindPopup(popup1)

var popup2 = "The New England Aquarium.";
aquarium.bindPopup(popup2);

var popup3 = "The Harvard University.";
harvard.bindPopup(popup3);

//add a circle
var circle = L.circle([42.359116, -71.049592], 4500, {
	color: 'red',
	fillColor: '#f03',
	fillOpacity: 0.5
}).addTo(map);

//add a polygon
var polygon = L.polygon([
	[42.346868, -71.034396],
	[42.351340, -71.040495],
	[42.359116, -71.049592],
	[42.376979, -71.116617]
		]).addTo(map);

// Create a marker first
// var bigfootIcon = {
// 		radius: 8,
// 		fillColor: "#ff7800",
// 		color: "#000",
// 		weight: 1,
// 		opacity: 1,
// 		fillOpacity: 0.8
// };

var bigfootIcon = L.icon({
    iconUrl: 'workshop/big_foot_orange.png',
    iconSize:     [15, 25], // size of the icon
});

//create the geojson layer
var geojson = L.geoJson(null,{
pointToLayer: function (geoJsonPoint, latlng) {
	return L.marker(latlng, {icon: bigfootIcon});
}
}).addTo(map);

// // new Http Request
// var xhttp = new XMLHttpRequest();

// // set the request method: get the data
// xhttp.open('GET', encodeURI("All_BFRO_Reports_points.geojson" ));

// //specify what must be done with the geojson data to the layer when request is succesfull
// xhttp.onload = function() {
// 	if (xhttp.readyState === 4) {
// 			// add the json data to the geojson layer we created before!
// 			geojson.addData(JSON.parse(xhttp.responseText));
// 		} else {
// 			alert('Request failed.  Returned status of ' + xhttp.readyState );
// 		}
// };

// // send the request
// xhttp.send();

Jquery method
$.getJSON("/workshop/data/All_BFRO_Reports_points.geojson", function(data) {

});

var popup = L.popup();

function onMapClick(e) {
    popup
        .setLatLng(e.latlng)
        .setContent("You clicked the map at " + e.latlng.toString())
        .openOn(map);
}

map.on('click', onMapClick);<commit_msg>jquery test<commit_after>//initialize the map
var map = L.map('map').setView([42.3600825, -71.0588801], 12);

//Create baselayer - tiles
var backgroundMap = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
	attribution: 'OpenStreetMapcontributors, CC-BY-SA',
	maxZoom: 19
});

var secondLayer = L.tileLayer(' http://tile.stamen.com/toner/{z}/{x}/{y}.png', {
	maxZoom: 19
});

var layers = {
	"basic" : backgroundMap,
	"extra" : secondLayer
}

backgroundMap.addTo(map);

// map.layers = [backgroundMap, secondLayer]

L.control.layers(layers).addTo(map);

//Add markers
var brewery = L.marker([42.346868, -71.034396]).addTo(map);
brewery.addTo(map);

var aquarium = L.marker([42.359116, -71.049592]);
aquarium.addTo(map);

var hotel = L.marker([42.351340, -71.040495]);
hotel.addTo(map);

var harvard = L.marker([42.376979, -71.116617]);
harvard.addTo(map);

//Add pop-ups
// var popup = "The Harpoon Brewery.";
// brewery.bindPopup(popup);

var popup1 = "Do you sleep in the SeaPort Hotel?";
hotel.bindPopup(popup1)

var popup2 = "The New England Aquarium.";
aquarium.bindPopup(popup2);

var popup3 = "The Harvard University.";
harvard.bindPopup(popup3);

//add a circle
var circle = L.circle([42.359116, -71.049592], 4500, {
	color: 'red',
	fillColor: '#f03',
	fillOpacity: 0.5
}).addTo(map);

//add a polygon
var polygon = L.polygon([
	[42.346868, -71.034396],
	[42.351340, -71.040495],
	[42.359116, -71.049592],
	[42.376979, -71.116617]
		]).addTo(map);

// Create a marker first
// var bigfootIcon = {
// 		radius: 8,
// 		fillColor: "#ff7800",
// 		color: "#000",
// 		weight: 1,
// 		opacity: 1,
// 		fillOpacity: 0.8
// };

var bigfootIcon = L.icon({
    iconUrl: '../big_foot_orange.png',
    iconSize:     [15, 25], // size of the icon
});

//create the geojson layer
var geojson = L.geoJson(null,{
pointToLayer: function (geoJsonPoint, latlng) {
	return L.marker(latlng, {icon: bigfootIcon});
}
}).addTo(map);

// // new Http Request
// var xhttp = new XMLHttpRequest();

// // set the request method: get the data
// xhttp.open('GET', encodeURI("All_BFRO_Reports_points.geojson" ));

// //specify what must be done with the geojson data to the layer when request is succesfull
// xhttp.onload = function() {
// 	if (xhttp.readyState === 4) {
// 			// add the json data to the geojson layer we created before!
// 			geojson.addData(JSON.parse(xhttp.responseText));
// 		} else {
// 			alert('Request failed.  Returned status of ' + xhttp.readyState );
// 		}
// };

// // send the request
// xhttp.send();

//Jquery method
$.getJSON("../workshop/data/All_BFRO_Reports_points.geojson", function(data) {

});

var popup = L.popup();

function onMapClick(e) {
    popup
        .setLatLng(e.latlng)
        .setContent("You clicked the map at " + e.latlng.toString())
        .openOn(map);
}

map.on('click', onMapClick);<|endoftext|>


<commit_before>// =============================================
// CSS `gulp css`
// compiles scss to css, autoprefixer, combines media queries and minifies if `--production`
// =============================================

module.exports = function (gulp, nodeModule, path, option, environment) {
    return function () {
        gulp.src(path.styles.source)
        .pipe(nodeModule.clipEmptyFiles())
        .pipe(environment.dev ? nodeModule.sourcemaps.init() : nodeModule.util.noop())
        .pipe(nodeModule.sass.sync().on('error', nodeModule.sass.logError))
        .pipe(nodeModule.autoPrefixer(option.autoprefixer))
        .pipe(environment.dev ? nodeModule.sourcemaps.write() : nodeModule.util.noop())
        .pipe(environment.production ? nodeModule.combineMq() : nodeModule.util.noop())
        .pipe(environment.production ? nodeModule.cssNano() : nodeModule.util.noop())
        .pipe(gulp.dest(path.styles.build))
        .pipe(environment.dev ? nodeModule.browserSync.reload({stream: true}) : nodeModule.util.noop());
    };
};
<commit_msg>rearranged pipes in the css task to prevent errors in the future<commit_after>// =============================================
// CSS `gulp css`
// compiles scss to css, autoprefixer, combines media queries and minifies if `--production`
// =============================================

module.exports = function (gulp, nodeModule, path, option, environment) {
    return function () {
        gulp.src(path.styles.source)
        .pipe(nodeModule.clipEmptyFiles())
        .pipe(environment.dev ? nodeModule.sourcemaps.init() : nodeModule.util.noop())
        .pipe(nodeModule.sass.sync().on('error', nodeModule.sass.logError))
        .pipe(nodeModule.autoPrefixer(option.autoprefixer))
        .pipe(environment.production ? nodeModule.combineMq() : nodeModule.util.noop())
        .pipe(environment.production ? nodeModule.cssNano() : nodeModule.util.noop())
        .pipe(environment.dev ? nodeModule.sourcemaps.write() : nodeModule.util.noop())
        .pipe(gulp.dest(path.styles.build))
        .pipe(environment.dev ? nodeModule.browserSync.reload({stream: true}) : nodeModule.util.noop());
    };
};
<|endoftext|>


<commit_before>export default {
  name: 'q-icon',
  functional: true,
  props: {
    name: String,
    mat: String,
    ios: String,
    color: String
  },
  render (h, ctx) {
    let name, text
    const
      prop = ctx.props,
      data = ctx.data,
      theme = ctx.parent.$q.theme,
      cls = ctx.data.staticClass,
      icon = prop.mat && theme === 'mat'
        ? prop.mat
        : (prop.ios && theme === 'ios' ? prop.ios : ctx.props.name)

    if (!icon) {
      name = ''
    }
    else if (icon.startsWith('fa-')) {
      name = `fa ${icon}`
    }
    else if (icon.startsWith('ion-')) {
      name = `${icon}`
    }
    else {
      name = 'material-icons'
      text = icon.replace(/ /g, '_')
    }

    data.staticClass = `${cls ? cls + ' ' : ''}q-icon${name.length ? ` ${name}` : ''}${prop.color ? ` text-${prop.color}` : ''}`
    if (!data.hasOwnProperty('attrs')) {
      data.attrs = {}
    }
    data.attrs['aria-hidden'] = 'true'
    return h('i', data, text ? [text, ctx.children] : [' ', ctx.children])
  }
}
<commit_msg>feat: QIcon - add Icon Moon support + "size" prop<commit_after>export default {
  name: 'q-icon',
  functional: true,
  props: {
    name: String,
    mat: String,
    ios: String,
    color: String,
    size: String
  },
  render (h, ctx) {
    let name, text
    const
      prop = ctx.props,
      data = ctx.data,
      theme = ctx.parent.$q.theme,
      cls = ctx.data.staticClass,
      icon = prop.mat && theme === 'mat'
        ? prop.mat
        : (prop.ios && theme === 'ios' ? prop.ios : ctx.props.name)

    if (!icon) {
      name = ''
    }
    else if (icon.startsWith('fa-')) {
      name = `fa ${icon}`
    }
    else if (icon.startsWith('ion-') || icon.startsWith('icon-')) {
      name = `${icon}`
    }
    else {
      name = 'material-icons'
      text = icon.replace(/ /g, '_')
    }

    data.staticClass = `${cls ? cls + ' ' : ''}q-icon${name.length ? ` ${name}` : ''}${prop.color ? ` text-${prop.color}` : ''}`

    if (!data.hasOwnProperty('attrs')) {
      data.attrs = {}
    }
    data.attrs['aria-hidden'] = 'true'

    if (prop.size) {
      const style = `font-size: ${prop.size};`
      data.style = data.style
        ? [data.style, style]
        : style
    }

    return h('i', data, text ? [text, ctx.children] : [' ', ctx.children])
  }
}
<|endoftext|>


<commit_before>Template.home.rendered = function () {
  // hide content depends on nb of APIs.
  if(Session.get('nb_results')>0){
    $("#homePageContent").slideUp();
  }

  // bug when going from validator page
  if($(".linedwrap"))
    $(".linedwrap").remove()

  //init paging values
  Session.set('paging_skip', 0);
  Session.set('paging_limit', 5);
};

Template.home.events({
    'keyup [name="search"]':function(e,context){
      var search_val = $("#search_input").val();
      if(e.keyCode != 13){ //when start typing and not 'return' key
        Session.set("apisResult", []);
        $("#homePageContent").slideDown();
      }

      if(search_val == ""){
        $("#homePageContent").slideDown();
        Session.set("search_keywords",""); // erase previous keywords search results
        Session.set("search_tags","");
      }
    },
    'click #search_submit, form submit':function(e,context) {
      e.preventDefault();
      var search_val = $("#search_input").val();

      //add search param to browser url
      var stateObj = { search: search_val };
      history.pushState(stateObj, "", "?search="+search_val);

      var reg = new RegExp(/(tag)(:)( )*((?:[a-z][a-z0-9_]*))/i);

      // Specific Operands
      if(search_val.match(reg)) {
        var arr = search_val.split(":");
        switch(arr[0]){
          case 'tag':
            Session.set("search_tags", arr[1].trim());
            var keenEvent = {"keywords_tags": Session.get("search_tags")};
            Meteor.call('sendKeenEvent','searchCollection',keenEvent);
            break;
          default:
            FlashMessages.sendError("Search format is incorrect");
            break;
        }
      }else{ //normal search
        if(search_val=="*")
          Session.set("search_keywords"," ");
        else
          Session.set("search_keywords", search_val.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&")); //taken from atmosphere repo

        searchAPI()
        var keenEvent = {"keywords": Session.get("search_keywords")};
        Meteor.call('sendKeenEvent','searchCollection',keenEvent);
        // console.log("ChhhL",c,keenEvent);
      }
    },
    'click .api_tag':function(e,context){
      Session.set("search_keywords","");
      $("#search_input").val("tag:"+this.name);
      $("#search_submit").click();
    },
    'click .suggested':function(e,context){
      Session.set("search_keywords","");
      $("#search_input").val($(e.target).data("keyword"));
      $("#search_submit").click();
    }
});

Template.searchForm.rendered = function () {
  if(!_.isUndefined(Session.get("search_keywords"))) { //load results if search param in URL
    searchAPI()
  }
};

Template.apisList.events({
  'click a': function (e) {
    if(e.currentTarget.id != "displayMore"){ //dont track on display more
      var self = this;
      var keenEvent;
      if(Object.keys(self).length==0){
        keenEvent = {type: "tag",value: self.name};
      }else if(_.contains(Object.keys(self),'description')){ // it's an API object
        keenEvent = {type: "outbound",value: self.name, url: self.humanURL};
      }else if(_.contains(Object.keys(self),'url') && _.contains(Object.keys(self),'type')){ //extra links
        keenEvent = {type: "outbound",value: self.type, url: self.url};
      }
      Meteor.call('trackOutbound',keenEvent);
    }
  },
  'click #displayMore':function(e){
    e.preventDefault();
    //Change paging settings and reload results
    var limit = parseInt(Session.get('paging_limit'),10) || 5;
    var skip = parseInt(Session.get('paging_skip'),10) + limit

    Session.set('paging_skip',skip)
    searchAPI();
  }
});

Template.apisList.helpers({
  apis: function () {
    var result = Session.get('apisResult')
    return result
  },
});

// find regExp in Array
containsRegExp = function (collection, regex) {
    return _.filter(collection, function(obj){ return obj.match(regex);});
};

// Function called to search in API database
searchAPI = function () {
  if(Session.get("search_keywords")){
      keywords = new RegExp(Session.get("search_keywords"), "i");

      var apisResult = []
      if(!_.isEmpty(Session.get('apisResult')))
        apisResult = Session.get('apisResult')

      var result = APIs.find(
        {$or:[{name:keywords},{description:keywords},{tags:keywords}]},
        {
          sort: {updatedAt: 1},
          limit: Session.get('paging_limit') || 5,
          skip: Session.get('paging_skip') || 0
        });

      var totalResult = APIs.find({$or:[{name:keywords},{description:keywords},{tags:keywords}]}).count();

      Session.set('paging_total', totalResult);

      //Sort by number of fields matched in search
      var res = result.fetch();
      _.each(res,function (r) {
        var relevance =0;
        if(!_.isUndefined(r.name))
          r.relevance += !_.isNull(r.name.match(keywords))

        if(!_.isUndefined(r.description))
          r.relevance += !_.isNull(r.description.match(keywords))

        if(!_.isUndefined(r.tags)){
          if(_.isArray(r.tags)){ //since 0.14
            r.relevance += !_.isEmpty(containsRegExp(r.tags,keywords)); //custom fct to search regexp in Array
          }else{
            r.relevance += !_.isNull(r.tags.match(keywords))
          }
        }

        r.relevance = relevance
      });

      if(keywords!="/ /i"){ //relevance not usefull when take all
        result = _.sortBy(res,function(r){
          return [r.relevance,r.name].join('_');
        }).reverse();
      }else{
        result = res;
      }

      // @FIXME SORT BY RELEVANCE

      console.log("NB results",result.length);
      Session.set('nb_results',result.length)

      if(result.length>0){
        $("#homePageContent").slideUp();
      }

      if(result.length===0){
        $("#homePageContent").slideDown();
        FlashMessages.sendError("No API was found :(");
      }
      apisResult = apisResult.concat(result)
      console.log("APIsresult",apisResult);
      Session.set('apisResult',apisResult);
    }else if(Session.get("search_tags")){ // if search are for tags
      keywords = new RegExp(Session.get("search_tags"), "i");
      result = APIs.find({tags:keywords}, {sort: {updatedAt: 1}});
      Session.set('nb_results',result.count())

      if(result.count()>0)
        $("#homePageContent").slideUp();

      if(result.count()===0){
        $("#homePageContent").slideDown();
        FlashMessages.sendError("No API was found :(");
      }
      apisResult = apisResult.concat(result)
      console.log("APIsresult",apisResult);
      Session.set('apisResult',apisResult);
      return apisResult;
    }
    if(Session.equals("search_keywords", "") || Session.equals("search_tags", "value"))
      Session.set('apisResult',null)
}<commit_msg>make it work for tags<commit_after>Template.home.rendered = function () {
  // hide content depends on nb of APIs.
  if(Session.get('nb_results')>0){
    $("#homePageContent").slideUp();
  }

  // bug when going from validator page
  if($(".linedwrap"))
    $(".linedwrap").remove()

  //init paging values
  Session.set('paging_skip', 0);
  Session.set('paging_limit', 5);
};

Template.home.events({
    'keyup [name="search"]':function(e,context){
      var search_val = $("#search_input").val();
      if(e.keyCode != 13){ //when start typing and not 'return' key
        Session.set("apisResult", []);
        $("#homePageContent").slideDown();
      }

      if(search_val == ""){
        $("#homePageContent").slideDown();
        Session.set("search_keywords",""); // erase previous keywords search results
        Session.set("search_tags","");
      }
    },
    'click #search_submit, form submit':function(e,context) {
      e.preventDefault();
      var search_val = $("#search_input").val();

      //add search param to browser url
      var stateObj = { search: search_val };
      history.pushState(stateObj, "", "?search="+search_val);

      var reg = new RegExp(/(tag)(:)( )*((?:[a-z][a-z0-9_]*))/i);

      // Specific Operands
      if(search_val.match(reg)) {
        var arr = search_val.split(":");
        switch(arr[0]){
          case 'tag':
            Session.set("search_tags", arr[1].trim());
            var keenEvent = {"keywords_tags": Session.get("search_tags")};
            Meteor.call('sendKeenEvent','searchCollection',keenEvent);
            searchAPI()
            break;
          default:
            FlashMessages.sendError("Search format is incorrect");
            break;
        }
      }else{ //normal search
        if(search_val=="*")
          Session.set("search_keywords"," ");
        else
          Session.set("search_keywords", search_val.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&")); //taken from atmosphere repo

        searchAPI()
        var keenEvent = {"keywords": Session.get("search_keywords")};
        Meteor.call('sendKeenEvent','searchCollection',keenEvent);
        // console.log("ChhhL",c,keenEvent);
      }
    },
    'click .api_tag':function(e,context){
      Session.set("search_keywords","");
      Session.set('apisResult', []);
      $("#search_input").val("tag:"+this.name);
      $("#search_submit").click();
    },
    'click .suggested':function(e,context){
      Session.set("search_keywords","");
      Session.set('apisResult', []);
      $("#search_input").val($(e.target).data("keyword"));
      $("#search_submit").click();
    }
});

Template.searchForm.rendered = function () {
  if(!_.isUndefined(Session.get("search_keywords")) || !_.isUndefined(Session.get("search_tags"))) { //load results if search param in URL
    searchAPI()
  }
};

Template.apisList.events({
  'click a': function (e) {
    if(e.currentTarget.id != "displayMore"){ //dont track on display more
      var self = this;
      var keenEvent;
      if(Object.keys(self).length==0){
        keenEvent = {type: "tag",value: self.name};
      }else if(_.contains(Object.keys(self),'description')){ // it's an API object
        keenEvent = {type: "outbound",value: self.name, url: self.humanURL};
      }else if(_.contains(Object.keys(self),'url') && _.contains(Object.keys(self),'type')){ //extra links
        keenEvent = {type: "outbound",value: self.type, url: self.url};
      }
      Meteor.call('trackOutbound',keenEvent);
    }
  },
  'click #displayMore':function(e){
    e.preventDefault();
    //Change paging settings and reload results
    var limit = parseInt(Session.get('paging_limit'),10) || 5;
    var skip = parseInt(Session.get('paging_skip'),10) + limit

    Session.set('paging_skip',skip)
    searchAPI();
  }
});

Template.apisList.helpers({
  apis: function () {
    var result = Session.get('apisResult')
    return result
  },
});

// find regExp in Array
containsRegExp = function (collection, regex) {
    return _.filter(collection, function(obj){ return obj.match(regex);});
};

// Function called to search in API database
searchAPI = function () {
  if(Session.get("search_keywords")){
      keywords = new RegExp(Session.get("search_keywords"), "i");

      var apisResult = []
      if(!_.isEmpty(Session.get('apisResult')))
        apisResult = Session.get('apisResult')

      var result = APIs.find(
        {$or:[{name:keywords},{description:keywords},{tags:keywords}]},
        {
          sort: {updatedAt: 1},
          limit: Session.get('paging_limit') || 5,
          skip: Session.get('paging_skip') || 0
        });

      var totalResult = APIs.find({$or:[{name:keywords},{description:keywords},{tags:keywords}]}).count();

      Session.set('paging_total', totalResult);

      //Sort by number of fields matched in search
      var res = result.fetch();
      _.each(res,function (r) {
        var relevance =0;
        if(!_.isUndefined(r.name))
          r.relevance += !_.isNull(r.name.match(keywords))

        if(!_.isUndefined(r.description))
          r.relevance += !_.isNull(r.description.match(keywords))

        if(!_.isUndefined(r.tags)){
          if(_.isArray(r.tags)){ //since 0.14
            r.relevance += !_.isEmpty(containsRegExp(r.tags,keywords)); //custom fct to search regexp in Array
          }else{
            r.relevance += !_.isNull(r.tags.match(keywords))
          }
        }

        r.relevance = relevance
      });

      if(keywords!="/ /i"){ //relevance not usefull when take all
        result = _.sortBy(res,function(r){
          return [r.relevance,r.name].join('_');
        }).reverse();
      }else{
        result = res;
      }

      // @FIXME SORT BY RELEVANCE

      console.log("NB results",result.length);
      Session.set('nb_results',result.length)

      if(result.length>0){
        $("#homePageContent").slideUp();
      }

      if(result.length===0){
        $("#homePageContent").slideDown();
        FlashMessages.sendError("No API was found :(");
      }
      apisResult = apisResult.concat(result)
      console.log("APIsresult",apisResult);
      Session.set('apisResult',apisResult);
    }else if(Session.get("search_tags")){ // if search are for tags
      console.log("TAG SEARCH", Session.get('search_tags'))
      var apisResult = []
      if(!_.isEmpty(Session.get('apisResult')))
        apisResult = Session.get('apisResult')

      keywords = new RegExp(Session.get("search_tags"), "i");
      result = APIs.find({tags:keywords}, {
          sort: {updatedAt: 1},
          limit: Session.get('paging_limit') || 5,
          skip: Session.get('paging_skip') || 0
        }).fetch();
      Session.set('nb_results',result.length)

      if(result.length>0)
        $("#homePageContent").slideUp();

      if(result.length===0){
        $("#homePageContent").slideDown();
        FlashMessages.sendError("No API was found :(");
      }
      apisResult = apisResult.concat(result)
      console.log("APIsresult",apisResult);
      Session.set('apisResult',apisResult);
      return apisResult;
    }
    if(Session.equals("search_keywords", "") || Session.equals("search_tags", "value"))
      Session.set('apisResult',null)
}<|endoftext|>


<commit_before>$( window ).load(function() {
  var togglePanel = function(panelId, link){
    var panel = $(panelId);
    // Commment toggling as the toggle function is being handled by shinyjs
    //panel.toggle();
    if(panel.is(":visible")){
      $(link).html('Show');
    }else{
      $(link).html('Hide');
    }
  };

  $('#togglePanel').click(function(){ togglePanel('#input_panel', this); });
  $('#toggleLegend').click(function(){ togglePanel('#zone_legend', this); });
  $('#toggleMapLegend').click(function(){ togglePanel('#map_legend', this); });

  $('select').addClass("form-control");
  var urlUpdater = function(lMap, oldRegion){
    var grp = lMap.layerManager.getLayerGroup("regionName");
    var currentRegion;
    if(grp && grp.getLayers()[0]) {
      currentRegion = grp.getLayers()[0].options.layerId;
    }
    if(!!oldRegion && !!currentRegion && oldRegion != currentRegion){
      var newUrl = (window.history.state == "changed") ? currentRegion : "../" + currentRegion
      window.history.pushState("changed", currentRegion, newUrl);
      setTimeout(urlUpdater, 500, lMap, currentRegion);
    } else {
      setTimeout(urlUpdater, 500, lMap, currentRegion || oldRegion);
    }
  };

  var initMap = function(){
    if($(map).data('leaflet-map')){
      // lMap is the leaflet map object see http://leafletjs.com/reference.html
      var lMap = $(map).data('leaflet-map');
      L.control.scale().addTo(lMap);
      urlUpdater(lMap, undefined);
    }
    else {
      setTimeout(initMap, 100);
    }
  };
  initMap();

  $("#printBtn").click(function(){
    $('#map').print();
  });
});
<commit_msg>Insert missing semi-colon<commit_after>$( window ).load(function() {
  var togglePanel = function(panelId, link){
    var panel = $(panelId);
    // Commment toggling as the toggle function is being handled by shinyjs
    //panel.toggle();
    if(panel.is(":visible")){
      $(link).html('Show');
    }else{
      $(link).html('Hide');
    }
  };

  $('#togglePanel').click(function(){ togglePanel('#input_panel', this); });
  $('#toggleLegend').click(function(){ togglePanel('#zone_legend', this); });
  $('#toggleMapLegend').click(function(){ togglePanel('#map_legend', this); });

  $('select').addClass("form-control");
  var urlUpdater = function(lMap, oldRegion){
    var grp = lMap.layerManager.getLayerGroup("regionName");
    var currentRegion;
    if(grp && grp.getLayers()[0]) {
      currentRegion = grp.getLayers()[0].options.layerId;
    }
    if(!!oldRegion && !!currentRegion && oldRegion != currentRegion){
      var newUrl = (window.history.state == "changed") ? currentRegion : "../" + currentRegion;
      window.history.pushState("changed", currentRegion, newUrl);
      setTimeout(urlUpdater, 500, lMap, currentRegion);
    } else {
      setTimeout(urlUpdater, 500, lMap, currentRegion || oldRegion);
    }
  };

  var initMap = function(){
    if($(map).data('leaflet-map')){
      // lMap is the leaflet map object see http://leafletjs.com/reference.html
      var lMap = $(map).data('leaflet-map');
      L.control.scale().addTo(lMap);
      urlUpdater(lMap, undefined);
    }
    else {
      setTimeout(initMap, 100);
    }
  };
  initMap();

  $("#printBtn").click(function(){
    $('#map').print();
  });
});
<|endoftext|>


<commit_before>/**
 * @file 下浮层基类
 * @author fe.xiaowu
 */

define(function (require) {
    'use strict';

    var $ = require('zepto');

    // 加载样式
    require('css!./base.css');

    /**
     * 构造函数
     *
     * @param {Object} options 配置对象
     * @param {string} options.content 内容
     * @param {string} options.className 窗口的类
     */
    function Base(options) {
        this.options = $.extend({}, Base.defaults, options);
        this.__init();
    }

    $.extend(Base.prototype, {
        __init: function () {
            var self = this;
            var $wrap = this.$wrap = $('
').addClass('zui-popup-wrap');
            var $inner = $('
').addClass('zui-popup-inner ' + this.options.className).html(this.options.content);

            // 添加遮罩层
            $wrap.append('

');

            $wrap.append($inner);

            $wrap.appendTo('body');

            $wrap.addClass('zui-popup-show');

            $inner.animate({
                transform: 'translateY(0)'
            }, 200);

            $wrap.find('.zui-popup-mask').on('click', self.close.bind(self)).on('touchmove', false);

            $inner = null;
        },

        /**
         * 关闭
         *
         * @return {Object} this
         */
        close: function () {
            var self = this;

            if (self._closed) {
                return self;
            }

            self._closed = true;

            self.$wrap.removeClass('zui-popup-show');

            self.$wrap.find('.zui-popup-inner').animate({
                transform: 'translateY(100%)'
            }, 200, 'ease', function () {
                self.$wrap.remove();
                delete self.$wrap;
            });

            return self;
        }
    });

    /**
     * 默认参数
     *
     * @type {Object}
     */
    Base.defaults = {
        className: '',
        content: ''
    };

    return Base;
});
<commit_msg>update: 抽离出动画运行的时间<commit_after>/**
 * @file 下浮层基类
 * @author fe.xiaowu
 */

define(function (require) {
    'use strict';

    var $ = require('zepto');

    // 加载样式
    require('css!./base.css');

    /**
     * 构造函数
     *
     * @param {Object} options 配置对象
     * @param {string} options.content 内容
     * @param {string} options.className 窗口的类
     */
    function Base(options) {
        this.options = $.extend({}, Base.defaults, options);
        this.__init();
    }

    $.extend(Base.prototype, {
        __init: function () {
            var self = this;
            var $wrap = this.$wrap = $('
').addClass('zui-popup-wrap');
            var $inner = $('
').addClass('zui-popup-inner ' + this.options.className).html(this.options.content);

            // 添加遮罩层
            $wrap.append('

');

            $wrap.append($inner);

            $wrap.appendTo('body');

            $wrap.addClass('zui-popup-show');

            $inner.animate({
                transform: 'translateY(0)'
            }, Base.animationTimeout);

            $wrap.find('.zui-popup-mask').on('click', self.close.bind(self)).on('touchmove', false);

            $inner = null;
        },

        /**
         * 关闭
         *
         * @return {Object} this
         */
        close: function () {
            var self = this;

            if (self._closed) {
                return self;
            }

            self._closed = true;

            self.$wrap.removeClass('zui-popup-show');

            self.$wrap.find('.zui-popup-inner').animate({
                transform: 'translateY(100%)'
            }, Base.animationTimeout, 'ease', function () {
                self.$wrap.remove();
                delete self.$wrap;
            });

            return self;
        }
    });

    /**
     * 默认参数
     *
     * @type {Object}
     */
    Base.defaults = {
        className: '',
        content: ''
    };

    /**
     * 动画显示时长
     *
     * @type {Number}
     */
    Base.animationTimeout = 200;

    return Base;
});
<|endoftext|>


<commit_before>'use strict'

/**
 * MenuItems components
 * @module
 * @name menuItems
 * @description A module to provide a function to create all of the menu items for the plugin
 */

/**
 * Class MenuItem
 * @var
 * @name MenuItem
 * @type class
 */
var MenuItem = require('../classes/MenuItem')

/**
 * UI module
 * @var
 * @name ui
 * @type {Module}
 */
var ui = require('../utils/ui')

/**
 * A selector to select the header and the footer but not the body
 * @const
 * @inner
 */
var HEADER_FOOTER_ONLY_SELECTOR = '.header-panel, .footer-panel'

// Static API
module.exports = {
  create: create,
  init: init
}

// Inner API
// _createInsertHeaderMenuItem()
// _createInsertFooterMenuItem()
// _createRemoveHeaderMenuItem()
// _createRemoveFooterMenuItem()
// _createInsertPageNumber(editor)
// _createinsertNumberOfPages(editor)

/**
 * Create a hash of all the menu items for the plugin
 * @function
 * @param {Editor} editor The tinymce active editor
 * @returns {object} the created hash of menu items
 */
function create (editor) {
  return {
    insertHeader: _createInsertHeaderMenuItem(),
    insertFooter: _createInsertFooterMenuItem(),
    removeHeader: _createRemoveHeaderMenuItem(),
    removeFooter: _createRemoveFooterMenuItem(),
    insertPageNumber: _createInsertPageNumber(editor),
    insertNumberOfPages: _createinsertNumberOfPages(editor)
  }
}

/**
 * Initialize menu items states (show, hide, ...) and implements onclick handlers
 * @method
 * @static
 * @param {HeaderFooterFactory} factory The header and footer factory
 * @param {object} menuItems The set of plugin's menu items
 * @returns undefined
 */
function init (factory, menuItems) {
  // on startup, hide remove buttons
  menuItems.removeHeader.hide()
  menuItems.removeFooter.hide()

  // override insertHeader, insertFooter, removeHeader and removeFooter onclick handlers
  menuItems.insertHeader.onclick = function () {
    factory.insertHeader()
    menuItems.insertHeader.hide()
    menuItems.removeHeader.show()
  }
  menuItems.insertFooter.onclick = function () {
    factory.insertFooter()
    menuItems.insertFooter.hide()
    menuItems.removeFooter.show()
  }
  menuItems.removeHeader.onclick = function () {
    factory.removeHeader()
    menuItems.insertHeader.show()
    menuItems.removeHeader.hide()
  }
  menuItems.removeFooter.onclick = function () {
    factory.removeFooter()
    menuItems.insertFooter.show()
    menuItems.removeFooter.hide()
  }
}

/**
 * Create a menu item to insert a header
 * @function
 * @inner
 * @returns {MenuItem}
 */
function _createInsertHeaderMenuItem () {
  return new MenuItem('insertHeader', {
    text: 'Insérer une entête',
    icon: 'abc',
    id: 'plugin-headersfooters-menuitem-insert-header',
    context: 'insert',
    onclick: function () {
      window.alert('insert header')
    }
  })
}

/**
 * Create a menu item to remove a header
 * @function
 * @inner
 * @returns {MenuItem}
 */
function _createRemoveHeaderMenuItem () {
  return new MenuItem('removeHeader', {
    text: "Supprimer l'entête",
    icon: 'text',
    context: 'insert',
    onclick: function () {
      window.alert('remove header')
    }
  })
}

/**
 * Create a menu item to insert a footer
 * @function
 * @inner
 * @returns {MenuItem}
 */
function _createInsertFooterMenuItem () {
  return new MenuItem('insertFooter', {
    text: 'Insérer un pied de page',
    icon: 'abc',
    context: 'insert',
    onclick: function () {
      window.alert('insert footer')
    }
  })
}

/**
 * Create a menu item to remove a footer
 * @function
 * @inner
 * @returns {MenuItem}
 */
function _createRemoveFooterMenuItem () {
  return new MenuItem('removeFooter', {
    text: 'Supprimer le pied de page',
    icon: 'text',
    context: 'insert',
    onclick: function () {
      window.alert('remove footer')
    }
  })
}

/**
 * Create a menu item to insert page number
 * @function
 * @inner
 * @returns {MenuItem}
 */
function _createInsertPageNumber (editor) {
  return new MenuItem('insertPageNumber', {
    text: 'Insérer le numéro de page',
    context: 'document',
    onPostRender: function () {
      ui.resetMenuItemState.call(this, editor, HEADER_FOOTER_ONLY_SELECTOR)
      editor.on('NodeChange', ui.resetMenuItemState.bind(this, editor, HEADER_FOOTER_ONLY_SELECTOR))
    },
    cmd: 'insertPageNumberCmd'
  })
}

/**
 * Create a menu item to insert the number of pages
 * @function
 * @inner
 * @returns {MenuItem}
 */
function _createinsertNumberOfPages (editor) {
  return new MenuItem('insertNumberOfPages', {
    text: 'Insérer le nombre de page',
    // icon: 'text',
    context: 'document',
    onPostRender: function () {
      ui.resetMenuItemState.call(this, editor, HEADER_FOOTER_ONLY_SELECTOR)
      editor.on('NodeChange', ui.resetMenuItemState.bind(this, editor, HEADER_FOOTER_ONLY_SELECTOR))
    },
    cmd: 'insertNumberOfPagesCmd'
  })
}
<commit_msg>implement and export _createEditFormatMenuItem()<commit_after>'use strict'

/**
 * MenuItems components
 * @module
 * @name menuItems
 * @description A module to provide a function to create all of the menu items for the plugin
 */

/**
 * Class MenuItem
 * @var
 * @name MenuItem
 * @type class
 */
var MenuItem = require('../classes/MenuItem')

/**
 * UI module
 * @var
 * @name ui
 * @type {Module}
 */
var ui = require('../utils/ui')

/**
 * A selector to select the header and the footer but not the body
 * @const
 * @inner
 */
var HEADER_FOOTER_ONLY_SELECTOR = '.header-panel, .footer-panel'

// Static API
module.exports = {
  create: create,
  init: init
}

// Inner API
// _createInsertHeaderMenuItem()
// _createInsertFooterMenuItem()
// _createRemoveHeaderMenuItem()
// _createRemoveFooterMenuItem()
// _createInsertPageNumberMenuItem(editor)
// _createinsertNumberOfPagesMenuItem(editor)
// _createEditFormatMenuItem(editor)

/**
 * Create a hash of all the menu items for the plugin
 * @function
 * @param {Editor} editor The tinymce active editor
 * @returns {object} the created hash of menu items
 */
function create (editor) {
  return {
    insertHeader: _createInsertHeaderMenuItem(),
    insertFooter: _createInsertFooterMenuItem(),
    removeHeader: _createRemoveHeaderMenuItem(),
    removeFooter: _createRemoveFooterMenuItem(),
    insertPageNumber: _createInsertPageNumberMenuItem(editor),
    insertNumberOfPages: _createinsertNumberOfPagesMenuItem(editor),
    editFormat: _createEditFormatMenuItem(editor)
  }
}

/**
 * Initialize menu items states (show, hide, ...) and implements onclick handlers
 * @method
 * @static
 * @param {HeaderFooterFactory} factory The header and footer factory
 * @param {object} menuItems The set of plugin's menu items
 * @returns undefined
 */
function init (factory, menuItems) {
  // on startup, hide remove buttons
  menuItems.removeHeader.hide()
  menuItems.removeFooter.hide()

  // override insertHeader, insertFooter, removeHeader and removeFooter onclick handlers
  menuItems.insertHeader.onclick = function () {
    factory.insertHeader()
    menuItems.insertHeader.hide()
    menuItems.removeHeader.show()
  }
  menuItems.insertFooter.onclick = function () {
    factory.insertFooter()
    menuItems.insertFooter.hide()
    menuItems.removeFooter.show()
  }
  menuItems.removeHeader.onclick = function () {
    factory.removeHeader()
    menuItems.insertHeader.show()
    menuItems.removeHeader.hide()
  }
  menuItems.removeFooter.onclick = function () {
    factory.removeFooter()
    menuItems.insertFooter.show()
    menuItems.removeFooter.hide()
  }
}

/**
 * Create a menu item to insert a header
 * @function
 * @inner
 * @returns {MenuItem}
 */
function _createInsertHeaderMenuItem () {
  return new MenuItem('insertHeader', {
    text: 'Insérer une entête',
    icon: 'abc',
    id: 'plugin-headersfooters-menuitem-insert-header',
    context: 'insert',
    onclick: function () {
      window.alert('insert header')
    }
  })
}

/**
 * Create a menu item to remove a header
 * @function
 * @inner
 * @returns {MenuItem}
 */
function _createRemoveHeaderMenuItem () {
  return new MenuItem('removeHeader', {
    text: "Supprimer l'entête",
    icon: 'text',
    context: 'insert',
    onclick: function () {
      window.alert('remove header')
    }
  })
}

/**
 * Create a menu item to insert a footer
 * @function
 * @inner
 * @returns {MenuItem}
 */
function _createInsertFooterMenuItem () {
  return new MenuItem('insertFooter', {
    text: 'Insérer un pied de page',
    icon: 'abc',
    context: 'insert',
    onclick: function () {
      window.alert('insert footer')
    }
  })
}

/**
 * Create a menu item to remove a footer
 * @function
 * @inner
 * @returns {MenuItem}
 */
function _createRemoveFooterMenuItem () {
  return new MenuItem('removeFooter', {
    text: 'Supprimer le pied de page',
    icon: 'text',
    context: 'insert',
    onclick: function () {
      window.alert('remove footer')
    }
  })
}

/**
 * Create a menu item to insert page number
 * @function
 * @inner
 * @returns {MenuItem}
 */
function _createInsertPageNumberMenuItem (editor) {
  return new MenuItem('insertPageNumber', {
    text: 'Insérer le numéro de page',
    context: 'document',
    onPostRender: function () {
      ui.resetMenuItemState.call(this, editor, HEADER_FOOTER_ONLY_SELECTOR)
      editor.on('NodeChange', ui.resetMenuItemState.bind(this, editor, HEADER_FOOTER_ONLY_SELECTOR))
    },
    cmd: 'insertPageNumberCmd'
  })
}

/**
 * Create a menu item to insert the number of pages
 * @function
 * @inner
 * @returns {MenuItem}
 */
function _createinsertNumberOfPagesMenuItem (editor) {
  return new MenuItem('insertNumberOfPages', {
    text: 'Insérer le nombre de page',
    // icon: 'text',
    context: 'document',
    onPostRender: function () {
      ui.resetMenuItemState.call(this, editor, HEADER_FOOTER_ONLY_SELECTOR)
      editor.on('NodeChange', ui.resetMenuItemState.bind(this, editor, HEADER_FOOTER_ONLY_SELECTOR))
    },
    cmd: 'insertNumberOfPagesCmd'
  })
}

/**
 * Create a menu item to edit the current format
 * @function
 * @inner
 * @returns {MenuItem}
 */
function _createEditFormatMenuItem (editor) {
  return new MenuItem('editFormat', {
    text: 'Format',
    // icon: 'text',
    context: 'document',
    cmd: 'editFormatCmd'
  })
}
<|endoftext|>


<commit_before>/*!
    FileReader.js - v0.9
    A lightweight wrapper for common FileReader usage.
    Copyright 2012 Brian Grinstead - MIT License.
    See http://github.com/bgrins/filereader.js for documentation.
*/

(function(window, document) {

    var FileReader = window.FileReader;
    var FileReaderSyncSupport = false;
    var workerScript = "self.addEventListener('message', function(e) { var data=e.data; try { var reader = new FileReaderSync; postMessage({ result: reader[data.readAs](data.file), extra: data.extra, file: data.file})} catch(e){ postMessage({ result:'error', extra:data.extra, file:data.file}); } }, false);";
    var syncDetectionScript = "self.addEventListener('message', function(e) { postMessage(!!FileReaderSync); }, false);";
    var fileReaderEvents = ['loadstart', 'progress', 'load', 'abort', 'error', 'loadend'];

    var FileReaderJS = window.FileReaderJS = {
        enabled: false,
        setupInput: setupInput,
        setupDrop: setupDrop,
        setupClipboard: setupClipboard,
        sync: false,
        output: [],
        opts: {
            dragClass: "drag",
            accept: false,
            readAsDefault: 'BinaryString',
            readAsMap: {
                'image/*': 'DataURL',
                'text/*' : 'Text'
            },
            on: {
                loadstart: noop,
                progress: noop,
                load: noop,
                abort: noop,
                error: noop,
                loadend: noop,
                skip: noop,
                groupstart: noop,
                groupend: noop,
                beforestart: noop
            }
        }
    };

    // Setup jQuery plugin (if available)
    if (typeof(jQuery) !== "undefined") {
        jQuery.fn.fileReaderJS = function(opts) {
            return this.each(function() {
                if ($(this).is("input")) {
                    setupInput(this, opts);
                }
                else {
                    setupDrop(this, opts);
                }
            });
        };

        jQuery.fn.fileClipboard = function(opts) {
            return this.each(function() {
                setupClipboard(this, opts);
            });
        };
    }

    // Not all browsers support the FileReader interface.  Return with the enabled bit = false.
    if (!FileReader) {
        return;
    }

    // WorkerHelper is a little wrapper for generating web workers from strings
    var WorkerHelper = (function() {

        var URL = window.URL || window.webkitURL;
        var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;

        // May need to get just the URL in case it is needed for things beyond just creating a worker.
        function getURL (script) {
            if (window.Worker && BlobBuilder && URL) {
                var bb = new BlobBuilder();
                bb.append(script);
                return URL.createObjectURL(bb.getBlob());
            }

            return null;
        }

        // If there is no need to revoke a URL later, or do anything fancy then just return the worker.
        function getWorker (script, onmessage) {
            var url = getURL(script);
            if (url) {
                var worker = new Worker(url);
                worker.onmessage = onmessage;
                return worker;
            }

            return null;
        }

        return {
            getURL: getURL,
            getWorker: getWorker
        };

    })();

    // setupClipboard: bind to clipboard events (intended for document.body)
    function setupClipboard(element, opts) {

        if (!FileReaderJS.enabled) {
            return;
        }
        var instanceOptions = extend(extend({}, FileReaderJS.opts), opts);

        element.addEventListener("paste", onpaste, false);

        function onpaste(e) {
            var files = [];
            var clipboardData = e.clipboardData || {};
            var items = clipboardData.items || [];

            for (var i = 0; i < items.length; i++) {
                var file = items[i].getAsFile();

                if (file) {

                    // Create a fake file name for images from clipboard, since this data doesn't get sent
                    var matches = new RegExp("/\(.*\)").exec(file.type);
                    if (!file.name && matches) {
                        var extension = matches[1];
                        file.name = "clipboard" + i + "." + extension;
                    }

                    files.push(file);
                }
            }

            if (files.length) {
                processFileList(e, files, instanceOptions);
                e.preventDefault();
                e.stopPropagation();
            }
        }
    }

    // setupInput: bind the 'change' event to an input[type=file]
    function setupInput(input, opts) {

        if (!FileReaderJS.enabled) {
            return;
        }
        var instanceOptions = extend(extend({}, FileReaderJS.opts), opts);

        input.addEventListener("change", inputChange, false);
        input.addEventListener("drop", inputDrop, false);

        function inputChange(e) {
            processFileList(e, input.files, instanceOptions);
        }

        function inputDrop(e) {
            e.stopPropagation();
            e.preventDefault();
            processFileList(e, e.dataTransfer.files, instanceOptions);
        }
    }

    // setupDrop: bind the 'drop' event for a DOM element
    function setupDrop(dropbox, opts) {

        if (!FileReaderJS.enabled) {
            return;
        }
        var instanceOptions = extend(extend({}, FileReaderJS.opts), opts);
        var dragClass = instanceOptions.dragClass;
        var initializedOnBody = false;

        // Bind drag events to the dropbox to add the class while dragging, and accept the drop data transfer.
        dropbox.addEventListener("dragenter", onlyWithFiles(dragenter), false);
        dropbox.addEventListener("dragleave", onlyWithFiles(dragleave), false);
        dropbox.addEventListener("dragover", onlyWithFiles(dragover), false);
        dropbox.addEventListener("drop", onlyWithFiles(drop), false);

        // Bind to body to prevent the dropbox events from firing when it was initialized on the page.
        document.body.addEventListener("dragstart", bodydragstart, true);
        document.body.addEventListener("dragend", bodydragend, true);
        document.body.addEventListener("drop", bodydrop, false);

        function bodydragend(e) {
            initializedOnBody = false;
        }

        function bodydragstart(e) {
            initializedOnBody = true;
        }

        function bodydrop(e) {
            if (e.dataTransfer.files && e.dataTransfer.files.length ){
                e.stopPropagation();
                e.preventDefault();
            }
        }

        function onlyWithFiles(fn) {
            return function() {
                if (!initializedOnBody) {
                    fn.apply(this, arguments);
                }
            };
        }

        function drop(e) {
            e.stopPropagation();
            e.preventDefault();
            if (dragClass) {
                removeClass(dropbox, dragClass);
            }
            processFileList(e, e.dataTransfer.files, instanceOptions);
        }

        function dragenter(e) {
            e.stopPropagation();
            e.preventDefault();
            if (dragClass) {
                addClass(dropbox, dragClass);
            }
        }

        function dragleave(e) {
            if (dragClass) {
                removeClass(dropbox, dragClass);
            }
        }

        function dragover(e) {
            e.stopPropagation();
            e.preventDefault();
            if (dragClass) {
                addClass(dropbox, dragClass);
            }
        }
    }

    // setupCustomFileProperties: modify the file object with extra properties
    function setupCustomFileProperties(files, groupID) {
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
            file.extra = {
                nameNoExtension: file.name.substring(0, file.name.lastIndexOf('.')),
                extension: file.name.substring(file.name.lastIndexOf('.') + 1),
                fileID: i,
                uniqueID: getUniqueID(),
                groupID: groupID,
                prettySize: prettySize(file.size)
            };
        }
    }

    // getReadAsMethod: return method name for 'readAs*' - http://www.w3.org/TR/FileAPI/#reading-a-file
    function getReadAsMethod(type, readAsMap, readAsDefault) {
        for (var r in readAsMap) {
            if (type.match(new RegExp(r))) {
                return 'readAs' + readAsMap[r];
            }
        }
        return 'readAs' + readAsDefault;
    }

    // processFileList: read the files with FileReader, send off custom events.
    function processFileList(e, files, opts) {

        var filesLeft = files.length;
        var group = {
            groupID: getGroupID(),
            files: files,
            started: new Date()
        };

        function groupEnd() {
            group.ended = new Date();
            opts.on.groupend(group);
        }

        function groupFileDone() {
            if (--filesLeft === 0) {
                groupEnd();
            }
        }

        FileReaderJS.output.push(group);
        setupCustomFileProperties(files, group.groupID);

        opts.on.groupstart(group);

        // No files in group - end immediately
        if (!files.length) {
            groupEnd();
            return;
        }

        var sync = FileReaderJS.sync && FileReaderSyncSupport;
        var syncWorker;

        // Only initialize the synchronous worker if the option is enabled - to prevent the overhead
        if (sync) {
            syncWorker = WorkerHelper.getWorker(workerScript, function(e) {
                var file = e.data.file;
                var result = e.data.result;

                // Workers seem to lose the custom property on the file object.
                if (!file.extra) {
                    file.extra = e.data.extra;
                }

                file.extra.ended = new Date();

                // Call error or load event depending on success of the read from the worker.
                opts.on[result === "error" ? "error" : "load"]({ target: { result: result } }, file);
                groupFileDone();

            });
        }

        Array.prototype.forEach.call(files, function(file) {

            file.extra.started = new Date();

            if (opts.accept && !file.type.match(new RegExp(opts.accept))) {
                opts.on.skip(file);
                groupFileDone();
                return;
            }

            if (opts.on.beforestart(file) === false) {
                opts.on.skip(file);
                groupFileDone();
                return;
            }

            var readAs = getReadAsMethod(file.type, opts.readAsMap, opts.readAsDefault);

            if (sync && syncWorker) {
                syncWorker.postMessage({
                    file: file,
                    extra: file.extra,
                    readAs: readAs
                });
            }
            else {

                var reader = new FileReader();
                reader.originalEvent = e;

                fileReaderEvents.forEach(function(eventName) {
                    reader['on' + eventName] = function(e) {
                        if (eventName == 'load' || eventName == 'error') {
                            file.extra.ended = new Date();
                        }
                        opts.on[eventName](e, file);
                        if (eventName == 'loadend') {
                            groupFileDone();
                        }
                    };
                });

                reader[readAs](file);
            }
        });
    }

    // checkFileReaderSyncSupport: Create a temporary worker and see if FileReaderSync exists
    function checkFileReaderSyncSupport() {
        var worker = WorkerHelper.getWorker(syncDetectionScript, function(e) {
            FileReaderSyncSupport = e.data;
        });

        if (worker) {
            worker.postMessage({});
        }
    }

    // noop: do nothing
    function noop() {

    }

    // extend: used to make deep copies of options object
    function extend(destination, source) {
        for (var property in source) {
            if (source[property] && source[property].constructor &&
                source[property].constructor === Object) {
                destination[property] = destination[property] || {};
                arguments.callee(destination[property], source[property]);
            }
            else {
                destination[property] = source[property];
            }
        }
        return destination;
    }

    // hasClass: does an element have the css class?
    function hasClass(el, name) {
        return new RegExp("(?:^|\\s+)" + name + "(?:\\s+|$)").test(el.className);
    }

    // addClass: add the css class for the element.
    function addClass(el, name) {
        if (!hasClass(el, name)) {
          el.className = el.className ? [el.className, name].join(' ') : name;
        }
    }

    // removeClass: remove the css class from the element.
    function removeClass(el, name) {
        if (hasClass(el, name)) {
          var c = el.className;
          el.className = c.replace(new RegExp("(?:^|\\s+)" + name + "(?:\\s+|$)", "g"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, '');
        }
    }

    // prettySize: convert bytes to a more readable string.
    function prettySize(bytes) {
        var s = ['bytes', 'kb', 'MB', 'GB', 'TB', 'PB'];
        var e = Math.floor(Math.log(bytes)/Math.log(1024));
        return (bytes/Math.pow(1024, Math.floor(e))).toFixed(2)+" "+s[e];
    }

    // getGroupID: generate a unique int ID for groups.
    var getGroupID = (function(id) {
        return function() {
            return id++;
        };
    })(0);

    // getUniqueID: generate a unique int ID for files
    var getUniqueID = (function(id) {
        return function() {
            return id++;
        };
    })(0);

    // The interface is supported, bind the FileReaderJS callbacks
    FileReaderJS.enabled = true;

})(this, document);
<commit_msg>Making filreader save for no conflicting mode<commit_after>/*!
    FileReader.js - v0.9
    A lightweight wrapper for common FileReader usage.
    Copyright 2012 Brian Grinstead - MIT License.
    See http://github.com/bgrins/filereader.js for documentation.
*/

(function(window, document) {

    var FileReader = window.FileReader;
    var FileReaderSyncSupport = false;
    var workerScript = "self.addEventListener('message', function(e) { var data=e.data; try { var reader = new FileReaderSync; postMessage({ result: reader[data.readAs](data.file), extra: data.extra, file: data.file})} catch(e){ postMessage({ result:'error', extra:data.extra, file:data.file}); } }, false);";
    var syncDetectionScript = "self.addEventListener('message', function(e) { postMessage(!!FileReaderSync); }, false);";
    var fileReaderEvents = ['loadstart', 'progress', 'load', 'abort', 'error', 'loadend'];

    var FileReaderJS = window.FileReaderJS = {
        enabled: false,
        setupInput: setupInput,
        setupDrop: setupDrop,
        setupClipboard: setupClipboard,
        sync: false,
        output: [],
        opts: {
            dragClass: "drag",
            accept: false,
            readAsDefault: 'BinaryString',
            readAsMap: {
                'image/*': 'DataURL',
                'text/*' : 'Text'
            },
            on: {
                loadstart: noop,
                progress: noop,
                load: noop,
                abort: noop,
                error: noop,
                loadend: noop,
                skip: noop,
                groupstart: noop,
                groupend: noop,
                beforestart: noop
            }
        }
    };

    // Setup jQuery plugin (if available)
    if (typeof(jQuery) !== "undefined") {
        jQuery.fn.fileReaderJS = function(opts) {
            return this.each(function() {
                if (jQuery(this).is("input")) {
                    setupInput(this, opts);
                }
                else {
                    setupDrop(this, opts);
                }
            });
        };

        jQuery.fn.fileClipboard = function(opts) {
            return this.each(function() {
                setupClipboard(this, opts);
            });
        };
    }

    // Not all browsers support the FileReader interface.  Return with the enabled bit = false.
    if (!FileReader) {
        return;
    }

    // WorkerHelper is a little wrapper for generating web workers from strings
    var WorkerHelper = (function() {

        var URL = window.URL || window.webkitURL;
        var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;

        // May need to get just the URL in case it is needed for things beyond just creating a worker.
        function getURL (script) {
            if (window.Worker && BlobBuilder && URL) {
                var bb = new BlobBuilder();
                bb.append(script);
                return URL.createObjectURL(bb.getBlob());
            }

            return null;
        }

        // If there is no need to revoke a URL later, or do anything fancy then just return the worker.
        function getWorker (script, onmessage) {
            var url = getURL(script);
            if (url) {
                var worker = new Worker(url);
                worker.onmessage = onmessage;
                return worker;
            }

            return null;
        }

        return {
            getURL: getURL,
            getWorker: getWorker
        };

    })();

    // setupClipboard: bind to clipboard events (intended for document.body)
    function setupClipboard(element, opts) {

        if (!FileReaderJS.enabled) {
            return;
        }
        var instanceOptions = extend(extend({}, FileReaderJS.opts), opts);

        element.addEventListener("paste", onpaste, false);

        function onpaste(e) {
            var files = [];
            var clipboardData = e.clipboardData || {};
            var items = clipboardData.items || [];

            for (var i = 0; i < items.length; i++) {
                var file = items[i].getAsFile();

                if (file) {

                    // Create a fake file name for images from clipboard, since this data doesn't get sent
                    var matches = new RegExp("/\(.*\)").exec(file.type);
                    if (!file.name && matches) {
                        var extension = matches[1];
                        file.name = "clipboard" + i + "." + extension;
                    }

                    files.push(file);
                }
            }

            if (files.length) {
                processFileList(e, files, instanceOptions);
                e.preventDefault();
                e.stopPropagation();
            }
        }
    }

    // setupInput: bind the 'change' event to an input[type=file]
    function setupInput(input, opts) {

        if (!FileReaderJS.enabled) {
            return;
        }
        var instanceOptions = extend(extend({}, FileReaderJS.opts), opts);

        input.addEventListener("change", inputChange, false);
        input.addEventListener("drop", inputDrop, false);

        function inputChange(e) {
            processFileList(e, input.files, instanceOptions);
        }

        function inputDrop(e) {
            e.stopPropagation();
            e.preventDefault();
            processFileList(e, e.dataTransfer.files, instanceOptions);
        }
    }

    // setupDrop: bind the 'drop' event for a DOM element
    function setupDrop(dropbox, opts) {

        if (!FileReaderJS.enabled) {
            return;
        }
        var instanceOptions = extend(extend({}, FileReaderJS.opts), opts);
        var dragClass = instanceOptions.dragClass;
        var initializedOnBody = false;

        // Bind drag events to the dropbox to add the class while dragging, and accept the drop data transfer.
        dropbox.addEventListener("dragenter", onlyWithFiles(dragenter), false);
        dropbox.addEventListener("dragleave", onlyWithFiles(dragleave), false);
        dropbox.addEventListener("dragover", onlyWithFiles(dragover), false);
        dropbox.addEventListener("drop", onlyWithFiles(drop), false);

        // Bind to body to prevent the dropbox events from firing when it was initialized on the page.
        document.body.addEventListener("dragstart", bodydragstart, true);
        document.body.addEventListener("dragend", bodydragend, true);
        document.body.addEventListener("drop", bodydrop, false);

        function bodydragend(e) {
            initializedOnBody = false;
        }

        function bodydragstart(e) {
            initializedOnBody = true;
        }

        function bodydrop(e) {
            if (e.dataTransfer.files && e.dataTransfer.files.length ){
                e.stopPropagation();
                e.preventDefault();
            }
        }

        function onlyWithFiles(fn) {
            return function() {
                if (!initializedOnBody) {
                    fn.apply(this, arguments);
                }
            };
        }

        function drop(e) {
            e.stopPropagation();
            e.preventDefault();
            if (dragClass) {
                removeClass(dropbox, dragClass);
            }
            processFileList(e, e.dataTransfer.files, instanceOptions);
        }

        function dragenter(e) {
            e.stopPropagation();
            e.preventDefault();
            if (dragClass) {
                addClass(dropbox, dragClass);
            }
        }

        function dragleave(e) {
            if (dragClass) {
                removeClass(dropbox, dragClass);
            }
        }

        function dragover(e) {
            e.stopPropagation();
            e.preventDefault();
            if (dragClass) {
                addClass(dropbox, dragClass);
            }
        }
    }

    // setupCustomFileProperties: modify the file object with extra properties
    function setupCustomFileProperties(files, groupID) {
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
            file.extra = {
                nameNoExtension: file.name.substring(0, file.name.lastIndexOf('.')),
                extension: file.name.substring(file.name.lastIndexOf('.') + 1),
                fileID: i,
                uniqueID: getUniqueID(),
                groupID: groupID,
                prettySize: prettySize(file.size)
            };
        }
    }

    // getReadAsMethod: return method name for 'readAs*' - http://www.w3.org/TR/FileAPI/#reading-a-file
    function getReadAsMethod(type, readAsMap, readAsDefault) {
        for (var r in readAsMap) {
            if (type.match(new RegExp(r))) {
                return 'readAs' + readAsMap[r];
            }
        }
        return 'readAs' + readAsDefault;
    }

    // processFileList: read the files with FileReader, send off custom events.
    function processFileList(e, files, opts) {

        var filesLeft = files.length;
        var group = {
            groupID: getGroupID(),
            files: files,
            started: new Date()
        };

        function groupEnd() {
            group.ended = new Date();
            opts.on.groupend(group);
        }

        function groupFileDone() {
            if (--filesLeft === 0) {
                groupEnd();
            }
        }

        FileReaderJS.output.push(group);
        setupCustomFileProperties(files, group.groupID);

        opts.on.groupstart(group);

        // No files in group - end immediately
        if (!files.length) {
            groupEnd();
            return;
        }

        var sync = FileReaderJS.sync && FileReaderSyncSupport;
        var syncWorker;

        // Only initialize the synchronous worker if the option is enabled - to prevent the overhead
        if (sync) {
            syncWorker = WorkerHelper.getWorker(workerScript, function(e) {
                var file = e.data.file;
                var result = e.data.result;

                // Workers seem to lose the custom property on the file object.
                if (!file.extra) {
                    file.extra = e.data.extra;
                }

                file.extra.ended = new Date();

                // Call error or load event depending on success of the read from the worker.
                opts.on[result === "error" ? "error" : "load"]({ target: { result: result } }, file);
                groupFileDone();

            });
        }

        Array.prototype.forEach.call(files, function(file) {

            file.extra.started = new Date();

            if (opts.accept && !file.type.match(new RegExp(opts.accept))) {
                opts.on.skip(file);
                groupFileDone();
                return;
            }

            if (opts.on.beforestart(file) === false) {
                opts.on.skip(file);
                groupFileDone();
                return;
            }

            var readAs = getReadAsMethod(file.type, opts.readAsMap, opts.readAsDefault);

            if (sync && syncWorker) {
                syncWorker.postMessage({
                    file: file,
                    extra: file.extra,
                    readAs: readAs
                });
            }
            else {

                var reader = new FileReader();
                reader.originalEvent = e;

                fileReaderEvents.forEach(function(eventName) {
                    reader['on' + eventName] = function(e) {
                        if (eventName == 'load' || eventName == 'error') {
                            file.extra.ended = new Date();
                        }
                        opts.on[eventName](e, file);
                        if (eventName == 'loadend') {
                            groupFileDone();
                        }
                    };
                });

                reader[readAs](file);
            }
        });
    }

    // checkFileReaderSyncSupport: Create a temporary worker and see if FileReaderSync exists
    function checkFileReaderSyncSupport() {
        var worker = WorkerHelper.getWorker(syncDetectionScript, function(e) {
            FileReaderSyncSupport = e.data;
        });

        if (worker) {
            worker.postMessage({});
        }
    }

    // noop: do nothing
    function noop() {

    }

    // extend: used to make deep copies of options object
    function extend(destination, source) {
        for (var property in source) {
            if (source[property] && source[property].constructor &&
                source[property].constructor === Object) {
                destination[property] = destination[property] || {};
                arguments.callee(destination[property], source[property]);
            }
            else {
                destination[property] = source[property];
            }
        }
        return destination;
    }

    // hasClass: does an element have the css class?
    function hasClass(el, name) {
        return new RegExp("(?:^|\\s+)" + name + "(?:\\s+|$)").test(el.className);
    }

    // addClass: add the css class for the element.
    function addClass(el, name) {
        if (!hasClass(el, name)) {
          el.className = el.className ? [el.className, name].join(' ') : name;
        }
    }

    // removeClass: remove the css class from the element.
    function removeClass(el, name) {
        if (hasClass(el, name)) {
          var c = el.className;
          el.className = c.replace(new RegExp("(?:^|\\s+)" + name + "(?:\\s+|$)", "g"), " ").replace(/^\s\s*/, '').replace(/\s\s*$/, '');
        }
    }

    // prettySize: convert bytes to a more readable string.
    function prettySize(bytes) {
        var s = ['bytes', 'kb', 'MB', 'GB', 'TB', 'PB'];
        var e = Math.floor(Math.log(bytes)/Math.log(1024));
        return (bytes/Math.pow(1024, Math.floor(e))).toFixed(2)+" "+s[e];
    }

    // getGroupID: generate a unique int ID for groups.
    var getGroupID = (function(id) {
        return function() {
            return id++;
        };
    })(0);

    // getUniqueID: generate a unique int ID for files
    var getUniqueID = (function(id) {
        return function() {
            return id++;
        };
    })(0);

    // The interface is supported, bind the FileReaderJS callbacks
    FileReaderJS.enabled = true;

})(this, document);
<|endoftext|>


<commit_before>// Custom British Library js

$(function() {

    // Add custom CSS
    $.get("assets/css/bl.css", function(data){
        var cssStr = "";
        $(cssStr).appendTo(document.head);
    });

    /** Pad the left of a string. */
    function pad(pad, str) {
        if (typeof str === 'undefined') {
            return pad;
        }
        return (pad + str).slice(-pad.length);
    }

    /** Return a link to the Digitised Manuscripts full display. */
    function renderDMLink(sm) {
        var escStr = sm.replace(/\s+/g, '_').toLowerCase(),
            url    = 'http://www.bl.uk/manuscripts/FullDisplay.aspx?ref=' + escStr,
            templ  = $("#link-template").html(),
            rend   = Mustache.render(templ, {url: url, text: sm});
        return rend;
    }

    /** Return a link to the Digitised Manuscripts viewer.  */
    function renderFolioLink(sm, folio) {
        var escStr = sm.replace(/\s+/g, '_').toLowerCase() + '_f' + pad('0000', folio);
            url    = 'http://www.bl.uk/manuscripts/Viewer.aspx?ref=' + escStr,
            templ  = $("#link-template").html(),
            rend   = Mustache.render(templ, {url: url, text: folio});
        return rend;
    }

    /** Format rows. */
    $('#tei-view table tr').each(function(i) {
        var sm;

        var shelfmarks = $(this).find('.shelfmark'),
            loci       = $(this).find('locus'),
            refs       = $(this).find('ref'),
            dimensions = $(this).find('dimensions'),
            layout     = $(this).find('layout'),
            hands      = $(this).find('handDesc'),
            extent     = $(this).find('extent'),
            addons     = $(this).find('[data-addon]');

        // Add shelfmark links
        $(shelfmarks).each(function() {
            sm = $(this).text();
            var link = renderDMLink(sm);
            $(this).html(link);
        });

        // Add loci links
        if (typeof(sm) !== 'undefined') {
            $(loci).each(function() {
                var n    = $(this).attr('n') || "",
                    to   = $(this).attr('to') || "",
                    from = $(this).attr('from') || "",
                    lStr = n;
                if (to.length > 0 && from.length > 0) {
                    lStr = lStr + to + "-" + from;
                } else if (n.length < 1) {
                    lStr = lStr + to + from;
                }
                lStr = lStr.replace(/[0-9]{1,3}[rv]/g, function (match, capture) {
                    return renderFolioLink(sm, match);
                });
                lStr = lStr.replace(/<\/a>[\n\r\s]+/g, '');
                lStr = lStr.replace(/-[\n\r\s]+<a/g, '- 0) {
                $(this).html(str);
            }
        });

        // Format extent
        $(extent).each(function() {
            var node = $(this).contents().filter(function() {
                    return this.nodeType == 3;
            })[0];
            node.nodeValue = $.trim(node.nodeValue) + "; ";
        });

        // Format dimensions
        $(dimensions).each(function() {
            var type   = $(this).attr('type') || "",
                unit   = $(this).attr('unit') || "",
                height = $(this).find('height').text() || "",
                width  = $(this).find('width').text() || "",
                str    = height + unit + " x " + width + unit;
            if (type.length > 0) {
                str = str + ' (' + type + '); ';
            }
            $(this).html(str);
        });

        // Format layout
        $(layout).each(function() {
            var layout = $(this);
            $.each(this.attributes, function(i, attr){
                if (attr.name == 'columns') {
                    layout.append('Columns: ' + attr.value + '
');
                } else if (attr.name == 'ruledlines') {
                    layout.append('Ruled lines: ' + attr.value + '
');
                } else if (attr.name == 'writtenlines') {
                    layout.append('Written lines: ' + attr.value + '
');
                }
             });
        });

        // Format hand description
        $(hands).each(function() {
            var n = $(this).attr('hands') || "";
            $(this).append('Hands: ' + n + '

');
        });

        // Format addons
        $(addons).each(function() {
            var attr     = $(this).data('addon'),
                children = $(this).find('[' + attr + ']');
            $(children).each(function() {
                var text  = $(this).text() || "",
                    addon = $(this).attr(attr) || "",
                    str   = (text + " (" + addon + ")");
                if (addon.length > 0) {
                    $(this).html(str);
                }
            });
        });
    });
});<commit_msg>Refactor bl.js<commit_after>// Custom British Library js

/** Add custom BL CSS. */
function addCustomCSS() {
    $.get("assets/css/bl.css", function(data){
        var cssStr = "";
        $(cssStr).appendTo(document.head);
    });
}

/**
 * Pad the left of a string if shorter than the specified padding.
 * @param {string} padding - The string used for padding.
 * @param {string} str - The string to be padded.
 */
function padLeft(padding, str) {
    if (typeof str === 'undefined') {
        return pad;
    }
    return (padding + str).slice(-padding.length);
}

/**
 * Return a link to the Digitised Manuscripts full display for a shelfmark.
 * @param {object} shelfmark - The shelfmark element.
 */
function renderDMLink(shelfmark) {
    var sStr  = shelfmark.trim().replace(/\s+/g, '_').toLowerCase(),
        url    = 'http://www.bl.uk/manuscripts/FullDisplay.aspx?ref=' + sStr,
        templ  = $("#link-template").html(),
        rend   = Mustache.render(templ, {url: url, text: shelfmark});
    return rend;
}

/**
 * Return a link to a folio in the Digitised Manuscripts viewer.
 * @param {object} shelfmark - The shelfmark element.
 */
function renderFolioLink(shelfmark, folio) {
    var sStr  = shelfmark.trim().replace(/\s+/g, '_').toLowerCase(),
        fStr  = '_f' + padLeft('0000', folio),
        url   = 'http://www.bl.uk/manuscripts/Viewer.aspx?ref=' + sStr + fStr,
        templ = $("#link-template").html(),
        rend  = Mustache.render(templ, {url: url, text: folio});
    return rend;
}

/**
 * Add a shelfmark link.
 * @param {object} shelfmark - The shelfmark element.
 */
function addShelfmarkLink(shelfmark) {
    var url = renderDMLink(shelfmark.text());
    shelfmark.html(url);
}

/**
 * Format a locus element.
 * @param {string} shelfmark - The shelfmark of the item.
 * @param {object} locus - The locus element.
 */
function formatLocus(shelfmark, locus) {
    var n    = locus.attr('n') || "",
        to   = locus.attr('to') || "",
        from = locus.attr('from') || "",
        lStr = n;
    if (to.length > 0 && from.length > 0) {
        lStr = lStr + to + "-" + from;
    } else if (n.length < 1) {
        lStr = lStr + to + from;
    }
    lStr = lStr.replace(/[0-9]{1,3}[rv]/g, function (match, capture) {
        return renderFolioLink(shelfmark, match);
    });
    lStr = lStr.replace(/<\/a>[\n\r\s]+/g, '');
    lStr = lStr.replace(/-[\n\r\s]+<a/g, '- 0) {
        $(this).html(str);
    }
}

/**
 * Format an extent element.
 * @param {object} extent - The extent element.
 */
function formatExtent(extent) {
    var node = extent.contents().filter(function() {
        return this.nodeType == 3;
    })[0];
    node.nodeValue = $.trim(node.nodeValue) + "; ";
}

/**
 * Format a dimensions element.
 * @param {object} dimensions - The dimensions element.
 */
function formatDimensions(dimensions) {
    var type   = dimensions.attr('type') || "",
        unit   = dimensions.attr('unit') || "",
        height = dimensions.find('height').text() || "",
        width  = dimensions.find('width').text() || "",
        str    = height + unit + " x " + width + unit;
    if (type.length > 0) {
        str = str + ' (' + type + '); ';
    }
    dimensions.html(str);
}

/**
 * Format a layout element.
 * @param {object} dimensions - The layout element.
 */
function formatLayout(layout) {
    $.each(layout.context.attributes, function(i, attr){
        if (attr.name == 'columns') {
            layout.append('Columns: ' +
                          attr.value.replace(/\s+/g, '-') +
                          '
');
        } else if (attr.name == 'ruledlines') {
            layout.append('Ruled lines: ' +
                          attr.value.replace(/\s+/g, '-')  +
                          '
');
        } else if (attr.name == 'writtenlines') {
            layout.append('Written lines: ' +
                          attr.value.replace(/\s+/g, '-')  +
                          '
');
        }
    });
}

/**
 * Format an element with the data-addon attribute.
 * @param {object} dimensions - The element.
 */
function formatAddon(addon) {
    var attr     = addon.data('addon'),
        children = addon.find('[' + attr + ']');
    $(children).each(function() {
        if (typeof($(this).attr(attr) !== 'undefined')) {
            $(this).html($(this).text() + " (" + $(this).attr(attr) + ")");
        }
    });
}

$(function() {
    addCustomCSS();

    // Format each row
    $('#tei-view table tr').each(function() {
        var shelfmark  = $(this).find('.shelfmark').first();

        // Add Digitised Manuscript links
        if (typeof(shelfmark) !== 'undefined') {
            addShelfmarkLink(shelfmark);
            $(this).find('locus').each(function() {
                formatLocus(shelfmark.text(), $(this));
            });
        }

        // Format references
        $(this).find('ref').each(function() {
            formatReference($(this));
        });

        // Format extent
        $(this).find('extent').each(function() {
            formatExtent($(this));
        });

        // Format dimensions
        $(this).find('dimensions').each(function() {
            formatDimensions($(this));
        });

        // Format layout
        $(this).find('layout').each(function() {
            formatLayout($(this));
        });

        // Format hand description
        $(this).find('handDesc').each(function() {
            var n = $(this).attr('hands') || "";
            $(this).append('
Hands: ' + n + '
');
        });

        // Format addons
        $(this).find('[data-addon]').each(function() {
            formatAddon($(this));
        });
    });
});<|endoftext|>