Skip to content
This repository has been archived by the owner on Feb 24, 2024. It is now read-only.

Commit

Permalink
createComponent feature added.
Browse files Browse the repository at this point in the history
  • Loading branch information
rizmyabdulla committed Oct 15, 2023
1 parent e893a3d commit 6399c9b
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 65 deletions.
5 changes: 4 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
<body>
<h1>ResponsiveDOM</h1>

<button class="button">Hello</button>
<div class="card">Hello</div>

<button id="destroy">Destroy Card</button>
<button id="init">Init Card</button>

<script type="module" src="./script.js"></script>
</body>
Expand Down
76 changes: 52 additions & 24 deletions script.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,59 @@
import ResponsiveDOM from "./src/ResponsiveDOM.js";

ResponsiveDOM.onMediaQueryChange(
["(max-width: 768px)", "(min-width: 769px)"],
[
() => {
console.log("Width is less than or equal to 768px");
},
() => {
console.log("Width is greater than or equal to 769px");
},
]
);
const DestroyBtn = document.getElementById("destroy");
const InitBtn = document.getElementById("init");

if (ResponsiveDOM.isMobile()) {
console.log("Its Mobile");
} else if (ResponsiveDOM.isTablet()) {
console.log("Its Tablet");
} else if (ResponsiveDOM.isDesktop()) {
console.log("Its Desktop");
} else if (ResponsiveDOM.isTV()) {
console.log("Its TV");
}
// ResponsiveDOM.onMediaQueryChange(
// ["(max-width: 768px)", "(min-width: 769px)"],
// [
// () => {
// console.log("Width is less than or equal to 768px");
// },
// () => {
// console.log("Width is greater than or equal to 769px");
// },
// ]
// );

const btn = ResponsiveDOM.createComponent(".button");
// if (ResponsiveDOM.isMobile()) {
// console.log("Its Mobile");
// } else if (ResponsiveDOM.isTablet()) {
// console.log("Its Tablet");
// } else if (ResponsiveDOM.isDesktop()) {
// console.log("Its Desktop");
// } else if (ResponsiveDOM.isTV()) {
// console.log("Its TV");
// }

btn.options.darkmode();
const card = ResponsiveDOM.createComponent(".card", {
breakpoints: {
mobile: (component) => {
component.element.style.backgroundColor = "red";
console.log("Mobile view");
},
tablet: (component) => {
component.element.style.backgroundColor = "green";
console.log("Tablet view");
},
desktop: (component) => {
component.element.style.backgroundColor = "blue";
console.log("Desktop view");
},
},
onResize: (component) => {
console.log("Resized");
},
onInit: (component) => {
console.log("Initialized");
},
onDestroy: (component) => {
console.log("Destroyed");
},
});

btn.element.addEventListener("click", () => {
btn.options.lightmode();
DestroyBtn.addEventListener("click", () => {
card.destroy();
});
InitBtn.addEventListener("click", () => {
card.init();
});
166 changes: 130 additions & 36 deletions src/ResponsiveDOM.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
/**
* A library for creating responsive DOM components that adapt to different device sizes.
* @namespace ResponsiveDOM
*/
const ResponsiveDOM = {
mediaQueryListeners: [],
components: [],

/**
* @param {string[]} queries
* Media queries to match
* @param {function[]} funcs
* functions to be called when the media query matches
* Adds listeners to media queries and executes corresponding functions when the media query matches.
* @param {Array<string>} queries - An array of media query strings.
* @param {Array<Function>} funcs - An array of callback functions to execute when the corresponding media query matches.
* @throws {Error} If queries or funcs are not arrays, or if an invalid query or callback function is provided.
*/
onMediaQueryChange(queries, funcs) {
if (!Array.isArray(queries) || !Array.isArray(funcs)) {
Expand Down Expand Up @@ -37,8 +41,9 @@ const ResponsiveDOM = {
},

/**
* @Note Removes all media query listeners
*
* Removes all media query listeners that were added using the `addMediaQueryListener` method.
* @memberof ResponsiveDOM
* @method
*/
removeMediaQueryListeners() {
this.mediaQueryListeners.forEach(({ mediaQueryList, callback }) => {
Expand All @@ -48,18 +53,17 @@ const ResponsiveDOM = {
},

/**
* @note Returns true if the device is mobile
* @query "(max-width: 767px)"
* Checks if the current device is a mobile device.
* @returns {boolean} - Returns true if the device is a mobile device, false otherwise.
*/

isMobile() {
const mobileMediaQuery = window.matchMedia("(max-width: 767px)");
return mobileMediaQuery.matches;
},

/**
* @note Returns true if the device is Tablet
* @query "(min-width: 768px) and (max-width: 1023px)"
* Checks if the current device is a tablet.
* @returns {boolean} - Returns true if the device is a tablet, false otherwise.
*/

isTablet() {
Expand All @@ -70,57 +74,147 @@ const ResponsiveDOM = {
},

/**
* @note Returns true if the device is Desktop
* @query "(max-width: 1024px)"
* Checks if the current device is a desktop based on the window width.
* @returns {boolean} Returns true if the device is a desktop, false otherwise.
*/

isDesktop() {
const desktopMediaQuery = window.matchMedia("(min-width: 1024px)");
return desktopMediaQuery.matches;
},

/**
* @note Returns true if the device is TV
* @query "(min-width: 1366px)"
* Checks if the current device has a TV screen size.
* @returns {boolean} Returns true if the device has a TV screen size, otherwise false.
*/

isTV() {
const tvMediaQuery = window.matchMedia("(min-width: 1366px)");
return tvMediaQuery.matches;
},

/**
* Creates a responsive DOM component with the given element selector and options.
*
* @param {string} elementSelector - selector for the element
* @param {object} options - options for the component
*
* @returns {object} component
*
* @note Creates a new component
* @param {string} elementSelector - The CSS selector for the HTML element to use as the component.
* @param {Object} options - The options for the component.
* @param {Object} options.breakpoints - The breakpoints for the component, with keys for "mobile", "tablet", and "desktop".
* @param {Function} options.onResize - The function to call when the component is resized.
* @param {Function} options.onInit - The function to call when the component is initialized.
* @param {Function} options.onDestroy - The function to call when the component is destroyed.
* @returns {Object} The created component object.
*/

createComponent(elementSelector, options) {
const Element = document.querySelector(elementSelector);
if (!Element) {
throw new Error(`Element with selector '${elementSelector}' not found.`);
const element = document.querySelector(elementSelector);

if (!element) {
console.error(`Element with selector '${elementSelector}' not found.`);
return null;
}

const component = {
element: Element,
options: options || {
darkmode: () => {
Element.classList.add("rd-dark");
},
lightmode: () => {
Element.classList.remove("rd-dark");
},
const defaultOptions = {
breakpoints: {
mobile: null,
tablet: null,
desktop: null,
},
onResize: null,
onInit: null,
onDestroy: null,
};

const componentOptions = Object.assign({}, defaultOptions, options);

const component = {
element,
options: componentOptions,
currentBreakpoint: null,
};

/**
* Handles the change in breakpoint for a component and performs actions based on the new breakpoint.
*/
const handleBreakpointChange = () => {
const newBreakpoint = ResponsiveDOM.determineBreakpoint(component);
if (newBreakpoint !== component.currentBreakpoint) {
component.currentBreakpoint = newBreakpoint;
// Perform actions based on the new breakpoint
if (component.options.breakpoints[newBreakpoint]) {
component.options.breakpoints[newBreakpoint](component);
}
}
};

/**
* Event listener for window resize events.
*
* @function
* @name resizeListener
* @memberof module:ResponsiveDOM
* @inner
* @param {Event} event - The resize event object.
* @returns {void}
*/
const resizeListener = () => {
if (component.options.onResize) {
component.options.onResize(component);
}
handleBreakpointChange();
};

/**
* Initializes the ResponsiveDOM component by calling the onInit callback function (if provided),
* determining the initial breakpoint, and adding a resize listener to the window.
*/
const init = () => {
if (component.options.onInit) {
component.options.onInit(component);
}
handleBreakpointChange();
window.addEventListener("resize", resizeListener);
};

/**
* Destroys the component and removes the resize listener.
* @function
* @memberof ResponsiveDOM
*/
const destroy = () => {
if (component.options.onDestroy) {
component.options.onDestroy(component);
}
window.removeEventListener("resize", resizeListener);
};

component.destroy = destroy;
component.init = init;

init();
this.components.push(component);

return component;
},

/**
* Determines the current breakpoint based on the window width and the component's breakpoints.
* @param {Object} component - The component to determine the breakpoint for.
* @returns {string} The current breakpoint ("mobile", "tablet", or "desktop").
*/
determineBreakpoint(component) {
const breakpoints = component.options.breakpoints;

let currentBreakpoint = "mobile";

const windowWidth = window.innerWidth;

if (windowWidth >= 768 && windowWidth < 1024) {
currentBreakpoint = "tablet";
} else if (windowWidth >= 1024) {
currentBreakpoint = "desktop";
} else if (windowWidth >= 1366) {
currentBreakpoint = "tv";
}

return currentBreakpoint;
},
};

export default ResponsiveDOM;
2 changes: 1 addition & 1 deletion src/ResponsiveDOM.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions style.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
.rd-dark {
background-color: black;
color: white;
.card {
width: 200px;
height: 200px;
border: 5px solid #bbbb;

display: flex;
justify-content: center;
align-items: center;

}

0 comments on commit 6399c9b

Please sign in to comment.