I am using a Select class I have found on Internet, the problem is that if i create the option in the Select dinnamically, using angluar ng-repeat, the option will not be clickable, but if i create it manually, also using dynamic values, it can be clicked.
This is the code :
MainFile :
...
<div id="SiteList" ng-controller="SiteController as siteCtrl" ng-if="masterCtrl.isUserLogged()" ng-include="'Select2/index.html'" ng-init="siteCtrl.getSites()" >
...
This is Select2/index.html
...
<body>
<div class="drop">
<div class="option active placeholder" data-value="placeholder">
Seleziona un sito
</div>
<div class="option" ng-repeat="sito in siteCtrl.siti" data-value="{{sito.name}}">{{sito.name}}</div>
</div>
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<script src="Select2/js/index.js"></script>
</body>
...
Then the Select2/js/index.js
$(document).ready(function() {
$(".drop .option").click(function() {
var val = $(this).attr("data-value"),
$drop = $(".drop"),
prevActive = $(".drop .option.active").attr("data-value"),
options = $(".drop .option").length;
$drop.find(".option.active").addClass("mini-hack");
$drop.toggleClass("visible");
$drop.removeClass("withBG");
$(this).css("top");
$drop.toggleClass("opacity");
$(".mini-hack").removeClass("mini-hack");
if ($drop.hasClass("visible")) {
setTimeout(function() {
$drop.addClass("withBG");
}, 400 + options*100);
}
triggerAnimation();
if (val !== "placeholder" || prevActive === "placeholder") {
$(".drop .option").removeClass("active");
$(this).addClass("active");
};
});
function triggerAnimation() {
var finalWidth = $(".drop").hasClass("visible") ? 22 : 20;
$(".drop").css("width", "24em");
setTimeout(function() {
$(".drop").css("width", finalWidth + "em");
}, 400);
}
});
Anyone has any idea about how to resolve this?
Avoid mixing Angular.js and jQuery.
Instead you can use Angular version of Select2:
https://github.com/angular-ui/ui-select
Related
I am supposed to build a store for a a javascript assignment. The store has three items and a counter which tallies the total of the items. Each item is updated through a click event which changes the value based on a data attribute defined in the html. It then saves this to cookies and allows us to use what was stored when we get to a checkout page. The cookies store and the totals update, but unfortunately, each time the click event occurs, the image disappears. I have been scouring the code and I cannot see why this is happening. Can anyone help?
$(document).ready(function() {
$("#jeans-line").text(Cookies.get("jeans") || 0)
$("#jeanJacket-line").text(Cookies.get("jeanJacket") || 0)
$("#belt-line").text(Cookies.get("belt") || 0)
$("#total").text(Cookies.get("total") || 0)
//The DOM will be changed to the key value of each cookie or 0
$('.item').click(function() {
itemTotal = parseInt($(this).text())
oneMore = itemTotal + ($(this).data('cost'))
$(this).text(oneMore)
Cookies.set($(this).data('name'), oneMore)
setTotal()
});
// //updating the total cost of the pseudo-items in shopping
function setTotal() {
var jeans = parseInt(Cookies.get("jeans"))
var jeanJacket = parseInt(Cookies.get("jeanJacket"))
var belt = parseInt(Cookies.get("belt"))
Cookies.set("total", (jeans + jeanJacket + belt) || 0)
$("#total").text(Cookies.get("total") || 0)
};
//Enter data and close the modal
var modal = $("#modal-box")
var email_input;
$(".email-submit").click(function(e) {
e.preventDefault();
email_input = $("#email-val").val()
console.log(email_input)
var checkEmail = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (checkEmail.test(email_input)) {
alert("This is a good email!")
Cookies.set("email", email_input)
modal.css("display", "none")
} else {
alert("This is not a valid email address!")
}
});
//closes the model with close click event
$(".close").click(function() {
modal.css("display", "none");
});
}) //closes document.ready
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
<div class="col-md-4">
<div class="item" data-cost="200" data-name="jeans">
<img id="jeansIMG" src="images/jeans.jpg">
<h2 class="item" id="jeans-line"></h2>
</div>
</div>
<div class="col-md-4">
<div class="item" data-cost="300" data-name="jeanJacket">
<img id="jeanJacketIMG" src="images/jean_jacket.jpg">
<h2 class="item" id="jeanJacket-line"></h2>
</div>
</div>
<div class="col-md-4">
<div class="item" data-cost="50" data-name="belt">
<img id="beltIMG" src="images/belt.jpg">
<h2 class="item" id="belt-line"></h2>
</div>
</div>
</div>
<!-- closes the bootstrap row -->
<div class="row">
<div class="col-md-4">
</div>
<div class="col-md-4">
<img class="shoppingCart" src="images/shopping_cart.jpg">
<h2 class="totalTitle">The total for these pseudo-products is:</h2>
<h2 id="total"></h2>
</div>
<div class="col-md-4">
</div>
</div>
The reason why images are getting remove is because of this code:
$('.item').click(function () {
itemTotal = parseInt($(this).text())
oneMore = itemTotal + ($(this).data('cost'))
$(this).text(oneMore) // <-- this overrides everything inside div.item
Cookies.set($(this).data('name'), oneMore)
setTotal()
});
Seeing your overall code, I'd suggest to change inner item class to something else (eg. item-total) so it won't be conflicting with the outer item class. After that adjust the javascript code:
$('.item').click(function() {
itemTotal = parseInt($(this).text())
oneMore = itemTotal + ($(this).data('cost'))
$('.item-total', this).text(oneMore) // <!-- change text in item-total
Cookies.set($(this).data('name'), oneMore)
setTotal()
});
You may also want to modify the setTotal to add default value || 0 so that it will calculate the total properly even if there is one or more items left unclicked:
function setTotal() {
var jeans = parseInt(Cookies.get("jeans") || 0)
var jeanJacket = parseInt(Cookies.get("jeanJacket") || 0)
var belt = parseInt(Cookies.get("belt") || 0)
Cookies.set("total", (jeans + jeanJacket + belt) || 0)
$("#total").text(Cookies.get("total") || 0)
};
You can check the simplified demo in https://jsfiddle.net/nm5dL9h1/
<div ng-repeat="widget in widgets"
ng-class="">
<div>{{widget.row}}</div>
</div>
I'm trying to apply a class inside the repeat based on a particular value in the repeat, for example if widget.row = 0 and it is the first widget with that value displayed then give it a class and all the other widgets that have row as 0 do not get the class. This will need to be the case if it equals 1 or 2 and so on so I can't just use $first as there will be multiple row values and multiple widgets for example it may output something like:
0 0 0 0 1 1 2 2 2 2
So the easiest way for me to achieve this was using the Adjacent sibling selector rather than do it with angular as each item is not really aware of the others:
<div ng-repeat="widget in widgets"
class="widget-row-{{widget.row}}">
<div>{{widget}}</div>
</div>
and then use CSS for:
.widget-row-0:first-child {}
.widget-row-0 + .widget-row-1 {}
.widget-row-1 + .widget-row-2 {}
.widget-row-2 + .widget-row-3 {}
Best practise is to prepare your data in a init function in your controller. It's nice and KISS! It's the best way to prepare your data in control function instead of misapply the E2E binding of AngularJS. It solve your problem so no class is written when there is no need for (as you asked for). Its proceeded once instead of calling a function again, again and again by E2E binding like ng-class="shouldIAddAClass()".
View
<div ng-repeat="widget in widgets"
ng-class="{ 'first' : widget.first }">
<div>{{widget.row}}</div>
</div>
Controller
$scope.widgets = [{
row: 0
}, {
row: 2
},{
row: 0
},{
row: 1
},{
row: 1
},{
row: 2
},{
row: 0
}];
//self calling init function
(function init () {
var widgetRowFound = {};
angular.forEach($scope.widgets, function (widget, key) {
if (angular.isDefined(widgetRowFound[widget.row])) {
$scope.widgets[key].first = false;
} else {
$scope.widgets[key].first = true;
widgetRowFound[widget.row] = true;
}
});
})();
Not the cleanest one but will work
<div ng-repeat="widget in widgets">
<div ng-class="{'myClass': applyClass(0, widget.row)}"></div>
</div>
----------
$scope.widgetsRows = {};
function applyClass(number, row){
if(!$scope.widgetsRows[row]){
$scope.widgetsRows[row] = true
}
return row == number && $scope.widgetsRows[row];
}
You can add the class you want to use to the widget objects in the controller first:
var tempRow = "";
for(var i = 0;i < $scope.widgets.length;i++) {
if($scope.widgets[i].row != tempRow) {
$scope.widgets[i].class = "myClass";
tempRow = $scope.widgets[i].row;
}
}
Then you can use that class:
<div id="widgets" ng-repeat="widget in widgets"
class="{{widget.class}}">
<div>{{widget.row}}</div>
</div>
Hope this helps
You can create a method that will be called from ng-class to achieve your goal. The method should return the class to be used.
$scope.firstHitFound = false;
$scope.isFirstZeroValue = function(value){
if($scope.firstHitFound == false && value == 0){
$scope.firstHitFound = true;
return class1;
}else{
return class2;
}
}
The HTML / Angular shoudl look as:
<div ng-class="isFirstZeroValue(widget.row)">
If you want to style it, add the class to all the widget that match your criteria, and use css to perform it only on the first of them.
Html:
<div id="widgets" ng-repeat="widget in widgets"
ng-class="{'widget-first': widget.row == 0}">
<div>{{widget.row}}</div>
</div>
Css:
#widgets.widget-first:first-of-type {
background: #ff0000;
}
You can use ng-class in addition of your ng-repeat:
Example
<div ng-repeat="widget in widgets" ng-class="{'test': widget.value === 0}">
<div>{{widget.row}}</div>
</div>
You need to call a method that will check if the row result is not same with previous value. If it not same , it will return true value and will be assigned ng-class, and if not return false. Filter this out using ng-if.
Html
<div ng-repeat="widget in widgets"
ng-class="">
<div ng-if="calculate(widget.row)">
<div ng-class="test">{{widget.row}}</div>
</div>
<div ng-if="!calculate(widget.row)">
<div>{{widget.row}}</div>
</div>
</div>
Controller
var arr = [];
$scope.calculate = function (row) {
arr.push(row);
var breakLoop = false;
angular.forEach(arr, function (oldVal, newVal) {
breakLoop = false;
if (oldVal != newVal) {
breakLoop = true;
}
)};
return breakLoop;
}
It might be over kill but this works. I copied the first variable in its entirety and and gave it a new name. Also, delinked it from call_files/header.html and css/header.css files. Instead, I linked it to the layout.css which governs the appearance of the second menu. I'm sure there is a way to stream line it.
<script type="text/javascript">
$().ready(function () {
var stickyPanelOptions = {
topPadding: 0,
afterDetachCSSClass: "BoxGlow_Grey2",
savePanelSpace: true,
onDetached: function (detachedPanel, spacerPanel) {
call_files/header.html(call_files/header.html() + " has been detached!");
css/header.css("background-color", "#1000ff");
},
onReAttached: function (detachedPanel) {
call_files/header.html(call_files/header.html().replace(" has been detached!", ""));
},
parentSelector: null
};
var secondstickyPanelOptions = {
topPadding: 150,
savePanelSpace: true,
onDetached: function (detachedPanel, spacerPanel) {
detachedPanel.html(detachedPanel.html() + " has been detached!");
layout.css("background-color", "#ffffff");
},
onReAttached: function (detachedPanel) {
detachedPanel.html(detachedPanel.html().replace(" has been detached!", ""));
},
parentSelector: null
};
// multiple panel example (you could also use the class ".stickypanel" to select both)
$("#Panel1").stickyPanel(stickyPanelOptions);
$("#Panel2").stickyPanel(secondstickyPanelOptions);
$("#Panel3").stickyPanel(stickyPanelOptions);
$("#UnstickPanel3").click(function () {
$("#Panel3").stickyPanel("unstick");
});
stickyPanelOptions.parentSelector = "#AbsoluteDiv";
$("#Panel4").stickyPanel(stickyPanelOptions);
stickyPanelOptions.parentSelector = "#NormalDiv";
$("#Panel5").stickyPanel(stickyPanelOptions);
});
</script>
HTML
<div id="Panel1" class="stickyPanel">
<div class="headerBGdiv"> </div>
<?php include('../call_files/pagesheader.html');?>
</div>
<div id="Panel2" class="stickyPanel">
<div id="navbar2">
<ul id="tabs">
<li>Buyer's Guide</li>
<li>Export Restrictions</li>
<li>Infrared 101</li>
<li>White Pages</li>
<li>Terminology</li>
<li>Newsroom</li>
<li>Gallery</li>
</ul>
</div>
</div>
Try This it uses separate config options for each panel.
<script type="text/javascript">
$().ready(function () {
var stickyPanelOptions = {
topPadding: 0,
savePanelSpace: true,
onDetached: function (detachedPanel, spacerPanel) {
call_files/header.html(call_files/header.html() + " has been detached!");
css/header.css("background-color", "#1000ff");
},
secondStickyPanelOptions = stickyPanelOptions,
onReAttached: function (detachedPanel) {
call_files/header.html(call_files/header.html().replace(" has been detached!", ""));
},
parentSelector: null
};
secondStickyPanelOptions.topPadding = 100;
// multiple panel example (you could also use the class ".stickypanel" to select both)
$("#Panel1").stickyPanel(stickyPanelOptions);
$("#Panel2").stickyPanel(secondStickyPanelOptions);
$("#Panel3").stickyPanel(stickyPanelOptions);
$("#UnstickPanel3").click(function () {
$("#Panel3").stickyPanel("unstick");
});
stickyPanelOptions.parentSelector = "#AbsoluteDiv";
$("#Panel4").stickyPanel(stickyPanelOptions);
stickyPanelOptions.parentSelector = "#NormalDiv";
$("#Panel5").stickyPanel(stickyPanelOptions);
});
</script>
I am trying to make a page where the user selects an item in a drop-down list, which then will create a duplicate drop-down list. The last drop-down list always needs to create a new one once an item is selected.
Using the following javascript code
<script type="text/javascript">
$(document).ready(function () {
$(function listselect() {
if (x == null) {
var x = 1;
}
//need to increment x after the completion of the following funciton so the function will trigger on different drop-down lists
$('#FooId' + x).change(function q() {
$('#FooId' + x).clone().attr('id', 'FooId' + (++x)).attr('name', 'Selected').insertAfter('#FooId' + (x - 1))
//return x;
});
//return x;
});
});
</script>
and the razor html
<div class ="container">
<div class="label">
#Html.LabelFor(Function(model) model.Foo, "Foo")
</div>
<div class="foo" id="foo">
#Html.DropDownList("FooId", Nothing, "--Select--", New With {.Name = "Selected", .Id = "FooId" & "1"})
//#*#Html.ValidationMessageFor(Function(model) model.Foo)*#
</div>
</div>
I am able to make the first list clone itself, but how do you return x from function q so that it can be used by its own function (Function q needs to trigger when an item is selected in Foo1, then Foo2, etc.).
(Sorry if this doesn't make sense, I am not sure how to word it. I am very new to coding). Thanks.
If I got you right, you don't need most of your code. And it's easier to use classes here. Just do it like this:
$(document).ready(function () {
$('.foo').on('change', function(e) {
var newFoo = $(e.target).clone();
$(e.target).after(newFoo);
});
});
And your markup part should be like this:
<div class ="container">
<div class="label">
#Html.LabelFor(Function(model) model.Foo, "Foo")
</div>
<div class="foo" id="foo">
#Html.DropDownList("FooId", Nothing, "--Select--", new {name = "Selected", #class = "foo" })
</div>
</div>
I don't remember Html.DropDownList signature so I created simple jsfiddle without it. I hope this is what you needed.
UPDATE:
I've corrected my fiddle as follows:
$(document).on('change', '.foo:last', function(e) {
var newFoo = $(e.target).clone();
$(e.target).after(newFoo);
});
Now it doesn't add extra selects if it's not the last select that was changed.
I have code like :
<div id="content">
<div id="widget1"></div>
<div id="widget89"></div>
<div id="widget78"></div>
..............
<div id="widget(anyIndex)"></div>
</div>
By adding content into widget (HTML/JS widget) I have :
<div id="content"
<div id="widget1">
<script type='text/javascript'>
jQuery("#widget1").selectme({
Numpost:4,
Stylepost:"papa",
});
</script>
</div>
<div id="widget89">
<script type='text/javascript'>
jQuery("#widget89").selectme({
Numpost:7,
Stylepost:"popo",
});
</script>
</div>
..............
<div id="widget(anyIndex)">.....</div>
</div>
It is so manual and time-consuming.
Now, I want use short code instead of repeating too much Javascript in each div like :
<div id="content"
<div id="widget1">[4][papa]</div>
<div id="widget89">[7][popo]</div>
..............
<div id="widget(anyIndex)">...</div>
</div>
JS :
<script>
(function (a) {
a.selectme = function (c, b) {
var d = this;
d.init = function () {
d.options = a.extend({}, a.selectme.defaultOptions, b);
...................something
};
d.init()
};
a.selectme.defaultOptions = {
Numpost:4,
Stylepost:"Enter your style",
};
a.fn.selectme = function (b) {
return this.each(function () {
(new a.selectme(this, b))
})
}
})(jQuery);
</script>
Notice :Widget(anyindex) is catch automatically. For example: widget89 is set current but I don't know the index of that widget (index = 89), just sure that I am inputting Javascript/Jquery code into it. When I add new widget I will have new index, for example : widget105 or also widget200 (anyindex)
How can I do that. Thanks for your help.
Here's a way using data attributes in markup and a simple each loop to initialize. Add data- attributes for the variables you need to specify in plugin.
<div id="widget89" data-numpost="7" data-style="popo">
alert( $('#widget89').data('numpost') );
To get index of widgets create a collection of them first to use to index against:
Using $.each to intialize the whole collection will give you the index of widget in collection ( I'm not clear what you need it for):
$('[id^=widget]').each(function(idx){
var $this=$(this), data=$this.data, INDEX=idx;
$this.selectme({
Numpost:data.numpost,
Stylepost:data.style
})
})
you can use a function
function setwidget(id,post,style)
{
jQuery("#"+id).selectme({
Numpost:post,
Stylepost:style
});
}
now call like
setwidget("widget1",4,"papa");
setwidget("widget89",7,"popo");