/*global define */
define(['jquery', 'underscore', 'backbone',
'models/filters/ToggleFilter',
'views/filters/FilterView',
'text!templates/filters/toggleFilter.html',
'text!templates/filters/booleanFilter.html'],
function($, _, Backbone, ToggleFilter, FilterView, Template, BooleanTemplate) {
'use strict';
/**
* @class ToggleFilterView
* @classdesc Render a view of a single ToggleFilter model
* @classcategory Views/Filters
* @extends FilterView
*/
var ToggleFilterView = FilterView.extend(
/** @lends ToggleFilterView.prototype */{
/**
* A ToggleFilter model to be rendered in this view
* @type {ToggleFilter} */
model: null,
/**
* @inheritdoc
*/
modelClass: ToggleFilter,
className: "filter toggle",
template: _.template(Template),
booleanTemplate: _.template(BooleanTemplate),
/**
* @inheritdoc
*/
events: function () {
try {
var events = FilterView.prototype.events.call(this);
events["click input[type='checkbox']"] = "updateModel";
return events
}
catch (error) {
console.log('There was an error creating the events object for a ToggleFilterView' +
' Error details: ' + error);
}
},
/**
* @inheritdoc
*/
render: function (templateVars = {}) {
try {
templateVars = _.extend(this.model.toJSON(), templateVars);
templateVars.id = this.model.cid;
if (!this.model.get("falseLabel")) {
//If the value is the same as the trueValue, the checkbox should be checked
templateVars.checked = (this.model.get("values")[0] == this.model.get("trueValue"))? true : false;
//Use the BooleanFilter template for toggles with only a true value
this.$el.addClass("boolean");
this.template = this.booleanTemplate
}
// Renders the template and inserts the FilterEditorView if the mode is uiBuilder
FilterView.prototype.render.call(this, templateVars);
this.listenTo(this.model, "change:values", this.updateToggle);
}
catch (error) {
console.log( 'There was an error rendering a ToggleFilterView.' +
' Error details: ' + error );
}
},
/**
* Actions to perform after the render() function has completed and this view's
* element is added to the webpage.
*/
postRender: function(){
this.setToggleWidth();
},
updateToggle: function(){
//If the model is set to true
if( this.model.get("values").length && this.model.get("values")[0] == this.model.get("trueValue") ){
this.$("input").prop("checked", true);
}
else if( this.model.get("values").length && this.model.get("values")[0] == this.model.get("falseValue") ){
this.$("input").prop("checked", false);
}
else if( !this.model.get("values").length ){
this.$("input").prop("checked", false);
}
this.setToggleWidth();
},
/**
* Gets the width of the toggle labels and sets the various CSS attributes
* necessary for the switch to fully display each label
*/
setToggleWidth: function(){
//If there is no toggle element, exit now
if( !this.$(".can-toggle-switch").length ){
return;
}
//Get the padding and widths of the switch elements
var switchPadding = 24,
onSwitchWidth = this.$(".true-label").width(),
offSwitchWidth = this.$(".false-label").width(),
totalSwitchWidth = onSwitchWidth + offSwitchWidth + (switchPadding * 2) + 2,
isChecked = this.$("input[type='checkbox']").prop("checked");
//Set the width on the whole view
this.$el.width(totalSwitchWidth + "px");
//Get the toggle switch element
var toggleSwitch = this.$(".can-toggle-switch");
//Add an identifier to the toggle switch element
toggleSwitch.attr("id", "toggle-" + this.model.cid);
//Change the width of the toggle switch
toggleSwitch.css("flex", "0 0 " + totalSwitchWidth + "px");
//Create CSS for the :before and :after pseudo elements, which is best done
// by adding a style tag directly to the DOM
if( isChecked ){
var newCSS = "#" + "toggle-" + this.model.cid + ":before{ " +
"transform: translate3d(" + (onSwitchWidth + switchPadding) + "px, 0, 0);" +
"width: " + (offSwitchWidth + switchPadding) + "px ;" +
"}" +
"#" + "toggle-" + this.model.cid + ":after{ " +
"width: " + (onSwitchWidth + switchPadding) + "px;" +
"transform: translate3d(0px, 0, 0);" +
"}";
}
else{
var newCSS = "#" + "toggle-" + this.model.cid + ":before{ " +
"width: " + (offSwitchWidth + switchPadding) + "px ;" +
"left: 0px ;" +
"}" +
"#" + "toggle-" + this.model.cid + ":after{ " +
"width: " + (onSwitchWidth + switchPadding) + "px;" +
"transform: translate3d(" + (offSwitchWidth + switchPadding) + "px, 0, 0);" +
"}";
}
//Get or create a style tag
var styleTag = toggleSwitch.children("style");
if( !styleTag.length ){
styleTag = $(document.createElement("style"));
toggleSwitch.append(styleTag);
}
//Add the CSS to the style tag
styleTag.html(newCSS);
},
/**
* Updates the value set on the ToggleFilter Model associated with this view.
* The filter value is grabbed from the checkbox element in this view.
*
*/
updateModel: function () {
//Check if the checkbox is checked
var isChecked = this.$("input").prop("checked");
//If the toggle is checked, then set the true toggle value on the model
if( isChecked ){
if( this.model.get("values")[0] !== this.model.get("trueValue") ){
this.model.set("values", [ this.model.get("trueValue") ]);
}
}
//If the toggle is not checked and there is no false value specified,
// then remove the value from the model completely
else if(!this.model.get("falseValue")){
if( this.model.get("values").length > 0 ){
this.model.set("values", []);
}
}
//If the toggle is not checked and there is a false value specified,
// then set the false toggle value on the model
else{
if( this.model.get("values")[0] !== this.model.get("falseValue") ){
this.model.set("values", [ this.model.get("falseValue") ]);
}
}
}
});
return ToggleFilterView;
});