{"product_id":"codnida-2k-security-camera-outdoor-360-ptz-wifi-camera-cctv-camera-with-24-7-recording-pir-human-detection-sound-and-light-alarm-support-16-128g-sd-card-works-with-alexa","title":"2K PTZ Security Camera","description":"\u003cdiv\u003e\n\u003cdiv class=\"aplus-v2 desktop celwidget\"\u003e\n\u003cscript type=\"application\/javascript\"\u003e\/\/ \u003c![CDATA[\n    \/**\n     * Common event handler for click and keydown events.\n     * @param {Event} event - The event object.\n     * @param {Function} handleClickOrEnter - Function to handle click or Enter key events.\n     * @param {Function} handleEsc - Function to handle Esc key events.\n     *\/\n    \/\/ [TODO][AplusMantle-8064] Create common event handler util(key events, click events) in AplusModuleResources\n    function handleClickAndKeyEvents(event, handleClickOrEnterOrSpace) {\n        const ENTER_KEY_CODE = 13;\n        const ESCAPE_KEY_CODE = 27;\n        const SPACE_KEY_CODE = 32;\n        const isClick = event.type === 'click';\n        const isKeydown = event.type === 'keydown';\n        const isEnter = isKeydown \u0026\u0026 event.keyCode === ENTER_KEY_CODE;\n        const isSpace = isKeydown \u0026\u0026 event.keyCode === SPACE_KEY_CODE;\n        const isEsc = isKeydown \u0026\u0026 event.keyCode === ESCAPE_KEY_CODE;\n\n        if (isClick || isEnter || isSpace) {\n            handleClickOrEnterOrSpace();\n        } else if (isEsc) {\n            handleEsc(event);\n        }\n    }\n\n    \/**\n    * Function to handle esc key event.\n    * @param {Event} event - The event object.\n    *\/\n    function handleEsc(event) {\n        event.target.blur()  \/\/ force remove focus\n    }\n\/\/ ]]\u003e\u003c\/script\u003e\u003cscript type=\"text\/javascript\"\u003e\/\/ \u003c![CDATA[\n(function(f) {var _np=(window.P._namespace(\"PremiumAplusModule\"));if(_np.guardFatal){_np.guardFatal(f)(_np);}else{f(_np);}}(function(P) {\nP.now('premium-module-11-faq').execute(function(init) {\n    if (init) {\n        return;\n    }\n    P.register('premium-module-11-faq', function() {\n        return function() {\n            P.when('A', 'jQuery', 'ready').execute(function(A, $){\n                function initFaq(module) {                   \n                    const MODULE_CLASS_NAME = 'premium-aplus-module-11';\n                    const FAQ_CONTAINER_CLASS_NAME = 'faqs-container';\n                    const FAQ_BLOCK_CLASS_NAME = 'faq-block';\n                    const moduleId = $(module).data('faq-block');\n                    const $faqBlocks = $('.aplus-v2 .' + MODULE_CLASS_NAME + ' .' + FAQ_CONTAINER_CLASS_NAME + '.' + moduleId + ' .' + FAQ_BLOCK_CLASS_NAME);\n\n                    \/**\n                    * Function to handle click or Enter or Space key events.\n                    * @param {Element} element - The this object from which the event is dispatched\n                    * @param {faqBlocks} faqBlocks - List of all the Question and Answer blocks.\n                    *\/\n                    function handleClickOrEnterOrSpace(element, faqBlocks) {\n                        const $element = $(element);\n                        const isActive = $element.hasClass('aplus-active');\n\n                        faqBlocks.removeClass('aplus-active');\n                        faqBlocks.find('[data-faq-question]').attr('aria-expanded', 'false');\n\n                        if (!isActive) {\n                            $element.addClass('aplus-active');\n                            $element.find('[data-faq-question]').attr('aria-expanded', 'true');\n                        }\n                    }\n\n                    \/* Using jQuery event namespace for preventing duplicate binding on twister refresh *\/\n                    $faqBlocks.unbind('click keydown.premiumAplusModule11ClickHandler').bind('click keydown.premiumAplusModule11ClickHandler', function(event) {\n                        handleClickAndKeyEvents(event, () =\u003e handleClickOrEnterOrSpace(this, $faqBlocks)); \n                    });\n                }\n                $(\".aplus-v2 .premium-aplus-module-11 .faqs-container\").each(function(index, module) {\n                    initFaq(module);\n                });\n            });\n        };\n    });\n});\n}));\n\/\/ ]]\u003e\u003c\/script\u003e\u003cscript type=\"text\/javascript\"\u003e\/\/ \u003c![CDATA[\n(function(f) {var _np=(window.P._namespace(\"PremiumAplusModule\"));if(_np.guardFatal){_np.guardFatal(f)(_np);}else{f(_np);}}(function(P) {\nP.now('premium-module-12-nav-carousel').execute(function(init) {\n    if (init) {\n        return;\n    }\n    P.register('premium-module-12-nav-carousel', function(){\n        return function() {\n            P.when('A', 'jQuery', 'a-carousel-framework', 'ready').execute(function (A, $, framework) {\n                function initiateCarousel(module) {\n                    var MODULE_ID = $(module).data('module-id');\n                    \/**\n                    * Carousel button element classname\n                    * @const\n                    *\/\n                    var GOTO_BTN_CLASS_NAME = \"aplus-goto-btn-\" + MODULE_ID;\n                    \/**\n                    * Carousel button element active classname\n                    * @const\n                    *\/\n                    var GOTO_BTN_ACTIVE_CLASS_NAME = \"aplus-active\";\n                    \/**\n                    * AUI name for aui carousel\n                    * @const\n                    *\/\n                    var CAROUSEL_NAME = \"premium-aplus-12-carousel-\" + MODULE_ID;\n                    \/**\n                    * Module class name\n                    * @const\n                    *\/\n                    var MODULE_CLASS_NAME = \".aplus-v2 .premium-aplus-module-12\";\n                    \/**\n                    * Carousel text container class name\n                    * @const\n                    *\/\n                    var TEXT_CONTAINER_CLASS_NAME = MODULE_CLASS_NAME + \" .aplus-carousel-text-container-\" + MODULE_ID;\n                    \/**\n                    * Carousel text hidden class name\n                    * @const\n                    *\/\n                    var TEXT_CONTAINER_HIDDEN = \"aplus-hidden\";\n                    \/**\n                    * Carousel horizontal scroll container class name\n                    * @const\n                    *\/\n                    var HORIZONTAL_SCROLL_CONTAINER_CLASS_NAME = MODULE_CLASS_NAME + \" .aplus-horizontal-scroll-container-\" + MODULE_ID;\n\n                    function showCarouselText(oldIndex, newIndex) {\n                        var oldClass = TEXT_CONTAINER_CLASS_NAME + \"-\" + oldIndex;\n                        var newClass= TEXT_CONTAINER_CLASS_NAME + \"-\" + newIndex;\n                        $(oldClass).addClass(TEXT_CONTAINER_HIDDEN);\n                        $(newClass).removeClass(TEXT_CONTAINER_HIDDEN);\n                    }\n\n                    function scrollToCarouselButton(scrollLeft) {\n                        if ($(HORIZONTAL_SCROLL_CONTAINER_CLASS_NAME).length) {\n                            $(HORIZONTAL_SCROLL_CONTAINER_CLASS_NAME).animate({scrollLeft}, 200);\n                        }\n                    }\n\n                    \/**\n                    * Creates a CarouselButton class for provided carousel instance\n                    * @param {object} carousel - AUI Carousel instance\n                    * @returns {Class} - CarouselButton Class\n                    *\/\n                    function CarouselButtonTemplate(carousel) {\n                        \/**\n                        * Button for controlling the active slide\n                        * @constructor\n                        * @param {number} index - slide index\n                        * @param {DOMElement} [elem] - optional DOM element to use as this objects DOM representation\n                        *\/\n                        function CarouselButton(index, elem) {\n                            var self = this;\n                            this.index = index;\n                            this.carousel = carousel;\n\n                            \/* create the button element *\/\n                            this.elem = this.getElem(elem);\n                            this.$elem = $(this.elem);  \/* store jquery version *\/\n                            this.elem.addEventListener('click', self.handleClick.bind(self));\n                            this.elem.setAttribute('role', 'tab');\n\n                            \/* add this object to the object manager *\/\n                            CarouselButton.objects.byId[index] = this;\n                            CarouselButton.objects.all.push(this);\n                        }\n\n                        \/**\n                        * Describe behavior for click events on this.elem\n                        * @memberOf CarouselButton\n                        *\/\n                        CarouselButton.prototype.handleClick = function(e) {\n                            e.preventDefault();\n                            this.carousel.gotoPage(this.index);\n                        };\n\n                        \/**\n                        * Enter active state\n                        * @memberOf CarouselButton\n                        *\/\n                        CarouselButton.prototype.activate = function() {\n                            this.$elem.addClass(GOTO_BTN_ACTIVE_CLASS_NAME).attr('aria-selected', 'true');\n                        };\n\n                        \/**\n                        * Enter inactive state\n                        * @memberOf CarouselButton\n                        *\/\n                        CarouselButton.prototype.deactivate = function() {\n                            this.$elem.removeClass(GOTO_BTN_ACTIVE_CLASS_NAME).attr('aria-selected', 'false');\n                        };\n\n                        \/**\n                        * Returns an existing or creates a new bound element for this object\n                        * @memberOf CarouselButton\n                        * @param {DOMElement} [elem] - optionally provide an existing element in the DOM to use\n                        * @returns {DOMElement} - this objects DOM representation\n                        *\/\n                        CarouselButton.prototype.getElem = function(elem) {\n                            if (this.elem) return this.elem;\n                            if (elem) return elem;\n\n                            var createdElem = document.createElement('span');\n                            createdElem.className = GOTO_BTN_CLASS_NAME;\n\n                            return createdElem;\n                        };\n\n                        \/** @const Object manager *\/\n                        CarouselButton.objects = {\n                            byId: {},\n                            all: [],\n                        };\n\n                        return CarouselButton;\n                    }\n\n                    framework.onInit(CAROUSEL_NAME, function(carousel) {\n                        \/** @const {Class} *\/\n                        var CarouselButton = CarouselButtonTemplate(carousel);\n\n                        \/* create carousel controls *\/\n                        var $carouselBtns = $(safeClassSelector(GOTO_BTN_CLASS_NAME));\n                        var btns = $carouselBtns.map(function(i, btnElem) {\n                            return new CarouselButton(i + 1, btnElem);\n                        });\n\n                        \/* activate first one *\/\n                        CarouselButton.objects.byId[1].activate();\n\n                        \/* Listen to slide changes *\/\n                        A.on(\"a:carousel:\" + CAROUSEL_NAME + \":change:pageNumber\", function (data) {\n                            var newCarouselButton = CarouselButton.objects.byId[data.newValue];\n                            var marginLeft = parseInt(getComputedStyle(newCarouselButton.elem).getPropertyValue('margin-left'));\n                            var positionLeft = newCarouselButton.elem.offsetLeft - marginLeft;\n\n                            newCarouselButton.activate();\n                            CarouselButton.objects.byId[data.oldValue].deactivate();\n                            scrollToCarouselButton(positionLeft);\n                            showCarouselText(data.oldValue, data.newValue);\n                        });\n                    });\n\n                    \/**\n                    * @returns {string} - css classname prefixed with module selector\n                    *\/\n                    function safeClassSelector(className) {\n                        return '.' + MODULE_CLASS_NAME + ' .' + className;\n                    }\n                }\n\n                $('.aplus-v2 .premium-aplus-module-12 .aplus-carousel-container').each(function (index, module) {\n                    initiateCarousel(module);\n                });\n                framework.createAll();\n                framework.initializeAll();\n            });\n        }\n    })\n});\n}));\n\/\/ ]]\u003e\u003c\/script\u003e\n\u003cdiv class=\"celwidget aplus-module premium-module-8-hero-video aplus-premium\"\u003e\n\u003cdiv class=\"a-section a-spacing-none premium-aplus premium-aplus-module-8\"\u003e\n\u003cdiv class=\"a-section a-spacing-none premium-aplus-module-8-video\"\u003e\n\u003cdiv class=\"a-section a-spacing-none video-placeholder\"\u003e\n\u003cp class=\"isSelectedEnd\"\u003e\u003cstrong\u003e\u003cspan\u003eDescription:\u003c\/span\u003e\u003c\/strong\u003e\u003cbr\u003e\u003cspan\u003eA smart indoor and outdoor security camera with 2K resolution, 360° PTZ viewing, motion detection, auto tracking, two-way audio, and colour night vision. It supports 24\/7 recording, app alerts, SD card or cloud storage, and Alexa compatibility for convenient home monitoring.\u003c\/span\u003e\u003c\/p\u003e\n\u003cp class=\"isSelectedEnd\"\u003e\u003cstrong\u003e\u003cspan\u003eSpecifications:\u003c\/span\u003e\u003c\/strong\u003e\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cspan\u003eResolution: 2K \/ 3MP\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eCamera Type: PTZ Security Camera\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eHorizontal Rotation: Up to 355°\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eVertical Rotation: Up to 90°\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eNight Vision: Colour and infrared\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eNight Vision Range: Up to 10m\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eMotion Detection: Yes\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eAuto Tracking: Yes\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eCustom Detection Zones: Yes\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eTwo-Way Audio: Yes\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eSound \u0026amp; Light Alarm: Yes\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eRecording: 24\/7 supported\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eSD Card Support: 16GB–128GB\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eCloud Storage: Supported\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eWi-Fi: 2.4GHz only\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eApp: CloudEdge\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eAlexa Compatible: Yes\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003ePower Cable Length: 3m\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eConnectivity: Wireless\u003c\/span\u003e\u003c\/li\u003e\n\u003cli\u003e\u003cspan\u003eRecommended Use: Indoor and outdoor security\u003c\/span\u003e\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv\u003e\u003c\/div\u003e","brand":"Sayby’s Sanctuary ","offers":[{"title":"Black","offer_id":56071780696329,"sku":"B0DCJYL91L","price":30.51,"currency_code":"GBP","in_stock":true},{"title":"1 Pack","offer_id":56071780729097,"sku":"B0CGL36F9C","price":26.43,"currency_code":"GBP","in_stock":true},{"title":"2 Pack","offer_id":56071780761865,"sku":"B0CPHSHQDQ","price":61.04,"currency_code":"GBP","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0859\/0508\/0585\/files\/codnida-2k-security-camera-outdoor-360-ptz-wifi-camera-cctv-camera-with-247-recording-pir-human-detection-sound-and-light-alarm-support-16-128g-sd-card-works-wi-4474646.jpg?v=1788169886","url":"https:\/\/saybys.com\/products\/codnida-2k-security-camera-outdoor-360-ptz-wifi-camera-cctv-camera-with-24-7-recording-pir-human-detection-sound-and-light-alarm-support-16-128g-sd-card-works-with-alexa","provider":"Sayby’s Ltd","version":"1.0","type":"link"}