I have one question. I am doing automatic slider with option to click on dot, which picture I want to show.
But I have problem with variable, which should find SVG and then I use this variable as a value for an array.
PROBLEM IS:
If I define this variable "dot" INSIDE of my object "Slider", it finds all SVG in div element.
But if I declare this variable "dot" OUTSIDE of my object, I will find elements instead of SVG.
Problematic part is:
dot = $('.images-switch').children(), - give different results if INSIDE or OUTSIDE of object SLIDER
Can you advise me how to solve it. And give my your opinion about my solution of slider?
Code is below (var dot is defined inside Slider object = find alls SVG):
var covers = $('.fadecovers'),
cover = $('.cover'),
imagesSwitch = $('.images-switch')
i = 0,
slideCount = $('.cover').length,
slide = $('.cover'),
slideArr = jQuery.makeArray(slide),
dot = $('.images-switch').children(),
dotArr = jQuery.makeArray(dot),
n = 0;
console.log(dot);
for (n = 0; n < (slideCount); n++) {
$(dotArr[n]).attr('data', n);
};
$('.images-switch').children().first().addClass('active');
//Zaciatok objektu
var Slider = {
// nastavenie atributov objektu Slider defaultne ako null
intervalID: null,
running: false,
start: function() {
intervalID = setInterval (function () {
var dot = $('.images-switch').children(),
dotArr = jQuery.makeArray(dot);
if (i == slideCount) {i = 0};
if (cover.eq(0).is(':visible')) {i = 1};
$(slideArr).fadeOut(700);
$(slideArr[i]).fadeIn(700);
$(dotArr).removeClass('active');
$(dotArr[i]).addClass('active')
i++;
running = true;
},3500);
},
pause: function() {
//stopne vykonavanie setInterval funkcie
clearInterval(intervalID);
intervalID = null;
running = false;
},
resume: function() {
//ak nie je interval prazdny (teda ako keby neexistuje), tak spusti vykonavanie setInterval funkcie
if (!intervalID) {this.start()};
},
//zlucenie funckii na stopnutie a znovu spustenie setInterval
toggle: function() {
if (running) this.pause();
else this.resume();
},
};
Slider.start();
covers.on('click', function() {
Slider.toggle();
});
imagesSwitch.on('click', 'svg', function() {
var dot = $('.images-switch').children(),
dotArr = jQuery.makeArray(dot),
data = $(this).attr('data');
i = data;
$(slideArr).fadeOut(700);
$(slideArr[i]).fadeIn(700);
$(dotArr).removeClass('active');
$(dotArr[i]).addClass('active')
i++;
});
Here is belonging HTML code:
<header class="article-header">
<div class="container">
<h1 class="post-title">
Naše portfólio prác
</h1>
</div>
<div class="fadecovers">
<div class="cover"><img src="img/dragon-1.jpg"></div>
<div class="cover fade-out" ><img src="img/dragon-2.jpg"></div>
<div class="cover fade-out"><img src="img/dragon-3.jpg"></div>
<div class="cover fade-out" ><img src="img/dragon-4.jpg"></div>
</div>
<div class="images-switch">
<i class="fas fa-circle"></i>
<i class="fas fa-circle"></i>
<i class="fas fa-circle"></i>
<i class="fas fa-circle"></i>
</div>
</header>
I finally solved it by myself. I changed the circles made by SVG to SPAN (circle made by CSS). Now it works.
Related
**I want to set the background of all objects of the .false class back to the default color before i change the correct class to green **
let objects = document.querySelectorAll('.false');
let myobject = document.querySelector('.correct');
myobject.addEventListener("click", function(){
for (let items in objects)
{
items.style.backgroundColor = "#d9edff";
}
document.getElementById("tr1").innerHTML = "CORRECT!";
document.querySelector(".correct").style.backgroundColor = "green";
});
EDIT: The full code. I needet to put the objects[object] in to let the background color change to default. But now the button that should get green dosnt work anymore...
<!DOCTYPE html>
<html lang="en">
<head>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght#500&display=swap" rel="stylesheet">
<link href="styles.css" rel="stylesheet">
<title>Trivia!</title>
<script>
document.addEventListener('DOMContentLoaded', function() {
let objects = document.querySelectorAll('.false'); // var mit object durch getElement function gefüllt mit .class
let myobject = document.querySelector('.correct'); // var mit object durch getElement function gefüllt mit .class
myobject.addEventListener("click", function(){
for (object in objects)
{
objects[object].style.backgroundColor = "#d9edff";
}
document.getElementById("tr1").innerHTML = "CORRECT!";
document.querySelector(".correct").style.backgroundColor = "green";
});
for (let i = 0; i < objects.length; i++)
{
objects[i].addEventListener("click", function(){
document.querySelector(".correct").style.backgroundColor = "#d9edff"; //reset correct button
objects[i].style.backgroundColor = "red";
document.getElementById("tr1").innerHTML = "FALSE!";
})
}
// Part2 without saving the check object in a let/var first and adding the eventlistener in 1 go
document.querySelector('.check').addEventListener("click", function(){
let input = document.querySelector("input");
if(input.value.toLowerCase() == "cs50")
{
input.style.backgroundColor = "green";
document.getElementById("tr2").innerHTML = "CORRECT!";
} else {
input.style.backgroundColor = "red";
document.getElementById("tr2").innerHTML = "FALSE!";
}
})
});
</script>
</head>
<body>
<div class="header">
<h1>Trivia!</h1>
</div>
<div class="container">
<div class="section">
<h2>Part 1: Multiple Choice </h2>
<hr>
<!-- TODO: Add multiple choice question here -->
<h3>This is the first question. Multiple choice with atleast 3 buttons? Second one is correct! Which one is correct?</h3>
<h4><p id = "tr1"> </p></h4>
<ul>
<button class="false">Click me to change my color to red</button>
<button class="correct">Click me to change my color to green</button>
<button class="false">Click me to change my color to red</button>
</ul>
</div>
<div class="section">
<h2>Part 2: Free Response</h2>
<hr>
<h3>This is the second question. What course is this? </h3>
<h4><p id = 'tr2'></p></h4>
<input type="Text" placeholder="Type answer here!">
<button class="check">submit</button>
</div>
</div>
</body>
</html>
querySelector returns NodeList instead of array. That's why you can't use some of array methods. You can use method for...of:
let objects = document.querySelectorAll('.false');
let myobject = document.querySelector('.correct');
myobject.addEventListener("click", function(){
for (let items of objects)
{
items.style.backgroundColor = "#d9edff";
}
document.getElementById("tr1").innerHTML = "CORRECT!";
document.querySelector(".correct").style.backgroundColor = "green";
});
Currently, this codepen I forked displays one tv monitor on the webpage as shown below where the channel button allows the user to toggle different gif's. This gif data is stored as an array in the js file. I want to create multiple tv sets, so I am thinking it may be better to create a TV class and instantiate the TV object n-times through a loop. I am new to OOP in a web dev context, so I haven't yet figured out how to rearchitect the code to accomplish this. Since id's only allow for one HTML element, duplicating the chunk of code below would visually create another tv but without any dynamic features. What then becomes of the tv-body display elements? Would they be enveloped with a show() fx nested with the script's TV class? Thank you so much in advance!
[Cropped Output Displayed Here][1]
HTML
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>CodePen - Vintage Analog TV</title>
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"><link rel="stylesheet" href="./style.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://code.jquery.com/jquery-3.5.0.js"></script>
</head>
<body>
<!-- partial:indexe.partial.html -->
<main>
<div class="tv-set">
<div class="tv-body">
<div class="screen-container">
<canvas class="static" width="380" height="280"></canvas>
<img class="displayed" src="" alt="Nothing" width="380" height="280">
<div class="screen">
<div class="screen-frame"></div>
<div class="screen-inset"></div>
</div>
</div>
<div class="logo-badge">
<div class="logo-text">Bush</div>
</div>
<div class="controls">
<div class="panel">
<div class="screw"></div>
<div class="dial">
<button class="channel dial-label pristine">Channel</button>
</div>
</div>
<div class="vents">
<div class="vent"></div>
<div class="vent"></div>
<div class="vent"></div>
<div class="vent"></div>
<div class="vent"></div>
<div class="vent"></div>
</div>
<div class="panel">
<div class="screw"></div>
<div class="dial">
<button class="dial-label" disabled>Volume</button>
</div>
</div>
</div>
</div>
<div class="legs">
<div class="leg"></div>
<div class="leg"></div>
</div>
</div>
</main>
<!-- partial -->
<script src="./script.js"></script>
</body>
</html>
JS
document.addEventListener("DOMContentLoaded", tv);
// Helper Functions
//returns tagname
jQuery.fn.tagName = function () {
return this.prop("tagName").toLowerCase;
};
// returns nth parent from target element
$.fn.nthParent = function (n) {
var p = this;
for (var i = 0; i < n; i++)
p = p.parent();
return p;
}
phases = [{
channels: ["red", "blue"]
},
{
channels: ["green", "yellow"]
},
{
channels: ["red", "green"]
},
{
channels: ["blue", "green"]
}
]
const container = document.getElementsByTagName("main")[0];
const template = document.getElementsByClassName("tv-set")
for (let i = 0; i < phases.length; i++) {
const clone = template[i].cloneNode(true);
clone.setAttribute("id", "tv-" + (i + 1))
console.log("clone id: ", clone.getAttribute("id"))
clone.setAttribute("data-channel", 0)
clone.setAttribute("name", "tv-" + i)
// clone.style.backgroundColor = phases[i].channels[0]
container.appendChild(clone)
}
function tv() {
let cnvs = document.querySelectorAll(".static");
//Gather all static elements
// let scrns = $(".static").getContext
// console.log("Screen 01: ", scrns)
// var cnv = document.getElementById("static"),
// var cnv = document.querySelector(".static"), //works in place of line above
// Need to establish a boolean array for the isStatic
let c = []
let isStatic_arr = []
// Need to establish a boolean array for the isStatic
cnvs.forEach((cnv) => {
isStatic_arr.push(false)
var c = cnv.getContext("2d"),
cw = cnv.offsetWidth,
ch = cnv.offsetHeight,
staticScrn = c.createImageData(cw, ch),
staticFPS = 30,
// isStatic_arr.push(false),
// isStatic = false,
staticTO,
gifData = [{
// file: "https://i.ibb.co/chSK1Zt/willie.gif",
file: "./media/back-to-school-chacha.gif",
desc: "Stephen Chow Fight Back to School"
// <video controls autoplay>
// <source src="fbts_chacha_sound.mp4" type="video/mp4">
// <source src="movie.ogg" type="video/ogg">
// Your browser does not support the video tag.
// </video>
},
{
file: "https://i.ibb.co/chSK1Zt/willie.gif",
desc: "Steamboat Willie (Mickey Mouse) steering a ship"
},
{
file: "https://i.ibb.co/0FqQVrj/skeletons.gif",
desc: "Spooky scary skeletons sending shivers down your spine"
},
{
file: "https://i.ibb.co/Hpnwgq2/kingkong.gif",
desc: "King Kong waving on Empire State Building",
},
{
file: "https://i.ibb.co/fp0PSjv/tracks.gif",
desc: "Looking at train tracks from behind a train",
},
{
file: "https://i.ibb.co/5FM7BtH/nuke.gif",
desc: "Nuclear explosion at sea",
}
],
gifs = [],
channel = 0;
for (g in gifData) {
gifs.push(new Image());
gifs[g].src = gifData[g].file;
gifs[g].alt = gifData[g].desc;
}
/* Static */
var runStatic = function () {
isStatic = true;
c.clearRect(0, 0, cw, ch);
for (var i = 0; i < staticScrn.data.length; i += 4) {
let shade = 127 + Math.round(Math.random() * 128);
staticScrn.data[0 + i] = shade;
staticScrn.data[1 + i] = shade;
staticScrn.data[2 + i] = shade;
staticScrn.data[3 + i] = 255;
}
c.putImageData(staticScrn, 0, 0);
staticTO = setTimeout(runStatic, 1e3 / staticFPS);
};
runStatic();
/* Channels */
var changeChannel = function (button, idx) {
console.log("Tv-set: ", idx)
console.log("Tv-set- " + idx + "button: " + button)
// var displayed = document.getElementById("displayed");
var displayed = document.querySelectorAll(".displayed")[idx];
var display_parent = $(".displayed")[1]
console.log("Display: ", displayed)
console.log("Display's parent: ", display_parent)
++channel;
if (channel > gifData.length)
channel = 1;
// this.classList.remove("pristine");
button.classList.remove("pristine");
// this.style.transform = `rotate(${channel * 360/(gifData.length + 1)}deg)`;
button.style.transform = `rotate(${channel * 360/(gifData.length + 1)}deg)`;
theCanvas = document.querySelectorAll(".static")[idx]
// cnv.classList.remove("hide");
theCanvas.classList.remove("hide");
displayed.classList.add("hide"); //CAUSING PROBLEMS
if (!isStatic[idx])
runStatic();
setTimeout(function () {
// cnv.classList.add("hide");
theCanvas.classList.add("hide");
displayed.classList.remove("hide");
displayed.src = gifs[channel - 1].src;
displayed.alt = gifs[channel - 1].alt;
isStatic = false;
clearTimeout(staticTO);
}, 300);
};
function iterate(item, index) {
console.log(`${item} has index ${index}`);
}
// const buttons = document.getElementsByClassName("channel dial-label pristine");
// const btns_arr = Array.from(document.querySelectorAll(".channel"))
const buttons = document.querySelectorAll(".channel")
buttons.forEach((btn, i) => {
btn.addEventListener('click', () => changeChannel(btn, i));
});
});
}
[1]: https://i.stack.imgur.com/INtzP.png
[2]: https://i.stack.imgur.com/aOxoQ.png
(11/14/20) #ggirodda, thank you so much for the example. Unfortunately, I am still a bit stuck. Why is it when I use const template = document.getElementsByClassName("tv-body").children[0], I get the error: script_001.js:154 Uncaught TypeError: Cannot read property '0' of undefined
at HTMLDocument.tv (script_001.js:154) Shouldn't the tv-body class have children based on the code snippet below?
(11/14/20) Addressed error above by removing .children[0] but unsure as to why that works and why it was undefined.
(11/19/20) Resolved! Sort of, that is. All tv clones can will run as intended, meaning the static display will remain active on all tv's whose channel button has not been pressed, and the channels can be changed independently. Here were the main changes I made on the original code:
All id's replaced with classes so that they can be accessed and wrapped the "tv-body" and "legs" in a separate div so that they can be cloned as a set.
Gathered all the "tv-set" class elements outside of the tv function() and then performed the setup functions forEach()
Converted a few of the variables e.g canvas, isStatic into arrays so that their states and displays could be toggled independently. I am sure there is more work to be done here as some of the variables may still be shared among the clones.
You can take some inspiration from the code below, the example is less complex but the idea is the same
const tvs = [
{ channels: ["red", "blue"] },
{ channels: ["green", "yellow"] }
]
function changeChannel(idx) {
const tv = tvs[idx]
const tvNode = document.getElementById("tv-" + idx)
const currentChannelIdx = parseInt(tvNode.getAttribute("data-channel"))
const nextChannelIdx = tv.channels[currentChannelIdx + 1] ? currentChannelIdx + 1 : 0;
tvNode.style.backgroundColor = tv.channels[nextChannelIdx]
tvNode.setAttribute("data-channel", nextChannelIdx)
}
const container = document.getElementById("container")
const template = document.getElementById("tv-template").children[0]
for (let i = 0; i < tvs.length; i++) {
const clone = template.cloneNode(true);
clone.setAttribute("id", "tv-" + i)
clone.setAttribute("data-channel", 0)
clone.style.backgroundColor = tvs[i].channels[0]
container.appendChild(clone)
}
const buttons = document.getElementsByClassName("channel-btn")
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', () => changeChannel(i), false);
}
<div id="container"></div>
<div id="tv-template" style="display: none;">
<div class="tv" style="width: 70px; height: 70px; margin-bottom: 20px;">
<button class="channel-btn">next</button>
</div>
</div>
I have implemented a swipe to reveal Oracle JET component.
Below is my Js code
this.action = ko.observable("No action taken yet");
this.handleReady = function()
{
// register swipe to reveal for all new list items
$("#listview").find(".item-marker").each(function(index)
{
var item = $(this);
var id = item.prop("id");
var startOffcanvas = item.find(".oj-offcanvas-start").first();
var endOffcanvas = item.find(".oj-offcanvas-end").first();
// setup swipe actions
oj.SwipeToRevealUtils.setupSwipeActions(startOffcanvas);
oj.SwipeToRevealUtils.setupSwipeActions(endOffcanvas);
// make sure listener only registered once
endOffcanvas.off("ojdefaultaction");
endOffcanvas.on("ojdefaultaction", function()
{
self.handleDefaultAction(item);
});
});
};
this.handleDestroy = function()
{
// register swipe to reveal for all new list items
$("#listview").find(".item-marker").each(function(index)
{
var startOffcanvas = $(this).find(".oj-offcanvas-start").first();
var endOffcanvas = $(this).find(".oj-offcanvas-end").first();
oj.SwipeToRevealUtils.tearDownSwipeActions(startOffcanvas);
oj.SwipeToRevealUtils.tearDownSwipeActions(endOffcanvas);
});
};
this.handleMenuBeforeOpen = function(event, ui)
{
var target = event.originalEvent.target;
var context = $("#listview").ojListView("getContextByNode", target);
if (context != null)
{
self.currentItem = $("#"+context['key']);
}
else
{
self.currentItem = null;
}
};
this.handleMenuItemSelect = function(event, ui)
{
var id = ui.item.prop("id");
if (id == "read")
self.handleRead();
else if (id == "more1" || id == "more2")
self.handleMore();
else if (id == "tag")
self.handleFlag();
else if (id == "delete")
self.handleTrash();
};
this.closeToolbar = function(which, item)
{
var toolbarId = "#"+which+"_toolbar_"+item.prop("id");
var drawer = {"displayMode": "push", "selector": toolbarId};
oj.OffcanvasUtils.close(drawer);
};
this.handleAction = function(which, action, event)
{
if (event != null)
{
self.currentItem = $(event.target).closest(".item-marker");
// offcanvas won't be open for default action case
if (action != "default")
self.closeToolbar(which, self.currentItem);
}
if (self.currentItem != null)
self.action("Handle "+action+" action on: "+self.currentItem.prop("id"));
};
this.handleRead = function(data, event)
{
self.handleAction("first", "read", event);
};
this.handleMore = function(data, event)
{
self.handleAction("second", "more", event);
};
this.handleFlag = function(data, event)
{
self.handleAction("second", "Rejected", event);
};
this.handleTrash = function(data, event)
{
self.handleAction("second", "Accepted", event);
self.remove(self.currentItem);
};
this.handleDefaultAction = function(item)
{
self.currentItem = item;
self.handleAction("second", "default");
self.remove(item);
};
this.remove = function(item)
{
// unregister swipe to reveal for removed item
var startOffcanvas = item.find(".oj-offcanvas-start").first();
var endOffcanvas = item.find(".oj-offcanvas-end").first();
oj.SwipeToRevealUtils.tearDownSwipeActions(startOffcanvas);
oj.SwipeToRevealUtils.tearDownSwipeActions(endOffcanvas);
alert(JSON.stringify(self.allItems()));
alert(item.toString());
self.allItems.remove(function(current)
{
return (current.id == item.prop("id"));
});
};
}
return PeopleViewModel;
});
HTML code:
<ul id="listview"
data-bind="ojComponent: {component: 'ojListView',
data: listViewDataSource,
item: {template: 'peoplelist_template'},
selectionMode: 'single',
ready: handleReady,
destroy: handleDestroy,
optionChange: changeHandler,
rootAttributes: {style: 'width:100%;height:100vh;overflow:auto; margin-top: 5px'},
scrollPolicy: 'loadMoreOnScroll',
scrollPolicyOptions: {fetchSize: 10}}">
</ul>
<script id="peoplelist_template">
<div style="padding:0.8571rem">
<div class="oj-flex oj-flex-items-pad">
<div class="oj-flex-item oj-lg-4 oj-md-4">
<img alt="employee image" class="demo-circular demo-employee-photo" style="float:left;" data-bind="attr: {src: $parent.getPhoto($data['name'])}"/>
<h2 class="demo-employee-name" data-bind="text: $data['from']"></h2>
<div class="demo-employee-title" data-bind="text: $data['title']"></div>
<div class="demo-employee-dept" data-bind="text: $data['deptName']"></div>
</div>
<div style="line-height: 1.5em; height: 3em; overflow: hidden; text-overflow: ellipsis" class="oj-text-sm oj-text-secondary-color" data-bind="text: $data['content']"></div>
</div>
</div>
<div tabIndex="-1" data-bind="attr: {id: 'first_toolbar_'+empId}" class="oj-offcanvas-start" style="width:75px">
<div data-bind="click:$parent.handleRead">
<div class="oj-flex-bar" style="height:100%">
<div class="oj-flex-bar-center-absolute">
<div class="oj-flex oj-sm-flex-direction-column">
<div title=".demo-library-icon-24" role="img" class="oj-flex-item demo-library-icon-24 demo-icon-font-24"></div>
<div style="padding-top: 10px" class="oj-flex-item">Read</div>
</div>
</div>
</div>
</div>
</div>
<div tabIndex="-1" data-bind="attr: {id: 'second_toolbar_'+empId}" class="oj-offcanvas-end" style="width:225px">
<div class="oj-swipetoreveal-more" data-bind="click: $parent.handleMore">
<div class="oj-flex-bar" style="height:100%">
<div class="oj-flex-bar-center-absolute">
<div class="oj-flex oj-sm-flex-direction-column">
<div title=".demo-library-icon-24" role="img" class="oj-flex-item fa fa-bars"></div>
<div style="padding-top: 10px" class="oj-flex-item">More</div>
</div>
</div>
</div>
</div>
<div style="background-color:#b81900" data-bind="click: $parent.handleFlag" class="oj-swipetoreveal-flag">
<div class="oj-flex-bar" style="height:100%">
<div class="oj-flex-bar-center-absolute">
<div class="oj-flex oj-sm-flex-direction-column">
<div title=".demo-library-icon-24" role="img" class="oj-flex-item fa fa-times"></div>
<div style="padding-top: 10px" class="oj-flex-item">Reject</div>
</div>
</div>
</div>
</div>
<div style="background-color:#009638" data-bind="click: $parent.handleTrash" class="oj-swipetoreveal-alert oj-swipetoreveal-default">
<div class="oj-flex-bar" style="height:100%">
<div class="oj-flex-bar-center-absolute">
<div class="oj-flex oj-sm-flex-direction-column">
<div title=".demo-library-icon-24" role="img" class="oj-flex-item fa fa-check"></div>
<div style="padding-top: 10px" class="oj-flex-item">Approve</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</li>
</script>
Actual problem is the listItem is not getting removed while approving.(The Approve div is call Handletrash function).
I dont know where I went wrong ??could anyone help me to solve this issue??
There's a lot of code here, which makes it hard to understand what everything is intended to do, and harder to pinpoint what the problem might be. That's why it's best to make a Minimal, Complete, and Verifiable Example. Also, in the process of removing all the code that does not directly affect your problem, you may solve it yourself.
I notice in your code that you have a number of jQuery calls. That's a significant red flag. Your contract with Knockout is that you will manipulate your data model and Knockout will use it to control the DOM. If you "go behind Knockout's back" and manipulate the DOM yourself, you and Knockout are going to be stepping on each other's toes.
Knockout provides two ways for you to customize how it manipulates the DOM: animated transitions and custom bindings. "Swipe to reveal" sounds like a transition to me, but looking at your code, it appears there's a whole lifecycle involved, so I think you need to make a custom binding handler.
All of your DOM-manipulating code should be inside the binding handler, and all of it should be restricted to the element of the binding handler. There should be no document-wide selectors.
I have a header text and a pencil image:
Here is the code snippet:
'use strict';
angular.module('myModule')
.directive('heading', function (messageFormatterUtil, templateHelperService,cartService) {
return {
restrict: 'E',
link: function(scope, elem, attrs)
scope.lineId = cartService.allLines[scope.$parent.$index].id;
scope.headingLineContent = templateHelperService.getComponentData(attrs.data).heading;
var title=scope.headingLineContent.title;
scope.headingLineContent = messageFormatterUtil.formatMessage
(title,[scope.$parent.$index + 1]);
scope.$watch('$parent.$index', function() {
scope.lineId = cartService.allLines[scope.$parent.$index].id;
scope.headingLineContent = messageFormatterUtil.formatMessage
(title,[scope.$parent.$index + 1]);
}, true);
scope.view = {
editableValue: scope.headingLineContent,
editorEnabled: false
};
scope.visible = true;
scope.toggle = function() {
scope.visible = scope.visible ? true : false;
};
scope.Open=function () {
scope.view.editorEnabled = true;
scope.view.editableValue = scope.headingLineContent;
var myEl = angular.element( document.querySelector( '#line'+scope.lineId ) );
myEl.attr('title',"true");
};
scope.disableEditor = function () {
scope.view.editorEnabled = false;
};
scope.save = function () {
scope.headingLineContent = scope.view.editableValue;
};
},
templateUrl: './app-modules/cart/views/heading.html'
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<span ng-hide="visible" ng-show="show" ng-mouseout="!show" class="m-t-lg m-b-sm inline-block ng-binding">
<input type="text" id="from" />
</span>
<h3 class="m-t-lg m-b-sm inline-block " id="line{{lineId}}" ng-show="!show">{{headingLineContent}}</h3>
<i class="fa fa-pencil pencil m-l-sm" ng-click="open()" ng-mousedown="save()"></i>
Q1. How to enable the header text(as text field) when clicking on the pencil image ?
Q2. When click mouse out of the text field it should convert to header text again and the edited value should save in the the session.
You need to add a state of your header text
$scope.editable = false;
Then create an input with ng-show="editable" and ng-model="headingLineContent", then add ng-show="!editable" to your header.
add ng-click callback for a pencil image, and change the editable there. If your need to make a request to save the data, you can also do it there.
You can apply this logic:
In HTML:
<pencil-icon data-ng-click="editHeader()"></pencil-icon>
header text: <input type="text" ng-mouseleave="save()" data-ng-show="editEnable" ng-model="headerText"/>
<span data-ng-show="!editEnable">{{headerText}}</span>
In controller: (Make sure you inject $sessionStorage in your controller)
$scope.headerText = "Sample header text";
$scope.editEnable = false;
$scope.editHeader = function(){
$scope.editEnable = !$scope.editEnable
};
$scope.save = function(){
$sessionStorage.headerText = $scope.headerText;
$scope.editEnable = false;
}
I have been learning how to read other people's code and when ever I see something like this <meganav-item item="item" ng-repeat="item in website.nav.primary"></meganav-item> I get stuck.
I have a basic understand of angular, but the problem is the <meganav> tag. I do not know what this is..I have done a Google search, but nothing useful is showing.
Update
I have managed to locate the file of the <meganav> element. After following the instructions from the links that you guys have provided, it led me to a file named "MegaNavItem.js". Here is the code:
window.tcoStore.directive('meganavItem', ['$timeout','transport', function($timeout,transport) {
var lockTimeout = false;
var meganavLocks = transport.getModel('meganavLocks', {lock : false});
var clear = function (){
if(meganavLocks.timeout){
$timeout.cancel(meganavLocks.timeout);
}
}
var action = function(callback, time) {
if(meganavLocks.lock){
return;
}
clear();
meganavLocks.timeout = $timeout(callback, time);
}
var dropLock = function(callback, time) {
meganavLocks.lock = false;
}
return {
restrict : 'E',
replace: true,
templateUrl : '/page/header/meganav/item.html',
scope : {
item : '=',
clickOnly : '#',
delayIn : '#',
delayOut : '#'
},
link : function($scope, elem, attrs){
if(!$scope.clickOnly){
$scope.delayInValue = parseInt($scope.delayIn || 300,10);
$scope.delayOutValue = parseInt($scope.delayOut || 500,10);
elem.on('mouseenter', $scope.showDelayed);
if($scope.delayOutValue > 0){
elem.on('mouseleave', $scope.hideDelayed);
}
}
},
controller: ['$scope', '$timeout', 'transport', '$location' ,
function($scope, $timeout, transport,$location) {
// When $location changes ...
$scope.$on('$locationChangeSuccess', function() {
$scope.hide(true);
$scope.isActive = !_.isUndefined($scope.item.link) && ($scope.item.link.replace(/\/+$/,'') == $location.path().replace(/\/+$/,''));
});
$scope.loadSubmenu =0;
// tranposrt model accessable by other items
var meganavVisibleModel = transport.getModel('meganavActive');
var meganavVisibleModelId = $scope.item.$$hashKey;
meganavVisibleModel[meganavVisibleModelId] = false;
// hide and show funs
$scope.hide = function(forceFullClose){
clear();
meganavVisibleModel[meganavVisibleModelId] = false;
if(forceFullClose) {
meganavLocks.lock = true;
$timeout.cancel(lockTimeout);
lockTimeout = $timeout(dropLock, 1000);
}
};
$scope.hideDelayed = function (delay) {
action($scope.hide, _.isNumber(delay) ? delay : $scope.delayOutValue);
};
$scope.show = function(){
if(meganavLocks.lock){
return;
}
clear();
$scope.loadSubmenu = 1;
for(var i in meganavVisibleModel){
meganavVisibleModel[i] = (meganavVisibleModelId == i);
}
};
$scope.showDelayed = function (delay) {
action($scope.show, _.isNumber(delay) ? delay : $scope.delayInValue);
};
$scope.$watch(function(){
$scope.visible = meganavVisibleModel[meganavVisibleModelId];
});
// first touch click, second touch go to link
$scope.touch = function($event, path){
if(!$scope.visible) {
//$event.preventDefault();
$scope.show();
}else if(tco.empty(path)) {
$scope.hide();
} else {
if(path.match(/^https?:/)){
window.location.href = path;
}else{
$location.path(path);
}
}
}
}]
}
}]);
And this file led me to another file named item.html. The code :
<li class="header--menu__item my-repeat-animation" ng-class="{ 'is-active': isActive, open : visible && item.groups.length}" off-click="hide()" >
<a ng-if=":: item.groups.length"
ng-class="{active: item.active}"
class="header--menu__item--link has-children"
ng-click="show()"
title="{{::item.name}}">
{{::item.name}}
</a>
<a ng-if=":: !item.groups.length"
class="header--menu__item--link"
href="{{::item.link}}"
title="{{::item.name}}">
{{::item.name}}
</a>
<div class="header-menu-dropdown ng-hide" ng-show="visible" ng-if=":: item.groups.length">
<ul class="header-menu-dropdown__meganavGroup">
<li ng-repeat="meganavGroup in item.groups" class="header--menu-group">
<span class="meganav--group--name">{{::meganavGroup.name}}</span>
<ul class="meganav--group--items">
<li ng-repeat="groupItem in meganavGroup.items">
{{::groupItem.name}}
<span class="icon"></span>
</li>
</ul>
</li>
<li class="header-menu-offers" ng-repeat="offer in item.offers">
<a href="{{::offer.offer_link}}" class="placeholder">
<img tco-image="offer.offer_image" crop="3" alt="{{::offer.offer_name}}" />
</a>
<span class="offer-name">{{::offer.offer_name}}</span>
</li>
</ul>
<div class="header-menu-message" ng-bind-html="item.message"></div>
</div>
</li>
My issue is now that I cannot make out what where to find {{::item.name}}, which is the thing that I want to change. What technique can I use to find {{::item.name}}?
Sorry for all the noob questions! Your help is much appreciated!
In Angular it is possible to build your own HTML element. You won't find any information about this element because it doesn't exist. The developer has created that on its own and handles the content inside a module. Have a look at http://www.aleaiactaest.ch/2012/07/29/build-your-own-html-element-with-angular/ for more information.
Hope this helps, Cheers.
As i've noticed it's Angular App, so probably there are defined an directive which is called meganavItem. See Angular Directive for more information, you have to find definition of that directive and discover what is html layout and logic lives under <meganav-item>. However if there are no directive with defined name.
Also it may be separate registered element, see "Custom Elements
"article of how it's done and it would be more easy for you to find out how it works ( if it registered in that way...)