Collecting input data and showing it in div - javascript

I have some quantity inputs. I want to collect the data in "inputs" and show them in "#yolcudropdown". But I just can't pull the data. Inputs must be disabled. There should be no manual entry. I did something at the bottom of the "javascript" section. But I couldn't run it.
(function( $ ) {
$.fn.number = function(customOptions) {
var options = {
'containerClass' : 'number-style',
'minus' : 'number-minus',
'plus' : 'number-plus',
'containerTag' : 'div',
'btnTag' : 'span'
};
options = $.extend(true, options, customOptions);
var input = this;
input.wrap('<' + options.containerTag + ' class="' + options.containerClass + '">');
var wrapper = input.parent();
wrapper.prepend('<' + options.btnTag + ' class="' + options.minus + '"></' + options.btnTag + '>');
var minus = wrapper.find('.' + options.minus);
wrapper.append('<' + options.btnTag + ' class="' + options.plus + '"></' + options.btnTag + '>');
var plus = wrapper.find('.' + options.plus);
var min = input.attr('min');
var max = input.attr('max');
if(input.attr('step')){
var step = +input.attr('step');
} else {
var step = 1;
}
if(+input.val() <= +min){
minus.addClass('disabled');
}
if(+input.val() >= +max){
plus.addClass('disabled');
}
minus.click(function () {
var input = $(this).parent().find('input');
var value = input.val();
if(+value > +min){
input.val(+value - step);
if(+input.val() === +min){
input.prev('.' + options.minus).addClass('disabled');
}
if(input.next('.' + options.plus).hasClass('disabled')){
input.next('.' + options.plus).removeClass('disabled')
}
} else if(!min){
input.val(+value - step);
}
});
plus.click(function () {
var input = $(this).parent().find('input');
var value = input.val();
if(+value < +max){
input.val(+value + step);
if(+input.val() === +max){
input.next('.' + options.plus).addClass('disabled');
}
if(input.prev('.' + options.minus).hasClass('disabled')){
input.prev('.' + options.minus).removeClass('disabled')
}
} else if(!max){
input.val(+value + step);
}
});
};
})(jQuery);
$('.quntity-input').each(function () {
$(this).number();
});
/* THIS IS IMPORTANT */
$(document).ready(function() {
$(document).on('change', '.btw', function() {
$('#yolcudropdown').text($(this).val());
});
});
.number-style {
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-ms-flex-pack: start !important;
justify-content: flex-start !important;
-ms-flex-align: center !important;
align-items: center !important;
}
.number-style .number-minus,
.number-style .number-plus {
height: 28px;
background: #ffffff;
border: 2px solid #e2e2e2 !important;
width: 28px;
-webkit-border-radius: 100%;
-moz-border-radius: 100%;
-ms-border-radius: 100%;
border-radius: 100%;
line-height: 23px;
font-size: 19px;
font-weight: 700;
text-align: Center;
border: none;
display: block;
cursor: pointer;
}
.number-style .number-minus:active,
.number-style .number-plus:active {
background: #e2e2e2;
}
.number-style .number-minus {
line-height: 20px;
}
.number-style .number-minus::after {
content: "-";
font-size: 10px;
}
.number-style .number-plus {
line-height: 18px;
}
.number-style .number-plus::after {
content: "+";
font-size: 10px;
}
.number-style .quntity-input {
width: 28px;
background: #e00f23;
-webkit-border-radius: 100%;
-moz-border-radius: 100%;
-ms-border-radius: 100%;
border-radius: 100%;
line-height: 21px;
font-size: 14px;
color: #ffffff;
font-weight: 700;
text-align: Center;
margin: 0 5px;
display: block;
cursor: pointer;
text-align: center;
border: none;
height: 28px;
font-weight: 600;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="quntity-input btw" type="text" value="0" step="1" min="0" max="10">
<input class="quntity-input btw" type="text" value="0" step="1" min="0" max="10">
<div id="yolcudropdown">İnput quantity show this div</div>
"class" names of "input" elements are the same. I need to collect inputs with the same value and display them in the div instantly

HTMLInputElement
Input type "text" has no min max or step attributes, so your HTML is absolutely invalid. Try not to write It-works, I'm a framework -code. Respect the W3C standards.
Use type="number" (CSS pseudos can help you remove default spinner arrows from such elements)
Also step could be floats. Respect that and use parseFloat() in JS
CSS Flex to align stuff
Seems you know about CSS-flex, use it! Height, therefore- line-height... 19? 20? 23px? No. Just use flex.
CSS !important
!important is sign of poor coding style and should be left to Bootstrap only. Or to hopefully override Bootstrap styles - or in that cases when developers actually know what they are doing.
jQuery Plugins
jQuery plugins, I suggest to read the DOCS and get a deeper knowledge on how plugins work. Almost every jQuery method is a plugin. .hide() , .addClass()... I won't count them all. Plugins are chainable .removeClass("foo").stop().fadeTo(1), and so should be your .number() plugin.
To achieve chain-ability you simply return the bound this. PS: that's not jQuery... that's how JS works.
jQuery Plugins are not meant to be called inside a $.each() loop. $() is already a collection of DOM Nodes wrapped in a jQuery Object. No need to .each(). Same like: you would rather use $('a').css({color:'blue'}) instead of $('a').each(){ $(this).css({color: 'blue'}); });. Same effect, less code. Plugins.
jQuery DOM ready
jQuery(function($) { }); // DOM ready and $ alias in scope
Or if you don't care about ±IE, or you use ES6 syntax and a toolchain like Babel than: jQuery($ => { }) will suffice.
jQuery $ Object Constructor
jQuery allows you to define an HTMLElement that will eventually become a new DOM element wrapped with all the jQuery powers, Methods. Meaning that, if instead of passing a selector, you pass a more complex Tag-alike string (say: $("<span/>", {}); - jQuery will create an inMemory SPAN element and allow you to use the second parameter {} for most of the available jQuery Methods for that $Element. Let's use this!
jQuery plugin callbacks
If you want to provide a callback after a user changes the input value, provide a callback method. Don't force a programmer to write new spaghetti code, stick to the scope of your available Plugin internal Methods.
Sum Elements values
To sum Elements values you can use Array.prototype.reduce, just make sure to use an initialValue to prevent possible TypeErrors.
Example
Finally, here's the simplified CSS and improved JS:
(function($) {
$.fn.number = function(customOptions) {
const options = $.extend(true, {
containerTag: "div",
containerClass: "number-style",
minusClass: "number-minus", // consistency in wording!
minusText: "-", // Give power to the user!
plusClass: "number-plus",
plusText: "+",
btnTag: "button",
onChange() {}, // Provide a nifty callback!
}, customOptions);
this.each(function() { // Use .each() here!
const $input = $(this);
let val = parseFloat($input.value || 0); // floats!
const min = parseFloat($input.attr("min"));
const max = parseFloat($input.attr("max"));
const step = parseFloat($input.is("[step]") ? $input.attr("step") : 1);
const handleStyles = () => {
$minus.toggleClass('disabled', val <= min);
$plus.toggleClass('disabled', val >= max);
};
const change = () => {
val = Math.max(min, Math.min(max, val)); // Keep val in range.
$input.val(val); // Update input value
handleStyles(); // Update styles
options.onChange.call($input[0], val); // Trigger a public callback
}
const decrement = () => {
val -= step;
change();
};
const increment = () => {
val += step;
change();
};
const $minus = $(`<${options.btnTag}>`, {
type: "button",
title: "Decrement",
class: options.minusClass,
text: options.minusText,
on: {
click: decrement
}
});
const $plus = $(`<${options.btnTag}>`, {
class: options.plusClass,
title: "Increment",
text: options.plusText,
on: {
click: increment
}
});
const $wrapper = $(`<${options.containerTag}>`, {
class: options.containerClass,
});
$input.after($wrapper);
$wrapper.append($minus, $input.detach(), $plus); // Append all
handleStyles(); // handle initial styles
});
return this; // make your plugin chainable!
};
})(jQuery);
jQuery(function($) { // DOM ready and $ alias in scope
const $quantityInp = $('.quantity-input'); // Cache your elements!
const $dropdown = $('#yolcudropdown'); // Cache your elements!
$quantityInp.number({
onChange(val) { // our custom onChange callback!
const tot = $quantityInp.get().reduce((acc, el) => {
acc += parseFloat(el.value);
return acc;
}, 0);
$dropdown.text(tot);
}
});
});
/* QuickReset */ * { margin:0; box-sizing:border-box; }
.number-style input::-webkit-outer-spin-button,
.number-style input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
.number-style {
display: flex;
}
.number-style > * {
height: 2em;
min-width: 2em;
border-radius: 2em;
display: flex; /* Use flex. */
justify-content: center;
text-align: center;
border: 0;
background: #ddd;
}
.number-style button {
background: #fff;
box-shadow: inset 0 0 0 2px #ccc;
cursor: pointer;
user-select: none;
/* no highlight, please! */
}
.number-style button:active {
background: #0bf;
}
.number-style input {
background: #e00f23;
color: #fff;
margin: 0 5px;
}
.number-style .disabled {
opacity: 0.2;
cursor: default;
}
/* Custom overrides: */
.number-style>* {
width: 2em;
/* just for roundness */
}
<input class="quantity-input" type="number" value="0" step="1" min="0" max="10">
<input class="quantity-input" type="number" value="0" step="1" min="0" max="10">
<div id="yolcudropdown">0</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
Additional reading:
HTMLInputElement
Math/min
Math/max
jQuery plugin-creation
$ new-elements
Array/reduce
jQuery.toggleClass()
And PS: it's "quantity", not "quntity"

Related

onmouseover not working in option [duplicate]

I am trying to show a description when hovering over an option in a select list, however, I am having trouble getting the code to recognize when hovering.
Relevant code:
Select chunk of form:
<select name="optionList" id="optionList" onclick="rankFeatures(false)" size="5"></select>
<select name="ranks" id="ranks" size="5"></select>
Manipulating selects (arrays defined earlier):
function rankFeatures(create) {
var $optionList = $("#optionList");
var $ranks = $("#ranks");
if(create == true) {
for(i=0; i<5; i++){
$optionList.append(features[i]);
};
}
else {
var index = $optionList.val();
$('#optionList option:selected').remove();
$ranks.append(features[index]);
};
}
This all works. It all falls apart when I try to deal with hovering over options:
$(document).ready(
function (event) {
$('select').hover(function(e) {
var $target = $(e.target);
if($target.is('option')) {
alert('yeah!');
};
})
})
I found that code while searching through Stack Exchange, yet I am having no luck getting it to work. The alert occurs when I click on an option. If I don't move the mouse and close the alert by hitting enter, it goes away. If I close out with the mouse a second alert window pops up. Just moving the mouse around the select occasionally results in an alert box popping up.
I have tried targeting the options directly, but have had little success with that. How do I get the alert to pop up if I hover over an option?
You can use the mouseenter event.
And you do not have to use all this code to check if the element is an option.
Just use the .on() syntax to delegate to the select element.
$(document).ready(function(event) {
$('select').on('mouseenter','option',function(e) {
alert('yeah');
// this refers to the option so you can do this.value if you need..
});
});
Demo at http://jsfiddle.net/AjfE8/
try with mouseover. Its working for me. Hover also working only when the focus comes out from the optionlist(like mouseout).
function (event) {
$('select').mouseover(function(e) {
var $target = $(e.target);
if($target.is('option')) {
alert('yeah!');
};
})
})
You don't need to rap in in a function, I could never get it to work this way. When taking it out works perfect. Also used mouseover because hover is ran when leaving the target.
$('option').mouseover(function(e) {
var $target = $(e.target);
if($target.is('option')) {
console.log('yeah!');
};
})​
Fiddle to see it working. Changed it to console so you don't get spammed with alerts. http://jsfiddle.net/HMDqb/
That you want is to detect hover event on option element, not on select:
$(document).ready(
function (event) {
$('#optionList option').hover(function(e) {
console.log(e.target);
});
})​
I have the same issue, but none of the solutions are working.
$("select").on('mouseenter','option',function(e) {
$("#show-me").show();
});
$("select").on('mouseleave','option',function(e) {
$("#show-me").hide();
});
$("option").mouseover(function(e) {
var $target = $(e.target);
if($target.is('option')) {
alert('yeah!');
};
});
Here my jsfiddle https://jsfiddle.net/ajg99wsm/
I would recommend to go for a customized variant if you like to ease
capture hover events
change hover color
same behavior for "drop down" and "all items" view
plus you can have
resizeable list
individual switching between single selection and multiple selection mode
more individual css-ing
multiple lines for option items
Just have a look to the sample attached.
$(document).ready(function() {
$('.custopt').addClass('liunsel');
$(".custopt, .custcont").on("mouseover", function(e) {
if ($(this).attr("id") == "crnk") {
$("#ranks").css("display", "block")
} else {
$(this).addClass("lihover");
}
})
$(".custopt, .custcont").on("mouseout", function(e) {
if ($(this).attr("id") == "crnk") {
$("#ranks").css("display", "none")
} else {
$(this).removeClass("lihover");
}
})
$(".custopt").on("click", function(e) {
$(".custopt").removeClass("lihover");
if ($("#btsm").val() == "ssm") {
//single select mode
$(".custopt").removeClass("lisel");
$(".custopt").addClass("liunsel");
$(this).removeClass("liunsel");
$(this).addClass("lisel");
} else if ($("#btsm").val() == "msm") {
//multiple select mode
if ($(this).is(".lisel")) {
$(this).addClass("liunsel");
$(this).removeClass("lisel");
} else {
$(this).addClass("lisel");
$(this).removeClass("liunsel");
}
}
updCustHead();
});
$(".custbtn").on("click", function() {
if ($(this).val() == "ssm") {
$(this).val("msm");
$(this).text("switch to single-select mode")
} else {
$(this).val("ssm");
$(this).text("switch to multi-select mode")
$(".custopt").removeClass("lisel");
$(".custopt").addClass("liunsel");
}
updCustHead();
});
function updCustHead() {
if ($("#btsm").val() == "ssm") {
if ($(".lisel").length <= 0) {
$("#hrnk").text("current selected option");
} else {
$("#hrnk").text($(".lisel").text());
}
} else {
var numopt = +$(".lisel").length,
allopt = $(".custopt").length;
$("#hrnk").text(numopt + " of " + allopt + " selected option" + (allopt > 1 || numopt === 0 ? 's' : ''));
}
}
});
body {
text-align: center;
}
.lisel {
background-color: yellow;
}
.liunsel {
background-color: lightgray;
}
.lihover {
background-color: coral;
}
.custopt {
margin: .2em 0 .2em 0;
padding: .1em .3em .1em .3em;
text-align: left;
font-size: .7em;
border-radius: .4em;
}
.custlist,
.custhead {
width: 100%;
text-align: left;
padding: .1em;
border: LightSeaGreen solid .2em;
border-radius: .4em;
height: 4em;
overflow-y: auto;
resize: vertical;
user-select: none;
}
.custlist {
display: none;
cursor: pointer;
}
.custhead {
resize: none;
height: 2.2em;
font-size: .7em;
padding: .1em .4em .1em .4em;
margin-bottom: -.2em;
width: 95%;
}
.custcont {
width: 7em;
padding: .5em 1em .6em .5em;
/* border: blue solid .2em; */
margin: 1em auto 1em auto;
}
.custbtn {
font-size: .7em;
width: 105%;
}
h3 {
margin: 1em 0 .5em .3em;
font-weight: bold;
font-size: 1em;
}
ul {
margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3>
customized selectable, hoverable resizeable dropdown with multi-line, single-selection and multiple-selection support
</h3>
<div id="crnk" class="custcont">
<div>
<button id="btsm" class="custbtn" value="ssm">switch to multi-select mode</button>
</div>
<div id="hrnk" class="custhead">
current selected option
</div>
<ul id="ranks" class="custlist">
<li class="custopt">option one</li>
<li class="custopt">option two</li>
<li class="custopt">another third long option</li>
<li class="custopt">another fourth long option</li>
</ul>
</div>

AppendTo but each new append is unique but still uses the same jquery

I'm wondering if it's possible to on each appendTo make the new div unique but still use the same jquery.
As you can see in the mark-up below, each new div shares the same jquery so doesn't work independently.
Within my Javascript i'm selecting the ID to fire each function.
I've tried just adding + 1 etc to the end of each ID, but with that it changes the name of the ID making the new created DIV not function.
I've thought of using DataAttribues, but i'd still have the same issue having to create multiple functions all doing the same job.
Any ideas?
Thanks
$(function() {
var test = $('#p_test');
var i = $('#p_test .upl_drop').length + 1;
$('#addtest').on('click', function() {
$('<div class="file-input"><div class="input-file-container upl_drop"><label for="p_test" class="input-file-trigger">Select a file...<input type="file" id="p_test" name="p_test_' + i + '" value=""class="input-file"></label></div><span class="remtest">Remove</span><p class="file-return"></p></div>').appendTo(test);
i++;
});
$('body').on('click', '.remtest', function(e) {
if (i > 2) {
$(this).closest('.file-input').remove();
i--;
}
});
});
var input = document.getElementById( 'file-upload' );
var infoArea = document.getElementById( 'file-upload-filename' );
input.addEventListener( 'change', showFileName );
function showFileName( event ) {
// the change event gives us the input it occurred in
var input = event.srcElement;
// the input has an array of files in the `files` property, each one has a name that you can use. We're just using the name here.
var fileName = input.files[0].name;
// use fileName however fits your app best, i.e. add it into a div
textContent = 'File name: ' + fileName;
$("#input-file-trigger").text(function () {
return $(this).text().replace("Select a file...", textContent);
});
}
/*
#### Drag & Drop Box ####
*/
.p_test{
display: inline-block;
}
.upl_drop{
border: 2px dashed #000;
margin: 0px 0px 15px 0px;
}
.btn--add p{
cursor: pointer;
}
.input-file-container {
position: relative;
width: auto;
}
.input-file-trigger {
display: block;
padding: 14px 45px;
background: #ffffff;
color: #1899cd;
font-size: 1em;
cursor: pointer;
}
.input-file {
position: absolute;
top: 0; left: 0;
width: 225px;
opacity: 0;
padding: 14px 0;
cursor: pointer;
}
.input-file:hover + .input-file-trigger,
.input-file:focus + .input-file-trigger,
.input-file-trigger:hover,
.input-file-trigger:focus {
background: #1899cd;
color: #ffffff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="p_test" id="p_test">
<div class="file-input">
<div class="input-file-container upl_drop">
<input class="input-file" id="file-upload" type="file">
<label tabindex="0" for="file-upload" id="input-file-trigger" class="input-file-trigger">Select a file...</label>
</div>
<div id="file-upload-filename"></div>
</div>
<button class="btn--add" id="addtest">
Add
</button>
</div>
I'd advise against using incremental id attributes. They become a pain to maintain and also make the logic much more complicated than it needs to be.
The better alternative is to use common classes along with DOM traversal to relate the elements to each other, based on the one which raised any given event.
In your case, you can use closest() to get the parent .file-input container, then find() any element within that by its class. Something like this:
$(function() {
var $test = $('#p_test');
$('#addtest').on('click', function() {
var $lastGroup = $test.find('.file-input:last');
var $clone = $lastGroup.clone();
$clone.find('.input-file-trigger').text('Select a file...');
$clone.insertAfter($lastGroup);
});
$test.on('click', '.remtest', function(e) {
if ($('.file-input').length > 1)
$(this).closest('.file-input').remove();
}).on('change', '.input-file', function(e) {
if (!this.files)
return;
var $container = $(this).closest('.file-input');
$container.find(".input-file-trigger").text('File name: ' + this.files[0].name);
});
});
.p_test {
display: inline-block;
}
.upl_drop {
border: 2px dashed #000;
margin: 0px 0px 15px 0px;
}
.btn--add p {
cursor: pointer;
}
.input-file-container {
position: relative;
width: auto;
}
.input-file-trigger {
display: block;
padding: 14px 45px;
background: #ffffff;
color: #1899cd;
font-size: 1em;
cursor: pointer;
}
.input-file {
position: absolute;
top: 0;
left: 0;
width: 225px;
opacity: 0;
padding: 14px 0;
cursor: pointer;
}
.input-file:hover+.input-file-trigger,
.input-file:focus+.input-file-trigger,
.input-file-trigger:hover,
.input-file-trigger:focus {
background: #1899cd;
color: #ffffff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="p_test" id="p_test">
<div class="file-input">
<div class="input-file-container upl_drop">
<input class="input-file" type="file">
<label tabindex="0" for="file-upload" class="input-file-trigger">Select a file...</label>
</div>
<div class="file-upload-filename"></div>
</div>
<button class="btn--add" id="addtest">Add</button>
</div>
Note that I've made a couple of other optimisations to the code. Firstly it now makes a clone() of the last available .file-input container when the Add button is clicked. This is preferred over writing the HTML in the JS file as it keeps the two completely separate. For example, if you need to update the UI, you don't need to worry about updating the JS now, as long as the classes remain the same.
Also note that you were originally mixing plain JS and jQuery event handlers. It's best to use one or the other. As you've already included jQuery in the page, I used that as it makes the code easier to write and more succinct.
Finally, note that you didn't need to provide a function to text() as you're completely over-writing the existing value. Just providing the new string is fine.

Polymer - before/after slider

I'm trying to create a before/after image slider similar to before-after.js or cocoen as a custom Polymer Web Component for Rails. However, I'm having some JavaScript issues with my implementation. Some have already been solved during the course of this question. The main remaining problems are:
Only the first instance of the component on the page works!
The web component's DOM elements are not found by the JS unless
they are inside window.onload, even though the script is included
at the very end of the .html for the component.
Here are the HTML, JS, and CSS files for the slider:
image-slider.html:
<dom-module id="image-slider">
<link rel="stylesheet" href="image-slider.css" />
<template>
<div id="dual-wrapper" style$="border: [[border]];
border-radius: [[border_radius]]; width: [[width]];
height: [[height]]; margin: [[margin]];">
<div id="img-snd-wrap">
<img src$="[[snd]]" class="img-snd">
</div>
<div id="img-fst-wrap">
<img src$="[[fst]]" class="img-fst">
</div>
<div class="img-blind" style="width: [[width]]; height: [[height]]"></div>
<div id="img-transition-slider" style$="height: [[height]];">
<div id="img-transition-slider-handle"
style$="margin-top: calc([[height]]/2 - [[handle_height]]/2);
height: [[handle_height]];">
</div>
</div>
</div>
</template>
<script src="image-slider.js"></script>
</dom-module>
image-slider.js:
Polymer({
is: "image-slider",
properties: {
fst: {
type: String
},
snd: {
type: String
},
width: {
type: String
},
height: {
type: String
},
border: {
type: String,
value: "none"
},
border_radius: {
type: String,
value: "0px"
},
handle_height: {
type: String,
value: "80px"
}
},
attached: function () {
var slider, first, second, container, x, prev_x, containerWidth;
slider = this.$['img-transition-slider'];
console.log(slider);
first = this.$['img-fst-wrap'];
second = this.$['img-snd-wrap'];
container = this.$['dual-wrapper'];
slider.onmousedown = function(e) {
document.body.style.cursor = "col-resize";
containerWidth = container.clientWidth;
prev_x = x - slider.offsetLeft;
slider.querySelector("#img-transition-slider-handle").style["background-color"] = '#888';
};
document.onmousemove = function(e) {
// X coordinate based on page, not viewport.
if (e.pageX) { x = e.pageX; }
// If the object specifically is selected, then move it to
// the X/Y coordinates that are always being tracked.
if(slider) {
var toReposition = (x - prev_x);
var newPosition = ((toReposition > containerWidth) ?
containerWidth - 2
: ((toReposition < 0) ?
0
:
toReposition
));
slider.style["margin-left"] = newPosition + 'px';
second.style["width"] = newPosition + "px";
first.style["width"] = (containerWidth - newPosition) + "px";
first.style["margin-left"] = newPosition + "px";
first.getElementsByTagName("img")[0].style["margin-left"] = (-newPosition) + "px";
}
};
document.onmouseup = function() {
document.body.style.cursor = "default";
slider.querySelector("#img-transition-slider-handle").style["background-color"] = '#555';
slider = false;
};
}
});
image-slider.css:
:host {
display: block;
}
#dual-wrapper {
display: block;
overflow: hidden;
position: relative;
-moz-user-select: -moz-none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
#img-fst-wrap, #img-snd-wrap {
display: block;
position: absolute;
overflow: hidden;
}
.img-blind {
display: block;
position: absolute;
}
#img-transition-slider {
position: absolute;
display: block;
width: 0px;
border: 1px solid #333;
border-top: none;
border-bottom: none;
}
#img-transition-slider:hover {
cursor: col-resize;
}
#img-transition-slider-handle {
width: 10px;
margin-left: -5px;
background-color: #555;
border-radius: 2px;
-webkit-transition: background-color .3s;
transition: background-color .3s;
}
If the web component is not duplicable, it is because you use document.getElementById() on ids that are themselves duplicated. So only the first (or last) element defined with this id will always be returned.
You should use this.$.[sub-element's id] to select an element inside the subtree of the Polymer element and add mouse event listener from inside the Polymer element, in the attached() callback method:
var slider = this.$['image-transition-slider']
//define the mouse event listeners inside the element
where this is the reference to the custom element itself.

Event Handlers On Newly Created Elements

I have a web app with a number of textareas and the ability to add more if you wish.
When you shift focus from one textarea to another, the one in focus animates to a larger size, and the rest shrink down.
When the page loads it handles the animation perfectly for the initial four boxes in the html file, but when you click on the button to add more textareas the animation fails to accomodate these new elements... that is, unless you place the initial queries in a function, and call that function from the addelement function tied to the button.
But!, when you do this it queries as many times as you add a new element. So, if you quickly add, say 10, new textareas, the next time you lay focus on any textarea the query runs 10 times.
Is the issue in my design, or jQueries implementation? If the former, how better can I design it, if it is the latter, how can I work around it?
I've tried to chop the code down to the relevant bits... I've tried everything from focus and blur, to keypresses, the latest is on click.
html::
<html>
<head>
<link rel="stylesheet" type="text/css" href="./sty/sty.css" />
<script src="./jquery.js"></script>
<script>
$().ready(function() {
var $scrollingDiv = $("#scrollingDiv");
$(window).scroll(function(){
$scrollingDiv
.stop()
//.animate({"marginTop": ($(window).scrollTop() + 30) + "px"}, "slow" );
.animate({"marginTop": ($(window).scrollTop() + 30) + "px"}, "fast" );
});
});
</script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>boxdforstacks</title>
</head>
<body>
<div class="grid">
<div class="col-left" id="left">
<div class="module" id="scrollingDiv">
<input type="button" value="add" onclick="addele()" />
<input type="button" value="rem" onclick="remele()" />
<p class="display">The value of the text input is: </p>
</div>
</div> <!--div class="col-left"-->
<div class="col-midd">
<div class="module" id="top">
<p>boxa</p>
<textarea class="tecksd" placeholder="begin typing here..." id="boxa" ></textarea>
<p>boxb</p>
<textarea class="tecksd" placeholder="begin typing here..." id="boxb"></textarea>
<p>boxc</p>
<textarea class="tecksd" placeholder="begin typing here..." id="boxc"></textarea>
<p>boxd</p>
<textarea class="tecksd" placeholder="begin typing here..." id="boxd"></textarea>
</div>
</div> <!--div class="col-midd"-->
</div> <!--div class="grid"-->
</body>
</html>
<script type="text/javascript" src="boxd.js"></script>
js:
function onit(){
$('textarea').on('keyup change', function() {
$('p.display').text('The value of the text input is: ' + $(this).val());
});
}
$('textarea').on("click",function(){
//alert(this.id.substring(0,3));
if ( this.id.substring(0,3) == 'box' ){
$('textarea').animate({ height: "51" }, 1000);
$(this).animate({ height: "409" }, 1000);
} else {
$('textarea').animate({ height: "51" }, 1000);
}
}
);
var boxfoc="";
var olebox="";
var numb = 0;
onit();
function addele() {
var tops = document.getElementById('top');
var num = numb + 1;
var romu = romanise(num);
var newbox = document.createElement('textarea');
var newboxid = 'box'+num;
newbox.setAttribute('id',newboxid);
newbox.setAttribute('class','tecksd');
newbox.setAttribute('placeholder','('+romu+')');
tops.appendChild(newbox);
numb = num;
onit();
} //addele(), add element
function remele(){
var tops = document.getElementById('top');
var boxdone = document.getElementById(boxfoc);
tops.removeChild(boxdone);
} // remele(), remove element
function romanise (num) {
if (!+num)
return false;
var digits = String(+num).split(""),
key = ["","c","cc","ccc","cd","d","dc","dcc","dccc","cm",
"","x","xx","xxx","xl","l","lx","lxx","lxxx","xc",
"","i","ii","iii","iv","v","vi","vii","viii","ix"],
roman = "",
i = 3;
while (i--)
roman = (key[+digits.pop() + (i * 10)] || "") + roman;
return Array(+digits.join("") + 1).join("M") + roman;
} // romanise(), turn numbers into roman numerals
css :
.tecksd {
width: 97%;
height: 51;
resize: none;
outline: none;
border: none;
font-family: "Lucida Console", Monaco, monospace;
font-weight: 100;
font-size: 70%;
background: white;
/* box-shadow: 1px 2px 7px 1px #0044FF;*/
}
.tecksded {
width: 97%;
resize: none;
outline: none;
border: none;
overflow: auto;
position: relative;
font-family: "Lucida Console", Monaco, monospace;
font-weight: 100;
font-size: 70%;
background: white;
/* box-shadow: 1px 2px 7px #FFDD00;*/
}
/*#postcomp {
width: 500px;
}*/
* {
#include box-sizing(border-box);
}
$pad: 20px;
.grid {
background: white;
margin: 0 0 $pad 0;
&:after {
/* Or #extend clearfix */
content: "";
display: table;
clear: both;
}
}
[class*='col-'] {
float: left;
padding-right: $pad;
.grid &:last-of-type {
padding-right: 0;
}
}
.col-left {
width: 13%;
}
.col-midd {
width: 43%;
}
.col-rght {
width: 43%;
}
.module {
padding: $pad;
}
/* Opt-in outside padding */
.grid-pad {
padding: $pad 0 $pad $pad;
[class*='col-']:last-of-type {
padding-right: $pad;
}
}
body {
padding: 10px 50px 200px;
background: #FFFFFF;
background-image: url('./backgrid.png');
}
h1 {
color: black;
font-size: 11px;
font-family: "Lucida Console", Monaco, monospace;
font-weight: 100;
}
p {
color: white;
font-size: 11px;
font-family: "Lucida Console", Monaco, monospace;
font-weight: 100;
}
You should use the following:
// New way (jQuery 1.7+) - .on(events, selector, handler)
$(document).on("click", "textarea", function () {
event.preventDefault();
alert('testlink');
});
Since the textarea is added dynamically, you need to use event delegation to register the event handler.
Try
$(document).on('click', 'textarea', function() {
// do something
});
The issue is you are binding the textareas only on the page load. I made a JSFiddle with working code: http://jsfiddle.net/VpABC/
Here's what I changed:
I wrapped:
$('textarea').on("click", function () {
//alert(this.id.substring(0,3));
if (this.id.substring(0, 3) == 'box') {
$('textarea').animate({
height: "51"
}, 1000);
$(this).animate({
height: "409"
}, 1000);
} else {
$('textarea').animate({
height: "51"
}, 1000);
}
});
in a function so it looked like this:
function bindTextAreas() {
$('textarea').unbind("click");
$('textarea').on("click", function () {
//alert(this.id.substring(0,3));
if (this.id.substring(0, 3) == 'box') {
$('textarea').animate({
height: "51"
}, 1000);
$(this).animate({
height: "409"
}, 1000);
} else {
$('textarea').animate({
height: "51"
}, 1000);
}
});
}
bindTextAreas();
What this does is it allows you to call this function, bindTextAreas, whenever you create a new textarea. This will unbind all the current events than rebind them. This will make it so your new textarea is has the click handler setup.
An place where this function is called is in the addele function like this:
function addele() {
var tops = document.getElementById('top');
var num = numb + 1;
var romu = romanise(num);
var newbox = document.createElement('textarea');
var newboxid = 'box' + num;
newbox.setAttribute('id', newboxid);
newbox.setAttribute('class', 'tecksd');
newbox.setAttribute('placeholder', '(' + romu + ')');
tops.appendChild(newbox);
numb = num;
onit();
bindTextAreas();
} //addele(), add element
Notice the bindTextAreas(); line near the bottom. This reloads all the click handlers.

jQuery Three Dots Plugin But Extandlable

Is there any jQuery plugin that will summarize my text i.e.:
123456789
into
1234...
However when I click that three dots it will expand it and show:
123456789
Without plugin css and jquery is welcome.
Any ideas?
There are several plugins for this, and it's so easy that you can probably create your own as well.
But, taking the work from someone else, here is a couple:
jQuery Expander Plugin
Jquery Plugin: readmore
CSS-only solution:
.truncate {
width: 250px; /* TODO: set as needed */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.truncate:hover {
white-space: normal;
overflow: visible;
text-overflow: inherit;
}
You could also rig something that'd do so on click via:
$(".truncate").click(function () { $(this).addClass("noTruncate"); }
and then change .truncate:hover to .noTruncate.
Here is a non-destructive, jQuery-binded and CSS-executed technique.
Considering this SCSS/LESS:
.collapsable {
margin-bottom: 10px; /* your <p> margin-bottom */
line-height: 20px; /* your <p> line-height */
p {
line-height: inherit;
margin-bottom: inherit;
&:last-child {
margin-bottom: 0;
}
}
&.collapsed {
position: relative;
overflow: hidden;
p {
margin: 0;
}
.expand-link-container {
position: absolute;
bottom: 0; right: 0;
display: block;
line-height: inherit;
padding: 0 2px 0 5px;
background-color: #FFF;
box-shadow: -5px 0 5px 0 white;
}
}
.expand-link-container {
display: none;
}
}
And this jQuery:
function collapseHTML(shownLines, expanderLink){
// Configuration
var shownLines = typeof(shownLines) === "undefined" ? 4 : shownLines,
expanderLink = typeof(expanderLink) === "undefined" ? "[...]" : expanderLink;
$('.collapsable').each(function(){
// If current collapsable has already been collapsed once, skip
if( $(this).find('.expand-link-container').length > 0 ) return false;
// Compute max-height from line-height and shownLines
var lineHeight = $(this).find('p').first().css('line-height');
maxHeight = parseInt(lineHeight, 10) * shownLines;
// If the current div needs collapsing
if( $(this).height() > maxHeight) {
$(this)
// Collapse it
.addClass('collapsed')
.css('max-height', maxHeight)
// Append expander link
.find('p:first-child').append(
'<div class="expand-link-container">' +
' ' + expanderLink + '' +
'</div>')
// Bind click to expander link
.find('.expand-link-container a').click(function(e){
e.preventDefault();
$(this).closest('.collapsable')
.removeClass('collapsed')
.css('max-height', '');
});
}
});
}
Calling collapseHTML() anywhere in your javascript will cause all div.collapse to collapse their HTML content.
Example in JSfiddle
I had used the Summary plugin before (http://plugins.learningjquery.com/summarize/index.html). However I do not know if it is available for the jQuery version that you are using.
You can use substr
Updated Fiddle - http://jsfiddle.net/GC2qC/1/
var ttext = $('span').text(); //Store value
$('span').text($('span').text().substr(0, 4)).append('...'); //Substring
$('body').on('click', 'span', function(){ //Display complete text
$(this).text(ttext);
});

Categories

Resources