Source: slider.js

/**
 * Slider Component<BR>
 * <BR><BR><img src=../images/slider.png width=40%>
 * <BR><BR><a href="../html/slider.html">DEMO</a>
 */
class Slider extends HTMLElement {
    constructor() {
        console.group("Slider.constructor")
	
        super();

        console.groupEnd();
    };
    
    /**
     * Set observable values here. When Changed, attributeChangedCallback is invoked
     * @observedAttributes
     */
    static get observedAttributes() {
        console.group("Slider.observedAttributes");

	this.observables = ["title", "pinned"];

        console.groupEnd();
        return this.observables;
    };

    /**
     * This function is called when this is attached to DOM
     * @connectedCallback. 
     */
    connectedCallback() {
        console.group("Slider.connectedCallback")
	
	let self = this;

	// GET PROPERTIES AND INTERESTING ELEMENTS
	this._initialize();

	let menus = this.querySelector("wc-slider-menus").innerHTML;
	let guts  = this.querySelector("wc-slider-guts").innerHTML;

	//alert(this.properties.title);

	// REPLACE CONTENT IF NECESSARY WITH NEW STUFF
	this.innerHTML = `
	    <nav class="wc-slider-menu" id="wc-slider-menu">
	        <div class="clearfix wc-slider-menu-title">
	           <div class="pull-left">
	  	       ${this.properties.title}
		   </div>
	           <div class="pull-right">
	               <i class='fa fa-thumb-tack fa-rotate-45' style=color:#FFF></i>
	           </div>
	        </div>

		${menus}
	    </nav>

	    <main class="wc-slider-panel" id="wc-slider-panel">
                ${guts}
	    </main>`

	// ADD STATS AND OTHER FINAL STUFF
	this._finalize();

	// SHOW IT NOW (NO FLICKERS) 
	this.style.visibility = "visible";

        console.groupEnd();
    };

    /**
     * Invoked When component is removed. Usually with a .remove() function call
     * @disconnectedCallback
     */
    disconnectedCallback() {
        console.group("Slider.disconnectedCallback")

	/* CLEAN UP NOW */

        console.groupEnd();
    };

    /**
     * Called with .setAttribute(...) function call
     * @attributeChangedCallback
     */
    attributeChangedCallback(attr, oldval, newval) {
        console.group("Slider.attributeChangedCallback:", attr, oldval, newval);

	this.properties = this.properties || [];

	let obs = Slider.observedAttributes;

	for (let i = 0; i < obs.length; i++) {
	    this.properties[obs[i]] = newval;
	    // YOUR CODE FOR CHANGES GO HERE 
	}
	
        console.groupEnd();
    };

    /**
     * Stores DOM elements of interest for future use
     * @_fetchElements
     */
    _fetchElements() {
	console.group("Slider._fetchElements");
	
	this.dom = this.dom || [];
	this.dom.content = this.innerHTML;

	console.groupEnd();
    };

    /**
     * Component attributes are _fetched and defaults are set if undefined
     * @_fetchAttributes
     * @param {string} [title="Menus"] background color
     */
    _fetchAttributes() {
	console.group("Slider._fetchAttributes");
	
	this.properties = {
	    "cname"	 : "Slider",
	    "author"     : "Mel Heravi",
	    "version"    : "1.0",
	    "title"      : "Menus",
	    "pinned"     : "false"
	};
	
	// SAVE WIDGET SPECIFIC PROPERTIES
	this.propertiesW = [];

	// SAVE ALL OTHER PROPERTIES
	let attrs = wc.getAttributes(this)
	
 	for (var key in attrs) {
	    this.properties[key]  = this.getAttribute(key);
	    this.propertiesW[key] = this.getAttribute(key);
	    console.log(key + ": " + attrs[key]);
	}

	console.log("attributes: ", this.properties);

	console.groupEnd();
    };

    /**
     * A sample callback usage function - see connectedCallback()
     * @_onClick
     */
    _onClick() {
	console.group("Slider._onClick:", this.id);

	wc.publish(this, "wc-slider", {
	    action: "click",
	    id: this.id,
	    uparam: this.properties.uparam
	});

	console.groupEnd();
    };

    /**
     * Destroy the instance object and artifacts
     * @_destroy
     */
    destroy() {
	console.group("Slider.destroy:", this.id);

	// FREE POINTER
	delete this;

	// REMOVE ITEM FROM DOM
	this.parentNode.removeChild(this);

	console.groupEnd();
    };

    /**
     * configure the instance object and artifacts
     * @_configure
     */
    configure(options) {
	console.group("Slider.configure:", JSON.stringify(options));

	// PROCESS ALL OPTIONS HERE

	console.groupEnd();
    };

    /**
     * SAVE DATA FOR ANALYTICS
     * @__initialize
     */
    _initialize() {
	console.group("Slider._initialize:", this.id);

	// FETCH ALL INTERESTING ELEMENTS
	this._fetchElements();

	// FETCH ALL ATTRIBUTES
	this._fetchAttributes();
	
	console.groupEnd();
    };

    /**
     * SAVE DATA FOR ANALYTICS
     * @__finalize
     */
    _finalize() {
	console.group("Slider._finalize:", this.id);

	self = this;

	this.classList.add("wc");

	// ADD ANALYTICS HERE
	wc.getStats(this, this.properties.cname, this.properties.version);
	
	self.slideout = new Slideout({
            'panel': document.getElementById('wc-slider-panel'),
            'menu':  document.getElementById('wc-slider-menu'),
            'padding': 256,
            'tolerance': 70
	});

	$('.toggle-button').on('click', e => {
	    this._toggle();
	});

	$('.wc-slider-menu a').on('click', function(e) {
	    self._toggle();

	    $('.wc-slider-menu a').removeClass("active");
	    $(this).addClass("active");

	    console.log('PUBLISHING slider menu click', $(this).attr("id"));
	    wc.publish(this, "wc-slider", {
		action: "click",
		id: this.id
	    });
	});

	$(".fa-thumb-tack").on("click", e => {
	    if ($(".fa-thumb-tack").hasClass("active")) {
		this.properties.pinned = "false";
		$(".fa-thumb-tack").removeClass("active");
		$(".fa-thumb-tack").addClass("fa-rotate-45");
		$(".fa-bars").show();
	    } else {
		this.properties.pinned = "true";
		$(".fa-thumb-tack").addClass("active");
		$(".fa-thumb-tack").removeClass("fa-rotate-45");
		$(".fa-bars").hide();
	    }
	});

	// INITIALLY OPENED
	this._toggle();
	
	console.groupEnd();
    };

    /**
     * SAVE DATA FOR ANALYTICS
     * @__toggle
     */
    _toggle() {
	console.group("slider._toggle");
	
	if (this.properties.pinned == "false") {
	    $(".wc-slider-menu").toggle(0, function(e) {
		self.slideout.toggle();
	    });
	}
	
	console.groupEnd();
    }
}

window.customElements.define('wc-slider', Slider);